对时效性要求不高的进程保活的实现

对时效性要求不高的进程保活的实现

实现的基本原理

定义一个ServiceGuard, ServiceGuard继承自Service类,程序主进程启动后,启动ServiceGuard,ServiceGuard定义为在主进程外的单独进程中运行,比如,.remote进程。
主进程中定义一个普通的Service类,比如, Rservice, RService继承自Service类。
ServiceGuard对外提供远程调用接口, startAndRegisterService, 主进程通过bindService启动ServiceGuard, 拿到ServiceGuard的proxy对象后,通过调用startAndRegisterService来启动主进程中的RService。
startAndRegisterService中通过bindService启动主进程中的RService,启动成功后,ServiceGuard中永久保存RService的proxy对象。
ServiceGuard中会进行无限循环,每一次循环会检查RService是否存活,检查方式就是调用ping函数,如果主进程已经被杀死或者RService对象已经不存在,ping会返回false,ServiceGuard会对RService进行启动,随之主进程也会被启动,主进程中的后台的任务的初始化,可以放在RService的启动函数中。

ServiceGuard可能被系统杀死
可以将RService也定义成一个ServiceGuard,这样RService和ServiceGuard可以互相保护。

主进程和remote进程可能同时被系统杀死,或者很短的间隔内相继被杀死
remote进程是很轻量的进程,几乎不耗费资源,如果还是被杀死的话,可以注册一些系统的广播,广播产生时再次启动主进程。

关于调用proxy对象的pingBinder函数

在Service启动完成的回调onServiceConnected中,返回的是远端Service的句柄,一个IBinder类型的引用,需要将该句柄封装到一个proxy对象中,proxy对象的调用会传导到binger机制的native层,native层通过binder驱动调用到远端进程。IBinder句柄用来标识远端进程里的Service对象。

代码实现

import android.app.Service;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.os.IInterface;
import android.os.RemoteException;
import android.util.Log;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;

public class ServiceGuard extends Service {
    public class ServiceGuardBinder extends IServiceGuard.Stub {
        public void startAndRegisterService(final String servicePath, final String serviceBinderPath) {
            mMapPath.put(serviceBinderPath, servicePath);
            Intent intent = new Intent(servicePath);
            ServiceConnection serviceConnection = new ServiceConnection() {
                @Override
                public void onServiceConnected(ComponentName name, IBinder service) {
                    mMapBinder.put(serviceBinderPath, service);
                }

                @Override
                public void onServiceDisconnected(ComponentName name) {
                }
            };
            bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
        }
    }

    public class ServiceThread extends Thread {
        @Override
        public void run() {
            while (true) {
                try {
                    sleep(500);
                } catch (Exception e) {
                }

                Log.d("debug_log","start run ...");
                Set<String> keys = mMapPath.keySet();
                Iterator<String> it = keys.iterator();
                while (it.hasNext()) {
                    String key = it.next();
                    String servicePath = mMapPath.get(key);
                    IBinder binder = mMapBinder.get(key);
                    Log.d("debug_log","service path is ..." + servicePath);

                    if (binder == null) {
                        Log.d("debug_log","binder is null ... start service");
                        startService(servicePath, key);
                        return;
                    }

                    IInterface iInterface = getBinderProxy(binder, key);
                    boolean ping = iInterface.asBinder().pingBinder();
                    Log.d("debug_log","ping is ....." + ping);
                    if (!ping) {
                        startService(servicePath, key);
                        return;
                    }
                }
            }
        }
    }

    private HashMap<String, String> mMapPath = new HashMap<>();
    private HashMap<String, IBinder> mMapBinder = new HashMap<>();
    private final IBinder mBinder = new ServiceGuardBinder();
    private ServiceThread mThread = new ServiceThread();

    private void startService(final String servicePath, final String serviceBinderPath) {
        Intent intent = new Intent(servicePath);
        ServiceConnection serviceConnection = new ServiceConnection() {
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
                mMapBinder.put(serviceBinderPath, service);
            }

            @Override
            public void onServiceDisconnected(ComponentName name) {
            }
        };
        bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
    }

    private android.os.IInterface getBinderProxy(IBinder service, String serviceBinderPath) {
        Class<?> clz = null;
        try {
            Method mStub = null;
            clz = Class.forName(serviceBinderPath);
            Class innner[] = clz.getDeclaredClasses();
            for (Class cls : innner) {
                if (cls.getName().equals("packagename.IRService$Stub")) { //此处将packagename替换为RService的包名
                    mStub = cls.getMethod("asInterface", IBinder.class);
                }
            }
            IInterface binder = (IInterface)mStub.invoke(null, service);
            if (binder != null) {
                return binder;
            }
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
        return null;
    }

    public IBinder onBind(Intent arg0) {
        if(mBinder != null) {
            return mBinder;
        }
        return null;
    }

    public void onCreate() {
        Log.d("debug_log", "ServiceGuard onCreate\n");
        mThread.start();
    }

    public int onStartCommand (Intent intent, int flags, int startId) {
        return START_NOT_STICKY;
        //return START_REDELIVER_INTENT;
    }
}
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;

public class RService extends Service {
    public class RServiceBinder extends IRService.Stub {
        public void test() {
            Log.w("debug_log","RemoteServiceBinder test   ");
        }
    }

    private final IBinder mBinder = new RServiceBinder();

    public IBinder onBind(Intent arg0) {
        if(mBinder != null) {
            return mBinder;
        }
        return null;
    }

    public void onCreate() {
        Log.d("debug_log", "TestService onCreate\n");
    }

    public int onStartCommand (Intent intent, int flags, int startId) {
        return START_NOT_STICKY;
        //return START_REDELIVER_INTENT;
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值