Android?6
1、運(yùn)行時(shí)權(quán)限
android6.0以前,我們把a(bǔ)pp需要用到的權(quán)限全部羅列在Manifest清單文件中。安裝app時(shí)android系統(tǒng)會(huì)詢(xún)問(wèn)用戶(hù)是否授予這些權(quán)限,拒絕后則無(wú)法安裝app。如果授予,則安裝app,之后無(wú)法修改授予狀態(tài)。
android6.0將權(quán)限分為普通權(quán)限(不涉及用戶(hù)隱私和安全)和危險(xiǎn)權(quán)限(設(shè)計(jì)用戶(hù)隱私和安全)。普通權(quán)限和andorid6.0之前一樣,在Manifest清單文件中申請(qǐng)即可。危險(xiǎn)權(quán)限需要在使用時(shí)動(dòng)態(tài)申請(qǐng),由用戶(hù)決定是否授予。
危險(xiǎn)權(quán)限分組:

2、HttpClient的移除
自Android6.0起,HttpClient系列代碼從SDK中剔除,推薦使用HttpURLConnection。
Android?7
1、應(yīng)用間共享文件
對(duì)于面向?Android?7.0?的應(yīng)用,Android?框架執(zhí)行的?StrictMode?API?政策禁止在您的應(yīng)用外部公開(kāi)?file://?URI。如果一項(xiàng)包含文件?URI?的?intent?離開(kāi)您的應(yīng)用,則應(yīng)用出現(xiàn)故障,并出現(xiàn)?FileUriExposedException?異常。
要在應(yīng)用間共享文件,您應(yīng)發(fā)送一項(xiàng)?content://?URI,并授予?URI?臨時(shí)訪(fǎng)問(wèn)權(quán)限。進(jìn)行此授權(quán)的最簡(jiǎn)單方式是使用?FileProvider?類(lèi)。
(1)在A(yíng)ndroidManifest.xml清單文件中注冊(cè)provider
<manifest>
?...
?<application>
?...
?<provider
?android:name="androidx.core.content.FileProvider"
?android:authorities="com.demo.fileprovider"
?android:exported="false"
?android:grantUriPermissions="true">
?<meta-data
?android:name="android.support.FILE_PROVIDER_PATHS"
?android:resource="@xml/paths"?/>
?</provider>
?...
?</application>
</manifest>
(2)res/xml中定義對(duì)外暴露的文件夾路徑:
<?xml?version="1.0"?encoding="utf-8"?>
<paths>
?<external-path
?name="external_storage_root"
?path="."?/>
?<files-path
?name="files-path"
?path="."?/>
?<cache-path
?name="cache-path"
?path="."?/>
?<external-files-path
?name="external_file_path"
?path="."?/>
?<external-cache-path
?name="external_cache_path"
?path="."?/>
?<root-path
?name="root-path"
?path=""?/>
</paths>
name:一個(gè)引用字符串。
path:文件夾“相對(duì)路徑”,完整路徑取決于當(dāng)前的標(biāo)簽類(lèi)型。
?代表Environment.getExternalStorageDirectory()
?代表context.getFilesDir()
?代表context.getCacheDir()
代表context.getExternalFilesDirs()
代表getExternalCacheDirs()
?代表設(shè)備的根目錄new?File("/");
7.0之前跳轉(zhuǎn)到系統(tǒng)相機(jī)拍照的代碼,需要提前設(shè)定好保存圖片的uri,跳轉(zhuǎn)到相機(jī)應(yīng)用
String?cachePath?=?getApplicationContext().getExternalCacheDir().getPath();
File?picFile?=?new?File(cachePath,?"test.jpg");
Uri?picUri?=?Uri.fromFile(picFile);
Intent?intent?=?new?Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT,?picUri);
startActivityForResult(intent,?100);
7.0之后:
String?cachePath?=?getApplicationContext().getExternalCacheDir().getPath();
File?picFile?=?new?File(cachePath,?"test.jpg");
Uri?uriForFile?=?null;
?if?(Build.VERSION.SDK_INT?>=?24)?{
?uriForFile?=?FileProvider.getUriForFile(MainActivity.this,?"com.demo.fileprovider",?picFile);
?}?else?{
?uriForFile?=?Uri.fromFile(picFile);
?}
Intent?intent?=?new?Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT,?uriForFile);
startActivityForResult(intent,?100);
將Uri.fromFile(file)換成了FileProvider.getUriForFile,這里getUriForFile方法的第二個(gè)參數(shù),就是第一步的provider的authorities
2、廣播
Android?7.0?移除了三項(xiàng)隱式廣播。
面向?Android?7.0?開(kāi)發(fā)的應(yīng)用不會(huì)收到?CONNECTIVITY_ACTION?廣播,即使它們已有清單條目來(lái)請(qǐng)求接受這些事件的通知。在主線(xiàn)程中通過(guò)Context.registerReceiver()動(dòng)態(tài)注冊(cè)了CONNECTIVITY_ACTION廣播,該應(yīng)用程序仍然可以接收到該廣播。
應(yīng)用無(wú)法發(fā)送或接收?ACTION_NEW_PICTURE?或?ACTION_NEW_VIDEO?廣播。此項(xiàng)優(yōu)化會(huì)影響所有應(yīng)用,而不僅僅是面向?Android?7.0?的應(yīng)用。
Android?8
1、通知渠道id
Android?8.0?引入了通知渠道,其允許您為要顯示的每種通知類(lèi)型創(chuàng)建用戶(hù)可自定義的渠道。用戶(hù)界面將通知渠道稱(chēng)之為通知類(lèi)別。targeSdk升級(jí)到26之后,所有的通知的實(shí)現(xiàn)都需要提供通知渠道,如果不提供通知渠道的話(huà),所有通知在8.0系統(tǒng)上面都不能正常展示。
//通知渠道id
?val?channelId?=?"channelId"
?val?notificationManager?=?getSystemService(Context.NOTIFICATION_SERVICE)?as?NotificationManager
?if?(Build.VERSION.SDK_INT?>=?Build.VERSION_CODES.O)?{
?//通知渠道名稱(chēng)
?val?channelName?=?"channelName"
?//通知渠道重要程度
?val?importance?=?NotificationManager.IMPORTANCE_HIGH
?//構(gòu)建通知渠道
?val?channel?=?NotificationChannel(channelId,?channelName,?importance)
?//設(shè)置通知渠道描述
?channel.description?=?""
?//向系統(tǒng)注冊(cè)通知渠道,注冊(cè)后則不能修改重要性以及其他通知行為,但可以刪除
?notificationManager.createNotificationChannel(channel)
?}
?val?notification?=?NotificationCompat.Builder(this,?"channelId")
?.setContentTitle("標(biāo)題")
?.setContentText("消息內(nèi)容")
?.setSmallIcon(R.drawable.ic_launcher_background)
?.setAutoCancel(true)//點(diǎn)擊自動(dòng)消失
?.build()
?//通知id,每個(gè)通知都應(yīng)該不同否則會(huì)覆蓋
?val?notifyId?=?1
?notificationManager.notify(notifyId,?notification)
2、后臺(tái)執(zhí)行限制
如果針對(duì)?Android?8.0?的應(yīng)用嘗試在不允許其創(chuàng)建后臺(tái)服務(wù)的情況下使用?startService()?函數(shù),則該函數(shù)將引發(fā)一個(gè)?IllegalStateException。
新的?Context.startForegroundService()?函數(shù)將啟動(dòng)一個(gè)前臺(tái)服務(wù)?,F(xiàn)在,即使應(yīng)用在后臺(tái)運(yùn)行,系統(tǒng)也允許其調(diào)用?Context.startForegroundService()。不過(guò),應(yīng)用必須在創(chuàng)建服務(wù)后的五秒內(nèi)調(diào)用該服務(wù)的?startForeground()?函數(shù)。
3、允許安裝未知來(lái)源應(yīng)用
8.0?的應(yīng)用需要在?AndroidManifest.xml?中聲明?REQUEST_INSTALL_PACKAGES?權(quán)限,否則將無(wú)法進(jìn)行應(yīng)用內(nèi)升級(jí)。
<uses-permission?android:name="android.permission.REQUEST_INSTALL_PACKAGES"?/>
4、隱式廣播的限制
我們自己定義的廣播隱式調(diào)用不能接收,顯式Intent可以接收?;蛘邉?dòng)態(tài)注冊(cè),然后隱式調(diào)用可以接收。
如果要接收系統(tǒng)廣播只能動(dòng)態(tài)注冊(cè)。
5、圖標(biāo)適配
在圖標(biāo)適配中有兩個(gè)部分,前景圖和背景圖,所以設(shè)計(jì)的時(shí)候需要提供前景圖和背景圖兩個(gè)圖,這樣在不同的廠(chǎng)商無(wú)論圖標(biāo)的背景怎么換都是對(duì)圖標(biāo)的背景圖進(jìn)行切割,而前景圖是不會(huì)變的。
6、權(quán)限
之前對(duì)于隱私權(quán)限只要申請(qǐng)一個(gè)就會(huì)將其在的權(quán)限組全部通過(guò),android?8.0以后申請(qǐng)單個(gè)只給單個(gè);
Android?9
1、在?Android?9?中,不能從非?Activity?環(huán)境中啟動(dòng)?Activity,除非您傳遞?Intent?標(biāo)志?FLAG_ACTIVITY_NEW_TASK。?如果您嘗試在不傳遞此標(biāo)志的情況下啟動(dòng)?Activity,則該?Activity?不會(huì)啟動(dòng),系統(tǒng)會(huì)在日志中輸出一則消息。
2、前臺(tái)服務(wù):針對(duì)?Android?9?或更高版本并使用前臺(tái)服務(wù)的應(yīng)用必須請(qǐng)求?FOREGROUND_SERVICE?權(quán)限。?這是普通權(quán)限,因此,系統(tǒng)會(huì)自動(dòng)為請(qǐng)求權(quán)限的應(yīng)用授予此權(quán)限。
3、默認(rèn)情況下啟用網(wǎng)絡(luò)傳輸層安全協(xié)議?(TLS):如果應(yīng)用以?Android?9?或更高版本為目標(biāo)平臺(tái),則默認(rèn)情況下?isCleartextTrafficPermitted()?函數(shù)返回?false。?如果您的應(yīng)用需要為特定域名啟用明文,您必須在應(yīng)用的網(wǎng)絡(luò)安全性配置中針對(duì)這些域名將?cleartextTrafficPermitted?顯式設(shè)置為?true。
在?res?目錄下新建xml文件夾,添加network_security_config.xml文件:
<?xml?version="1.0"?encoding="utf-8"?>
<network-security-config>
?<base-config?cleartextTrafficPermitted="true">
?<trust-anchors>
?<certificates?src="system"?/>
?<certificates?src="user"?/>
?</trust-anchors>
?</base-config>
</network-security-config>
AndroidManifest.xml中的application添加:
<?xml?version="1.0"?encoding="utf-8"?>
<manifest?...?>
?<application?android:networkSecurityConfig="@xml/network_security_config">
?...
?</application>
</manifest>
4、對(duì)非?SDK?接口的限制:現(xiàn)已禁止訪(fǎng)問(wèn)特定的非?SDK?接口,無(wú)論是直接訪(fǎng)問(wèn),還是通過(guò)?JNI?或反射進(jìn)行間接訪(fǎng)問(wèn)。嘗試訪(fǎng)問(wèn)受限制的接口時(shí),會(huì)生成?NoSuchFieldException?和?NoSuchMethodException?之類(lèi)的錯(cuò)誤。
5、為改善?Android?9?中的應(yīng)用穩(wěn)定性和數(shù)據(jù)完整性,應(yīng)用無(wú)法再讓多個(gè)進(jìn)程共用同一?WebView?數(shù)據(jù)目錄。?此類(lèi)數(shù)據(jù)目錄一般存儲(chǔ)?Cookie、HTTP?緩存以及其他與網(wǎng)絡(luò)瀏覽有關(guān)的持久性和臨時(shí)性存儲(chǔ)。
如果開(kāi)發(fā)者需要在多進(jìn)程中使用?WebView,則必須先調(diào)用?WebView.setDataDirectorySuffix()?方法為每個(gè)進(jìn)程設(shè)置用于存儲(chǔ)?WebView?數(shù)據(jù)的目錄。若多進(jìn)程?WebView?之間需要共享數(shù)據(jù),開(kāi)發(fā)者需自己通過(guò)?IPC?的方式實(shí)現(xiàn)。
此外,若開(kāi)發(fā)者只想在一個(gè)進(jìn)程中使用?WebView,并且希望嚴(yán)格執(zhí)行這個(gè)規(guī)則,可以通過(guò)在其他進(jìn)程中調(diào)用?WebView.disableWebView()?方法,這樣其他進(jìn)程創(chuàng)建?WebView?實(shí)例就會(huì)拋出異常。
6、在?Android?9?中,Build.SERIAL?始終設(shè)置為?"UNKNOWN"?以保護(hù)用戶(hù)的隱私。
如果您的應(yīng)用需要訪(fǎng)問(wèn)設(shè)備的硬件序列號(hào),您應(yīng)改為請(qǐng)求?READ_PHONE_STATE?權(quán)限,然后調(diào)用?getSerial()。
Android10
1、分區(qū)存儲(chǔ):
分區(qū)存儲(chǔ)將外部存儲(chǔ)分成兩部分:
(1)App-specific?directory?(沙盒目錄)
APP只能在Context.getExternalFilesDir()目錄下通過(guò)File的方式創(chuàng)建文件,APP卸載的時(shí)候,這個(gè)目錄下的文件會(huì)被刪除;無(wú)法通過(guò)File的方式在其他路徑創(chuàng)建文件。
(2)Public?Directory?公共目錄?
公共目錄包括:多媒體公共目錄(Photos,?Images,?Videos,?Audio)和下載文件目錄(Downloads)。
APP可以通過(guò)MediaStore或者SAF(System?Access?Framework)的方式訪(fǎng)問(wèn)其中的文件。APP卸載后,文件不會(huì)被刪除。
Android?Q以上移除了WRITE_EXTERNAL_STORAGE權(quán)限,應(yīng)用不需要這個(gè)權(quán)限就可以向沙盒內(nèi)存儲(chǔ)文件,也可以通過(guò)媒體數(shù)據(jù)庫(kù)的方式保存媒體數(shù)據(jù)至特定位置。
App卸載后,對(duì)應(yīng)的沙盒目錄也會(huì)被刪除,如果APP想要在卸載時(shí)保留沙盒目錄下的數(shù)據(jù),要在A(yíng)ndroidManifest.xml中聲明android:hasFragileUserData="true",這樣在?APP卸載時(shí)就會(huì)有彈出框提示用戶(hù)是否保留應(yīng)用數(shù)據(jù)。
2、后臺(tái)運(yùn)行時(shí)訪(fǎng)問(wèn)設(shè)備位置信息需要權(quán)限
Android?10?引入了?ACCESS_BACKGROUND_LOCATION?權(quán)限(危險(xiǎn)權(quán)限)。
該權(quán)限允許應(yīng)用程序在后臺(tái)訪(fǎng)問(wèn)位置。如果請(qǐng)求此權(quán)限,則還必須請(qǐng)求ACCESS_FINE_LOCATION?或?ACCESS_COARSE_LOCATION權(quán)限。只請(qǐng)求此權(quán)限無(wú)效果。
Android?10中必須具有?ACCESS_FINE_LOCATION?權(quán)限才能使用的類(lèi)和方法:
電話(huà)
TelephonyManager
getCellLocation()
getAllCellInfo()
requestNetworkScan()
requestCellInfoUpdate()
getAvailableNetworks()
getServiceState()
TelephonyScanManager
requestNetworkScan()
TelephonyScanManager.NetworkScanCallback
onResults()
PhoneStateListener
onCellLocationChanged()
onCellInfoChanged()
onServiceStateChanged()
WLAN
WifiManager
startScan()
getScanResults()
getConnectionInfo()
getConfiguredNetworks()
WifiAwareManager
WifiP2pManager
WifiRttManager
藍(lán)牙
BluetoothAdapter
startDiscovery()
startLeScan()
startScan()
BluetoothAdapter.LeScanCallback
BluetoothLeScanner
3、后臺(tái)啟動(dòng)?Activity?的限制
應(yīng)用處于后臺(tái)時(shí),無(wú)法啟動(dòng)Activity。
4、深色主題
(1)手動(dòng)適配---資源替換
res?下新建?values-night目錄,創(chuàng)建對(duì)應(yīng)的colors.xml文件。
(2)自動(dòng)適配---Force?Dark
應(yīng)用必須選擇啟用?Force?Dark,方法是在其主題背景中設(shè)置?android:forceDarkAllowed="true"。此屬性會(huì)在所有系統(tǒng)及?AndroidX?提供的淺色主題背景(例如?Theme.Material.Light)上設(shè)置。
Force?Dark需要注意幾點(diǎn):
如果使用的是?DayNight?或?Dark?Theme?主題,則設(shè)置forceDarkAllowed?不生效。
如果有需要排除適配的部分,可以在對(duì)應(yīng)的View上設(shè)置forceDarkAllowed為false。
5、標(biāo)識(shí)符和數(shù)據(jù)
對(duì)不可重置的設(shè)備標(biāo)識(shí)符實(shí)施了限制
受影響的方法包括:
Build
getSerial()
TelephonyManager
getImei()
getDeviceId()
getMeid()
getSimSerialNumber()
getSubscriberId()
從?Android?10?開(kāi)始,應(yīng)用必須具有?READ_PRIVILEGED_PHONE_STATE?特許權(quán)限才能正常使用以上這些方法。
如果你的應(yīng)用沒(méi)有該權(quán)限,卻仍然使用了以上的方法,則返回的結(jié)果會(huì)因目標(biāo)?SDK?版本而異:
如果應(yīng)用以?Android?10?或更高版本為目標(biāo)平臺(tái),則會(huì)發(fā)生?SecurityException。
如果應(yīng)用以?Android?9(API?級(jí)別?28)或更低版本為目標(biāo)平臺(tái),則相應(yīng)方法會(huì)返回?null?或占位符數(shù)據(jù)(如果應(yīng)用具有?READ_PHONE_STATE?權(quán)限)。否則,會(huì)發(fā)生?SecurityException。
這項(xiàng)改動(dòng)表示第三方應(yīng)用無(wú)法獲取Device?ID這類(lèi)唯一標(biāo)識(shí)。
6、限制了對(duì)剪貼板數(shù)據(jù)的訪(fǎng)問(wèn)權(quán)限
除非您的應(yīng)用是默認(rèn)輸入法?(IME)?或是目前處于焦點(diǎn)的應(yīng)用,否則它無(wú)法訪(fǎng)問(wèn)?Android?10?或更高版本平臺(tái)上的剪貼板數(shù)據(jù)。
7、對(duì)啟用和停用?WLAN?實(shí)施了限制
以?Android?10?或更高版本為目標(biāo)平臺(tái)的應(yīng)用無(wú)法啟用或停用?WLAN。WifiManager.setWifiEnabled()方法始終返回?false。
Android11
1、分區(qū)存儲(chǔ)強(qiáng)制執(zhí)行
Android?11在分區(qū)存儲(chǔ)基礎(chǔ)上限制了應(yīng)用訪(fǎng)問(wèn)其他應(yīng)用的文件。
分區(qū)存儲(chǔ)將存儲(chǔ)空間分為兩部分:
公共目錄:Downloads、Documents、Pictures?、DCIM、Movies、Music、Ringtones等
公共目錄的文件在A(yíng)pp卸載后,不會(huì)刪除
可以通過(guò)SAF、MediaStore接口訪(fǎng)問(wèn)
擁有權(quán)限,也能通過(guò)路徑直接訪(fǎng)問(wèn)
應(yīng)用專(zhuān)屬目錄
應(yīng)用專(zhuān)屬目錄只能自己直接訪(fǎng)問(wèn)
?App卸載,數(shù)據(jù)會(huì)清除。
將應(yīng)用更新為以?Android?11?為目標(biāo)平臺(tái)后,您將無(wú)法使用requestLegacyExternalStorage,而且也沒(méi)有其他標(biāo)記可以提供停用分區(qū)存儲(chǔ)。
所有文件訪(fǎng)問(wèn)權(quán)限MANAGE_EXTERNAL_STORAGE,用來(lái)獲取所有文件的管理權(quán)限。
<uses-permission?android:name="android.permission.MANAGE_EXTERNAL_STORAGE"?/>
val?intent?=?Intent()
intent.action=?Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION
startActivity(intent)
//判斷是否獲取MANAGE_EXTERNAL_STORAGE權(quán)限:
val?isHasStoragePermission=?Environment.isExternalStorageManager()
2、電話(huà)號(hào)碼相關(guān)權(quán)限
Android?11?更改了應(yīng)用在讀取電話(huà)號(hào)碼時(shí)使用的與電話(huà)相關(guān)的權(quán)限。
如果應(yīng)用以?Android?11?或更高版本為目標(biāo)平臺(tái),并且需要訪(fǎng)問(wèn)以下列表中顯示的電話(huà)號(hào)碼?API,則必須請(qǐng)求?READ_PHONE_NUMBERS?權(quán)限,而不是?READ_PHONE_STATE?權(quán)限。
TelephonyManager?類(lèi)和?TelecomManager?類(lèi)中的?getLine1Number()?方法。
TelephonyManager?類(lèi)中不受支持的?getMsisdn()?方法。
如果應(yīng)用聲明?READ_PHONE_STATE?以調(diào)用前面列表中的方法以外的方法,可以繼續(xù)在所有?Android?版本中請(qǐng)求?READ_PHONE_STATE。不過(guò),如果僅對(duì)前面列表中的方法使用?READ_PHONE_STATE?權(quán)限,請(qǐng)按以下方式更新您的清單文件:
更改?READ_PHONE_STATE?的聲明,以使應(yīng)用僅在?Android?10(API?級(jí)別?29)及更低版本中使用該權(quán)限。
添加?READ_PHONE_NUMBERS?權(quán)限。
<manifest>
?<!--?Grants?the?READ_PHONE_STATE?permission?only?on?devices?that?run
?Android?10?(API?level?29)?and?lower.?-->
?<uses-permission?android:name="READ_PHONE_STATE"
?android:maxSdkVersion="29"?/>
?<uses-permission?android:name="READ_PHONE_NUMBERS"?/>
</manifest>
3、自定義消息框視圖被屏蔽
出于安全方面的考慮,同時(shí)也為了保持良好的用戶(hù)體驗(yàn),如果包含自定義視圖的消息框是以?Android?11?或更高版本為目標(biāo)平臺(tái)的應(yīng)用從后臺(tái)發(fā)送的,系統(tǒng)會(huì)屏蔽這些消息框。請(qǐng)注意,仍允許使用文本消息框;此類(lèi)消息框是使用?Toast.makeText()?創(chuàng)建的,并不調(diào)用?setView()。
如果您的應(yīng)用仍嘗試從后臺(tái)發(fā)布包含自定義視圖的消息框,系統(tǒng)不會(huì)向用戶(hù)顯示相應(yīng)的消息,而是會(huì)在?logcat?中記錄以下消息:
W/NotificationService:?Blocking?custom?toast?from?package?\
?<package>?due?to?package?not?in?the?foreground
消息框回調(diào)
如果您希望在消息框(文本消息框或自定義消息框)出現(xiàn)或消失時(shí)收到通知,請(qǐng)使用?Android?11?中添加的?addCallback()?方法。
文本消息框?API?變更
以?Android?11?或更高版本為目標(biāo)平臺(tái)的應(yīng)用會(huì)發(fā)現(xiàn)文本消息框受到以下負(fù)面影響:
getView()?方法返回?null。
以下方法的返回值并不反映實(shí)際值,因此您不應(yīng)在應(yīng)用中依賴(lài)于它們:
getHorizontalMargin()
getVerticalMargin()
getGravity()
getXOffset()
getYOffset()
以下方法是空操作,因此您的應(yīng)用不應(yīng)使用它們:
setMargin()
setGravity()
4、媒體intent操作需要系統(tǒng)默認(rèn)相機(jī)
從?Android?11?開(kāi)始,只有預(yù)裝的系統(tǒng)相機(jī)應(yīng)用可以響應(yīng)以下?intent?操作:
android.media.action.VIDEO_CAPTURE
android.media.action.IMAGE_CAPTURE
android.media.action.IMAGE_CAPTURE_SECURE
也就是說(shuō),如果我調(diào)用intent喚起照相機(jī),使用VIDEO_CAPTURE的action,只有系統(tǒng)的相機(jī)能夠響應(yīng),而第三方的相機(jī)應(yīng)用不會(huì)響應(yīng)了。
如果要使用特定的第三方相機(jī)應(yīng)用來(lái)代表其捕獲圖片或視頻,可以通過(guò)為intent設(shè)置軟件包名稱(chēng)或組件來(lái)使這些intent變得明確。
5、5G
Android?11?添加了在您的應(yīng)用中支持?5G?的功能。
新的Android11也是支持了5G相關(guān)的一些功能,包括:
檢測(cè)是否連接到了5G網(wǎng)絡(luò)
檢查按流量計(jì)費(fèi)性
檢測(cè)5G網(wǎng)絡(luò),通過(guò)TelephonyManager的監(jiān)聽(tīng)方法:
private?fun?getNetworkType(){
?val?tManager?=?getSystemService(Context.TELEPHONY_SERVICE)?as?TelephonyManager
?tManager.listen(object?:?PhoneStateListener()?{
?@RequiresApi(Build.VERSION_CODES.R)
?override?fun?onDisplayInfoChanged(telephonyDisplayInfo:?TelephonyDisplayInfo)?{
?if?(ActivityCompat.checkSelfPermission(this@Android11Test2Activity,?android.Manifest.permission.READ_PHONE_STATE)?!=?android.content.pm.PackageManager.PERMISSION_GRANTED)?{
?return
?}
?super.onDisplayInfoChanged(telephonyDisplayInfo)
?when(telephonyDisplayInfo.networkType)?{
?TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_ADVANCED_PRO?->?showToast("高級(jí)專(zhuān)業(yè)版?LTE?(5Ge)")
?TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA?->?showToast("NR?(5G)?-?5G?Sub-6?網(wǎng)絡(luò)")
?TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE?->?showToast("5G+/5G?UW?-?5G?mmWave?網(wǎng)絡(luò)")
?else?->?showToast("other")
?}
?}
?},?PhoneStateListener.LISTEN_DISPLAY_INFO_CHANGED)
}
檢測(cè)流量計(jì)費(fèi)方法,監(jiān)聽(tīng)網(wǎng)絡(luò),在回調(diào)中判斷:
val?manager?=?getSystemService(CONNECTIVITY_SERVICE)?as?ConnectivityManager
?manager.registerDefaultNetworkCallback(object?:?ConnectivityManager.NetworkCallback()?{
?override?fun?onCapabilitiesChanged(network:?Network,?networkCapabilities:?NetworkCapabilities)?{
?super.onCapabilitiesChanged(network,?networkCapabilities)
?//true?代表連接不按流量計(jì)費(fèi)
?val?isNotFlowPay=networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED)?||
?networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_TEMPORARILY_NOT_METERED)
?}
})
6、后臺(tái)位置信息訪(fǎng)問(wèn)權(quán)限
在搭載?Android?11?的設(shè)備上,當(dāng)應(yīng)用中的某項(xiàng)功能請(qǐng)求在后臺(tái)訪(fǎng)問(wèn)位置信息時(shí),用戶(hù)看到的系統(tǒng)對(duì)話(huà)框不再包含用于啟用后臺(tái)位置信息訪(fǎng)問(wèn)權(quán)限的按鈕。如需啟用后臺(tái)位置信息訪(fǎng)問(wèn)權(quán)限,用戶(hù)必須在設(shè)置頁(yè)面上針對(duì)應(yīng)用的位置權(quán)限設(shè)置一律允許選項(xiàng)。
7、軟件包可見(jiàn)性
Android?11?更改了應(yīng)用查詢(xún)用戶(hù)已在設(shè)備上安裝的其他應(yīng)用以及與之交互的方式。使用??元素,應(yīng)用可以定義一組自身可訪(fǎng)問(wèn)的其他軟件包。通過(guò)告知系統(tǒng)應(yīng)向應(yīng)用顯示哪些其他軟件包,此元素有助于鼓勵(lì)最小權(quán)限原則。此外,此元素還可幫助?Google?Play?等應(yīng)用商店評(píng)估應(yīng)用為用戶(hù)提供的隱私權(quán)和安全性。
如果應(yīng)用以?Android?11?或更高版本為目標(biāo)平臺(tái),您可能需要在應(yīng)用的清單文件中添加??元素。在??元素中,您可以按軟件包名稱(chēng)、intent?簽名或提供程序授權(quán)指定軟件包。
8、前臺(tái)服務(wù)類(lèi)型
從?Android?9?開(kāi)始,應(yīng)用僅限于在前臺(tái)訪(fǎng)問(wèn)攝像頭和麥克風(fēng)。為了進(jìn)一步保護(hù)用戶(hù),Android?11?更改了前臺(tái)服務(wù)訪(fǎng)問(wèn)攝像頭和麥克風(fēng)相關(guān)數(shù)據(jù)的方式。如果您的應(yīng)用以?Android?11?為目標(biāo)平臺(tái)并且在某項(xiàng)前臺(tái)服務(wù)中訪(fǎng)問(wèn)這些類(lèi)型的數(shù)據(jù),您需要在該前臺(tái)服務(wù)的聲明的?foregroundServiceType?屬性中添加新的?camera?和?microphone?類(lèi)型。
應(yīng)用某項(xiàng)前臺(tái)服務(wù)需要訪(fǎng)問(wèn)位置信息、攝像頭和麥克風(fēng),那么就要在清單文件中這樣添加:
<manifest>
?<service?...
?android:foregroundServiceType="location|camera|microphone"?/>
</manifest>
Android?12
1、SplashScreen
從?Android?12?開(kāi)始,在搭載?Android?12?或更高版本的設(shè)備上運(yùn)行時(shí),所有應(yīng)用都將擁有啟動(dòng)動(dòng)畫(huà)。這包括啟動(dòng)時(shí)的進(jìn)入應(yīng)用動(dòng)作、顯示應(yīng)用圖標(biāo)的啟動(dòng)畫(huà)面,以及向應(yīng)用本身的過(guò)渡。

(1)應(yīng)用圖標(biāo)應(yīng)該是矢量可繪制對(duì)象(AVD?XML),它可以是靜態(tài)或動(dòng)畫(huà)形式。雖然動(dòng)畫(huà)的時(shí)長(zhǎng)可以不受限制,但我們建議不超過(guò)1,000?毫秒。默認(rèn)情況下,使用啟動(dòng)器圖標(biāo)。
(2)可以選擇添加圖標(biāo)背景;在圖標(biāo)與窗口背景之間需要更高的對(duì)比度時(shí)圖標(biāo)背景很有用。如果您使用一個(gè)自適應(yīng)圖標(biāo),當(dāng)該圖標(biāo)與窗口背景之間的對(duì)比度足夠高時(shí),就會(huì)顯示其背景。
(3)與自適應(yīng)圖標(biāo)一樣,前景的三分之一被遮蓋。
(4)窗口背景由不透明的單色組成。如果窗口背景已設(shè)置且為純色,則未設(shè)置相應(yīng)的屬性時(shí)默認(rèn)使用該背景。
2、更安全的組件導(dǎo)出
以Android?12為目標(biāo)平臺(tái)的App,如果其包含的四大組件中使用到了Intent過(guò)濾器(intent-filter),則必須顯式聲明?android:exported?屬性,否則App將無(wú)法在A(yíng)ndroid?12及更高系統(tǒng)版本的設(shè)備上安裝。
3、定位權(quán)限:大概位置
如果您的應(yīng)用請(qǐng)求ACCESS_COARSE_LOCATION但未請(qǐng)求ACCESS_FINE_LOCATION,則此變更不會(huì)影響您的應(yīng)用。
如果您的應(yīng)用請(qǐng)求ACCESS_FINE_LOCATION?運(yùn)行時(shí)權(quán)限,您還應(yīng)請(qǐng)求ACCESS_COARSE_LOCATION權(quán)限,以便處理用戶(hù)授予應(yīng)用大致位置訪(fǎng)問(wèn)權(quán)限的情形。
4、PendingIntent可變性
如果您的應(yīng)用程序以Android?12為目標(biāo)平臺(tái),您必須為應(yīng)用創(chuàng)建的每個(gè)?PendingIntent?對(duì)象指定可變性。這項(xiàng)額外的要求可提高應(yīng)用的安全性。因?yàn)槿絘pp可以通過(guò)劫持PendingIntent,然后改寫(xiě)里面的action、category、data等,造成重定向攻擊。
適配的具體就是在創(chuàng)建?PendingIntent時(shí),使用?PendingIntent.FLAG_MUTABLE?或?PendingIntent.FLAG_IMMUTABLE?標(biāo)志。否則運(yùn)行時(shí)會(huì)報(bào)IllegalArgumentException。
5、藍(lán)牙權(quán)限
如果您的應(yīng)用程序面向Android?12或更高版本,使用藍(lán)牙功能時(shí)請(qǐng)?jiān)趹?yīng)用程序的清單文件中聲明以下權(quán)限:
BLUETOOTH_SCAN:允許藍(lán)牙設(shè)備掃描。
BLUETOOTH_CONNECT:允許藍(lán)牙設(shè)備連接。
BLUETOOTH_ADVERTISE:允許當(dāng)前藍(lán)牙設(shè)備可以被其他藍(lán)牙設(shè)備發(fā)現(xiàn)。
對(duì)于以前的與藍(lán)牙相關(guān)的權(quán)限聲明,設(shè)置android:maxSdkVersion到30。此應(yīng)用兼容性步驟可幫助系統(tǒng)僅授予您的應(yīng)用在運(yùn)行Android?12?的設(shè)備上安裝時(shí)所需的藍(lán)牙權(quán)限。
<manifest>
?<!--?Request?legacy?Bluetooth?permissions?on?older?devices.?-->
?<uses-permission?android:name="android.permission.BLUETOOTH"
?android:maxSdkVersion="30"?/>
?<uses-permission?android:name="android.permission.BLUETOOTH_ADMIN"
?android:maxSdkVersion="30"?/>
?<uses-permission?android:name="android.permission.BLUETOOTH_SCAN"?/>
?<uses-permission?android:name="android.permission.BLUETOOTH_ADVERTISE"?/>
?<uses-permission?android:name="android.permission.BLUETOOTH_CONNECT"?/>
?<!--?只有當(dāng)您的應(yīng)用程序使用藍(lán)牙掃描結(jié)果來(lái)獲取物理位置時(shí)才需要?-->
?<uses-permission?android:name="android.permission.ACCESS_FINE_LOCATION"?/>
?...
</manifest>
如果您的應(yīng)用程序使用藍(lán)牙掃描結(jié)果來(lái)獲取物理位置,請(qǐng)聲明ACCESS_FINE_LOCATION。以前版本中(6.0?~?11)是必須申請(qǐng)定位權(quán)限,才可以進(jìn)行藍(lán)牙掃描。
在A(yíng)ndroid?12上,如果你的應(yīng)用程序不使用藍(lán)牙掃描結(jié)果來(lái)獲取物理位置??梢蕴砑觓ndroid:usesPermissionFlags屬性到您的BLUETOOTH_SCAN權(quán)限聲明,并將該屬性的值設(shè)置為neverForLocation。
<manifest>
?<uses-permission?android:name="android.permission.BLUETOOTH_SCAN"
?android:usesPermissionFlags="neverForLocation"?/>
?<!--可以刪除定位權(quán)限?-->
?<uses-permission?android:name="android.permission.ACCESS_FINE_LOCATION"?/>
?...
</manifest>
Android13
1、細(xì)化的媒體權(quán)限
如果應(yīng)用以?Android?13?或更高版本為目標(biāo)平臺(tái),并且需要訪(fǎng)問(wèn)其他應(yīng)用已經(jīng)創(chuàng)建的媒體文件,必須請(qǐng)求以下一項(xiàng)或多項(xiàng)細(xì)化的媒體權(quán)限,而不是READ_EXTERNAL_STORAGE?權(quán)限:
媒體類(lèi)型請(qǐng)求權(quán)限
圖片和照片READ_MEDIA_IAMGES
視頻READ_MEDIA_VIDEO
音頻文件READ_MEDIA_AUDIO
如果用戶(hù)之前向您的應(yīng)用授予了?READ_EXTERNAL_STORAGE?權(quán)限,系統(tǒng)會(huì)自動(dòng)向您的應(yīng)用授予細(xì)化的媒體權(quán)限。否則,當(dāng)應(yīng)用請(qǐng)求上表中顯示的任何權(quán)限時(shí),系統(tǒng)會(huì)顯示面向用戶(hù)的對(duì)話(huà)框。
<manifest?...>
?<!--?Required?only?if?your?app?targets?Android?13.?-->
?<!--?Declare?one?or?more?the?following?permissions?only?if?your?app?needs
?to?access?data?that's?protected?by?them.?-->
?<uses-permission?android:name="android.permission.READ_MEDIA_IMAGES"?/>
?<uses-permission?android:name="android.permission.READ_MEDIA_AUDIO"?/>
?<uses-permission?android:name="android.permission.READ_MEDIA_VIDEO"?/>
?<!--?Required?to?maintain?app?compatibility.?-->
?<uses-permission?android:name="android.permission.READ_EXTERNAL_STORAGE"
?android:maxSdkVersion="32"?/>
?<application?...>
?...
?</application>
</manifest>
2、通知運(yùn)行時(shí)權(quán)限
在A(yíng)ndroidManifest.xml中對(duì)發(fā)送通知權(quán)限進(jìn)行聲明:
<manifest?...>
?<uses-permission?android:name="android.permission.POST_NOTIFICATIONS"/>
?<application?...>
?...
?</application>
</manifest>
POST_NOTIFICATIONS權(quán)限只有在應(yīng)用程序的targetSdk指定成33或更高時(shí)才會(huì)有用。
要確認(rèn)用戶(hù)是否已啟用通知,請(qǐng)調(diào)用?areNotificationsEnabled()。
3、通知權(quán)限會(huì)影響前臺(tái)服務(wù)的顯示
如果用戶(hù)拒絕授予通知權(quán)限,就不會(huì)在抽屜式通知欄中看到與前臺(tái)服務(wù)相關(guān)的通知。?不過(guò),無(wú)論是否授予通知權(quán)限,用戶(hù)都會(huì)在前臺(tái)服務(wù)?(FGS)?任務(wù)管理器中看到與前臺(tái)服務(wù)相關(guān)的通知。
4、WebView
從Android?13開(kāi)始,以Android13(API?33+)為目標(biāo)平臺(tái)的應(yīng)用,WebView存在以下方法與API調(diào)整:
WebSettings.setAppCacheEnabled()?方法廢棄。
WebSettings.setForceDark()?方法廢棄。
4、靜態(tài)廣播注冊(cè)
從Android?13開(kāi)始,以Android13(API?33+)為目標(biāo)平臺(tái)的應(yīng)用,注冊(cè)靜態(tài)廣播時(shí),需設(shè)置對(duì)其他應(yīng)用的可見(jiàn)性:
若對(duì)其他應(yīng)用可見(jiàn),廣播注冊(cè)時(shí)設(shè)置:Context.RECEIVER_EXPORTED
若僅應(yīng)用內(nèi)使用,廣播注冊(cè)時(shí)設(shè)置:Context.RECEIVER_NOT_EXPORTED
private?void?registerTestReceiver()?{
?IntentFilter?filter?=?new?IntentFilter();
?filter.addAction("com.xiaxl.test.action");
?//?api?>=?33
?if?(Build.VERSION.SDK_INT?>=?Build.VERSION_CODES.TIRAMISU)?{
?//?跨應(yīng)用間使用
?MainActivity.this.registerReceiver(mTestReceiver,?filter,?Context.RECEIVER_EXPORTED);
?//?應(yīng)用內(nèi)使用
?//MainActivity.this.registerReceiver(mTestReceiver,?filter,?Context.RECEIVER_EXPORTED);
?}
?//?api?<=?32
?else?{
?MainActivity.this.registerReceiver(mTestReceiver,?filter);
?}
}
目前該增強(qiáng)措施并非默認(rèn)生效,開(kāi)發(fā)者需啟用?DYNAMIC_RECEIVER_EXPLICIT_EXPORT_REQUIRED兼容性框架,并在動(dòng)態(tài)注冊(cè)廣播時(shí)指定是否接受其他應(yīng)用的廣播。
如果啟用了?DYNAMIC_RECEIVER_EXPLICIT_EXPORT_REQUIRED?兼容性框架更改,則必須為每個(gè)廣播接收器指定?RECEIVER_EXPORTED?或?RECEIVER_NOT_EXPORTED。否則,當(dāng)您嘗試注冊(cè)廣播接收器時(shí),系統(tǒng)會(huì)拋出?SecurityException。
5、Wi-Fi?權(quán)限
在以前的?Android?版本中,用戶(hù)需要向您的應(yīng)用授予?在以前的?Android?版本中,用戶(hù)需要向您的應(yīng)用授予?ACCESS_FINE_LOCATION?權(quán)限,應(yīng)用才能完成一些常見(jiàn)的?Wi-Fi?用例。
由于用戶(hù)很難將位置信息權(quán)限與?Wi-Fi?功能相關(guān)聯(lián),因此?Android?13(API?級(jí)別?33)在?NEARBY_DEVICES?權(quán)限組中引入了運(yùn)行時(shí)權(quán)限,適用于管理設(shè)備與附近?Wi-Fi?接入點(diǎn)連接情況的應(yīng)用。此權(quán)限?(NEARBY_WIFI_DEVICES)?可滿(mǎn)足以下?Wi-Fi?用例:
查找或連接到附近的設(shè)備,如打印機(jī)或媒體投射設(shè)備。通過(guò)該工作流,您的應(yīng)用可以完成以下類(lèi)型的任務(wù):
通過(guò)帶外方式(例如通過(guò)?BLE)接收?AP?信息。
使用僅限本地使用的熱點(diǎn),通過(guò)?Wi-Fi?感知和連接功能發(fā)現(xiàn)并連接到設(shè)備。
通過(guò)?Wi-Fi?直連發(fā)現(xiàn)和連接到設(shè)備。
發(fā)起與已知?SSID(例如汽車(chē)或智能家居設(shè)備)的連接。
開(kāi)啟僅限本地使用的熱點(diǎn)。
連接到附近的?Wi-Fi?感知設(shè)備。
6、在后臺(tái)使用身體傳感器需要新的權(quán)限
Android?13?中引入了“在使用時(shí)”訪(fǎng)問(wèn)身體傳感器(例如心率、體溫和血氧飽和度)的概念。
如果您的應(yīng)用以?Android?13?為目標(biāo)平臺(tái),并且在后臺(tái)運(yùn)行時(shí)需要訪(fǎng)問(wèn)身體傳感器信息,那么除了現(xiàn)有的?BODY_SENSORS?權(quán)限外,您還必須聲明新的?BODY_SENSORS_BACKGROUND?權(quán)限。