这个地方借鉴了前一段时间吵得热闹的 蜻蜓FM app的问题,蜻蜓FM app在内部做了5个进程,并且这5个进程互相保护,不被安全APP杀死.
大致的原理: 5个进程不断查询其他某一个进程的运行状况,当有所监查的进程不存在了,无论是因为安全软件kill了还是因为程序本身奔溃了,就将其重新启动,但是如果监控的服务和被监控的服务如果在同一个进程,那就无法实现,因为被监控的进程crash了,意味着监控的进程也crash了,那么两者都奔溃了,就不可能重启了,所以监控和被监控的两个对象必须不能够在同一个进程中.
下面做一个简单测试工程:
<1> : 工程树如下:
<2> : 工程文件内容如下:
IProtectServiceA.aidl
// IProtectServiceA.aidl package org.durian.durianprotectprocess; // Declare any non-default types here with import statements interface IProtectServiceA { /** * Demonstrates some basic types that you can use as parameters * and return values in AIDL. */ void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString); void startServiceB(); void stopServiceB(); }
IProtectServiceB.aidl
// IProtectServiceB.aidl package org.durian.durianprotectprocess; // Declare any non-default types here with import statements interface IProtectServiceB { /** * Demonstrates some basic types that you can use as parameters * and return values in AIDL. */ void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString); void startServiceA(); void stopServiceA(); }
ProtectServiceA.java
package org.durian.durianprotectprocess.org.durian.protectservice; import android.app.Service; import android.content.Intent; import android.os.IBinder; import android.os.RemoteException; import org.durian.durianprotectprocess.IProtectServiceA; import static org.durian.durianprotectprocess.IProtectServiceA.*; public class ProtectServiceA extends Service { private final static String TAG="ProtectServiceA"; public ProtectServiceA() { } @Override public IBinder onBind(Intent intent) { // TODO: Return the communication channel to the service. throw new UnsupportedOperationException("Not yet implemented"); } private IProtectServiceA mProtA=new Stub(){ @Override public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException { } @Override public void startServiceB() throws RemoteException { Intent intent=new Intent(ProtectServiceA.this,ProtectServiceB.class); ProtectServiceA.this.startService(intent); } @Override public void stopServiceB() throws RemoteException { Intent intent=new Intent(ProtectServiceA.this,ProtectServiceB.class); ProtectServiceA.this.stopService(intent); } }; @Override public void onCreate() { super.onCreate(); new Thread() { public void run() { while (true) { boolean isRun = Utils.isProessRunning(ProtectServiceA.this, Utils.DURIAN_PROCESS_B); if (isRun==false) { try { mProtA.startServiceB(); } catch (RemoteException e) { e.printStackTrace(); } } } }; }.start(); } }
ProtectServiceB.java
package org.durian.durianprotectprocess.org.durian.protectservice; import android.app.Service; import android.content.Intent; import android.os.IBinder; import android.os.RemoteException; import org.durian.durianprotectprocess.IProtectServiceB; public class ProtectServiceB extends Service { public ProtectServiceB() { } @Override public IBinder onBind(Intent intent) { // TODO: Return the communication channel to the service. throw new UnsupportedOperationException("Not yet implemented"); } private IProtectServiceB mProtB=new IProtectServiceB.Stub(){ @Override public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException { } @Override public void startServiceA() throws RemoteException { Intent intent=new Intent(ProtectServiceB.this,ProtectServiceA.class); ProtectServiceB.this.startService(intent); } @Override public void stopServiceA() throws RemoteException { Intent intent=new Intent(ProtectServiceB.this,ProtectServiceA.class); ProtectServiceB.this.stopService(intent); } }; @Override public void onCreate() { super.onCreate(); new Thread() { public void run() { while (true) { boolean isRun = Utils.isProessRunning(ProtectServiceB.this, Utils.DURIAN_PROCESS_A); if (isRun==false) { try { mProtB.startServiceA(); } catch (RemoteException e) { e.printStackTrace(); } } } }; }.start(); } }
Utils.java
package org.durian.durianprotectprocess.org.durian.protectservice; import android.app.ActivityManager; import android.content.Context; import android.util.Log; import java.util.List; /** * Created by zhibao.liu on 2016/1/7. */ public class Utils { public final static String DURIAN_PROCESS_A="org.durian.protect.a"; public final static String DURIAN_PROCESS_B="org.durian.protect.b"; //服务是否运行 public boolean isServiceRunning(Context context, String serviceName) { boolean isRunning = false; ActivityManager am = (ActivityManager) context .getSystemService(Context.ACTIVITY_SERVICE); List<ActivityManager.RunningServiceInfo> lists = am.getRunningServices(30); for (ActivityManager.RunningServiceInfo info : lists) {// 获取运行服务再启动 if (info.service.getClassName().equals(serviceName)) { Log.i("Service1进程", "" + info.service.getClassName()); isRunning = true; } } return isRunning; } // 进程是否运行 public static boolean isProessRunning(Context context, String proessName) { boolean isRunning = false; ActivityManager am = (ActivityManager) context .getSystemService(Context.ACTIVITY_SERVICE); List<ActivityManager.RunningAppProcessInfo> lists = am.getRunningAppProcesses(); for (ActivityManager.RunningAppProcessInfo info : lists) { if (info.processName.equals(proessName)) { //Log.i("Service1进程", "" + info.processName); isRunning = true; } } return isRunning; } }
DurianMainActivity.java
package org.durian.durianprotectprocess; import android.content.Intent; import android.os.Bundle; import android.support.v7.app.ActionBarActivity; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.widget.Button; import org.durian.durianprotectprocess.org.durian.protectservice.ProtectServiceA; import org.durian.durianprotectprocess.org.durian.protectservice.ProtectServiceB; public class DurianMainActivity extends ActionBarActivity { private Button mButton; private Intent mService; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.durian_main); mButton=(Button)findViewById(R.id.button); mButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { mService=new Intent(DurianMainActivity.this, ProtectServiceA.class); DurianMainActivity.this.startService(mService); mService=new Intent(DurianMainActivity.this, ProtectServiceB.class); DurianMainActivity.this.startService(mService); } }); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.menu_durian_main, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); //noinspection SimplifiableIfStatement if (id == R.id.action_settings) { return true; } return super.onOptionsItemSelected(item); } }
布局:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout 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" android:orientation="vertical"> <Button android:id="@+id/button" android:text="start service" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </LinearLayout>
<3> : 运行以后 :
查看系统进程:
> adb shell
> su
> ps
杀死其中一个进程:
> kill 进程ID
比如杀死A 进程 :
> kill 18313
然后在ps一次,因为不是每隔一段时间检查的,只要一旦检查到就重启了.
注意看这时a进程的id号,对比上面变化了,说明服务被重启了.