Wons' Blog

个人博客

后端程序猿 - Python / C++ / Java


回首向来萧瑟处,也无风雨也无晴

Android防止Service被杀死

1. Service被杀死的两种场景

1.2 系统回收

在系统内存空间不足时可能会被系统杀死以回收内存,内存不足时Android会依据Service的优先级来清除Service。

1.2 用户清除

用户可以在”最近打开”(多任务窗口、任务管理窗口)中清除最近打开的任务,当用户清除了Service所在的任务时,Service可能被杀死(不同ROM有不同表现,在小米、魅族等第三方产商定制ROM上一般会被立即杀死,在Android N上没有被立即杀死)。

2. 解决方案

对于第一种场景(系统回收),如果不用黑科技(双进程互开等),我们只能够尽量提高Service的优先级,一种比较好的方式是使用前台Service

对于第二种场景(用户手动清除),可以将启动Service的任务排除出系统的最近任务列表。

2.1 前台Service

前台Service是一种有前台界面(Notification)、优先级非常高的Service,只有在系统内存空间严重不足时,才会清除前台Service。

只需要在Service的onCreate() 或者 onStartCommand() 内调用startForeground,就能将Service转为前台Service。示例如下:


private Notification buildForegroundNotification() {
   Notification.Builder builder = new Notification.Builder(this);

   builder.setOngoing(true);

   builder.setContentTitle(getString(R.string.notification_title))
           .setContentText(getString(R.string.notification_content))
           .setSmallIcon(R.mipmap.ic_launcher)
           .setTicker(getString(R.string.notification_ticker));
   builder.setPriority(Notification.PRIORITY_MAX);
   return builder.build();
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
   Log.e(TAG, "onStartCommand");

   WindowManager windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
   mRootView = new FloatRootView(this);
   mRootView.attach(windowManager);
   mRootView.showBubble();
   startForeground(1, buildForegroundNotification());

   return START_STICKY;

}

2.2 移出最近任务

为了使Service不会被用户从”最近打开”中清除,我们可以将启动Service的任务从系统的最近应用列表中删除。做法是将任务Activity的excludeFromRecents设为true,如下:


<activity android:name=".MainActivity"
         android:excludeFromRecents="true">
   <intent-filter>
       <action android:name="android.intent.action.MAIN"/>

       <category android:name="android.intent.category.LAUNCHER"/>
   </intent-filter>
</activity>

最近的文章

Android获取外置SD卡读写路径

1. 外置SD卡的一些问题1.1 关于外置SD卡上的读写路径Android 4.4及以上版本,应用的外置SD卡读写路径被限定在固定路径上(外置SD卡根路径/Android/data/包名/files)。Android4.4以下版本,申请了外置SD卡读写权限的应用在整个外置SD卡上都有读写权限。1.2 关于外置SD卡路径另外Android没有提供获取外置SD卡路径的API(getExternalStorageDirectory()获取的实际是内置SD卡路径)。2. 获取应用在外置SD卡读写根...…

Android继续阅读
更早的文章

Java下合并多个文件

在实际项目中,在处理较大的文件时,常常将文件拆分为多个子文件进行处理,最后再合并这些子文件。Java中合并子文件最容易想到的就是利用BufferedStream进行读写。利用BufferedStream合并多个文件public static boolean mergeFiles(String[] fpaths, String resultPath) { if (fpaths == null || fpaths.length < 1 || TextUtils.isEmpty(re...…

Java继续阅读