Android开机启动广播
- 理论概述
- 核心代码
第一章 理论概述
第01节 基础说明
1、开机启动的过程当中, 定义开机启动广播。
2、接收到开机启动广播之后, 可以开启 Service
A. 低版本实现 Android8.0 之前的实现
B. 高版本实现 Android8.0 之后的实现
3、接收到开机启动广播之后, 可以开启 Activity
A. 低版本实现 Android8.0 之前的实现
B. 高版本实现 Android8.0 之后的实现
第02节 基础步骤
1. 定义清单文件
A. 三种权限(开机广播、后台服务、后台Activity)
B. 定义三类(Activity、Service、Receiver)
2. 定义广播接收者 Receiver
A. 重写方法 onReceive()
B. 分版本开启 Service
C. 分版本开启 Activity
3. 定义服务 Service
A. 重写方法 onBind()
B. 重写方法 onCreate()
C. 重写方法 onStartCommand()
4. 定义 Activity
A. 重写方法 onCreate()
第03节 效果图
开机启动Activity 高版本效果
开机启动Activity 低版本效果
开机启动Service高版本效果
开机启动Service低版本效果
第二章 核心方法
第01节 清单文件
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="chc.svip">
<!-- 设置权限 -->
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<!-- 后台服务的权限 -->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<!-- 后台Activity的权限 -->
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.USE_FULL_SCREEN_INTENT" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.MyDemo">
<!-- 定义Activity,接收开机启动的广播当中,跳入到Activity当中 -->
<activity
android:name=".MainActivity"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!-- 定义广播接收者,准备用于开机的过程当中,接收开机启动的广播 -->
<receiver
android:name=".BootCompleteReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
<!-- 定义服务Service,接收开机启动的广播当中,跳入到Service当中 -->
<service android:name=".HelloService" />
</application>
</manifest>
1、 权限定义
2、组件定义
第02节 Activity
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
public class MainActivity extends AppCompatActivity {
private static final String TAG = "hello";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.i(TAG, "onCreate: hello ===>MainActivity启动了");
}
}
1、成员变量 主要是用于打印的标记
TAG
2、成员方法 主要是onCreate
重写的方法
第03节 Service
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;
import androidx.annotation.Nullable;
/*
Android 8.0 系统不允许后台应用创建后台服务,故只能使用Context.startForegroundService()启动服务
创建服务后,应用必须在5秒内调用该服务的 startForeground() 显示一条可见通知,
声明有服务在挂着,不然系统会停止服务 + ANR 套餐送上。
Notification 要加 Channel,系统的要求
为什么要在onStart里再次调用startForeground()?
答:这一条主要是针对后台保活的服务,如果在服务A运行期间,保活机制又startForegroundService启动了一次服务A,
那么这样不会调用服务A的onCreate方法,只会调用onStart方法。如果不在onStart方法里再挂个通知的话,
系统会认为你使用了 startForegroundService 却不在 5 秒内给通知,很傻地就停止服务 + ANR 套餐送
*/
public class HelloService extends Service {
private static final String TAG = "hello";
public static final String CHANNEL_ID_STRING = "service_01";
private Notification notification;
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate() {
Log.i(TAG, "onCreate: ...服务创建...");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i(TAG, "onStartCommand: start....服务启动...");
//下面是判断 Android8.0 以后的服务,设置为后台服务的操作
NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
NotificationChannel mChannel = null;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
mChannel = new NotificationChannel(CHANNEL_ID_STRING,
getString(R.string.app_name),
NotificationManager.IMPORTANCE_LOW);
manager.createNotificationChannel(mChannel);
notification = new Notification.Builder(getApplicationContext(), CHANNEL_ID_STRING).build();
//注意 startForeground(1, notification);中不能为0,不然会出现如下问题
//Context.startForegroundService() did not then call Service.startForeground()
startForeground(1, notification);
}
return super.onStartCommand(intent, flags, startId);
}
}
1、成员变量
A. 用于打印的标记
TAG
B. 用于通知的标记
CHANNEL_ID_STRING
C. 用于通知的对象
Notification
2、成员方法
A. 绑定方法
onBind
B. 创建方法
onCreate
C. 开启方法
onStartCommand
第04节 Receiver
import static android.content.Context.NOTIFICATION_SERVICE;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.util.Log;
import android.widget.Toast;
import androidx.core.app.NotificationCompat;
import androidx.core.app.NotificationManagerCompat;
/***
* 开机启动的广播
*/
public class BootCompleteReceiver extends BroadcastReceiver {
private static final String TAG = "hello";
private static final String BOOT_ACTION = "android.intent.action.BOOT_COMPLETED";
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "Boot Complete 开机启动的广播接收者", Toast.LENGTH_LONG).show();
Log.i(TAG, "onReceive: Boot Complete 开机启动的广播接收者");
//开机的过程当中,启动 Activity的操作,判断当前启动的动作是开机启动的
if (BOOT_ACTION.equals(intent.getAction())) {
//开启Activity
openActivity(context);
//开启Service
//openService(context);
}
}
/***
* 启动Service的方法
*
* @param context
*/
public void openService(Context context) {
Intent newIntent = new Intent(context,HelloService.class);
//判断当前编译的版本是否高于等于 Android8.0 或 26 以上的版本
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
context.startForegroundService(newIntent);
} else {
context.startService(newIntent);
}
Log.i(TAG, "openService: 启动Service");
}
/***
* 启动Activity的方法
*
* @param context
*/
public void openActivity(Context context) {
//判断当前编译的版本是否高于等于 Android8.0 或 26 以上的版本
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
startActivityVersionHeight(context);
}else{
startActivityVersionLower(context);
}
Log.i(TAG, "openActivity: 启动Activity");
}
/***
* 低版本的实现
* @param context
*/
public void startActivityVersionLower(Context context) {
Intent myIntent = new Intent(context,MainActivity.class);
myIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(myIntent);
}
/***
* 高版本的实现
* @param context
*/
public void startActivityVersionHeight(Context context) {
Intent intent1 = new Intent(context,MainActivity.class);
intent1.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
PendingIntent fullScreenPendingIntent = PendingIntent.getActivity(context, 0,
intent1, PendingIntent.FLAG_UPDATE_CURRENT);
String channelID = "my_channel_ID";
String channelNAME = "my_channel_NAME";
int level = NotificationManager.IMPORTANCE_HIGH;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
NotificationManager manager = (NotificationManager)
context.getSystemService(NOTIFICATION_SERVICE);
NotificationChannel channel = new NotificationChannel(channelID, channelNAME, level);
manager.createNotificationChannel(channel);
}
NotificationCompat.Builder notification =
new NotificationCompat.Builder(context, channelID)
.setSmallIcon(R.drawable.ic_launcher_background)
.setContentTitle("Start Activity")
.setContentText("click me")
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setCategory(NotificationCompat.CATEGORY_CALL)
.setAutoCancel(true)
.setFullScreenIntent(fullScreenPendingIntent, true);
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context);
notificationManager.notify(100, notification.build());
}
}
1、成员变量
A. 打印日志的标记
TAG
B. 开机启动的广播
BOOT_ACTION
2、成员方法
A. 接收广播的方法
onReceive
B. 开启服务的方法
openService
C. 开启Activity的方法
openActivity
D. 低版本启动 Activity的实现
startActivityVersionLower
E. 高版本启动 Activity的实现
startActivityVersionHeight