Android APP进程保护,在APP进程异常崩溃后能够重启

这个地方借鉴了前一段时间吵得热闹的 蜻蜓FM app的问题,蜻蜓FM app在内部做了5个进程,并且这5个进程互相保护,不被安全APP杀死.

大致的原理: 5个进程不断查询其他某一个进程的运行状况,当有所监查的进程不存在了,无论是因为安全软件kill了还是因为程序本身奔溃了,就将其重新启动,但是如果监控的服务和被监控的服务如果在同一个进程,那就无法实现,因为被监控的进程crash了,意味着监控的进程也crash了,那么两者都奔溃了,就不可能重启了,所以监控和被监控的两个对象必须不能够在同一个进程中.


下面做一个简单测试工程:

<1> : 工程树如下:

Android APP进程保护,在APP进程异常崩溃后能够重启_第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号,对比上面变化了,说明服务被重启了.




你可能感兴趣的:(Android APP进程保护,在APP进程异常崩溃后能够重启)