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

时间:2013-05-20 13:49:49

标签: android service android-activity restart shutdown

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

final Context context = base.getApplicationContext();
final Intent intent = new Intent(context, MyService.class);
startService(intent);

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

14 个答案:

答案 0 :(得分:39)

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

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

答案 1 :(得分:12)

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

答案 2 :(得分:12)

让你在Mainifest中以这样的方式服务

 <service
            android:name=".sys.service.youservice"
            android:exported="true"
        android:process=":ServiceProcess" />

然后您的服务将在名为ServiceProcess的其他进程

上运行

如果你想让你的服务永不消亡:

  1. onStartCommand()返回START_STICKY

  2. onDestroy() - &gt; startself

  3. 创建Deamon服务

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

  5. startForeground(),有一种方法可以在没有通知的情况下启动地面,google it

答案 3 :(得分:3)

应用程序关闭时无法启动服务的主要问题,Android OS(在某些操作系统中)将终止资源优化服务,如果您无法重新启动该服务,请调用警报管理器像这样启动reciver,这是整个代码,这段代码将保持你的服务。

清单是,

         <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");
    }
}

答案 4 :(得分:3)

服务有时非常复杂。

当您从活动(或您的流程)启动服务时,该服务基本上处于相同的流程中。

引用开发者说明

  

关于Service类的大多数混淆实际上都围绕着它不是:

     

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

     

服务不是线程。它不是从主线程开始工作的手段(以避免应用程序无响应错误)。

所以,这意味着,如果用户将应用程序从最近的任务中移开,它将删除您的进程(这包括您的所有活动等)。 现在,我们来看三个场景。

首先 服务没有前景通知。

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

第二 服务 前景通知

在这种情况下,服务不会被杀死,进程也不会被杀死

第三次 方案 如果该服务没有前台通知,则在应用关闭时它仍然可以继续运行。我们可以通过使服务在不同的进程中运行来实现。 (但是,我听说有人说这可能不起作用。留给你自己尝试

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

<强>机器人:过程=&#34;:yourService&#34;

android:process =&#34; yourService&#34; 进程名称必须以小写字母开头。

引用开发者说明

  

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

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

答案 5 :(得分:2)

试试这个,它会让服务在后台运行。

<强> BackServices.class

public class BackServices extends Service{

    @Override
    public IBinder onBind(Intent arg0) {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
   public int onStartCommand(Intent intent, int flags, int startId) {
      // Let it continue running until it is stopped.
      Toast.makeText(this, "Service Started", Toast.LENGTH_LONG).show();
      return START_STICKY;
   }
   @Override
   public void onDestroy() {
      super.onDestroy();
      Toast.makeText(this, "Service Destroyed", Toast.LENGTH_LONG).show();
   }
}
MainActivity onCreate中的

删除此行代码

startService(new Intent(getBaseContext(), BackServices.class));

现在该服务将继续在后台运行。

答案 6 :(得分:1)

最佳解决方案是在android中使用同步适配器来启动服务。创建一个同步适配器并在onPerformSync方法中调用启动服务..要创建同步帐户,请参阅此链接https://developer.android.com/training/sync-adapters/index.html

为何选择SyncAdapter? Ans:因为之前您曾经使用App上下文启动服务。因此,每当您的应用程序进程被杀死时(当您从任务管理器中移除它或操作系统因为缺乏资源而将其杀死时),您的服务也将被删除。 SyncAdapter将无法在应用程序线程中工作..所以,如果你在里面调用..服务将不再被删除..除非你写代码删除它。

答案 7 :(得分:1)

对服务和活动使用相同的过程以及服务中的START_STICKY或START_REDELIVER_INTENT是在应用程序重新启动时能够重新启动服务的唯一方法,例如,当用户关闭应用程序时,以及何时由于优化原因,系统决定关闭它。您无法拥有永久运行且不会中断的服务。这是设计,智能手机不能长时间运行连续过程。这是因为电池寿命是最高优先级。您需要设计服务,以便随时处理停止服务。

答案 8 :(得分:1)

您必须在Service类中添加此代码,以便在处理您的进程时处理该案例

 @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);
    }

答案 9 :(得分:1)

由于https://developer.android.com/about/versions/oreo/background,您无法在Android O中将服务用于长时间运行的后台操作。 Jobservice将是Jobscheduler实施的更好选择。

答案 10 :(得分:0)

为什么不使用IntentService?

IntentService在主线程之外打开一个新线程并在那里工作,这样关闭应用程序就不会影响它

建议IntentService运行onHandleIntent(),当它完成服务关闭时,看看它是否符合您的需求。 http://developer.android.com/reference/android/app/IntentService.html

答案 11 :(得分:0)

<service android:name=".Service2"
            android:process="@string/app_name"
            android:exported="true"
            android:isolatedProcess="true"
            />

在清单中声明此内容。为您的流程提供自定义名称,并将该流程隔离并导出。

答案 12 :(得分:0)

运行意向服务会更容易。在应用程序中创建线程但仍在应用程序中的服务。

答案 13 :(得分:-5)

在你的第一个可见活动中覆盖onDestroy方法,比如在你拥有主页之后,从splash到主页重定向你已经完成了启动。所以在主页上放毁。并停止该方法的服务。