Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/selenium/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 导致崩溃的后台服务_Android_Android Intent_Android Service - Fatal编程技术网

Android 导致崩溃的后台服务

Android 导致崩溃的后台服务,android,android-intent,android-service,Android,Android Intent,Android Service,我的问题可能是对服务和我对它们的使用的明显误解,或者poss与其他应用程序的冲突。当我启动一个特定的活动时,我会启动两个后台服务-位置跟踪以给出行驶的距离和经过的计时器,这两个服务都通过广播接收器传递给活动。我通过主活动中的Intent对象以Long启动每个服务: if (!Utils.isServiceRunning(this, TrackService.class)) { Intent i = new Intent(this, TrackService.class); i.p

我的问题可能是对服务和我对它们的使用的明显误解,或者poss与其他应用程序的冲突。当我启动一个特定的活动时,我会启动两个后台服务-位置跟踪以给出行驶的距离和经过的计时器,这两个服务都通过
广播接收器传递给活动。我通过主
活动中的
Intent
对象以
Long
启动每个服务:

if (!Utils.isServiceRunning(this, TrackService.class)) {
    Intent i = new Intent(this, TrackService.class);
    i.putExtra("SUB_ID", submissionID);
    startService(i);
}
我使用以下代码来检测服务是否已在运行:

public static boolean isServiceRunning(Activity activity, Class<?> serviceClass) {
    ActivityManager manager = (ActivityManager) activity.getSystemService(Context.ACTIVITY_SERVICE);
    for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
        if (serviceClass.getName().equals(service.service.getClassName())) {
            return true;
        }
    }
    return false;
}
在某些设备上,这似乎工作得很好-该服务在后台工作,允许我使用应用程序中的其他活动&也可以在应用程序中进出,当我下次打开我的特定活动时,距离和时间会更新并正确

然而,我收到了大量的崩溃报告,来自用户的轶事证据表明,是在退出我的应用程序后才使用相机的(我还没有确定我的应用程序中的崩溃是在使用另一个应用程序时发生的,还是在他们重新进入我的应用程序时发生的):

在我看来,由于某种原因,服务正在停止,并且在重新启动时无法从意图访问数据(我理解什么是空指针错误)。这是因为我返回的
START\u STICKY
在重新启动时返回空数据吗

有人知道服务停止的原因吗?我怎样才能防止这种情况发生


我无法使用我自己的设备(Moto G4,Android 7.0)重新创建,在那里它可以像我希望的那样工作。

解决此问题的快速方法是:

在服务的onStartCommand()回调中返回
START\u REDELIVER\u INTENT
,而不是
START\u STICKY
,以便在重新启动后发送整个INTENT

您可以使用以下if条件将代码包装到onstart命令中:

if (null == intent || null == intent.getAction ()) {


        return START_STICKY;
}else{
  //ur code goes in

   return START_STICKY;
 }
此空指针异常的原因可能是:
“如果没有任何挂起的启动命令要传递给服务,它将被一个null intent对象调用,因此您必须注意检查它。”

Android中的任何东西都可以在任何时候被终止,例如,如果系统资源很少。所以你的代码应该随时准备好。而后台服务处理方式的巨大变化将在O。 鉴于此,我认为你可以阅读Android:

如果此服务尚未运行,它将被实例化并启动(如果需要,为其创建一个进程);如果它正在运行,则它将保持运行。对此方法的每次调用都将导致对目标服务的onStartCommand(Intent,int,int)方法的相应调用,其目的如下所示

因此,不要把所有责任都交给打电话的人,而要把责任转移到被叫人身上。在需要向服务传递一些信息的任何时候启动服务,然后让服务(它已经知道它是否已实例化并正在运行)处理该案例。另外,要像在Android中一样防止空值:

// caller, no if-check here (no responsibility)
startService(new Intent(this, TrackService.class).putExtra("SUB_ID", submissionID));
然后另一方,被调用的服务:

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
    if (intent == null) {
        // do nothing and return
        return START_STICKY;
    }

    // here your intent is not null, use it
    submissionID = intent.getLongExtra("SUB_ID", 0L);
    // if you got the most recent data already, do nothing
    // else, retrieve data using the passed id

    return START_STICKY;
最后但并非最不重要的一点是,请注意您不需要调用super.onStartCommand(intent、flags、startId),看看它的实现。 请记住责任倒置,因为这是一种更通用的方法,您可以使用相当多的Android编码,而不仅仅是在本例中。希望有帮助

Android可以(也将)随时停止您的
服务。因为您已经从
onStartCommand()
返回了
START\u STICKY
,Android应该在您的
服务被终止后重新启动它。在这种情况下,重新启动后,
onStartCommand()
中会出现null
Intent
。如果安卓想要杀死你的
服务
,那么没有办法阻止它


您需要定期将任何有用的数据保存在持久性存储(SharedReferences、文件、数据库等)中,以便在重启后恢复

您是否在清单文件的意向操作中注册了您的广播接收器?或者?

在你的
TrackService
类的第102行有一个空指针。我的主要问题可能是“为什么服务应该停止”,这导致了空指针(我知道其中一个是什么)。服务停止是因为它遇到了空的意图引用,start_sticky是罪魁祸首谢谢。使用
START\u REDELIVER\u INTENT
是否不会将位置跟踪和经过的时间重置回起始点?如果发生这种情况,那么数据将是无用的,因为我需要这些数据的延续。我更关心的是在一开始就试图阻止它重新启动,以及为什么它会重新启动。它重新启动是因为你通过调用START_STICKYOK来这么做,为不太清楚表示歉意,重新措辞:为什么服务会停止?动态地。清单中只注册了服务。然后在OnResume和OnPause上检查您是否正在注册和注销接收器,并检查[Alessio]的回答[
// caller, no if-check here (no responsibility)
startService(new Intent(this, TrackService.class).putExtra("SUB_ID", submissionID));
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
    if (intent == null) {
        // do nothing and return
        return START_STICKY;
    }

    // here your intent is not null, use it
    submissionID = intent.getLongExtra("SUB_ID", 0L);
    // if you got the most recent data already, do nothing
    // else, retrieve data using the passed id

    return START_STICKY;