- 程序之美
- 进程和线程
- 服务
- 保活机制
当应用组件启动且该应用未运行任何其他组件时,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
很感谢您能在百忙之中阅读这篇文章,也希望您能从中有所收获,谢谢!



