栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Android开发问题集锦(四)--双进程保活

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Android开发问题集锦(四)--双进程保活

Android开发问题集锦四--双进程保活
  • 程序之美
  • 进程和线程
  • 服务
  • 保活机制

程序之美 进程和线程

当应用组件启动且该应用未运行任何其他组件时,Android 系统会使用单个执行线程为应用启动新的 Linux 进程。默认情况下,同一应用的所有组件会在相同的进程和线程(称为“主”线程)中运行。如果某个应用组件启动且该应用已存在进程(因为存在该应用的其他组件),则该组件会在此进程内启动并使用相同的执行线程。但是,您可以安排应用中的其他组件在单独的进程中运行,并为任何进程创建额外的线程。

服务

Service 作为 Android 四大组件之一,在Android系统中有着非常重要的作用,Service 设计的初衷就是为在后台长时间执行而不需要提供页面的任务。
服务在Android系统中主要发挥以下作用:
1.保证一个长期在后台运行并且不与用户交互的操作;
2.为其他应用程序提供服务。

Service的启动有两种方式:context.startService() 和 context.bindService()

Service分为本地服务(LocalService)和远程服务(RemoteService):

1、本地服务依附在主进程上而不是独立的进程,它节约了资源并且不需要IPC,也不需要AIDL通信。主进程被杀死后,服务便会终止。

2、远程服务为独立的进程,在Activity所在进程被Kill的时候,该服务依然在运行,不受其他进程影响。因其为独立的进程,会占用一定资源,可采用AIDL通信。

保活机制

下面说下保活
为什么要保活?由于业务需求,我们希望自己的APP永远有一个后台程序在运行,时刻保持着与服务器通信,当APP退出或者被杀掉时,仍然能被唤醒,接受通知等,我们就需要一个常驻服务,这就牵扯到服务为啥会被杀掉,这个就要从Android自身的机制来说了,Android中的进程是托管的,当系统进程空间紧张的时候,会依照优先级自动进行进程的回收,会优先杀掉进程优先级低的程序。故而为了能够保证service不被杀死,网友们提出了多种保活方法:

android六种方法保证service不被杀死
柴君
一、在onStartCommand方法,返回START_STICKY
测试当内存不足时,service会被kill,但当内存恢复的时候,service就会被重新创建, 但不是保证任何情况下都能被重建,比如进程挂了…
二、提升service优先级,提升service进程优先级

service优先级:可在AndroidManifest.xml文件中,修改intent-filter的android:priority = “1000”属性设置最高优先级,降低被杀的概率。
  service进程优先级由低到高以此为:
  1.前台进程( FOREGROUND_APP)
  2.可视进程(VISIBLE_APP )
  3.次要服务进程(SECONDARY_SERVER )
  4.后台进程 (HIDDEN_APP)
  5.内容供应节点(CONTENT_PROVIDER)
  6.空进程(EMPTY_APP)
  在低内存时提升service进程优先级,kill的几率会低一些

四、在onDestroy方法里重启service
当APP进程被正常销毁时是可以执行onDestroy,但有些非正常的退出,onDestroy方法都进不来,无法保证其必须执行。
五、将APK安装在/system/app使其成为系统级应用,这个需要对App签名,如果没有签名文件,无法实现。

为了做到保活,这里介绍下双进程保活机制,相信很多朋友都已经等不及了,废话少说,说了估计也没人听,直接上代码。

远程服务GuardService.java

public class GuardService extends Service {
    private static final String TAG = GuardService.class.getName();

    private MyBinder mBinder;

    private ServiceConnection connection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            Log.e(TAG, " GuardService Connected.");
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
//            Toast.makeText(RemoteService.this,"链接断开,重新启动 LocalService",Toast.LENGTH_LONG).show();
            Log.e(TAG, " GuardService Disconnected.");
            startService(new Intent(GuardService.this, StepService.class));
            bindService(new Intent(GuardService.this, StepService.class),connection, Context.BIND_importANT);
        }
    };

    @Override
    public void onCreate() {
        super.onCreate();
        Log.e(TAG, " GuardService onCreate.");
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
//        Toast.makeText(this,"RemoteService 启动",Toast.LENGTH_LONG).show();
        Log.e(TAG, " GuardService onStartCommand.");
        bindService(new Intent(this, StepService.class),connection,Context.BIND_importANT);
        return START_STICKY;
    }

    @Override
    public IBinder onBind(Intent intent) {
        mBinder = new MyBinder();
        return mBinder;
    }

    private  class MyBinder extends IDaemonInterface.Stub{
        @Override
        public void keepAlive() throws RemoteException {
            startService(new Intent(GuardService.this, StepService.class));
            bindService(new Intent(GuardService.this, StepService.class),connection, Context.BIND_importANT);
        }
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        unbindService(connection);
        Log.e(TAG, " GuardService onDestroy.");
    }

    @Override
    public boolean onUnbind(Intent intent) {
        return super.onUnbind(intent);
    }
}

本地服务StepService.java

public class StepService extends Service {
    private static final String TAG = "StepService";
    private static final long HEART_BEAT_INTERVAL = 5000L;
    private boolean isServiceStarted = false;
    private PowerManager.WakeLock wakeLock = null;
    private final static int NOTIFICATION_ID = android.os.Process.myPid();
    private String address = "";
    private String port = "";
    private String password = "";
    private String username = "";

    private linkedBlockingQueue frameQueue = new linkedBlockingQueue(800);
    private boolean bRunningHeartBeat = false;
    private MyBinder mBinder;

    private ServiceConnection connection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            ISvrManagerInterface iSvrManagerInterface = ISvrManagerInterface.Stub.asInterface(service);
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
//            Toast.makeText(RemoteService.this,"链接断开,重新启动 LocalService",Toast.LENGTH_LONG).show();
            startService(new Intent(StepService.this, GuardService.class));
            bindService(new Intent(StepService.this, GuardService.class),connection, Context.BIND_importANT);
        }
    };

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        startService(new Intent(StepService.this, GuardService.class));
        bindService(new Intent(StepService.this, GuardService.class), connection, Context.BIND_importANT);

        return START_STICKY;
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        mBinder = new MyBinder();
        return mBinder;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        startHeartBeat();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        stopHeartBeat();
    }

    public class MyBinder extends ISvrManagerInterface.Stub {

        @Override
        public void keepAlive() throws RemoteException {

        }
    }


    private void startService() {
        if (isServiceStarted) return;
        isServiceStarted = true;

        PowerManager pm = (PowerManager)getSystemService(Context.POWER_SERVICE);
        wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "StepService::lock");//持有唤醒锁
        wakeLock.acquire(10 * 60 * 1000L);//30s亮屏
    }

    private void stopService() {
        try {
            wakeLock.release();
            stopForeground(true);
            unbindService(connection);
            stopSelf();
        } catch (Exception e) {

        }
        isServiceStarted = false;
    }

    private Thread heartBeatThread = new Thread(){
        @Override
        public void run() {
            super.run();
            while (bRunningHeartBeat) {
                try {
                    Thread.sleep(HEART_BEAT_INTERVAL);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                Log.i(TAG, " StepService keep alive ....");
                //业务逻辑
            }
        }
    };

    private void startHeartBeat(){
        bRunningHeartBeat = true;
        heartBeatThread.start();
        ProcessThread.start();
        PutBufferThread_0.start();
        PutBufferThread_1.start();
        PutBufferThread_2.start();
        PutBufferThread_3.start();
        PutBufferThread_4.start();
        PutBufferThread_5.start();
        PutBufferThread_6.start();
        PutBufferThread_7.start();
        PutBufferThread_8.start();
        PutBufferThread_9.start();
        PutBufferThread_10.start();
        PutBufferThread_11.start();
        PutBufferThread_12.start();
    }
    private void stopHeartBeat(){
        bRunningHeartBeat = false;
    }

    private Notification getNotification() {
        Intent intent = new Intent(this, MainActivity.class);
        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent,
                PendingIntent.FLAG_UPDATE_CURRENT);
        NotificationCompat.Builder builder = new NotificationCompat.Builder(this, "")
                .setContentTitle("服务运行于前台")
                .setContentText("service被设为前台进程")
                .setTicker("service正在后台运行...")
                .setPriority(NotificationCompat.PRIORITY_MAX)
                .setWhen(System.currentTimeMillis())
                .setDefaults(NotificationCompat.DEFAULT_ALL)
                .setContentIntent(pendingIntent);
        Notification notification = builder.build();
        notification.flags = Notification.FLAG_AUTO_CANCEL;
        return notification;
    }

    Runnable mRunnable = new Runnable() {

        @Override
        public void run() {
            while (true) {
                Log.e(TAG, "" + System.currentTimeMillis());
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    };

    public static final int PROCESS_INDEX = 1000000;
    private int processIndex_0 = 0;
    private int processIndex_1 = 0;
    private int processIndex_2 = 0;
    private int processIndex_3 = 0;
    private int processIndex_4 = 0;
    private int processIndex_5 = 0;
    private int processIndex_6 = 0;
    private int processIndex_7 = 0;
    private int processIndex_8 = 0;
    private int processIndex_9 = 0;
    private int processIndex_10 = 0;
    private int processIndex_11 = 0;
    private int processIndex_12 = 0;

    private Thread PutBufferThread_0 = new Thread(){
        @Override
        public void run() {
            super.run();
            while (bRunningHeartBeat) {
                byte[] buffer = new byte[1024 * 1024];

                for (int i = 0; i < 1024 * 1024; i ++) {
                    buffer[i] = 0x08;
                }
                processIndex_0 = (processIndex_0 + 1) % PROCESS_INDEX;

                Log.e(TAG, "PutBufferThread index_0:" + processIndex_0);

                try {
                    DataInfo di = new DataInfo();
                    di.data = buffer;
                    di.len = 1024 * 1024;
                    frameQueue.put(di);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    };

    private Thread PutBufferThread_1 = new Thread(){
        @Override
        public void run() {
            super.run();
            while (bRunningHeartBeat) {
                byte[] buffer = new byte[1024 * 1024];

                for (int i = 0; i < 1024 * 1024; i ++) {
                    buffer[i] = 0x08;
                }
                processIndex_1 = (processIndex_1 + 1) % PROCESS_INDEX;

                Log.e(TAG, "PutBufferThread index_1:" + processIndex_1);

                try {
                    DataInfo di = new DataInfo();
                    di.data = buffer;
                    di.len = 1024 * 1024;
                    frameQueue.put(di);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    };

    private Thread PutBufferThread_2 = new Thread(){
        @Override
        public void run() {
            super.run();
            while (bRunningHeartBeat) {
                byte[] buffer = new byte[1024 * 1024];

                for (int i = 0; i < 1024 * 1024; i ++) {
                    buffer[i] = 0x08;
                }
                processIndex_2 = (processIndex_2 + 1) % PROCESS_INDEX;

                Log.e(TAG, "PutBufferThread index_2:" + processIndex_2);

                try {
                    DataInfo di = new DataInfo();
                    di.data = buffer;
                    di.len = 1024 * 1024;
                    frameQueue.put(di);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    };

    private Thread PutBufferThread_3 = new Thread(){
        @Override
        public void run() {
            super.run();
            while (bRunningHeartBeat) {
                byte[] buffer = new byte[1024 * 1024];

                for (int i = 0; i < 1024 * 1024; i ++) {
                    buffer[i] = 0x08;
                }
                processIndex_3 = (processIndex_3 + 1) % PROCESS_INDEX;

                Log.e(TAG, "PutBufferThread index_3:" + processIndex_3);

                try {
                    DataInfo di = new DataInfo();
                    di.data = buffer;
                    di.len = 1024 * 1024;
                    frameQueue.put(di);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    };

    private Thread PutBufferThread_4 = new Thread(){
        @Override
        public void run() {
            super.run();
            while (bRunningHeartBeat) {
                byte[] buffer = new byte[1024 * 1024];

                for (int i = 0; i < 1024 * 1024; i ++) {
                    buffer[i] = 0x08;
                }
                processIndex_4 = (processIndex_4 + 1) % PROCESS_INDEX;

                Log.e(TAG, "PutBufferThread index_4:" + processIndex_4);

                try {
                    DataInfo di = new DataInfo();
                    di.data = buffer;
                    di.len = 1024 * 1024;
                    frameQueue.put(di);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    };

    private Thread PutBufferThread_5 = new Thread(){
        @Override
        public void run() {
            super.run();
            while (bRunningHeartBeat) {
                byte[] buffer = new byte[1024 * 1024];

                for (int i = 0; i < 1024 * 1024; i ++) {
                    buffer[i] = 0x08;
                }
                processIndex_5 = (processIndex_5 + 1) % PROCESS_INDEX;

                Log.e(TAG, "PutBufferThread index_5:" + processIndex_5);

                try {
                    DataInfo di = new DataInfo();
                    di.data = buffer;
                    di.len = 1024 * 1024;
                    frameQueue.put(di);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    };

    private Thread PutBufferThread_6 = new Thread(){
        @Override
        public void run() {
            super.run();
            while (bRunningHeartBeat) {
                byte[] buffer = new byte[1024 * 1024];

                for (int i = 0; i < 1024 * 1024; i ++) {
                    buffer[i] = 0x08;
                }
                processIndex_6 = (processIndex_6 + 1) % PROCESS_INDEX;

                Log.e(TAG, "PutBufferThread index_6:" + processIndex_6);

                try {
                    DataInfo di = new DataInfo();
                    di.data = buffer;
                    di.len = 1024 * 1024;
                    frameQueue.put(di);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    };

    private Thread PutBufferThread_7 = new Thread(){
        @Override
        public void run() {
            super.run();
            while (bRunningHeartBeat) {
                byte[] buffer = new byte[1024 * 1024];

                for (int i = 0; i < 1024 * 1024; i ++) {
                    buffer[i] = 0x08;
                }
                processIndex_7 = (processIndex_7 + 1) % PROCESS_INDEX;

                Log.e(TAG, "PutBufferThread index_7:" + processIndex_7);

                try {
                    DataInfo di = new DataInfo();
                    di.data = buffer;
                    di.len = 1024 * 1024;
                    frameQueue.put(di);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    };

    private Thread PutBufferThread_8 = new Thread(){
        @Override
        public void run() {
            super.run();
            while (bRunningHeartBeat) {
                byte[] buffer = new byte[1024 * 1024];

                for (int i = 0; i < 1024 * 1024; i ++) {
                    buffer[i] = 0x08;
                }
                processIndex_8 = (processIndex_8 + 1) % PROCESS_INDEX;

                Log.e(TAG, "PutBufferThread index_8:" + processIndex_8);

                try {
                    DataInfo di = new DataInfo();
                    di.data = buffer;
                    di.len = 1024 * 1024;
                    frameQueue.put(di);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    };

    private Thread PutBufferThread_9 = new Thread(){
        @Override
        public void run() {
            super.run();
            while (bRunningHeartBeat) {
                byte[] buffer = new byte[1024 * 1024];

                for (int i = 0; i < 1024 * 1024; i ++) {
                    buffer[i] = 0x08;
                }
                processIndex_9 = (processIndex_9 + 1) % PROCESS_INDEX;

                Log.e(TAG, "PutBufferThread index_9:" + processIndex_9);

                try {
                    DataInfo di = new DataInfo();
                    di.data = buffer;
                    di.len = 1024 * 1024;
                    frameQueue.put(di);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    };

    private Thread PutBufferThread_10 = new Thread(){
        @Override
        public void run() {
            super.run();
            while (bRunningHeartBeat) {
                byte[] buffer = new byte[1024 * 1024];

                for (int i = 0; i < 1024 * 1024; i ++) {
                    buffer[i] = 0x08;
                }
                processIndex_10 = (processIndex_10 + 1) % PROCESS_INDEX;

                Log.e(TAG, "PutBufferThread index_10:" + processIndex_10);

                try {
                    DataInfo di = new DataInfo();
                    di.data = buffer;
                    di.len = 1024 * 1024;
                    frameQueue.put(di);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    };

    private Thread PutBufferThread_11 = new Thread(){
        @Override
        public void run() {
            super.run();
            while (bRunningHeartBeat) {
                byte[] buffer = new byte[1024 * 1024];

                for (int i = 0; i < 1024 * 1024; i ++) {
                    buffer[i] = 0x08;
                }
                processIndex_11 = (processIndex_11 + 1) % PROCESS_INDEX;

                Log.e(TAG, "PutBufferThread index_11:" + processIndex_11);

                try {
                    DataInfo di = new DataInfo();
                    di.data = buffer;
                    di.len = 1024 * 1024;
                    frameQueue.put(di);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    };

    private Thread PutBufferThread_12 = new Thread(){
        @Override
        public void run() {
            super.run();
            while (bRunningHeartBeat) {
                byte[] buffer = new byte[1024 * 1024];

                for (int i = 0; i < 1024 * 1024; i ++) {
                    buffer[i] = 0x08;
                }
                processIndex_12 = (processIndex_12 + 1) % PROCESS_INDEX;

                Log.e(TAG, "PutBufferThread index_12:" + processIndex_12);

                try {
                    DataInfo di = new DataInfo();
                    di.data = buffer;
                    di.len = 1024 * 1024;
                    frameQueue.put(di);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    };

    private Thread ProcessThread = new Thread(){
        @Override
        public void run() {
            super.run();
            while (bRunningHeartBeat) {

                try {
                    DataInfo di = frameQueue.take();
                    if (di != null){
                        if (di.data != null){
                            if (di.data.length == di.len){
                                Log.e(TAG, "ProcessThread Process once ...");
                            }
                        }
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    };

    class DataInfo{
        public byte[] data;
        public int len;
    }
}



运行一下,看看效果吧,当一个进程被杀死了,很快会被重新调起来,Demo中加入了多线程处理,用于测试资源紧张时,保活机制的有效性,有需要完整工程Demo的朋友可以进行下载。
下载地址:https://download.csdn.net/download/hnjzfwy/33298464
很感谢您能在百忙之中阅读这篇文章,也希望您能从中有所收获,谢谢!

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/336937.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号