【问题标题】:IntentService STICKY and sensor monitoring stops when it shouldn't in AndroidIntentService STICKY 和传感器监控在 Android 中不应该停止时停止
【发布时间】:2012-03-04 08:15:23
【问题描述】:

在我的应用程序 onCreate 中,我检查了一些条件,然后像这样启动一个 Activity:

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

从该活动中,我启动了一个 IntentService,它为传感器注册了一些侦听器,它以 STICKY 启动,这意味着它应该明确停止。该 IntentService 监控传感器。

我的问题是,当我回到第一个 Activity 时,传感器不再感应(我在 onSensorChanged 中放置了一个 Log.v(开始显示数据,然后停止)。

如果我没有明确停止它,为什么它会停止? 此外,我有时会看到 IntentService 的 OnDestroy 被调用,但同样,如果它是 STICKY 并且我没有调用 stopself() 并且没有以任何其他方式停止,如何调用它?

谢谢!吉列尔莫。

编辑

这是 IntentService 的代码(它应该一直运行,即使手机进入睡眠状态或按下主页按钮(我知道电池和其他一切,用户会收到警告并会有机会在他想要的时候关闭应用程序。

从 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并且通知图标消失。

我现在很绝望!请帮忙解决这个问题!

谢谢!吉列尔莫。

【问题讨论】:

    标签: android android-intent android-sensors intentservice


    【解决方案1】:

    根据IntentService documentation

    服务根据需要启动,依次使用 工作线程,并在工作结束时自行停止

    另外,根据相同的文档,您不应该在您的IntentService 中覆盖onStartCommand()onDestroy(),因为它实现了上面指定的自己的特殊行为。也许你需要扩展Service 而不是IntentService

    【讨论】:

    • 嗨,谢谢你的回答,我已经用代码更新了帖子。任何帮助将不胜感激。
    • 尝试了 startForeground 但 onDestroy 一直被调用,我真的不明白为什么。
    • 在进一步查看 IntentService 的文档后,我更新了我的答案。祝你好运
    • 嗯...我认为这就是粘性。当你让它变得粘稠时,你就可以处理它的生命周期。顺便说一句,我看到另一个问题的回复,有一个人说这是 Android 中的一个错误,我按照他的建议将代码移动到 onCreate 而不是 onHandleIntent 并且它有效!所以,如果没有人告诉我这是我的代码有问题,对我来说这将是一个错误。谢谢!。
    • IntentService 执行以下操作: ....“在处理完所有启动请求后停止服务,因此您无需调用 stopSelf()。”同意 gnobal 的回答......难道你应该扩展服务,而不是 IntentService。
    【解决方案2】:

    好的,我看到另一个问题的回复,并且有一个人说这是Android中的一个错误,我按照他的建议将代码移动到onCreate而不是onHandleIntent并且它起作用了!所以,如果没有人告诉我这是我的代码有问题,对我来说这将是一个错误。谢谢!

    【讨论】:

    • 然而,真正的答案是 IntentService 并不意味着处理回调或其他异步行为。您为此使用服务。无论如何,您基本上已经覆盖了这里的所有 IntentService 行为,而不仅仅是覆盖 onHandleIntent。
    猜你喜欢
    • 1970-01-01
    • 2020-09-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多