为什么服务仍在运行,如果它的进程被杀死?

时间:2014-03-08 14:57:42

标签: android process android-service

我通过反编译检查过,在某些应用程序的清单中,服务不是通过单独的进程启动的。顺便说一下,在任务管理器中,它显示为“正在运行”。

例如Facebook,在Android 4.4.2上,有0个进程和2个服务正在运行。 从文档中(如果我错了,请纠正我)我已经明白服务在其应用程序的相同过程中运行。如果进程终止,则服务停止(可以通过AlarmManager或START_STICKY自动重启)。

因此,如果它没有在一个单独的进程内启动,那么至少应该有一个服务可以运行的进程。那么,即使没有进程,服务是否可能运行?我再说一遍,服务(来自清单)没有得到指令android:background

编辑1: 它似乎是Android 4.4.2的一个错误。请参阅thisthis。在我的情况下,当我从列表中滑动应用程序时遇到问题(如第二个链接中所述)

编辑2: 如果我错了,请纠正我,这是我所理解的。

调用Service时首次创建startService()对象。将在该服务对象上调用onCreate(),然后onStartCommand()将跟随。从现在开始:

  • 如果进程终止,服务对象仍然存在(如果stopSelf() 没有被调用但是它没有运行。
  • 如果服务中断,则重新创建的唯一方法是从START_STICKY(和其他重启常量)或手动调用startService()。当服务从系统中终止时,将再次调用onCreate。

现在,这是Android上的正常行为< 4.4.2。在KitKat上,如果从LRU列表中滑动应用程序,则进程会死亡,即使使用START_STICKY,它也不会自动重新启动。解决方法是AlarmManager。这是对的吗?

2 个答案:

答案 0 :(得分:1)

您的服务是您的申请的一部分。根据定义,您的应用程序在服务运行时运行。例如,当AlarmManager在预定时间调用您的服务时,Android首先启动应用程序的进程(如果它尚未运行),然后在正在运行的应用程序中调用您的服务。

一般来说,你是对的:如果应用程序(进程)死了,服务就会死掉。

Android支持清单属性android:process,它允许您指定应用程序的特定组件应在单独的进程中运行。实际上,这在多个进程中运行多个相同的应用程序副本。 Android只使用其中一个进程来运行一个组件而另一个运行另一个组件。您的应用程序正在两者中运行。

混淆的原因是设置>应用页面使用“进程”和“服务”字样。它似乎使用前者来计算具有UI组件的进程,而后者用于计算所有其他进程。如果您使用adb连接到您的设备并使用“ps”命令,您将获得更好地反映对这些词的共同理解的内容。

答案 1 :(得分:0)

某些Android操作系统的主要问题是当应用程序关闭时,Android 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");
    }
}