Android应用程序closures时,Android服务停止
我从我的主要Android活动中启动一项服务,如下所示:
final Context context = base.getApplicationContext(); final Intent intent = new Intent(context, MyService.class); startService(intent);
当我通过从最近的应用程序列表中滑出来closures活动页面时,该服务停止运行并在一段时间后重新启动。 由于我的应用程序需求,我无法使用持续服务。 我如何使服务不重新启动或closures,只是继续在应用程序退出运行?
我处于同样的情况,到目前为止,我了解到,当应用程序closures服务closures也是因为它们在一个线程,所以服务应该在另一个线程,以便它不被closures,看看并查看保持服务与警报pipe理器在这里举例http://www.vogella.com/articles/AndroidServices/article.html这样你的服务将不会显示在通知中。;
最后,在我所做的所有研究之后,我意识到长时间运行的服务的最佳select是startForeground()
,因为它是为了实现这个目的而实际处理好你的服务。
这可能会帮助你。 我可能弄错了,但在我看来,这与在onStartCommand()
方法中返回START_STICKY
有关。 您可以通过返回START_NOT_STICKY
来避免再次调用该服务。
让你在你的Mainifest中像这样的服务
<service android:name=".sys.service.youservice" android:exported="true" android:process=":ServiceProcess" />
那么你的服务将运行在名为ServiceProcess的其他进程上
如果你想让你的服务永不死亡:
-
onStartCommand()返回START_STICKY
-
onDestroy() – >自己开始
-
创build一个Deamon服务
-
jin – >创build一个Native Deamon进程,你可以在github上find一些开源项目
-
startForeground(),有没有通知,谷歌它startForeground的方法
试试这个,它会让服务在后台运行。
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));
现在服务将保持在后台运行。
在closures应用程序时无法启动服务的主要问题,android操作系统( 在某些操作系统 )将终止资源优化服务,如果您不能重新启动服务,然后调用警报pipe理器来启动这样的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>
在主要活动启动闹铃pipe理器这样,
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; } }
而这个Alaram reciver在Android应用程序被打开和应用程序closures时会调用一次。这个服务就是这样,
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"); } }
为什么不使用IntentService?
IntentService打开一个新的线程,除了主线程,并在那里工作,closures应用程序不会影响它
请注意,IntentService运行onHandleIntent(),并在服务closures时查看它是否符合您的需求。 http://developer.android.com/reference/android/app/IntentService.html
最好的解决scheme是使用android中的同步适配器来启动服务。 创build一个同步适配器,并调用启动服务他们..内onPerformSync方法。 创build同步帐户请参考此链接https://developer.android.com/training/sync-adapters/index.html
为什么SyncAdapter? Ans:因为之前你曾经使用App上下文来启动服务。 所以每当你的应用程序进程被杀死(当你从任务pipe理器或操作系统中删除它因为缺乏资源而被杀死),那么你的服务也将被删除。 SyncAdapter将不能在应用程序线程中工作..所以如果你在它内部调用..服务将不再被删除..除非你写代码删除它。
<service android:name=".Service2" android:process="@string/app_name" android:exported="true" android:isolatedProcess="true" />
在清单中声明这个。 为您的stream程提供一个自定义名称,并将该stream程隔离并导出。
在服务和活动中使用相同的进程,在服务中使用START_STICKY或START_REDELIVER_INTENT是在应用程序重新启动时能够重新启动服务的唯一方式,例如,当用户closures应用程序时,而且在系统决定时为了优化原因closures它。 你不能有一个永久运行,没有任何中断的服务。 这是devise,智能手机不是长时间运行连续的过程。 这是由于电池寿命是最重要的事实。 您需要devise您的服务,以便在任何时候处理被停止。
服务有时很复杂。
当你从一个活动(或你的过程)开始一个服务时,这个服务本质上是在同一个过程中。
从开发人员的报价引用
关于服务类的大部分困惑实际上围绕着什么不是:
服务不是一个单独的过程。 服务对象本身并不意味着它在自己的进程中运行; 除非另有说明,它运行在与它所属的应用程序相同的进程中。
服务不是一个线程。 这不是一个方法本身做主线程的工作(以避免应用程序不响应错误)。
所以,这意味着,如果用户将应用程序从最近的任务中删除,它将删除您的过程(这包括所有的活动等)。 现在,让我们采取三种情况。
首先 ,服务没有前台通知。
在这种情况下,你的过程与你的服务一起被杀死。
其次服务有前台通知
在这种情况下,该服务不会被杀死,这个过程也不是
第三种情况如果服务没有前台通知,如果应用程序closures,它仍然可以继续运行。 我们可以通过使服务在不同的进程中运行来做到这一点。 (但是,我听说有人说这可能行不通,你自己去试试吧 )
您可以通过在清单中包含以下属性在单独的进程中创build服务。
机器人:过程= “:yourService”
要么
android:process =“yourService”进程名称必须以小写字母开头。
从开发人员的笔记引用
如果分配给该属性的名称以冒号(':')开始,则在需要时会创build一个专用于应用程序的新进程,并在该进程中运行该服务。 如果进程名称以小写字母开头,则该服务将以该名称的全局进程运行,前提是它有权这样做。 这允许不同应用程序中的组件共享一个进程,从而减less资源使用。
这是我所收集的,如果任何人是专家,请纠正我,如果我错了:)
您必须将此代码添加到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); }
运行意向服务将会更容易。 在应用程序中创build线程的服务,但它仍然在应用程序中。
只要在第一个可见的活动中覆盖onDestroy方法,就像在你有主页的时候一样,在从splash到主页的redirect之后,你已经完成了飞溅。 所以把它摧毁在主页上。 并停止该方法的服务。