注册

Android App唤醒丶保活详解 , 以及代码展示

安卓进程进程保活分为:


黑色保活,白色保活,灰色保活


黑色保活:


可以说黑色保活,可以通过网络切换,拍照,拍视频,开机,利用系统产生的广播唤醒app,接入三方的sdk也会唤醒一些app,如支付宝,微信..........这样的话,这样的话,不敢想象系统存活会给系统带来多大的负担,所以我们的安卓手机也变得卡了,google官方可能也认识了这么一点,所以取消了


ACTION_NEW_PICTURE(拍照),ACTION_NEW_VIDEO(拍视频),CONNECTIVITY_ACTION(网络切换)


app也会随着做一点改变,(不过sdk的使用还是会通过一个app启动相关的一些app , 黑色保活我个人认为不推荐使用,毕竟为了我们广大安卓用户。)


白色保活:


白色保活手段非常简单,就是调用系统api启动一个前台的Service进程,这样会在系统的通知栏生成一个Notification,用来让用户知道有这样一个app在运行着,哪怕当前的app退到了后台。


3f7e4d39ddbb4ea59bb152a09de272dd.png


不过用户看到这个图标的时候,都会把它清空的。。。。



灰色保活:


可以说,灰色保活是用的最多,当用户不知不觉中这个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匹配规则。


————————————————
版权声明:本文为CSDN博主「看美丽风晴」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/nazicsdn/article/details/79752617

0 个评论

要回复文章请先登录注册