Android 接收開機廣播啟動service/activity
前言:
此文章針對于普通手機APP,在沒有限制之前直接可以通過接收開機廣播,然后通過intent即可實作開機啟動service/activity,
Intent intent = new Intent(context,XXXXX.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);//啟動activity
context.startService(intent);//啟動service
對于啟動service:
Android 8.0 對特定函式做出了以下變更:
- 如果針對 Android 8.0 的應用嘗試在不允許其創建后臺服務的情況下使用
startService()函式,則該函式將引發一個IllegalStateException,- 新的
Context.startForegroundService()函式將啟動一個前臺服務,現在,即使應用在后臺運行,系統也允許其呼叫Context.startForegroundService(),不過,應用必須在創建服務后的五秒內呼叫該服務的startForeground()函式,如果不呼叫就會出現ANR,
對于啟動activity:
Android Q限制在沒有用戶互動的情況下加載Activity,這一變化可以最大限度的減少對用戶的打擾,保持用戶對螢屏上所顯示內容的可控性,
運行在Android Q上的APP僅在以下一種或多種情況下可運行Activity:
- APP存在一個可視的視窗,例如一個處于前臺的Activity
- 另外一個處于前臺的APP發送一個屬于當前APP的PendingIntent,例如Custom Tabs provider發送一個menu item pending intent,
- 系統發送一個PendingIntent,例如點擊一個通知,
- 系統給APP發送一個廣播,如SECRET_CODE_ACTION,
注:APP啟動一個前臺運行的Service并不代表該APP處于前臺運行狀態,
所以并不能啟動service之后再service中直接啟動activity,
解決辦法:
啟動service:
前面我們已經知道了可以通過startForegroundService()來啟動service,然后在oncreate中呼叫startForeground()即可:
BootReceiver:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
context.startForegroundService(intent);
} else {
context.startService(intent);
}
service的onCreate():
//設定點擊跳轉
Intent intent = new Intent(this, MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
String id = "1";
String name = "channel_name_1";
NotificationManager notificationManager = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE);
Notification notification = null;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel mChannel = new NotificationChannel(id, name, NotificationManager.IMPORTANCE_DEFAULT);
mChannel.setSound(null, null);
notificationManager.createNotificationChannel(mChannel);
notification = new Notification.Builder(this)
.setChannelId(id)
.setContentTitle("123")
.setContentIntent(pendingIntent)
.setAutoCancel(false)
.setSmallIcon(R.drawable.ic_launcher_background).build();
} else {
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
.setContentTitle("123")
.setContentIntent(pendingIntent)
.setPriority(Notification.PRIORITY_DEFAULT)// 設定該通知優先級
.setAutoCancel(false)
.setSmallIcon(R.drawable.ic_launcher_background);
notification = notificationBuilder.build();
}
startForeground(1, notification);
這樣即可實作在開機時啟動服務,但是會在通知欄創建一條訊息,
如果不實作startForeground()就會onDestory
最后記得在Mainfest.xml中添加權限:
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
啟動activity:
直接使用context.startactivity(intent)是不能夠啟動的,會報一些空指標錯誤之類的,
谷歌官方推薦使用全屏Intent:
BootReceiver:
Intent intent1 = new Intent(context, MainActivity2.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 = createNotificationChannel("my_channel_ID", "my_channel_NAME", NotificationManager.IMPORTANCE_HIGH, context);
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)
// Use a full-screen intent only for the highest-priority alerts where you
// have an associated activity that you would like to launch after the user
// interacts with the notification. Also, if your app targets Android 10
// or higher, you need to request the USE_FULL_SCREEN_INTENT permission in
// order for the platform to invoke this notification.
.setFullScreenIntent(fullScreenPendingIntent, true);
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context);
notificationManager.notify(100, notification.build());
createNotificationChannel:
private String createNotificationChannel(String channelID, String channelNAME, int level, Context context) {
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);
return channelID;
} else {
return null;
}
}
在接收到開機廣播后會在通知欄創建一個訊息,然后用戶點擊訊息跳轉到對應的activity,
最后記得在Mainfest.xml中添加權限:
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.USE_FULL_SCREEN_INTENT" />
總結:
隨著版本的升級,android對后臺限制越來越嚴格,想要悄無聲息的啟動service和activity有一定的困難,
而且普通app接收開機廣播接收也很慢,在開機后10多秒才能接收到,把優先級設為最高,會有一定的效果
android:priority="2147483647"
最后:不同的手機廠商的限制也有所不同,也有可能以上方法不適用于某些手機,
在鎖屏狀態下也不會接收到開機廣播,應該也是手機廠商做了限制,
參考文獻:
Android10適配-針對從后臺啟動 Activity 的限制
顯示有時效性的通知
Android Q 限制后臺啟動Activity
Android8.0 啟動后臺Service問題
Android 保活后臺啟動Service 8.0踩坑記錄
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/254768.html
標籤:其他
