Andrioid进程保护

原创 2017年08月08日 15:53:52

转载请注明出处: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

版权声明:本文为博主原创文章,转载请注明出处。博客首页:http://blog.csdn.net/u012975705。订阅:http://blog.csdn.net/u012975705/rss/list

Android 如何实现应用卸载反馈,卸载监控

市面上有很多Android 的App在卸载之后会弹出一个反馈页面,让用户填写卸载原因,收集用户的卸载反馈。这是怎么实现的呢?应用自身已经被卸载了,怎么还能弹出一个反馈页面呢 ? 首先,可以排除的是Br...

android 通过广播唤醒被杀死的app

今天,简单讲讲如何唤醒被杀死的app。 这个唤醒app主要通过广播来唤醒。 1. 静态广播唤醒 广播的exported属性和enabled属性 exported默认为tru...

Eclipse开发andrioid常用快捷键

熟悉eclipse开发android的一些快捷键,能很大的提高效率,分享在下面: Ctrl+1 快速修复(最经典的快捷键,就不用多说了)  Ctrl+D: 删除当前行  Ctrl+Alt+↓...

Andrioid项目之九图灵机器人

Andrioid项目之九图灵机器人 要实现一个图灵机器人,首先需要在 http://www.tuling123.com/ 中注册,然后创建一个应用, 便可通过应用的API key使用图灵机器人。图...

andrioid 创建等待框

这里是用一个线程来模仿后台程序的运行,在用线程来关闭。 这里主要是调用ProgressDialog来构造,注意的是必须在后台程序结束前运行完毕。用dismiss来关闭取得焦点的等待框 主要程序如下...

Andrioid学习--文件下载初步

1.使用HTTP协议下载文件 文件下载步骤: (1)传递一个URL地址,新建一个URL类的对象 URLurl = new URL(urlStr); (2)创建一个HttpURL...

andrioid ppt

  • 2011年04月22日 08:24
  • 1.51MB
  • 下载

Andrioid 中关于CDMA和GSM基站定位

在googleAPI里提供了基站信息的获取类TelephonyManager,通过其方法getCellLocation得到CellLocation即可获取到基站相关信息 但CellLocatio...

如何用Selenium的AndroidDriver在Andrioid模拟器上进行自动化测试

如何用Selenium的AndroidDriver在Andrioid模拟器上进行自动化测试 分类: QA and Testing Mobile 2012-05-02 17:0424人阅读评论(...

Andrioid自定义标题栏

MainActivyty.javapackage com.example.uimyview;import android.app.Activity; import android.os.Bundle;...
  • ACM_TH
  • ACM_TH
  • 2015年09月11日 00:00
  • 587
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Andrioid进程保护
举报原因:
原因补充:

(最多只允许输入30个字)