关闭

Andrioid进程保护

标签: aidl进程保活jobservice双进程守护
1582人阅读 评论(0) 收藏 举报
分类:

转载请注明出处:z_zhaojun的博客       原文地址


这篇博文主要是关于进程保活的应用,通过对网上各种进程保活方式的学习,自己理解后做汇总、优化、简单封装。

进程保活,主要就为了加强你写的app在手机上的生存能力,降低被手机干掉的几率。当然,如果想要完全保证app不被杀死,那是不可能的(因为就是你再厉害,也厉害不过手机厂商),所以只能是尽量提高app的存活几率。下面将通过‘AIDL +JobService(JobScheduler)’来实现这个目标。


第一步、通过AIDL来实现双进程守护,达到初步加强app存活能力的目的
          显示在最开始你必须先新建一个AIDL服务(具体玩法自行百度),先上相关代码:

LocalService.java

//LocalService是一个运行在当前app进程的一个服务,在这里你可以实现你想要一直放在后台执行的功能。实现了ServiceConnection接口,用于监听兄弟服务RemoteService(具体代码请往下看)状态,在监听到RemoteService被杀死后,重新开启兄弟服务RemoteSerivce
class LocalService extends Service implements ServiceConnection {

    private static final String TAG = "LocalService";

    private LocalServiceBinder localBinder;

    private Notification notification;

    @Override
    public void onCreate() {
        Log.d(TAG, "onCreate");
        if (null == localBinder) {
            //与RemoteService绑定时需要
            localBinder = new LocalServiceBinder();
        }
        super.onCreate();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.d(TAG, "onStartCommand");
        startJob();
        //提高服务优先级,降低被杀的概率
        startForeground(startId, getNotification());
        //与兄弟服务RemoteService绑定,这有这样才能监听到RemoteService的状态
        bindService(new Intent(LocalService.this, RemoteService.class),
                this, Context.BIND_IMPORTANT);
        return START_STICKY;
    }

    //在这里开始你想要实现的功能,已经做了简单封装,博文末尾会有操作方式
    private boolean startJob() {
        return AliveServiceManagerImpl.getInstance().startJob();
    }

    @NonNull
    private Notification getNotification() {
        if (null == notification) {
            Notification.Builder builder = new Notification.Builder(this);
            builder.setDefaults(NotificationCompat.FLAG_AUTO_CANCEL);
            builder.setContentTitle(TAG);
            builder.setSmallIcon(R.drawable.logonews);
            builder.setSubText(TAG);
            builder.setContentText(TAG);
            builder.setWhen(System.currentTimeMillis());
            /*PendingIntent pi = PendingIntent.getActivity(this, 0, intent, 0);
            builder.setContentIntent(pi);*/
            notification = builder.build();
        }
        return notification;
    }

    @Override
    public IBinder onBind(Intent intent) {
        Log.d(TAG, "onBind");
        return localBinder;
    }

    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
        Log.d(TAG, "onServiceConnected");
    }

    //当兄弟服务RemoteService被杀死时,会触发onServiceDisconnected方法,在这里重新开启RemoteService,并绑定
    @Override
    public void onServiceDisconnected(ComponentName name) {
        Log.d(TAG, "onServiceDisconnected");
        startService(new Intent(this, RemoteService.class));
        bindService(new Intent(this, RemoteService.class), this, Context.BIND_IMPORTANT);
    }

    //AIDL服务
    private class LocalServiceBinder extends IServiceAidlInterface.Stub {

        @Override
        public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {
            Log.d(TAG, "basicTypes");
        }
    }
}

RemoteService .java

//RemoteService 是一个运行在与当前app进程相独立的进程中的服务,并实现了ServiceConnection接口,用于监听兄弟服务LocalService的状态,在监听到LocalService被杀死后,重新开启兄弟服务LocalService
class RemoteService extends Service implements ServiceConnection {

    private static final String TAG = "RemoteService";

    private RemoteServiceBinder remoteBinder;

    private Notification notification;

    @Override
    public void onCreate() {
        Log.d(TAG, "onCreate");
        if (null == remoteBinder) {
            remoteBinder = new RemoteServiceBinder();
        }
        super.onCreate();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.d(TAG, "onStartCommand");
        //提高服务优先级,降低被杀的概率
        startForeground(startId, getNotification());
        //与兄弟服务LocalService绑定,这有这样才能监听到LocalService的状态
        bindService(new Intent(this, LocalService.class), this, Context.BIND_IMPORTANT);
        return START_STICKY;
    }

    @NonNull
    private Notification getNotification() {
        if (null == notification) {
            Notification.Builder builder = new Notification.Builder(this);
            builder.setDefaults(NotificationCompat.FLAG_AUTO_CANCEL);
            builder.setContentTitle(TAG);
            builder.setSmallIcon(R.mipmap.ic_launcher);
            builder.setSubText(TAG);
            builder.setContentText(TAG);
            builder.setWhen(System.currentTimeMillis());
            /*PendingIntent pi = PendingIntent.getActivity(this, 0, intent, 0);
            builder.setContentIntent(pi);*/
            notification = builder.build();
        }
        return notification;
    }

    @Override
    public IBinder onBind(Intent intent) {
        Log.d(TAG, "onBind");
        return remoteBinder;
    }

    //当兄弟服务LocalService被杀死时,会触发onServiceDisconnected方法,在这里重新开启LocalService,并绑定
    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
        Log.d(TAG, "onServiceConnected");
    }

    @Override
    public void onServiceDisconnected(ComponentName name) {
        Log.d(TAG, "onServiceDisconnected");
        startService(new Intent(this, LocalService.class));
        bindService(new Intent(this, LocalService.class), this, Context.BIND_IMPORTANT);
    }

    private class RemoteServiceBinder extends IServiceAidlInterface.Stub {

        @Override
        public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {
            Log.d(TAG, "basicTypes");
        }
    }
}

LocalService、RemoteService在AndroidManifest.xml中的添加方式:

<service
            android:name=".aliveservice.LocalService"
            android:enabled="true"
            android:exported="true">
        </service>
        <service
            android:name=".aliveservice.RemoteService"
            android:process=":remote"//用于开启新的进程:包名+“:remoteandroid:enabled="true"
            android:exported="true">//为true表示对其它进程可见
        </service>

第二步、结合JobService使用
          JobService+Jobschedule有点类似手机系统闹钟(alertmanager),是android5.0之后提供的机制,可以让系统在某些特定环境下或固定时间间隔里,异步执行一些作业,其主要目的就是为了优化电池。当然,在这里主要是为了保护兄弟服务LocalService+RemoteService。

具体代码:

LocalJobService.java

<service
            android:name=".aliveservice.LocalJobService"
            android:permission="android.permission.BIND_JOB_SERVICE"
            android:enabled="true"
            android:exported="true">
        </service>
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
class LocalJobService extends JobService {
    private static final String TAG = "LocalJobService";
    private static final String KEY_LOCAL_SERVICE_NAME = LocalService.class.getName();
    private static final String KEY_REMOTE_SERVICE_NAME = RemoteService.class.getName();

    private JobInfo jobInfo;

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.i(TAG, "onStartCommand");
        scheduleJob(getJobInfo());
        return START_NOT_STICKY;
    }

    //一旦开启当前服务,系统会定时调用onStartJob方法,在其中判断兄弟服务LocalService+RemoteService的存活情况,如果被杀死则重新启动相应服务
    @Override
    public boolean onStartJob(JobParameters params) {
        Log.i(TAG, "onStartJob");
        boolean isLocalServiceWork = isServiceWork(this, KEY_LOCAL_SERVICE_NAME);
        boolean isRemoteServiceWork = isServiceWork(this, KEY_REMOTE_SERVICE_NAME);
        if (!isLocalServiceWork) {
            this.startService(new Intent(this, LocalService.class));
        }
        if (!isRemoteServiceWork) {
            this.startService(new Intent(this, RemoteService.class));
        }
        return true;
    }

    @Override
    public boolean onStopJob(JobParameters params) {
        Log.i(TAG, "onStopJob");
        scheduleJob(getJobInfo());
        return true;
    }

    /**
     * 将任务作业发送到作业调度中去
     */
    public void scheduleJob(JobInfo info) {
        Log.i(TAG, "scheduleJob");
        JobScheduler js = (JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE);
        js.schedule(info);
    }

    public JobInfo getJobInfo() {
        Log.i(TAG, "getJobInfo");
        if (null == jobInfo) {
            JobInfo.Builder builder = new JobInfo.Builder(0, new ComponentName(this, LocalJobService.class));
            builder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY);
            builder.setPersisted(true);
            builder.setRequiresCharging(false);
            builder.setRequiresDeviceIdle(false);
            //间隔100毫秒
            builder.setPeriodic(100);
            jobInfo = builder.build();
        }
        return jobInfo;
    }

    /**
     * 判断服务是否正在运行
     */
    public boolean isServiceWork(Context mContext, String serviceName) {
        if (TextUtils.isEmpty(serviceName)) {
            return false;
        }

        boolean isWorking = false;
        ActivityManager manager = (ActivityManager) mContext
                .getSystemService(Context.ACTIVITY_SERVICE);
        List<ActivityManager.RunningServiceInfo> list = manager.getRunningServices(100);
        for (ActivityManager.RunningServiceInfo info : list) {
            String name = info.service.getClassName();
            if (serviceName.equals(name)) {
                isWorking = true;
                break;
            }
        }
        return isWorking;
    }
}

第三步、简单封装
                     具体实现请看代码:
AliveServiceManagerImpl.java

/**
 * package: com.zzj.chris.processalivedemo.aliveservice
 * <p>
 * description: 保活service管理
 * <p>
 * Created by chris on 2017/8/7.
 */

public class AliveServiceManagerImpl implements AliveServiceManager {
    private static final Byte[] LOCK = new Byte[0];

    private static AliveServiceManager mInstance;

    private List<JobSchedule> mJobObservers;

    private AliveServiceManagerImpl() {}

    //单例
    public static AliveServiceManager getInstance() {
        if (null == mInstance){
            synchronized (LOCK) {
                if (null == mInstance){
                    mInstance = new AliveServiceManagerImpl();
                }
            }
        }
        return mInstance;
    }

    //在这里开启进程保活功能
    @Override
    public void start(Context context) {//app.getContext
        context.startService(new Intent(context, LocalService.class));
        context.startService(new Intent(context, RemoteService.class));
        if (Build.VERSION.SDK_INT >= 21) {
            context.startService(new Intent(context, LocalJobService.class));
        }
    }

    @Override
    public void stop(Context context) {

    }

    @Override
    public void destroy() {
        if (null != mJobObservers) {
            mJobObservers.clear();
            mJobObservers = null;
        }
        mInstance = null;
    }

    //开始执行你在后台想要实现的功能
    @Override
    public boolean startJob() {
        boolean isWorking = false;
        getObservers();
        for (JobSchedule schedule : mJobObservers) {
            if (!schedule.isWorking()) {
                schedule.start();
                isWorking = true;
            }
        }
        return isWorking;
    }

    private void getObservers() {
        if (null == mJobObservers) {
            mJobObservers = new ArrayList<>();
        }
        if (mJobObservers.size() <= 0) {
            //这里需要手动添加
            mJobObservers.add(NotificationHelper.getInstance());
            mJobObservers.add(*******);
            ......
        }
    }
}

使用实例:
新建NotificationHelper类实现AliveServiceManager.JobSchedule接口(具体请看demo源码,末尾附下载地址):

NotificationHelper。java

public class NotificationHelper implements AliveServiceManager.JobSchedule {
    private static final String TAG = "NotificationHelper";

    private static NotificationHelper mHelper;

    private boolean isWork;

    private NotificationHelper() {}

    public static NotificationHelper getInstance() {
        if (null == mHelper) {
            mHelper = new NotificationHelper();
        }
        return mHelper;
    }

    @Override
    public void start() {//在这执行需要实现的工作
        if (!isWork) {
//            startTimer();
            isWork = true;
        }
    }

    @Override
    public void stop() {
//        stopTimer();
        isWork = false;
    }

    @Override
    public boolean isWorking() {
        return isWork;
    }

最后就是具体用法:

AliveServiceManagerImpl.getInstance().start(this);

下载地址:
      CSDN
      GitHub

1
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:148614次
    • 积分:2156
    • 等级:
    • 排名:第18389名
    • 原创:44篇
    • 转载:29篇
    • 译文:0篇
    • 评论:52条
    博客专栏
    友情链接
    最新评论