(转)Android Service 双进程常驻后台(2)
2016-07-06 09:58
399 查看
最近项目用到Service常驻后台,研究了一下发现手Q和微信都是使用了双进程来保证一键清理后自动复活,copy网上双进程Service的例子,再结合onTrimMemory(),基本实现一键清理后自动复活。
使用双进程Service,关键是在AndroidManifest.xml里面定义Service时加入Android:process=":service1":
双进程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
Service1.java
Service2.java
Utils.java
StrongService.aidl
使用双进程Service,关键是在AndroidManifest.xml里面定义Service时加入Android:process=":service1":
<service android:enabled="true" android:name="com.service.demo.Service1" android:process=":service1"></service> <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
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.servicetest2" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="14" android:targetSdkVersion="19" /> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name="com.service.demo.Main"> <intent-filter > <action android:name="android.intent.action.MAIN"/> <category android:name="android.intent.category.LAUNCHER"/> </intent-filter> </activity> <!-- 关键代码 --> <service android:enabled="true" android:name="com.service.demo.Service1" android:process=":service1"></service> <service android:enabled="true" android:name="com.service.demo.Service2" android:process=":service2"></service> </application> </manifest>
Service1.java
package com.service.demo; import java.util.List; import android.app.ActivityManager; import android.app.ActivityManager.RunningAppProcessInfo; import android.app.Service; import android.app.ActivityManager.RunningServiceInfo; import android.content.ComponentCallbacks; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.content.res.Configuration; import android.os.Handler; import android.os.IBinder; import android.os.RemoteException; import android.util.Log; import android.widget.Toast; /** * * @author hellogv * */ public class Service1 extends Service { private String TAG = getClass().getName(); // 用于判断进程是否运行 private String Process_Name = "com.example.servicetest2:service2"; /** *启动Service2 */ private StrongService startS2 = new StrongService.Stub() { @Override public void stopService() throws RemoteException { Intent i = new Intent(getBaseContext(), Service2.class); getBaseContext().stopService(i); } @Override public void startService() throws RemoteException { Intent i = new Intent(getBaseContext(), Service2.class); getBaseContext().startService(i); } }; @Override public void onTrimMemory(int level){ Toast.makeText(getBaseContext(), "Service1 onTrimMemory..."+level, Toast.LENGTH_SHORT) .show(); keepService2();//保持Service2一直运行 } @Override public void onCreate() { Toast.makeText(Service1.this, "Service1 onCreate...", Toast.LENGTH_SHORT) .show(); keepService2(); } /** * 判断Service2是否还在运行,如果不是则启动Service2 */ private void keepService2(){ boolean isRun = Utils.isProessRunning(Service1.this, Process_Name); if (isRun == false) { try { Toast.makeText(getBaseContext(), "重新启动 Service2", Toast.LENGTH_SHORT).show(); startS2.startService(); } catch (RemoteException e) { e.printStackTrace(); } } } @Override public int onStartCommand(Intent intent, int flags, int startId) { return START_STICKY; } @Override public IBinder onBind(Intent intent) { return (IBinder) startS2; } }
Service2.java
package com.service.demo; import java.util.List; import android.app.ActivityManager; import android.app.ActivityManager.RunningAppProcessInfo; import android.app.ActivityManager.RunningServiceInfo; import android.app.Application; import android.app.Service; import android.content.Context; import android.content.Intent; import android.os.Handler; import android.os.IBinder; import android.os.RemoteException; import android.util.Log; import android.widget.Toast; /** * * @author 掌缘生灭 * */ public class Service2 extends Service { private String TAG = getClass().getName(); private String Process_Name = "com.example.servicetest2:service1"; /** *启动Service1 */ private StrongService startS1 = new StrongService.Stub() { @Override public void stopService() throws RemoteException { Intent i = new Intent(getBaseContext(), Service1.class); getBaseContext().stopService(i); } @Override public void startService() throws RemoteException { Intent i = new Intent(getBaseContext(), Service1.class); getBaseContext().startService(i); } }; @Override public void onTrimMemory(int level){ Toast.makeText(getBaseContext(), "Service2 onTrimMemory..."+level, Toast.LENGTH_SHORT) .show(); keepService1(); } public void onCreate() { Toast.makeText(Service2.this, "Service2 onCreate...", Toast.LENGTH_SHORT).show(); keepService1(); } /** * 判断Service1是否还在运行,如果不是则启动Service1 */ private void keepService1(){ boolean isRun = Utils.isProessRunning(Service2.this, Process_Name); if (isRun == false) { try { Toast.makeText(getBaseContext(), "重新启动 Service1", Toast.LENGTH_SHORT).show(); startS1.startService(); } catch (RemoteException e) { e.printStackTrace(); } } } @Override public int onStartCommand(Intent intent, int flags, int startId) { return START_STICKY; } @Override public IBinder onBind(Intent intent) { return (IBinder) startS1; } }
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
package com.service.demo; interface StrongService{ void startService(); void stopService(); }
相关文章推荐
- Android 设计模式 笔记 - PackageManagerService信息树
- Android开源特效常用链接大集合
- android升级sdk
- Android Rtmp客户端搭建
- Android 跨进程通信Aidl的使用及注意事项
- 关于Android应用开发的一些安全注意事项
- Android Recovery模式下字体
- Android短信验证
- Android 发布版本名字
- Android获取View尺寸的三种方法
- Android模版化编程系列(一)
- android spinner控件
- Android反编译分析工具
- (转)Android 从底层实现让应用杀不死【失效Closed】(1)
- Android内存管理之道
- Android 编程下 Touch 事件的分发和消费机制
- android中读取properties文件
- Android开发平台搭建
- Android 程序框架设计
- android:id="@+id/button1" 与 android:id="@id/button1" 区别 @string