之前項目targetSdk
基于Android
6.0即API版本號為23進行開發(fā)漓骚,現(xiàn)在需要升級到9.0蝌衔,期間跨越了好幾個版本需要進行適配,那沒有辦法蝌蹂,動手開干噩斟,現(xiàn)在將適配所需要注意的點記錄下來。
7.0適配
文件共享適配
1.首先需要在AndroidManifest.xml
文件中孤个,添加provider
節(jié)點
<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/file_paths" />
</provider>
2.然后要在res
目錄文件夾下創(chuàng)建xml
文件夾剃允,并且創(chuàng)建file_paths.xml
文件
<?xml version="1.0" encoding="utf-8"?>
<!-- 7.0文件共享配置 @author Steven -->
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="my_download" path="download"/>
<!-- path字段在存儲文件時使用到,比如拍照后存儲的路徑,需要設(shè)置為改路徑斥废,這個是目錄名 -->
<external-path name="my_feedback" path="feedback"/>
</paths>
在paths節(jié)點內(nèi)部支持以下幾個子節(jié)點椒楣,分別為:
-
<root-path/>
代表設(shè)備的根目錄new File("/")
-
<files-path/>
代表context.getFilesDir()
-
<cache-path/>
代表context.getCacheDir()
-
<external-path/>
代表Environment.getExternalStorageDirectory()
-
<external-files-path>
代表context.getExternalFilesDirs()
-
<external-cache-path>
代表getExternalCacheDirs()
每個節(jié)點都支持兩個屬性:
- name
- path
path即為代表目錄下的子目錄,比如:
<external-path
name="external"
path="download" />
代表的目錄即為:Environment.getExternalStorageDirectory()/download
牡肉,其他同理捧灰。
8.0適配
Android8.0通知欄適配
Android8.0的通知欄,如果你的targetSdk在26及其以上统锤,沒有進行適配的話毛俏,即使你的應(yīng)用開啟了通知,通知欄也不會顯示
具體設(shè)置為在你項目Application
中添加以下代碼在onCreate()
方法中進行調(diào)用
private void initMessageChannel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
String channelId = "channelId";
String channelName = "channelName";
String description = "description";
// 通知的級別
int importance = NotificationManager.IMPORTANCE_HIGH;
NotificationChannel channel = new NotificationChannel(channelId, channelName, importance);
channel.setDescription(description);
NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
assert notificationManager != null;
notificationManager.createNotificationChannel(channel);
}
}
通知的級別一共有四類饲窿,你可以根據(jù)你具體的需求進行設(shè)置煌寇,可以設(shè)置多個級別的通知,默認級別即使你不設(shè)置也會存在免绿。
-
IMPORTANCE_MIN
開啟通知唧席,不會彈出,但沒有提示音嘲驾,狀態(tài)欄中無顯示 -
IMPORTANCE_LOW
開啟通知淌哟,不會彈出,不發(fā)出提示音辽故,狀態(tài)欄中顯示 -
IMPORTANCE_DEFAULT
開啟通知徒仓,不會彈出,發(fā)出提示音誊垢,狀態(tài)欄中顯示 -
IMPORTANCE_HIGH
開啟通知掉弛,會彈出,發(fā)出提示音喂走,狀態(tài)欄中顯示
8.0不能自動安裝APK問題適配
在Android8.0之后殃饿,未知應(yīng)用安裝權(quán)限默認關(guān)閉,且權(quán)限入口隱藏芋肠。
1.必須要在清單文件中添加權(quán)限
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/>
2.判斷8.0以上系統(tǒng)是否有安裝應(yīng)用權(quán)限乎芳,并且進行適配
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
// 判斷是否有安裝的權(quán)限
// 這里需要注意:targetSdkVersion是26以上才能獲取正確的canRequestPackageInstalls,否則就一直返回false
boolean hasInstallPermission = context.getPackageManager().canRequestPackageInstalls();
if (!hasInstallPermission) {
Intent intent = new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
((Activity)context).startActivityForResult(intent,REQUEST_CODE_APP_INSTALL);
return;
}
}else{
install(context,filePath)
}
// 安裝APK的方法
public static void install(Context context, String filePath) {
try {
File file = new File(filePath);
Intent intent = new Intent(Intent.ACTION_VIEW);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
Uri apkUri = FileProvider.getUriForFile(context, "com.jinr.core.provider", file);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.setDataAndType(apkUri, "application/vnd.android.package-archive");
} else {
intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
}
context.startActivity(intent);
} catch (Exception e) {
e.printStackTrace();
}
}
8.0系統(tǒng)彈框(懸浮框)不生效問題適配
8.0中應(yīng)用只能使用TYPE_APPLICATION_OVERLAY
窗口類型來創(chuàng)建懸浮窗帖池,其它窗口類型在8.0已經(jīng)被廢棄掉奈惑。
如果應(yīng)用中存在以下幾種窗口類型來創(chuàng)建懸浮框,都需要進行適配睡汹,因為8.0已經(jīng)不支持了肴甸。
TYPE_PHONE
TYPE_PRIORITY_PHONE
TYPE_SYSTEM_ALERT
TYPE_SYSTEM_OVERLAY
TYPE_SYSTEM_ERROR
TYPE_TOAST
在用到這些類型的懸浮框的時候,需要加上版本判斷
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
window.setType(WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY);
}else {
window.setType(WindowManager.LayoutParams.TYPE_TOAST);
}
8.0靜態(tài)廣播無法使用適配
Android8.0中囚巴,Google已經(jīng)明確提出應(yīng)用無法使用其清單文件注冊的大部分隱式廣播原在,即我們常說的靜態(tài)廣播友扰。
所以最好所用到的廣播,都進行動態(tài)注冊庶柿。
9.0適配
9.0禁止網(wǎng)絡(luò)明文傳輸適配
Android9.0禁止網(wǎng)絡(luò)明文傳輸焕檬,需要進行適配
1.在res
目錄文件夾下創(chuàng)建xml
文件夾,并且創(chuàng)建network_security_config.xml
文件
<!-- Android 9.0 系統(tǒng)不允許進行明文網(wǎng)絡(luò)傳輸需要添加的配置 @author Steven -->
<network-security-config>
<base-config cleartextTrafficPermitted="true" />
</network-security-config>
***2.在AndroidManifest.xml
文件中,application節(jié)點下添加以下代碼
<?xml version="1.0" encoding="utf-8"?>
<manifest ...>
<application
...
android:networkSecurityConfig="@xml/network_security_config"
...>
...
</application>
</manifest>
該種方法既可以支持7.0抓包澳泵,也可以支持9.0明文請求
當然如果不需要抓包的功能实愚,還有一種簡單的方法進行配置,直接在清單文件中加入android:usesCleartextTraffic="true"
屬性即可
<?xml version="1.0" encoding="utf-8"?>
<manifest ...>
<application
...
android:usesCleartextTraffic="true"
...>
...
</application>
</manifest>
9.0 Apache Http請求出錯適配
項目中如果使用Volley的話兔辅,在android 9.0會出現(xiàn)異常腊敲,提示ProtocolVersion的異常、
在AndroidManifest.xml
文件下的application
節(jié)點下添加以下代碼即可
<?xml version="1.0" encoding="utf-8"?>
<manifest ...>
<application
...>
<uses-library android:name="org.apache.http.legacy" android:required="false"/>
...
</application>
</manifest>
9.0使用前臺服務(wù)適配
在Android 9.0上使用前臺服務(wù)维苔,需要添加權(quán)限
<?xml version="1.0" encoding="utf-8"?>
<manifest ...>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
</manifest>
總結(jié)
當然碰辅,這里只是列出來部分常見的適配,具體碰到的別的問題介时,還得另外進行適配没宾。以后再遇到再進行補充吧。