(转)Android Service 双进程常驻后台(2)

最近项目用到Service常驻后台,研究了一下发现手Q和微信都是使用了双进程来保证一键清理后自动复活,copy网上双进程Service的例子,再结合onTrimMemory(),基本实现一键清理后自动复活。

使用双进程Service,关键是在AndroidManifest.xml里面定义Service时加入Android:process=":service1"

1 <service android:enabled="true" android:name="com.service.demo.Service1" android:process=":service1"></service>  
2 <service android:enabled="true" android:name="com.service.demo.Service2" android:process=":service2"></service>  

双进程Service可以让2个进程互相保护,其中一个Service被清理后,另外没被清理的进程可以立即重启进程。

--------以下onTrimMemory的解释引用于网络

onTrimMemory()是Android 4.0之后提供的API,系统会根据不同的内存状态来回调。根据不同的内存状态,来响应不同的内存释放策略。OnTrimMemory的参数是一个int数值,代表不同的内存状态:

TRIM_MEMORY_COMPLETE:内存不足,并且该进程在后台进程列表最后一个,马上就要被清理
TRIM_MEMORY_MODERATE:内存不足,并且该进程在后台进程列表的中部。
TRIM_MEMORY_BACKGROUND:内存不足,并且该进程是后台进程。
TRIM_MEMORY_UI_HIDDEN:内存不足,并且该进程的UI已经不可见了。 
以上4个是4.0增加
TRIM_MEMORY_RUNNING_CRITICAL:内存不足(后台进程不足3个),并且该进程优先级比较高,需要清理内存
TRIM_MEMORY_RUNNING_LOW:内存不足(后台进程不足5个),并且该进程优先级比较高,需要清理内存
TRIM_MEMORY_RUNNING_MODERATE:内存不足(后台进程超过5个),并且该进程优先级比较高,需要清理内存 
以上3个是4.1增加。

本文的例子源码可以到这里下载http://pan.baidu.com/s/1qW3KvtM

以下是本文运行DEMO的结果:开启服务后双进程Service分别启动(Toast显示出来),然后使用“一键加速”来清理内存,双进程Service被逐一清理(触发Service的onTrimMemory()),但后面又分别重新启动了。

代码分析 :

AndroidManifest.xml

 1 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
 2     package="com.example.servicetest2"
 3     android:versionCode="1"
 4     android:versionName="1.0" >
 5 
 6     <uses-sdk
 7         android:minSdkVersion="14"
 8         android:targetSdkVersion="19" />
 9 
10     <application
11         android:allowBackup="true"
12         android:icon="@drawable/ic_launcher"
13         android:label="@string/app_name"
14         android:theme="@style/AppTheme" >
15         
16         <activity android:name="com.service.demo.Main">
17             <intent-filter >
18                 <action android:name="android.intent.action.MAIN"/>
19                 <category android:name="android.intent.category.LAUNCHER"/>
20             </intent-filter>
21         </activity>
22         <!-- 关键代码 -->
23         <service android:enabled="true" android:name="com.service.demo.Service1" android:process=":service1"></service>
24         <service android:enabled="true" android:name="com.service.demo.Service2" android:process=":service2"></service>
25         
26     </application>
27 
28 </manifest>

Service1.java

 1 package com.service.demo;
 2 
 3 import java.util.List;
 4 
 5 import android.app.ActivityManager;
 6 import android.app.ActivityManager.RunningAppProcessInfo;
 7 import android.app.Service;
 8 import android.app.ActivityManager.RunningServiceInfo;
 9 import android.content.ComponentCallbacks;
10 import android.content.ComponentName;
11 import android.content.Context;
12 import android.content.Intent;
13 import android.content.ServiceConnection;
14 import android.content.res.Configuration;
15 import android.os.Handler;
16 import android.os.IBinder;
17 import android.os.RemoteException;
18 import android.util.Log;
19 import android.widget.Toast;
20 
21 /**
22  * 
23  * @author hellogv
24  * 
25  */
26 public class Service1 extends Service {
27 
28     private String TAG = getClass().getName();
29     // 用于判断进程是否运行
30     private String Process_Name = "com.example.servicetest2:service2";
31 
32     /**
33      *启动Service2 
34      */
35     private StrongService startS2 = new StrongService.Stub() {
36         @Override
37         public void stopService() throws RemoteException {
38             Intent i = new Intent(getBaseContext(), Service2.class);
39             getBaseContext().stopService(i);
40         }
41 
42         @Override
43         public void startService() throws RemoteException {
44             Intent i = new Intent(getBaseContext(), Service2.class);
45             getBaseContext().startService(i);
46         }
47     };
48 
49     @Override
50     public void onTrimMemory(int level){
51         Toast.makeText(getBaseContext(), "Service1 onTrimMemory..."+level, Toast.LENGTH_SHORT)
52         .show();
53         
54         keepService2();//保持Service2一直运行
55         
56     }
57 
58     @Override
59     public void onCreate() {
60         Toast.makeText(Service1.this, "Service1 onCreate...", Toast.LENGTH_SHORT)
61                 .show();
62         keepService2();
63     }
64 
65     /**
66      * 判断Service2是否还在运行,如果不是则启动Service2
67      */
68     private  void keepService2(){
69         boolean isRun = Utils.isProessRunning(Service1.this, Process_Name);
70         if (isRun == false) {
71             try {
72                 Toast.makeText(getBaseContext(), "重新启动 Service2", Toast.LENGTH_SHORT).show();
73                 startS2.startService();
74             } catch (RemoteException e) {
75                 e.printStackTrace();
76             }
77         }
78     }
79     
80     @Override
81     public int onStartCommand(Intent intent, int flags, int startId) {
82         return START_STICKY;
83     }
84 
85     @Override
86     public IBinder onBind(Intent intent) {
87         return (IBinder) startS2;
88     }
89 }

Service2.java

 1 package com.service.demo;
 2 
 3 import java.util.List;
 4 
 5 import android.app.ActivityManager;
 6 import android.app.ActivityManager.RunningAppProcessInfo;
 7 import android.app.ActivityManager.RunningServiceInfo;
 8 import android.app.Application;
 9 import android.app.Service;
10 import android.content.Context;
11 import android.content.Intent;
12 import android.os.Handler;
13 import android.os.IBinder;
14 import android.os.RemoteException;
15 import android.util.Log;
16 import android.widget.Toast;
17 /**
18  * 
19  * @author 掌缘生灭
20  *
21  */
22 public class Service2 extends Service {
23     private String TAG = getClass().getName();
24     private String Process_Name = "com.example.servicetest2:service1";
25 
26     /**
27      *启动Service1 
28      */
29     private StrongService startS1 = new StrongService.Stub() {
30 
31         @Override
32         public void stopService() throws RemoteException {
33             Intent i = new Intent(getBaseContext(), Service1.class);
34             getBaseContext().stopService(i);
35         }
36 
37         @Override
38         public void startService() throws RemoteException {
39             Intent i = new Intent(getBaseContext(), Service1.class);
40             getBaseContext().startService(i);
41             
42         }
43     };
44     
45     @Override
46     public void onTrimMemory(int level){
47         Toast.makeText(getBaseContext(), "Service2 onTrimMemory..."+level, Toast.LENGTH_SHORT)
48         .show();
49         keepService1();
50     }
51     
52     public void onCreate() {
53         Toast.makeText(Service2.this, "Service2 onCreate...", Toast.LENGTH_SHORT).show();
54         keepService1();
55     }
56 
57     /**
58      * 判断Service1是否还在运行,如果不是则启动Service1
59      */
60     private  void keepService1(){
61         boolean isRun = Utils.isProessRunning(Service2.this, Process_Name);
62         if (isRun == false) {
63             try {
64                 Toast.makeText(getBaseContext(), "重新启动 Service1", Toast.LENGTH_SHORT).show();
65                 startS1.startService();
66             } catch (RemoteException e) {
67                 e.printStackTrace();
68             }
69         }
70     }
71     @Override
72     public int onStartCommand(Intent intent, int flags, int startId) {
73         return START_STICKY;
74     }
75 
76     @Override
77     public IBinder onBind(Intent intent) {
78         return (IBinder) startS1;
79     }
80 
81 }

Utils.java

package com.service.demo;

import java.util.List;

import android.app.ActivityManager;
import android.app.ActivityManager.RunningAppProcessInfo;
import android.content.Context;

public class Utils {

    
    /**
     * 判断进程是否运行
     * @return
     */
    public static boolean isProessRunning(Context context, String proessName) {

        boolean isRunning = false;
        ActivityManager am = (ActivityManager) context
                .getSystemService(Context.ACTIVITY_SERVICE);

        List<RunningAppProcessInfo> lists = am.getRunningAppProcesses();
        for (RunningAppProcessInfo info : lists) {
            if (info.processName.equals(proessName)) {
                isRunning = true;
            }
        }

        return isRunning;
    }
}

StrongService.aidl

1 package com.service.demo;
2 interface StrongService{
3     void startService();
4     void stopService();
5 }

 

posted @ 2016-07-06 09:58  QqiaoQ  阅读(6766)  评论(1编辑  收藏  举报