Android 适配
1. 适配 targetSdkVersion=28
1.1. 适配http
Google针对Android P的应用程序,将要求默认使用加密连接,这意味着 Android P 将禁止 App 使用所有未加密的连接,因此运行 Android P 系统的安卓设备无论是接收或者发送流量
针对这个问题,有以下三种解决方法:
1.APP改用https请求
2.更改网络安全配置:
1.在res文件夹下创建一个xml文件夹,然后创建一个network_security_config.xml文件,文件内容如下:
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config cleartextTrafficPermitted="true">
<!--bugly-->
<base includeSubdomains="true">android.bugly.qq.com</base>
//其他域名请对应上面bugly的配置
</base-config>
</network-security-config>
2.接着,在AndroidManifest.xml文件下的application标签增加以下属性:
<application
android:networkSecurityConfig="@xml/network_security_config"
1.2. 适配HttpClient
自 Android 6 发布,就移除了对 Apache HTTP 客户端的支持,而推荐改用 HttpURLConnection 类
Android 9默认 Apache HTTP API 不可用,要继续使用 Apache HTTP 客户端,以 Android 9 及更高版本为目标的应用可以向其 AndroidManifest.xml 添加以下内容:
<application
...
<uses-library android:name="org.apache.http.legacy" android:required="false"/>
1.3. 关于反射调用非SDK接口
Android 9 引入了针对非 SDK 接口的使用限制,无论是直接使用还是
通过反射或 JNI 间接使用。 无论应用是引用非 SDK 接口还是尝试使用
反射或 JNI 获取其句柄,均适用这些限制。
需要使用工具做检测,但是没有wind版本//TODO
1.4. 取不到值Build.SERIAL
Build.SERIAL 始终设置为 “UNKNOWN” 以保护用户的隐私
1.5. 取消了大部分静态广播
取消大部分静态注册广播
<receiver
android:name=".TestReceiver"
android:enabled="true">
<intent-filter>
<action android:name="com.test.example.testreceiver.action"></action>
</intent-filter>
</receiver>
//上面在清单文件里注册的广播无法通过下面的方法接受到
Intent intent = new Intent();
intent.setAction("com.test.example.testreceiver.action");
sendBroadcast(intent);
如果要使静态广播生效,需要明确指定广播的接受对象即(需要签名权限的广播不受此限制所限),使用:
intent.setComponent(new ComponentName("包名",
"广播路径"));
1.5. 后台服务限制
当应用处于后台时:
1.在后台运行的服务在几分钟内会被stop掉。在这段时间内,应用仍可以创建和使用服务。
2.在应用处于后台几分钟后,应用将不能再通过startService创建后台服务,如果创建则抛出异常
用到service的地方且长期运行的需要适配代码如下:
//启动服务
if (Build.VERSION_CODES.O <= Build.VERSION.SDK_INT) {
getActivity().startForegroundService(intent);
}
else {
getActivity().startService(intent);
}
/**
* 8.0开启前台服务 记得5秒钟内调用showStartForeground
* (举个例子)
*/
@RequiresApi(api = Build.VERSION_CODES.O)
public void showStartForeground(Service service, String title, String content, int smallIcon, int notificationId) {
NotificationManager mNotificationManager = (NotificationManager) service.getSystemService(Context.NOTIFICATION_SERVICE);
// 通知渠道的id
String CHANNEL_ID = "down_new_apk";
// 用户可以看到的通知渠道的名字.
CharSequence name = "下载更新";
//用户可以看到的通知渠道的描述
String description = "下载最新的版本";
int importance = NotificationManager.IMPORTANCE_HIGH;
NotificationChannel mChannel = new NotificationChannel(CHANNEL_ID, name, importance);
//配置通知渠道的属性
mChannel.setDescription(description);
//设置通知出现时的闪灯(如果 android 设备支持的话)
mChannel.enableLights(false);
//设置通知出现时的震动(如果 android 设备支持的话)
mChannel.enableVibration(false);
//mChannel.setVibrationPattern(new long[]{100, 200, 300, 400, 500, 400, 300, 200, 400});
//最后在notificationmanager中创建该通知渠道 //
mNotificationManager.createNotificationChannel(mChannel);
// 通知渠道的id
Notification notification = new Notification.Builder(service)
.setContentTitle(title).setContentText(content)
.setSmallIcon(smallIcon)
.setChannelId(CHANNEL_ID)
.setOngoing(true)
.setAutoCancel(false)
.build();
service.startForeground(notificationId, notification);
}
/**
* 8.0关闭前台服务
* @param service
* @param id
*/
public void hideStartForeground(Service service) {
service.stopForeground(true);
}
2. 适配 Android Q
2.1. 应用存储空间限制(应用自己的外部存储空间也是私有,同内部存储空间一样,的其他应用无法读取)
外部存储设备中存储文件的最佳位置是 Context.getExternalFilesDir()
这个路径是不需要任何权限是私有的
应用通过File接口只能读写应用自己沙箱目录的文件,无法直接
读写沙箱外文件,应用需要使用安卓提供的接口读写沙箱外的文件
适配点:
1.分享图片给第三方应用的功能(强制与targetSdkVersion 无关)
2.读取非私有文件下的其他文件(强制与targetSdkVersion 无关)
3.如果targetSdkVersion < Q应用可以访问在 MediaStore 集合中存储的所有文件,否则只能访问自己创建的文件如果卸载重装也不能访问这些文件
2.2.禁止应用读取deviceid,Wifi Mac地址随机化(强制与targetSdkVersion 无关)
适配点:获取唯一标识的地方
2.3.不允许后台弹页面(强制与targetSdkVersion 无关)
适配点:锁屏广告通过服务弹activity的功能
2.4.新开发的应用,2019-8-1以后上架谷歌Play要求应用的native代码需要提供64位的版本更新的应用,2019-11-1以后上架谷歌play要求应用的native代码需要提供64位的版本
2.5.新开发的应用,2019-8-1以后上架谷歌Play要求应用的TargetSdkVersion>=28 更新的应用,2019-11-1以后上架谷歌play要求应用的TargetSdkVersion>=28
2.6.应用的targetSdkVersion<23,应用首次启动会弹框警
2.7.折叠屏
适配点:提供统一的折叠屏方案和适配接口