package cc.c; import java.util.List; import android.os.Bundle; import android.os.Process; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.app.Activity; import android.app.ActivityManager; import android.app.ActivityManager.RunningAppProcessInfo; import android.app.ActivityManager.RunningTaskInfo; import android.content.ComponentName; import android.content.Context; /** * Demo描述: * 实现防止被系统回收的Service. * 在某些情况下Service会被系统kill掉.在网上找了不少方法,虽然都号称 * 可以避免被系统回收,但貌似都不够可靠. * 在此换一种方式来实现,思路: * 利用AlarmManager定时间隔(比如5S,20S)来不断的startService(). * (1)如果该服务被回收,那么会调用Service的onCreate()和onStart() * (2)如果未该服务被回收,则只会调用Service的onStart() * 利用该方式曲线实现防止被系统回收Service * * 测试环境: * Android:2.3.6 + ME525+ * * 测试方法: * 1 部署应用到设备 * 2 重启设备 * 3 设备重启后,点击进入该应用.点击界面上的Button * 4 查看Log * * * 注意事项: * 1 4.0及其以上请注意开机广播监听的实现 * 2 注意权限 * <uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES" /> * <uses-permission android:name="android.permission.GET_TASKS"/> * * 备注说明: * 1 在杀死某进程时有时需要判断该进程所属的Activity是否正在屏幕上显示 * 该方法请参见getTopActivityNameAndProcessName() * 2 若有其余的方法,请留言指教.多谢. * */ public class MainActivity extends Activity { private Button mButton; private long lastTime = 0; private Context mContext; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); init(); } private void init() { mContext = this; lastTime = System.currentTimeMillis(); mButton = (Button) findViewById(R.id.button); mButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View view) { if ((System.currentTimeMillis() - lastTime) > 2000) { lastTime = System.currentTimeMillis(); cleanMemory(mContext); } } }); } //模拟服务被系统回收 private void cleanMemory(Context context) { RunningAppProcessInfo runningAppProcessInfo = null; ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); List<RunningAppProcessInfo> runningAppProcessInfoList = activityManager.getRunningAppProcesses(); if (runningAppProcessInfoList != null) { for (int i = 0; i < runningAppProcessInfoList.size(); ++i) { runningAppProcessInfo = runningAppProcessInfoList.get(i); String processName = runningAppProcessInfo.processName; if (processName.startsWith("cc.c")) { System.out.println("------>杀掉本应用"); int pid = runningAppProcessInfo.pid; Process.killProcess(pid); } } } } //获取栈顶Activity及其所属进程 public static String getTopActivityNameAndProcessName(Context context){ String processName=null; String topActivityName=null; ActivityManager activityManager = (ActivityManager)(context.getSystemService(android.content.Context.ACTIVITY_SERVICE )) ; List<RunningTaskInfo> runningTaskInfos = activityManager.getRunningTasks(1) ; if(runningTaskInfos != null){ ComponentName f=runningTaskInfos.get(0).topActivity; String topActivityClassName=f.getClassName(); String temp[]=topActivityClassName.split("\\."); //栈顶Activity的名称 topActivityName=temp[temp.length-1]; int index=topActivityClassName.lastIndexOf("."); //栈顶Activity所属进程的名称 processName=topActivityClassName.substring(0, index); System.out.println("---->topActivityName="+topActivityName+",processName="+processName); } return topActivityName+","+processName; } }
BootCompletedBroadcastReceiver如下:
package cc.c; import android.app.AlarmManager; import android.app.PendingIntent; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.os.SystemClock; //监听开机广播 public class BootCompletedBroadcastReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { //接收到开机广播 if(intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)){ sendCheckServiceBroadcast(context); } } //发送广播 private void sendCheckServiceBroadcast(Context context) { Intent intent = new Intent(context, CheckServiceBroadcastReceiver.class); intent.setAction("com.cn.checkServicebroadcasreceiver"); PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0); long firstime = SystemClock.elapsedRealtime(); AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); //每间隔20秒发送广播startService alarmManager.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, firstime,20 * 1000, pendingIntent); } }
CheckServiceBroadcastReceiver如下:
package cc.c; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; //检查Service public class CheckServiceBroadcastReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { if (intent.getAction().equals("com.cn.checkServicebroadcasreceiver")) { Intent serviceIntent = new Intent(); serviceIntent.setAction("cn.com.servicesubclass"); context.startService(serviceIntent); } } }
ServiceSubclass如下:
package cc.c; import android.app.Service; import android.content.Intent; import android.os.IBinder; //执行业务逻辑的Service public class ServiceSubclass extends Service { @Override public IBinder onBind(Intent arg0) { return null; } @Override public void onCreate() { super.onCreate(); System.out.println("------>service onCreate()"); } @Override public void onStart(Intent intent, int startId) { super.onStart(intent, startId); System.out.println("------>service onStart()"); } }
main.xml如下:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" > <Button android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:text="杀掉进程" /> </RelativeLayout>
AndroidManifest.xml如下:
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="cc.c" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="10" android:targetSdkVersion="10" /> <!-- 杀死进程的权限 --> <uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES" /> <!-- 获取Task的权限 --> <uses-permission android:name="android.permission.GET_TASKS"/> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name="cc.c.MainActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <!-- 注册开机广播接收者 --> <receiver android:name=".BootCompletedBroadcastReceiver" > <intent-filter> <action android:name="android.intent.action.BOOT_COMPLETED" /> </intent-filter> </receiver> <!-- 注册广播接收者--> <receiver android:name=".CheckServiceBroadcastReceiver" > <intent-filter> <action android:name="com.cn.checkServicebroadcasreceiver" /> </intent-filter> </receiver> <!-- 注册服务 --> <service android:name=".ServiceSubclass"> <intent-filter> <action android:name="cn.com.servicesubclass"/> </intent-filter> </service> </application> </manifest>