> Android6.0到9.0的适配
Android6.0到9.0的适配爬坑总结- https://blog.csdn.net/feelinghappy/article/details/84521067
Android 6.0、7.0、8.0、9.0适配- https://www.jianshu.com/p/a8fd3d1fa0a3
-- 在调起这个申请动态权限后,权限框刚开发就瞬间消失了;
原因是:AndroidManifest(清单文件)中没有配置该权限;
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
在清单文件中也增加该权限就不会出现 权限框闪一下退出的问题了;
Android App兼容8.0和9.0- https://blog.csdn.net/u014644594/article/details/86748035
1.项目中如果使用Volley的话,在android 9.0会出现异常,提示ProtocolVersion的异常,之后,就在AndroidManifest的application节点下添加,
<!--解决android9.0上使用ProtocolVersion抛异常的bug--> org.apache.http.HttpStatus
<uses-library android:name="org.apache.http.legacy" android:required="false" />
2. Permission Denial: startForeground requires android.permission.FOREGROUND_SERVICE。
解决办法是在AndroidManifest中添加
<!--android 9.0上使用前台服务,需要添加权限-->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
3.<!-- 8.0安装apk权限,需要允许安装未知应用 -->
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
<uses-library android:name="org.apache.http.legacy" android:required="false"/>
<!--android 9.0上使用前台服务,需要添加权限-->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
<uses-permission android:name="android.permission.WRITE_MEDIA_STORAGE" />
Android 9.0中sdcard 的权限和挂载问题- https://blog.csdn.net/shift_wwx/article/details/85633801
getCacheDir()方法用于获取/data/data/<application package>/cache目录
getFilesDir()方法用于获取/data/data/<application package>/files目录
通过Context.getExternalFilesDir()方法可以获取到 SDCard/Android/data/你的应用的包名/files/ 目录,一般放一些长时间保存的数据
通过Context.getExternalCacheDir()方法可以获取到 SDCard/Android/data/你的应用包名/cache/目录,一般存放临时缓存数据
-- android9.0来电无法获取处理:
限制访问电话号码, 在未首先获得 READ_CALL_LOG 权限的情况下,除了应用的用例需要的其他权限之外,运行于 Android 9 上的应用无法读取电话号码或手机状态。
与来电和去电关联的电话号码可在手机状态广播(比如来电和去电的手机状态广播)中看到,并可通过 PhoneStateListener 类访问。 但是,如果没有 READ_CALL_LOG 权限,则 PHONE_STATE_CHANGED 广播和 PhoneStateListener 提供的电话号码字段为空。
要从手机状态中读取电话号码,请根据您的用例更新应用以请求必要的权限:
要通过 PHONE_STATE Intent 操作读取电话号码,同时需要 READ_CALL_LOG 权限和 READ_PHONE_STATE 权限。
要从 onCallStateChanged() 中读取电话号码,只需要 READ_CALL_LOG 权限。 不需要 READ_PHONE_STATE 权限。
只用在项目权限列表添加权限:
<uses-permission android:name="android.permission.READ_CALL_LOG" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
android.permission.READ_CONTACTS android.permission.WRITE_CONTACTS
> targetSdkVersion从23升级到26
Android targetSdkVersion 26 升级后 应用内部版本更新失败的问题- https://blog.csdn.net/zy987654zy/article/details/83306445
Target sdk 26 (Android 8.0)一些版本兼容问题- https://blog.csdn.net/xinlvmylife/article/details/82837218
target-api 升级到26遇到的问题 国产ROM动态权限的坑- https://blog.csdn.net/weixin_33909059/article/details/87478034
关于targetSDKVersion=26适配8.0以上的一些坑- https://blog.csdn.net/u011449334/article/details/79193043
android 8.0 (API=26) 升级适配遇到的两个问题- https://blog.csdn.net/zp1307700/article/details/82688851
1.透明窗口设置的问题
Caused by: java.lang.IllegalStateException: Only fullscreen opaque activities can request orientation
“有全屏不透明的activity才可以设置方向”
修改:(1)全屏设置,(2)透明设置,(3)方向设置
试了一下跟全屏好像没有什么关系,主要是
android:windowIsTranslucent=true(透明)
android:screenOrientation(方向)
的冲突。
解决方法:
(1)去掉android:screenOrientation;(可以横屏了,不太好,需求都被程序员改了);
(2)android:windowIsTranslucent 改为false; 如果需要透明的设置加上android:windowDisablePreview =true;
2.通知栏不显示的问题
https://developer.android.google.cn/training/notify-user/build-notification
自定义通知:
建议使用NotificationCompat.Builder
new NotificationCompat.Builder(context, ID);
加上自定义的ID,
或者使用NotificationCompat.Builder.setChannelId(ID)
> Android App兼容7.0, 8.0和9.0
安卓开发中,如果用vivo手机调试程序,很可能会遇到运行的时候安装应用失败。
Android Studio真机调试,vivo手机安装失败,解析包时出现问题
在工程目录的 gradle.properties 中添加以下代码即可:android.injected.testOnly = false
Android debug 包不能安装
gradle.properties 文件中添加:android.injected.testOnly=false
升级3.0之后自动启用了instant run功能,生成的apk包是不完整的,设置中关闭即可,应该是这个导致的
http://blog.csdn.net/sxw1900/article/details/78489294
1.设置你的AS,关闭Instant Run。File->Settings->BUild,Execution...->Instant Run , 关闭勾选Enable Instant Run...
2.在你的gradle.properties文件添加一句:android.injected.testOnly = false
------------
-- targetSdkVersion 26 升级
1.Android 7.0系统,无法进行版本升级,提示文件解析失败。
第一步: 在res文件夹下面 创建xml文件夹。创建一个文件。文件名称:files_paths.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<paths>
<external-path path="." name="文件名称自定义"/>
<files-path path ="." name = "文件名称自定义"/>
<cache-path path ="." name = "文件名称自定义"/>
<external-path name="external_storage_root" path="." />
</paths>
</resources>
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="${applicationId}.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/files_paths" />
</provider>
第三步:在安装app的地方调整方式
File apkfile : 这个是你的apk文件地址对象。
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
Uri apkUri = FileProvider.getUriForFile(mContext, BuildConfig.APPLICATION_ID + ".provider", apkfile); // 这个地方 关键
Intent install = new Intent(Intent.ACTION_VIEW);
install.setDataAndType(apkUri, "application/vnd.android.package-archive");
install.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
install.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);//添加这一句表示对目标应用临时授权该Uri所代表的文件
mContext.startActivity(install);
} else {
Intent i = new Intent(Intent.ACTION_VIEW);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
i.setDataAndType(Uri.parse("file://" + apkfile.toString()),
"application/vnd.android.package-archive");
mContext.startActivity(i);
}
2.Android 8.0系统,安装Apk权限,添加未知应用的权限:
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
解决方法: 添加允许安装未知应用市场权限,这个权限不是动态权限,所以不用进行动态申请。
//兼容8.0
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
boolean hasInstallPermission = getPackageManager().canRequestPackageInstalls();
if (!hasInstallPermission) {
Tip.toast(this, "请打开安装未知应用的许可!");
startInstallPermissionSettingActivity(this);
return;
}
}
/**
* 跳转到设置-允许安装未知来源-页面
*/
@RequiresApi(api = Build.VERSION_CODES.O)
private void startInstallPermissionSettingActivity(Context context) {
//注意这个是8.0新API
Intent intent = new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
}
3.Android8.0通知栏 ,使得APP能在Android8.0中显示通知,需要进行版本判断,然后给builder设置Channel; 通知已经适配好了
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(id, name, NotificationManager.IMPORTANCE_LOW);
getNotifyMgr(context).createNotificationChannel(channel);
builder = new NotificationCompat.Builder(context, id);
} else {
builder = new NotificationCompat.Builder(context);
}
!
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
String channelId = "chat";
String channelName = "聊天消息";
int importance = NotificationManager.IMPORTANCE_HIGH;
createNotificationChannel(channelId, channelName, importance);
channelId = "subscribe";
channelName = "订阅消息";
importance = NotificationManager.IMPORTANCE_DEFAULT;
createNotificationChannel(channelId, channelName, importance);
}
}
@TargetApi(Build.VERSION_CODES.O)
private void createNotificationChannel(String channelId, String channelName, int importance) {
NotificationChannel channel = new NotificationChannel(channelId, channelName, importance);
NotificationManager notificationManager = (NotificationManager) getSystemService(
NOTIFICATION_SERVICE);
notificationManager.createNotificationChannel(channel);
}
}
类似于微信的App,其中App通知主要可以分为两类,一类是我和别人的聊天消息,这类消息非常重要,因此重要等级我设为了IMPORTANCE_HIGH。另一类是公众号的订阅消息,这类消息不是那么重要,因此重要等级我设为了IMPORTANCE_DEFAULT。除此之外,重要等级还可以设置为IMPORTANCE_LOW、IMPORTANCE_MIN,分别对应了更低的通知重要程度。
setPriority() 方法共有5个等级:
1. PRIORITY_MIN - 最低级别(-2);
2. PRIORITY_LOW - 较低级别(-1);
3. PRIORITY_DEFAULT - 默认级别(0);
4. PRIORITY_HIGH - 较高级别(1);
5. PRIORITY_MAX - 最高级别(2);
IMPORTANCE_DEFAULT = 3; 会在状态栏中显示,允许有声音提示,但不会弹窗,通知下拉栏会展示
IMPORTANCE_HIGH = 4; 会弹窗提示,允许有提示音
IMPORTANCE_LOW = 2; 会在状态栏中显示,但不会弹窗,通知下拉栏会展示
IMPORTANCE_MAX = 5; 会弹窗提示,允许有提示音,可以使用全屏
IMPORTANCE_MIN = 1; 不提示,在通知下拉栏会展示,但是是收起的
IMPORTANCE_NONE = 0; 不提示,不展示
NotificationChannel channel = new NotificationChannel(CommonParams.NOTIFICATION_GROUP_DOWNLOAD, "下载通知消息", NotificationManager.IMPORTANCE_DEFAULT);
mNotificationManager.createNotificationChannel(channel);
Android通知栏微技巧,8.0系统中通知栏的适配- https://blog.csdn.net/guolin_blog/article/details/79854070
Android 8.0系统通知栏适配Demo- https://download.csdn.net/download/sinyu890807/10349044
Android 8.0 通知适配-https://blog.csdn.net/y331271939/article/details/83342519
Android O 通知栏- https://github.com/YBill/NotificationTest https://github.com/OptimusPrimeRen/Android-O-Adaptive.git
public static void showChannel1Notification(Context context) {
int notificationId = 0x1234;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
// Notification.Builder builder = new Notification.Builder(context, "group_download"); // 与channelId对应
NotificationCompat.Builder builder = new NotificationCompat.Builder(context,"group_download");
NotificationChannel channel = new NotificationChannel("group_download", // Constants.CHANNEL_CHAT group_download
"下载通知消息", NotificationManager.IMPORTANCE_DEFAULT);
NotificationManager mNotificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.createNotificationChannel(channel);
// icon title text必须包含, 不然影响桌面图标小红点的展示
builder.setSmallIcon(android.R.drawable.stat_notify_chat)
.setContentTitle("xxx")
.setContentText("xxx")
.setNumber(3); // 久按桌面图标时允许的此条通知的数量
// NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(notificationId, builder.build());
}
}
// 通知栏的通知渠道ID
public static final String NOTIFICATION_GROUP_DOWNLOAD = "carlife_group_download";
public static final String NOTIFICATION_GROUP_NAME = "下载通知";
mNotificationManager = (NotificationManager) mActivity
.getSystemService(Context.NOTIFICATION_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
mBuilder = new NotificationCompat.Builder(mActivity, CommonParams.NOTIFICATION_GROUP_DOWNLOAD);
NotificationChannel channel = new NotificationChannel(CommonParams.NOTIFICATION_GROUP_DOWNLOAD,
CommonParams.NOTIFICATION_GROUP_NAME, NotificationManager.IMPORTANCE_DEFAULT);
channel.setSound(null, null); // 不需要提示声音
mNotificationManager.createNotificationChannel(channel);
} else {
mBuilder = new NotificationCompat.Builder(mActivity);
}
mBuilder.setSmallIcon(R.drawable.ic_launcher)
.setContentTitle(mActivity.getString(R.string.tts_setting_navi_voicepackage) + voiceName)
.setProgress(100, progress, false).setContentIntent(resultPendingIntent)
.setOngoing(true);
-- 关于Android 8.0后notification通知声音无法关闭或开启的问题
一、更新channelId,设置为一个新的值,跟以往任何一个都不重复,然后再设置channel.setSound(null, null);就可以了。
二、卸载app,如果代码之前没问题,卸载重新安装就好了,
三、手动调用清空channelId的方法,(这个我没试过,但应该是可以的)
四、卸载app后把importance参数设置为NotificationManager.IMPORTANCE_LOW或者更低。再安装运行就好了。
五、mBuilder.setOnlyAlertOnce(true)设置为true,这样的话,每次只会提醒一次声音,不会重复提醒。
六、如果你不想卸载app的话,有个最好的办法就是同时更换channelId和NotificationManager.IMPORTANCE_LOW就可以了。
4. Android9.0
.项目中如果使用Volley的话,在android 9.0会出现异常,提示ProtocolVersion的异常,之后,就在AndroidManifest的application节点下添加,
<!--解决android9.0上使用ProtocolVersion抛异常的bug--> org.apache.http.HttpStatus
<uses-library android:name="org.apache.http.legacy" android:required="false" />
. Permission Denial: startForeground requires android.permission.FOREGROUND_SERVICE。
解决办法是在AndroidManifest中添加
<!--android 9.0上使用前台服务,需要添加权限-->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
.<!-- 8.0安装apk权限,需要允许安装未知应用 -->
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
<uses-library android:name="org.apache.http.legacy" android:required="false"/>
<!--android 9.0上使用前台服务,需要添加权限-->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
<uses-permission android:name="android.permission.WRITE_MEDIA_STORAGE" />
> 然后调研了下,都需要验证下:
1.Android 7.0 files_paths.xml与FileProvider,文件共享;(已经适配)
2.Android 8.0系统,安装Apk权限,添加未知应用的权限:应用内升级
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />;
3.Android8.0通知栏问题;(已经适配); 8.0 App Logo圆形图标;
4.Android9.0 <!--android 9.0上使用前台服务,需要添加权限-->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.WRITE_MEDIA_STORAGE" />
<!--解决android9.0上使用ProtocolVersion抛异常的bug, Volley --> org.apache.http.HttpStatus
<uses-library android:name="org.apache.http.legacy" android:required="false" />
startForeground requires android.permission.FOREGROUND_SERVICE
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
5.升级安卓P之后,隐式广播将会被全面禁止,在AndroidManifest中注册的Receiver将不能够生效, 并在应用中进行动态注册
非全屏透明Activity禁用设置orientation
非全屏透明页面不允许设置方向,否则会抛Caused by: java.lang.IllegalStateException: Only fullscreen opaque activities can request orientation异常,解决方案:android:windowIsTranslucent设置为false。
6.在 Android 9.0 版本中,谷歌加入了非 SDK 接口使用限制,无论是通过调用、反射还是JNI等方式,开发者都无法对非 SDK 接口进行访问,此接口的滥用将会带来严重的系统兼容性问题。 在开发过程中,开发者如果调用了非 SDK 接口,会导致应用出现crash,无法启动;或在运行过程中出现崩溃、闪退等现象;也可能导致应用功能不可用等严重兼容性问题,其影响范围波及所有调用此接口的应用。
非SDK接口的类型,分为三类:
(1)Light grey list: targetSDK>=P时,警告;
(2)Dark grey list: targetSDK<P时,警告;>=p时,不允许调用;
(3)Black list:三方应用不允许调用。
7.如果该应用适配了8.0,则应用只能使用TYPE_APPLICATION_OVERLAY窗口类型来创建悬浮窗。(其它窗口类型在8.0已经被废弃掉)
TYPE_PHONE
TYPE_PRIORITY_PHONE
TYPE_SYSTEM_ALERT
TYPE_SYSTEM_OVERLAY
TYPE_SYSTEM_ERROR
TYPE_TOAST
---------------------
mApkFile=/storage/emulated/0/release.apk
com.baidu.carlife was not granted this permission: android.permission.WRITE_SETTINGS.
android.provider.Settings.isCallingPackageAllowedToPerformAppOpsProtectedOperation
Android系统下载管理DownloadManager功能
下载APK后打开APK,在安装时的报错 android.os.FileUriExposedException:exposed beyond app through Intent.getData()- https://blog.csdn.net/biickvtkd/article/details/78803481
下载安装APK(兼容Android7.0)- https://www.jianshu.com/p/577816c3ce93
Android 下载并安装apk,兼容7.0和8.0- https://blog.csdn.net/qq_33601179/article/details/85198222
Android 8.0 解决不能自动安装APK问题(完美适配)- https://blog.csdn.net/zzz2017/article/details/81172229
关于 Android 7.0 适配中 FileProvider 部分的总结- https://blog.csdn.net/c_furong/article/details/80362102
<!--Android8.0允许安装未知来源权限(更新版本安装APK)-->
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
<?xml version="1.0" encoding="utf-8"?>
<resources>
<paths>
<external-path path="" name="camera_photos" />
<!--<external-path path="." name="external_storage_root"/>-->
<external-path name="external_files" path="."/>
</paths>
</resources>
<!--安卓7.0文件权限-->
<provider
android:name="carlife.support.v4.content.FileProvider"
android:authorities="com.baidu.carlife.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<!-- 元数据 -->
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_provider" />
</provider>
<!--Android8.0允许安装未知来源权限(更新版本安装APK)-->
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
/**
* 安装最新的apk包
*/
public void installNewApk2(Activity activity) {
LogUtil.e("desaco", "mApkFile=" + (Environment.getExternalStorageDirectory().toString() + "/carlife-release.apk"));
mApkFile = new File(Environment.getExternalStorageDirectory().toString() + "/carlife-release.apk");
if (mApkFile == null) {
return;
}
// 安装应用
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
Uri contentUri = FileProvider.getUriForFile(activity, "com.baidu.carlife.fileprovider", mApkFile );
intent.setDataAndType(contentUri,"application/vnd.android.package-archive");
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
} else {
intent.setDataAndType(Uri.fromFile(mApkFile), "application/vnd.android.package-archive");
}
activity.startActivity(intent);
}
<?xml version="1.0" encoding="utf-8"?>
<resources>
<paths>
<!-- Context.getFilesDir() + "/path/" -->
<files-path
name="my_files"
path="mazaiting/"/>
<!-- Context.getCacheDir() + "/path/" -->
<cache-path
name="my_cache"
path="mazaiting/"/>
<!-- Context.getExternalFilesDir(null) + "/path/" -->
<external-files-path
name="external-files-path"
path="mazaiting/"/>
<!-- Context.getExternalCacheDir() + "/path/" -->
<external-cache-path
name="name"
path="mazaiting/" />
<!-- Environment.getExternalStorageDirectory() + "/path/" -->
<external-path
name="my_external_path"
path="mazaiting/"/>
<!-- Environment.getExternalStorageDirectory() + "/path/" -->
<external-path
name="files_root"
path="Android/data/<包名>/"/>
<!-- path设置为'.'时代表整个存储卡 Environment.getExternalStorageDirectory() + "/path/" -->
<external-path
name="external_storage_root"
path="."/>
</paths>
</resources>
适配Android7.0应用内更新App和Android8.0安装未知来源的App
Android App兼容8.0和9.0- https://blog.csdn.net/wxz1179503422/article/details/83031724
AndroidP新特性适配处理- https://www.jianshu.com/p/f125ccb72da0
安卓P兼容Demo- https://github.com/YangHaoyi/AndroidPDemo
Android8.0适配那点事(一)- https://www.cnblogs.com/lrcaoxiang/p/9266944.html
Android 8.0 适配- https://www.jianshu.com/p/d9f5b0801c6b
-- Notification
IMPORTANCE_MIN 开启通知,不会弹出,但没有提示音,状态栏中无显示
IMPORTANCE_LOW 开启通知,不会弹出,不发出提示音,状态栏中显示
IMPORTANCE_DEFAULT 开启通知,不会弹出,发出提示音,状态栏中显示
IMPORTANCE_HIGH 开启通知,会弹出,发出提示音,状态栏中显示
-- 在Android 8.0中系统不允许后台应用创建后台服务。因此,Android 8.0引入了一种全新的方法,即Context.startForegroundService(),以在前台启动新服务。在系统创建服务后,应用有五秒的时间来调用该服务的startForeground()方法以显示新服务的用户可见通知,如果应用在此时间限制内未调用startForeground(),则系统将停止服务并声明此应用为ANR
if (Build.VERSION_CODES.O <= Build.VERSION.SDK_INT) {
getActivity().startForegroundService(intent);
}
else {
getActivity().startService(intent);
}
-- 广播限制,Android 7.0(API级别25)对广播施加了一些限制,而Android 8.0让这些限制更为严格。
针对 Android 8.0的应用无法继续在其清单中为隐式广播注册广播接收器
应用可以继续在它们的清单中注册显式广播
应用可以在运行时使用Context.registerReceiver()为任意广播(不管是隐式还是显式)注册接收器
需要签名权限的广播不受此限制所限,因为这些广播只会发送到使用相同证书签名的应用,而不是发送到设备上的所有应用
在许多情况下,之前注册隐式广播的应用使用JobScheduler作业可以获得类似的功能
注意,还有很多隐式广播当前不受此限制所限。 应用可以继续在其清单中为这些广播注册接收器,不管应用针对哪个API级别。
使用Android7.0,在AndroidManifest中注册隐式广播的支持已经被删除了。当app在Android O上运行时,所有的在manifest中注册的隐式广播将会停止工作。
最常见的不受影响的是ACTION_BOOT_COMPLETED,ACTION_HEADSET_PLUG,ACTION_CONNECTION_STATE_CHANGED用于蓝牙状态更改.
JobScheduler很好的与Android系统和Doze模式相适应,他允许基于你定义的条件执行任务。 JobScheduler只支持Android棉花糖以及以上的系统,如果你的app的minSdkVersion小于21,则有类似API的库提供向后兼容,正式推荐的是FirebaseJobDispatcher。
摆脱Manifest文件中的所有隐式广播,使用JobScheduler,FirebaseJobDispatcher或替代方案替代您的任务,如果不支持你的广播,那么请在activity、fragment、service中注册你的广播。
能动态注册,就不静态注册;
如果一定要静态注册, 发送的时候指定包名,即发送显式广播;
如果要接收系统广播,而对应的广播在Android8.0中无法被接收,那么只能暂时把App的targetSdkVersion改为25或以下,但这招已经不顶用了,工信部要求targetSDK必须26以上;
发送广播的时候携带intent.addFlags(0x01000000); 即能让广播突破隐式广播限制。