Гироскоп с сенсорным контролем, не получающий данных через одну минуту в фоновом режиме - PullRequest
0 голосов
/ 30 октября 2019

Так что он отлично работает, когда приложение на переднем плане и первая минута на заднем плане. Но после этого слушатель перестает получать гироскопические данные. Но пост-ветка и слушатель местоположения продолжают работать.

Я много чего перепробовал, и у меня ничего не получалось.

public final class Secret extends Service implements SensorEventListener, LocationListener {
    private final String create = "CREATE TABLE IF NOT EXISTS data(lat float, lon float, x float, y float, z float, timestamp bigint)";
    private SensorManager sensorManager;
    private Database database;
    private Location location;

    @Override
    public final void onCreate() {
        /* Init sensor manager */
        this.sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
    }

    @Override
    public final int onStartCommand(final Intent intent, final int flags, final int startId) {
        /* Initialize & load database */
        this.database = new Database(openOrCreateDatabase("name_data.db", MODE_PRIVATE, null));
        this.database.exec(this.create);

        /* Init location manager */
        final LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);

        try {
            /* Register sensor change listener */
            this.sensorManager.registerListener(this, this.sensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY), SensorManager.SENSOR_STATUS_ACCURACY_HIGH);

            /* Register location change listener */
            locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 1, this);
        } catch (final SecurityException e) {
            Toast.makeText(this, "Failed to start: " + e.getMessage(), Toast.LENGTH_LONG).show();
            e.printStackTrace();
        }

        /* Post data every 5 minutes */
        final Thread thread = new Thread(new Runnable() {
            @Override
            public final void run() {
                /* Secret instance */
                final Secret secret = Secret.this;

                /* 5 minutes */
                final long time = 15000;

                while (true) {
                    try {
                        /* Wait 5 minutes */
                        Thread.sleep(time);

                        /*
                         * Unregister sensor change listener,
                         * this way posting wont cause any database errors,
                         * and the sensor events wont time out when app is running in the background
                         */
                        sensorManager.unregisterListener(secret);

                        /* Post database */
                        final int returned = post();

                        /* Register sensor change listener */
                        sensorManager.registerListener(secret, sensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE), SensorManager.SENSOR_STATUS_ACCURACY_HIGH);

                        switch (returned) {
                            case -1:
                                System.err.println("Database too small to post");
                                break;

                            case HttpURLConnection.HTTP_OK:
                                System.out.println("Posted database");
                                break;

                            default:
                                System.err.println("Post failed: " + returned);
                        }
                    } catch (final InterruptedException e) {
                        System.err.println("Failed to sleep");
                        e.printStackTrace();
                    }
                }
            }
        });

        /* Set thread priority and start */
        thread.setPriority(Thread.MIN_PRIORITY);
        thread.start();
        return START_STICKY;
    }

    @Nullable
    @Override
    public final IBinder onBind(final Intent intent) {
        return null;
    }

    @Override
    public final void onSensorChanged(final SensorEvent event) {
        System.out.println(System.currentTimeMillis());
        /* Store data if location is known */
        if (event == null || this.location == null) return;
        float[] gyro = event.values;

        /* Insert data into database */
        this.database.exec("INSERT INTO data(lat, lon, x, y, z, timestamp) VALUES(" + this.location.getLatitude() + "," + this.location.getLongitude() + "," + gyro[0] + "," + gyro[1] + "," + gyro[2] + "," + System.currentTimeMillis() + ")");
    }

    @Override
    public final void onAccuracyChanged(final Sensor sensor, final int accuracy) {
    }

    @Override
    public final void onLocationChanged(final Location location) {
        this.location = location;
    }

    @Override
    public final void onStatusChanged(final String provider, final int status, final Bundle extras) {
    }

    @Override
    public final void onProviderEnabled(final String provider) {
    }

    @Override
    public final void onProviderDisabled(final String provider) {
    }

    /**
     * Post database to server
     */
    private final int post() {
        /* Check if database is large enough (8 MB) to be pushed */
        if (this.database.getFile().length() <= 8192) return -1;

        /* Push database to server */
        final int returned = Connection.post(this.database.getFile());

        /* Check if database was pushed successfully */
        if (returned == HttpURLConnection.HTTP_OK) {
            /* Clear database if it was pushed to server successfully */
            this.database.close();
            this.database.getFile().delete();

            /* Create new database */
            this.database = new Database(openOrCreateDatabase("name_data.db", MODE_PRIVATE, null));
            this.database.exec(this.create);
        }

        return returned;
    }
}

OnDestroy срабатывает, а затем датчик перестает давать данные. Поток и локация продолжают работать.

...