从应用程序托盘中删除应用程序后,将终止服务进程

时间:2013-12-15 07:46:41

标签: android android-service

我在启动活动时启动服务(或重新启动正在运行的服务),使用:

Intent intent = new Intent(this, MyService.class); startService(intent);

稍后基于某些操作,相同的活动使用

绑定到服务
bindService(new Intent(this, MyService.class), mConnection, Context.BIND_AUTO_CREATE);

当活动被破坏时,我打电话给

unbindService(mConnection);

之前,当我从应用程序托盘中杀死相同的活动/应用程序并在运行的应用程序下显示“消息1进程1服务正在运行”时,该服务用于重新启动。

现在,服务不会在杀死相同的活动/应用程序时重新启动。

我收到消息“0进程1服务正在运行”,这意味着服务实际上没有运行。

在关闭应用程序时,服务不会重新启动。我的申请包含一项活动。在系统启动后启动时,服务也会成功启动。

为什么在使用startService()??

启动服务时,服务进程会被终止

修改

我从应用程序托盘关闭应用程序后,用于重新启动的服务。但现在突然使用相同的代码,它没有。当我关闭它时,它也会与其他应用程序一起发生。例如。

enter image description here

6 个答案:

答案 0 :(得分:51)

这是我遇到的一种解决方法,如果在关闭应用程序时它的进程被终止,则可以很好地重新启动服务。在您的服务中,添加以下代码。

我在this帖子中遇到了这种解决方法。

@Override
public void onTaskRemoved(Intent rootIntent){
    Intent restartServiceIntent = new Intent(getApplicationContext(), this.getClass());
    restartServiceIntent.setPackage(getPackageName());

    PendingIntent restartServicePendingIntent = PendingIntent.getService(getApplicationContext(), 1, restartServiceIntent, PendingIntent.FLAG_ONE_SHOT);
    AlarmManager alarmService = (AlarmManager) getApplicationContext().getSystemService(Context.ALARM_SERVICE);
    alarmService.set(
    AlarmManager.ELAPSED_REALTIME,
    SystemClock.elapsedRealtime() + 1000,
    restartServicePendingIntent);

    super.onTaskRemoved(rootIntent);
 }

似乎是应用程序进程被杀死的错误。如果服务的进程被终止,服务就没有意义了。

答案 1 :(得分:6)

请注意: onDestroy并不总是被调用。你不应该这样放置代码。
当系统异常关闭或关闭活动时,onDestroy不会被调用。

答案 2 :(得分:4)

不幸的是,由于Android的工作方式,这是一个复杂的问题。有许多策略可以解决问题的不同部分。 为了获得最佳效果,请将多种策略结合使用。

请注意,在最近的Android版本中可能不再需要其中一些策略。

1。开始活动

怎么做

取自Foreground service killed when receiving broadcast after acitivty swiped away in task list

  

在前台服务中:

  @Override
    public void onTaskRemoved( Intent rootIntent ) {
       Intent intent = new Intent( this, DummyActivity.class );
       intent.addFlags( Intent.FLAG_ACTIVITY_NEW_TASK );
       startActivity( intent );
    }
     

在清单中:

  <activity
    android:name=".DummyActivity"
    android:theme="@android:style/Theme.NoDisplay"
    android:enabled="true"
    android:allowTaskReparenting="true"
    android:noHistory="true"
    android:excludeFromRecents="true"
    android:alwaysRetainTaskState="false"
    android:stateNotNeeded="true"
    android:clearTaskOnLaunch="true"
    android:finishOnTaskLaunch="true"
    /> 

(如果您的服务处于不同的流程,请将此活动的流程设置为相同的流程。)

  

在DummyActivity.java中:

  public class DummyActivity extends Activity {
        @Override
        public void onCreate( Bundle icicle ) {
            super.onCreate( icicle );
            finish();
        }
    }

副作用

使最近活动关闭。通常,刷掉应用程序并不会关闭最近的活动。

缺点

这只会生效when the dummy activity starts,这可能需要半秒或更长时间,所以这仍然可以使服务处于打开状态。

解释

当您移除/滑动您的应用时,名为waitingToKill的标记为set。设置此标记后,Android可能会终止进程{​​{3}},例如at any point in the future。开始活动when you receive a broadcast

2。使用clears this flag.

垃圾邮件BroadcastReceiver

怎么做

将其合并到您的服务代码中:

if (Build.VERSION.SDK_INT >= 16) {
    Intent intent = new Intent(this, DummyReceiver.class);
    intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);

    //This seems to be timing-related; the more times we do this,
    //the less likely the process gets killed
    for (int i = 0; i < 50; ++i)
        sendBroadcast(intent);
}

创建虚拟广播接收器:

public class DummyReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {}
}

将接收器添加到清单中:

<receiver android:name=".DummyReceiver" />

副作用

从最近屏幕移除任务时,可能会导致轻微(~250ms)延迟/挂起。

缺点

这只会在接收广播时使进程保持活动状态。 foreground broadcasts标志仍然设置,因此之后可能仍然会杀死该进程,例如收到广播时。

解释

如果您的流程未以前台优先级waitingToKill运行。接收前台广播会暂时阻止此操作,从而导致设置Android will try to kill it immediately标志。

3。不要绑定服务

waitingToKill

答案 3 :(得分:1)

我知道这个问题已经过时但我最近遇到了这个问题,突然我的服务在关闭应用时停止了。早些时候它工作正常。这个问题浪费了我很多时间。对于有类似问题的其他人,请确保您的背景数据限制已关闭。 这是我遇到的问题,它实际上是有道理的,因为后台数据是受限制的后台进程将无法运行。

答案 4 :(得分:1)

onDestroy并不总是被调用。你的情况下的主要问题是当app关闭时你无法启动服务,那时android OS( In Some OS )将会杀死服务,如果你无法重启服务,那就打电话给警报管理员来启动这样的接收器,

清单是,

         <service
            android:name=".BackgroundService"
            android:description="@string/app_name"
            android:enabled="true"
            android:label="Notification" />
        <receiver android:name="AlarmReceiver">
            <intent-filter>
                <action android:name="REFRESH_THIS" />
            </intent-filter>
        </receiver>

IN Main Activty以这种方式启动报警管理器,

String alarm = Context.ALARM_SERVICE;
        AlarmManager am = (AlarmManager) getSystemService(alarm);

        Intent intent = new Intent("REFRESH_THIS");
        PendingIntent pi = PendingIntent.getBroadcast(this, 123456789, intent, 0);

        int type = AlarmManager.RTC_WAKEUP;
        long interval = 1000 * 50;

        am.setInexactRepeating(type, System.currentTimeMillis(), interval, pi);

这将调用reciver和reciver,

public class AlarmReceiver extends BroadcastReceiver {
    Context context;

    @Override
    public void onReceive(Context context, Intent intent) {
        this.context = context;

        System.out.println("Alarma Reciver Called");

        if (isMyServiceRunning(this.context, BackgroundService.class)) {
            System.out.println("alredy running no need to start again");
        } else {
            Intent background = new Intent(context, BackgroundService.class);
            context.startService(background);
        }
    }

    public static boolean isMyServiceRunning(Context context, Class<?> serviceClass) {
        ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
        List<ActivityManager.RunningServiceInfo> services = activityManager.getRunningServices(Integer.MAX_VALUE);

        if (services != null) {
            for (int i = 0; i < services.size(); i++) {
                if ((serviceClass.getName()).equals(services.get(i).service.getClassName()) && services.get(i).pid != 0) {
                    return true;
                }
            }
        }
        return false;
    }
}

当打开Android应用程序并关闭应用程序时,这个Alaram会调用一次。服务是这样的,

public class BackgroundService extends Service {
    private String LOG_TAG = null;

    @Override
    public void onCreate() {
        super.onCreate();
        LOG_TAG = "app_name";
        Log.i(LOG_TAG, "service created");
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.i(LOG_TAG, "In onStartCommand");
        //ur actual code
        return START_STICKY;
    }

    @Override
    public IBinder onBind(Intent intent) {
        // Wont be called as service is not bound
        Log.i(LOG_TAG, "In onBind");
        return null;
    }

    @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
    @Override
    public void onTaskRemoved(Intent rootIntent) {
        super.onTaskRemoved(rootIntent);
        Log.i(LOG_TAG, "In onTaskRemoved");
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.i(LOG_TAG, "In onDestroyed");
    }
}

答案 5 :(得分:-1)

当没有绑定到服务或已建立的前景时,android系统会将该服务识别为应该关闭的未使用的重载服务。即使应用已关闭,以下是维持服务的最佳方式:AlarmManager or Service