应用程序关闭时Android服务停止

Bam*_*Bam 70 service android shutdown restart android-activity

我从我的主要Android活动开始提供服务,如下所示:

final Context context = base.getApplicationContext();
final Intent intent = new Intent(context, MyService.class);
startService(intent);
Run Code Online (Sandbox Code Playgroud)

当我通过从最近的应用程序列表中滑出来关闭活动页面时,服务会停止运行并在一段时间后重新启动.由于我的应用程序要求,我无法将持久服务与通知一起使用.如何使服务不重启或关闭,并继续在应用程序退出运行?

小智 42

我处于相同的情况,到目前为止,我知道应用程序关闭时服务也因为它们在一个线程中而关闭,所以服务应该在另一个线程上,以便它不被关闭,看看并通过这里的示例http://www.vogella.com/articles/AndroidServices/article.html查看使用警报管理器保持服务的活动状态,这样您的服务就不会显示在通知中.

最后,经过我所做的所有研究后,我逐渐意识到长期服务的最佳选择是startForeground(),因为它是为此而制定的,系统实际上可以很好地处理您的服务.

  • @Bam我有这个确切的问题.但是,我的服务是一个前台服务,当我的活动关闭时它仍然会被杀死.我将我的intent初始化参数从上下文getApplicationContext()改为getBaseContext(),它解决了这个问题. (8认同)
  • 我应该使用 `startForeground(intent.getIntExtra("notification_Id, 0), builder.build()); 而不是使用 `notificationManager.notify(intent.getIntExtra("notification_Id", 0), builder.build());` ` ? 我正在使用NotificationCompat.Builder (2认同)

art*_*tex 12

可能对你有所帮助.我可能会弄错,但在我看来,这与START_STICKY你的onStartCommand()方法中的返回有关.您可以通过返回START_NOT_STICKY来避免再次调用服务.

  • 实际上,当我退出或关闭应用程序(然后重新启动服务)时,服务停止运行.当我退出/关闭应用程序时,我不希望服务暂停/停止; 我希望它继续运行.我相信解决方案与在单独的流程上运行服务有关,但我不太确定. (3认同)

ala*_*ban 12

让你在Mainifest中像这样服务

 <service
            android:name=".sys.service.youservice"
            android:exported="true"
        android:process=":ServiceProcess" />
Run Code Online (Sandbox Code Playgroud)

那么您的服务将在名为ServiceProcess的其他进程上运行


如果你想让你的服务永远不会死:

  1. onStartCommand()返回START_STICKY

  2. onDestroy() - > startself

  3. 创建一个Deamon服务

  4. jin - >创建一个Native Deamon进程,你可以在github上找到一些开源项目

  5. startForeground(),有一种方法可以启动没有通知的startForeground,google它

  • 非常确定在onDestroy中启动它会被认为是对抗android系统,这是不好的做法. (11认同)

Aji*_*K P 6

主要问题是应用程序关闭时无法启动服务,android操作系统(在某些操作系统中)将终止服务以进行资源优化,如果您无法重新启动服务,则调用警报管理器来启动接收器,如下所示,这是完整的代码,此代码将使您的服务保持活动状态。

体现为,

         <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>
Run Code Online (Sandbox Code Playgroud)

在 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);
Run Code Online (Sandbox Code Playgroud)

这将调用接收者,接收者是,

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

当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");
    }
}
Run Code Online (Sandbox Code Playgroud)


小智 5

有时服务非常复杂。

当您从活动(或您的流程)启动服务时,该服务本质上是在同一流程上。

引用开发者注释

关于Service类的最困惑实际上是围绕它不是什么:

服务不是独立的过程。Service对象本身并不意味着它在自己的进程中运行;除非另有说明,否则它将与它所属的应用程序在同一进程中运行。

服务不是线程。它本身并不是在主线程之外工作的一种方式(以避免Application Not Responding错误)。

因此,这意味着,如果用户将应用程序从最近的任务中滑出,它将删除您的流程(包括您的所有活动等)。现在,让我们来看三种情况。

首先,该服务没有前台通知。

在这种情况下,您的过程将与服务一起被杀死。

其次,服务具有前台通知

在这种情况下,服务不会被终止,进程也不会被终止

第三种情况如果该服务没有前台通知,则在应用程序关闭时仍可以继续运行。我们可以通过使服务在不同的流程中运行来做到这一点。(但是,我听说有人说它可能不起作用。请您自己尝试一下

您可以通过在清单中包含以下属性来在单独的过程中创建服务。

android:process =“:yourService”

要么

android:process =“ yourService”流程名称必须以小写字母开头。

引用开发人员注释

如果分配给此属性的名称以冒号(':')开头,则会在需要时创建一个新的进程,该进程是应用程序专用的,并且服务在该进程中运行。如果进程名称以小写字母开头,则该服务将在具有该名称的全局进程中运行,前提是它具有这样做的权限。这允许不同应用程序中的组件共享进程,从而减少资源使用。

这是我收集的信息,如果有人是专家,如果我错了,请纠正我:)


小智 5

从 Android O 开始,您无法使用这些服务来进行长时间运行的后台操作,因为https://developer.android.com/about/versions/oreo/background。Jobservice 将是 Jobscheduler 实施的更好选择。