安卓进程进程保活分为:
黑色保活,白色保活,灰色保活
黑色保活:
可以说黑色保活,可以通过网络切换,拍照,拍视频,开机,利用系统产生的广播唤醒app,接入三方的sdk也会唤醒一些app,如支付宝,微信..........这样的话,这样的话,不敢想象系统存活会给系统带来多大的负担,所以我们的安卓手机也变得卡了,google官方可能也认识了这么一点,所以取消了
ACTION_NEW_PICTURE(拍照),ACTION_NEW_VIDEO(拍视频),CONNECTIVITY_ACTION(网络切换)
app也会随着做一点改变,(不过sdk的使用还是会通过一个app启动相关的一些app , 黑色保活我个人认为不推荐使用,毕竟为了我们广大安卓用户。)
白色保活:
白色保活手段非常简单,就是调用系统api启动一个前台的Service进程,这样会在系统的通知栏生成一个Notification,用来让用户知道有这样一个app在运行着,哪怕当前的app退到了后台。
不过用户看到这个图标的时候,都会把它清空的。。。。
灰色保活:
可以说,灰色保活是用的最多,当用户不知不觉中这个app程序已经在后台运行了。
它是利用系统的漏洞来启动一个前台的Service进程,与普通的启动方式区别在于,它不会在系统通知栏处出现一个Notification,看起来就如同运行着一个后台Service进程一样。这样做带来的好处就是,用户无法察觉到你运行着一个前台进程(因为看不到Notification),但你的进程优先级又是高于普通后台进程的。API < 18,启动前台Service时直接传入new Notification();API >= 18,同时启动两个id相同的前台Service,然后再将后启动的Service做stop处理;
安卓app唤醒:
其实app唤醒的介绍很好说,app唤醒就是当打开一个app的时候,另一个app里有对应刚打开那个app的属性标志,根据你想要的唤醒方式,执行不同的代码操作,这样就可以唤醒另一个没打开的app了。(代码在最下面)
下面我展示一下这几种状态下的代码:
这个是xml布局,主要是为了展示我所介绍的几种保活方式:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin"> <Button android:id="@+id/mBtn_white" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="白色保活" /> <Button android:id="@+id/mBtn_gray" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="灰色保活" /> <Button android:id="@+id/mBtn_black" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="黑色保活(发广播)" /> <Button android:id="@+id/mBtn_background_service" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="普通后台 Service 进程" /> </LinearLayout>
下面是主要实现类:
WakeReceiver
import android.app.Notification; import android.app.Service; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.os.Build; import android.os.IBinder; import android.util.Log; public class WakeReceiver extends BroadcastReceiver { private final static String TAG = WakeReceiver.class.getSimpleName(); private final static int WAKE_SERVICE_ID = -1111; /** * 灰色保活手段唤醒广播的action */ public final static String GRAY_WAKE_ACTION = "com.wake.gray"; @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (GRAY_WAKE_ACTION.equals(action)) { Log.i(TAG, "wake !! wake !! "); Intent wakeIntent = new Intent(context, WakeNotifyService.class); context.startService(wakeIntent); } } /** * 用于其他进程来唤醒UI进程用的Service */ public static class WakeNotifyService extends Service { @Override public void onCreate() { Log.i(TAG, "WakeNotifyService->onCreate"); super.onCreate(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.i(TAG, "WakeNotifyService->onStartCommand"); if (Build.VERSION.SDK_INT < 18) { startForeground(WAKE_SERVICE_ID, new Notification());//API < 18 ,此方法能有效隐藏Notification上的图标 } else { Intent innerIntent = new Intent(this, WakeGrayInnerService.class); startService(innerIntent); startForeground(WAKE_SERVICE_ID, new Notification()); } return START_STICKY; } @Override public IBinder onBind(Intent intent) { // TODO: Return the communication channel to the service. throw new UnsupportedOperationException("Not yet implemented"); } @Override public void onDestroy() { Log.i(TAG, "WakeNotifyService->onDestroy"); super.onDestroy(); } } /** * 给 API >= 18 的平台上用的灰色保活手段 */ public static class WakeGrayInnerService extends Service { @Override public void onCreate() { Log.i(TAG, "InnerService -> onCreate"); super.onCreate(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.i(TAG, "InnerService -> onStartCommand"); startForeground(WAKE_SERVICE_ID, new Notification()); //stopForeground(true); stopSelf(); return super.onStartCommand(intent, flags, startId); } @Override public IBinder onBind(Intent intent) { // TODO: Return the communication channel to the service. throw new UnsupportedOperationException("Not yet implemented"); } @Override public void onDestroy() { Log.i(TAG, "InnerService -> onDestroy"); super.onDestroy(); } } }
BackGroundService
import android.app.Service; import android.content.Intent; import android.os.IBinder; import android.util.Log; /** * 普通的后台Service进程 * * @author clock * @since 2016-04-12 */ public class BackgroundService extends Service { private final static String TAG = BackgroundService.class.getSimpleName(); @Override public void onCreate() { Log.i(TAG, "onCreate"); super.onCreate(); } @Override public IBinder onBind(Intent intent) { // TODO: Return the communication channel to the service. throw new UnsupportedOperationException("Not yet implemented"); } @Override public void onDestroy() { Log.i(TAG, "onDestroy"); super.onDestroy(); } }
GrayService
import android.app.AlarmManager; import android.app.Notification; import android.app.PendingIntent; import android.app.Service; import android.content.Context; import android.content.Intent; import android.os.Build; import android.os.IBinder; import android.util.Log; import com.example.renzheng.receiver.WakeReceiver; /** * 灰色保活手法创建的Service进程 * * @author Clock * @since 2016-04-12 */ public class GrayService extends Service { private final static String TAG = GrayService.class.getSimpleName(); /** * 定时唤醒的时间间隔,5分钟 */ private final static int ALARM_INTERVAL = 5 * 60 * 1000; private final static int WAKE_REQUEST_CODE = 6666; private final static int GRAY_SERVICE_ID = -1001; @Override public void onCreate() { Log.i(TAG, "GrayService->onCreate"); super.onCreate(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.i(TAG, "GrayService->onStartCommand"); if (Build.VERSION.SDK_INT < 18) { startForeground(GRAY_SERVICE_ID, new Notification());//API < 18 ,此方法能有效隐藏Notification上的图标 } else { Intent innerIntent = new Intent(this, GrayInnerService.class); startService(innerIntent); startForeground(GRAY_SERVICE_ID, new Notification()); } //发送唤醒广播来促使挂掉的UI进程重新启动起来 AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE); Intent alarmIntent = new Intent(); alarmIntent.setAction(WakeReceiver.GRAY_WAKE_ACTION); PendingIntent operation = PendingIntent.getBroadcast(this, WAKE_REQUEST_CODE, alarmIntent, PendingIntent.FLAG_UPDATE_CURRENT); alarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), ALARM_INTERVAL, operation); return START_STICKY; } @Override public IBinder onBind(Intent intent) { throw new UnsupportedOperationException("Not yet implemented"); } @Override public void onDestroy() { Log.i(TAG, "GrayService->onDestroy"); super.onDestroy(); } /** * 给 API >= 18 的平台上用的灰色保活手段 */ public static class GrayInnerService extends Service { @Override public void onCreate() { Log.i(TAG, "InnerService -> onCreate"); super.onCreate(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.i(TAG, "InnerService -> onStartCommand"); startForeground(GRAY_SERVICE_ID, new Notification()); //stopForeground(true); stopSelf(); return super.onStartCommand(intent, flags, startId); } @Override public IBinder onBind(Intent intent) { // TODO: Return the communication channel to the service. throw new UnsupportedOperationException("Not yet implemented"); } @Override public void onDestroy() { Log.i(TAG, "InnerService -> onDestroy"); super.onDestroy(); } } }
WhileService
import android.app.Notification; import android.app.PendingIntent; import android.app.Service; import android.content.Intent; import android.os.IBinder; import android.support.v7.app.NotificationCompat; import android.util.Log; import com.example.renzheng.MainActivity; import com.example.renzheng.R; /** * 正常的系统前台进程,会在系统通知栏显示一个Notification通知图标 * * @author clock * @since 2016-04-12 */ public class WhiteService extends Service { private final static String TAG = WhiteService.class.getSimpleName(); private final static int FOREGROUND_ID = 1000; @Override public void onCreate() { Log.i(TAG, "WhiteService->onCreate"); super.onCreate(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.i(TAG, "WhiteService->onStartCommand"); NotificationCompat.Builder builder = new NotificationCompat.Builder(this); builder.setSmallIcon(R.mipmap.ic_launcher); builder.setContentTitle("Foreground"); builder.setContentText("I am a foreground service"); builder.setContentInfo("Content Info"); builder.setWhen(System.currentTimeMillis()); Intent activityIntent = new Intent(this, MainActivity.class); PendingIntent pendingIntent = PendingIntent.getActivity(this, 1, activityIntent, PendingIntent.FLAG_UPDATE_CURRENT); builder.setContentIntent(pendingIntent); Notification notification = builder.build(); startForeground(FOREGROUND_ID, notification); return super.onStartCommand(intent, flags, startId); } @Override public IBinder onBind(Intent intent) { // TODO: Return the communication channel to the service. throw new UnsupportedOperationException("Not yet implemented"); } @Override public void onDestroy() { Log.i(TAG, "WhiteService->onDestroy"); super.onDestroy(); } }
MainActivity
import android.content.Intent; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.view.View; import com.example.renzheng.service.BackgroundService; import com.example.renzheng.service.GrayService; import com.example.renzheng.service.WhiteService; public class MainActivity extends AppCompatActivity implements View.OnClickListener { private final static String TAG = MainActivity.class.getSimpleName(); /** * 黑色唤醒广播的action */ private final static String BLACK_WAKE_ACTION = "com.wake.black"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); findViewById(R.id.mBtn_white).setOnClickListener(this); findViewById(R.id.mBtn_gray).setOnClickListener(this); findViewById(R.id.mBtn_black).setOnClickListener(this); findViewById(R.id.mBtn_background_service).setOnClickListener(this); } @Override public void onClick(View v) { int viewId = v.getId(); if (viewId == R.id.mBtn_white) { //系统正常的前台Service,白色保活手段 Intent whiteIntent = new Intent(getApplicationContext(), WhiteService.class); startService(whiteIntent); } else if (viewId == R.id.mBtn_gray) {//利用系统漏洞,灰色保活手段(API < 18 和 API >= 18 两种情况) Intent grayIntent = new Intent(getApplicationContext(), GrayService.class); startService(grayIntent); } else if (viewId == R.id.mBtn_black) { //拉帮结派,黑色保活手段,利用广播唤醒队友 Intent blackIntent = new Intent(); blackIntent.setAction(BLACK_WAKE_ACTION); sendBroadcast(blackIntent); } else if (viewId == R.id.mBtn_background_service) {//普通的后台进程 Intent bgIntent = new Intent(getApplicationContext(), BackgroundService.class); startService(bgIntent); } } }
代码注册权限:
<receiver android:name=".receiver.WakeReceiver" android:enabled="true" android:exported="false"> <intent-filter> <action android:name="com.wake.gray" /> </intent-filter> </receiver> <service android:name=".service.WhiteService" android:enabled="true" android:exported="false" android:process=":white" /> <service android:name=".service.GrayService" android:enabled="true" android:exported="false" android:process=":gray" /> <service android:name=".service.GrayService$GrayInnerService" android:enabled="true" android:exported="false" android:process=":gray" /> <service android:name=".service.BackgroundService" android:enabled="true" android:exported="false" android:process=":bg" /> <service android:name=".receiver.WakeReceiver$WakeNotifyService" android:enabled="true" android:exported="false" /> <service android:name=".receiver.WakeReceiver$WakeGrayInnerService" android:enabled="true" android:exported="false" />
下面是app唤醒代码:
有2个APP,分别为A和B,当A活着的时候,试着开启B的后台服务,将原本杀死的B的后台服务程序活起来。反之也一样。
1.先看B的代码:
创建一个服务B,给服务添加一个process属性,设置action。
<service android:name=".B" android:process=":test"> <intent-filter> <action android:name="yangyang" /> </intent-filter> </service>B的代码,在onStartCommand方法中弹出toast:
public class B extends Service { @Nullable @Override public IBinder onBind(Intent intent) { return null; } @Override public int onStartCommand(Intent intent, int flags, int startId) { Toast.makeText(this, "B 已经唤醒", Toast.LENGTH_SHORT).show(); return START_STICKY; } }2.看A的代码,在MainActivity中点击开启B应用的B服务的代码:
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button btn = (Button) findViewById(R.id.btn); btn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { sendService(); } }); } private void sendService() { boolean find = false; ActivityManager mActivityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE); Intent serviceIntent = new Intent(); for (ActivityManager.RunningServiceInfo runningServiceInfo : mActivityManager.getRunningServices(100)) { if (runningServiceInfo.process.contains(":test")) {//判断service是否在运行 Log.e("zhang", "process:" + runningServiceInfo.process); find = true; } } //判断服务是否起来,如果服务没起来,就唤醒 if (!find) { serviceIntent.setPackage("com.example.b); serviceIntent.setAction("yangyang"); startService(serviceIntent); Toast.makeText(this, "开始唤醒 B", Toast.LENGTH_SHORT).show(); }else { Toast.makeText(this, "B 不用唤醒", Toast.LENGTH_SHORT).show(); } } }
这里只是写了A启动B服务的代码,反之也是一样的。被启动应用的Servcie在AndroidMainfest.xml中注册时注意,添加process属性,和设置action匹配规则。