ЗАЛИПАНИЕ IntentService и мониторинг датчиков прекращаются, когда этого не должно быть в Android

StackOverflow https://stackoverflow.com/questions/9501163

Вопрос

В моем приложении onCreate я проверяю некоторые условия, а затем запускаю действие, подобное этому:

Intent startIntent = new Intent(getApplicationContext(), EnableLocationProviderActivity.class);
startIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
getApplicationContext().startActivity(startIntent);

Из этого действия я запускаю IntentService, который регистрирует некоторые прослушиватели для датчиков, он запускается как STICKY, что означает, что он должен быть явно остановлен.Этот IntentService отслеживает работу датчиков.

Моя проблема в том, что когда я возвращаюсь к первому действию, датчики больше не регистрируют (я помещаю Log.v в onSensorChanged (начинает показывать данные, а затем останавливается).

Почему могло случиться так, что это остановилось, если я не остановил это явно?Более того, я вижу, что иногда вызывается onDestroy IntentService, но опять же, как он может быть вызван, если он ЛИПКИЙ, и я не вызывал stopself() и не останавливался каким-либо другим способом?

Спасибо!Гильермо.

Редактировать

Это код IntentService (который должен быть запущен все время, несмотря на то, что мобильный телефон переходит в спящий режим или нажата кнопка home (я знаю о батарее и всем остальном, пользователь будет предупрежден об этом и будет иметь возможность закрыть приложение, когда захочет.

Служба вызывается из MainActivity следующим образом:

Intent startIntent = new Intent(GdpTesisApplication.getInstance().getApplicationContext(), SensingService.class);
startService(startIntent);

И сервисный код вот этот:

public class SensingService extends IntentService implements SensorEventListener {
    private float[] mAccelerationValues;
    private SensorManager mSensorManager = null;
    String sensorType = "";

    public SensingService(String name) {
        super(name);
        setIntentRedelivery(true);
    }

    public SensingService() {
        super("SensingService");
        setIntentRedelivery(true);
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.v(ApplicationName,"SensingService.onStartCommand");
        super.onStartCommand(intent, flags, startId); // If this is not written then onHandleIntent is not called.
        return START_STICKY;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        Log.v(ApplicationName, "SensingService.onCreate");
        initialize();
    }

    private void initialize() {
        mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); // This must be in onCreate since it needs the Context to be created.
        mAccelerationValues = new float[3];

        Log.v(ApplicationName, "Opening Location Service from Sensing Service");
        LocationService myLocation = new LocationService();
        myLocation.getLocation(this, locationResult);
    }

    @Override
    public void onDestroy() {
        Log.v(ApplicationName, "SensingService.onDestroy");
        super.onDestroy();
        if (mSensorManager != null) {
            mSensorManager.unregisterListener(this);
        }
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        Log.v(ApplicationName, "SensingService.onHandleIntent");
        if (mSensorManager != null) {
            registerListeners();
        }
    }

    public LocationResult locationResult = new LocationResult() {
        @Override
        public void gotLocation(final Location location) {
            if (location != null) {
                Log.v(ApplicationName, "Location != null : (" + location.getLatitude() + "," + location.getLongitude() + ")");
            } else {
                Log.v(ApplicationName, "Location == null : (0,0)");
            }
        }
    };

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

    public void onSensorChanged(SensorEvent currentEvent) {
        if (currentEvent.accuracy == SensorManager.SENSOR_STATUS_UNRELIABLE) {
            return;
        }

        synchronized (this) {
            float[] accelVals = null;
            float totalForce = 0.0f;

            int sensor = currentEvent.sensor.getType();
            System.arraycopy(currentEvent.values, 0, mAccelerationValues, 0, 3); // We use System.arraycopy because of this:
            switch (sensor) {
            case Sensor.TYPE_ACCELEROMETER:
                sensorType = "Accelerometer";
                totalForce = SensorsHelpers.getTotalForceInGs(mAccelerationValues); 
                break;
            case Sensor.TYPE_LINEAR_ACCELERATION:
                sensorType = "LinearAcceleration";
                totalForce = SensorsHelpers.getTotalForceInGs(mAccelerationValues) + 1; 
                break;
            case Sensor.TYPE_GRAVITY:
                totalForce = SensorsHelpers.getTotalForceInGs(mAccelerationValues); 
                sensorType = "Gravity";
                break;
            } 
            Log.v(ApplicationName,DateHelper.GetUTCdatetimeFromDate(new Date()) + " - from sensingService");
        }
    }

    private void registerListeners() {
        Log.v(ApplicationName, "Registering sensors listeners");
        mSensorManager.registerListener(this, mSensorManager.getDefaultSensor(Sensor.TYPE_LINEAR_ACCELERATION), SensorManager.SENSOR_DELAY_UI);
        mSensorManager.registerListener(this, mSensorManager.getDefaultSensor(Sensor.TYPE_GRAVITY),SensorManager.SENSOR_DELAY_UI);
        mSensorManager.registerListener(this, mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_UI);
    }
}

ОБНОВЛЕНИЕ 2

Теперь я добавил это в метод onCreate:

int NOTIFICATION_ID = 1;
Intent intent = new Intent(this, MainActivity.class);
PendingIntent pi = PendingIntent.getActivity(this, 1, intent, 0);
Notification notification = new Notification(R.drawable.ic_dialog_info, "Running in the Foregound", System.currentTimeMillis());
notification.setLatestEventInfo(this, "Title", "Text", pi);
notification.flags = notification.flags | Notification.FLAG_ONGOING_EVENT;
startForeground(NOTIFICATION_ID, notification);

чтобы запустить его как startForground, но он помещает значок в панель уведомлений, затем в службе вызывается onDestroy, и значок уведомления исчезает.

Теперь я в отчаянии!Пожалуйста, помогите в этом!

Спасибо!Гильермо.

Это было полезно?

Решение 2

Хорошо, я увидел ответ на другой вопрос, и там есть парень, который сказал, что это ошибка в Android, я последовал его предложению переместить код в onCreate вместо onHandleIntent, и это сработало!Итак, если никто не покажет мне, что это проблема с моим кодом, для меня это будет ошибкой.Спасибо!

Другие советы

Согласно Документация IntentService:

служба запускается по мере необходимости, обрабатывает каждое намерение, в свою очередь, с помощью рабочий поток , и останавливается сам, когда у него заканчивается работа

Кроме того, согласно той же документации, вы не должны переопределять onStartCommand() и onDestroy() в вашем IntentService, Я предполагаю, потому что он реализует свое собственное особое поведение, как указано выше.Может быть, вам нужно расширить Service вместо того, чтобы IntentService.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top