您好,登錄后才能下訂單哦!
本文總結分析了Android7.0版本影響開發的改進。分享給大家供大家參考,具體如下:
低電耗模式
會對鬧鈴、GPS 和 Wi-Fi 掃描 產生限制.
可參考Optimizing for Doze and App Standby
使用GCM來發送和接受消息
后臺優化
Android N 刪除了三項隱式廣播,隱式廣播會在后臺頻繁啟動已注冊偵聽這些廣播的應用。 刪除這些廣播可以顯著提升設備性能和用戶體驗.
偵聽網絡變化的主線程廣播改為: CONNECTIVITY_CHANGE。
對所有應用都無法 發送和接受 ACTION_NEW_PICTURE 或 ACTION_NEW_VIDEO .
可以使用JobScheduler API ,更多參考后臺優化
系統權限更改
為了提高私有文件的安全性,面向 Android 7.0或更高版本的App私有目錄被限制訪問(0700)。此設置可防止私有文件的元數據泄漏,如它們的大小或是否存在(狀態)。此權限策略的更改有多重副作用:
私有文件的文件權限不應再由所有者放寬,為使用MODE_WORLD_READABLE和MODE_WORLD_WRITEABLE而進行的此類嘗試將觸發SecurityException,會導致App崩潰的。
注:迄今為止,這種限制還不能完全執行。App仍可能使用原生API或File API來修改它們的私有目錄權限。但是Google強烈反對放寬私有目錄的權限。
傳遞軟件包網域外的 file://URI可能給接收器留下無法訪問的路徑。因此傳遞file://URI會觸發 FileUriExposedException。分享私有文件內容的推薦方法是使用FileProvider。
DownloadManager不再按文件名分享私人存儲的文件。老的App在訪問COLUMN_LOCAL_FILENAME時可能出現無法訪問的路徑。針對Android 7.0或更高版本開發的應用在嘗試訪問COLUMN_LOCAL_FILENAME時會觸發 SecurityException。通過使用DownloadManager.Request.setDestinationInExternalFilesDir())或DownloadManager.Request.setDestinationInExternalPublicDir())將下載位置設置為公共位置的老App仍可以訪問COLUMN_LOCAL_FILENAME中的路徑,但是Google還是強烈反對使用這種方法。訪問由DownloadManager公開的文件的首選方式是使用ContentResolver.openFileDescriptor())。
應用間共享文件
對于針對Android 7.0的應用,Android framework執行的StrictMode API禁止向你的App外公開file://URI。如果一個包含文件URI的Intent發送到你的應用之外,App會發生FileUriExposedException異常。
若要在應用間共享文件,您應發送一項content://URI,并授予URI臨時訪問權限。進行此授權的最簡單方式是使用FileProvider類。如需有關權限和共享文件的更多信息,請參閱共享文件。
解決 Android N 上 安裝Apk時報錯:android.os.FileUriExposedException:
在AndroidManifest.xml中添加如下代碼
<provider android:name="android.support.v4.content.FileProvider" android:authorities="app的包名.fileProvider" android:grantUriPermissions="true" android:exported="false"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths" /> </provider>
注意:
authorities:app的包名.fileProvider
grantUriPermissions:必須是true,表示授予 URI 臨時訪問權限
exported:必須是false
resource:中的@xml/file_paths是我們接下來要添加的文件
在res目錄下新建一個xml文件夾,并且新建一個file_paths的xml文件(如下圖)
輸入以下內容
<?xml version="1.0" encoding="utf-8"?> <paths> <external-path path="Android/data/app的包名/" name="files_root" /> <external-path path="." name="external_storage_root" /> </paths>
path:需要臨時授權訪問的路徑(.代表所有路徑)
name:就是你給這個訪問路徑起個名字
最后修改代碼:
Intent intent = new Intent(Intent.ACTION_VIEW); //判斷是否是AndroidN以及更高的版本 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); Uri contentUri = FileProvider.getUriForFile(context, BuildConfig.APPLICATION_ID + ".fileProvider", apkFile); intent.setDataAndType(contentUri, "application/vnd.android.package-archive"); } else { intent.setDataAndType(Uri.fromFile(apkFile), "application/vnd.android.package-archive"); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); } startActivity(intent); //以前我們直接 Uri.fromFile(apkFile)構建出一個Uri,現在我們使用FileProvider.getUriForFile(context, BuildConfig.APPLICATION_ID + ".fileProvider", apkFile); //BuildConfig.APPLICATION_ID直接是應用的包名
屏幕縮放
Android 7.0支持用戶設置顯示尺寸,以放大或縮小屏幕上的所有元素,從而提升設備對視力不佳用戶的可訪問性。用戶無法將屏幕縮放至低于最小屏幕寬度sw320dp,該寬度是Nexus 4的寬度,也是常規中等大小手機的寬度。
當設備密度發生更改時,系統會以如下方式通知正在運行的應用:
1. 如果是面向API leve 23或更低版本系統的應用,系統會自動終止其所有后臺進程。也就是說如果用戶切換后離開你的App,打開“Settings”更改Display size設置,則系統會像處理內存不足的情況一樣終止該應用。如果應用具有任何前臺進程,則系統會如處理運行時變更中所述將配置變更通知給這些進程,就像對待設備屏幕方向變更一樣,具體大家可以再看看這個超鏈接。
2. 如果是針對Android 7.0的App,則其所有進程(前臺和后臺)都會收到有關配置變更的通知,如處理運行時變更中所講的那樣。 大多數App并不需要進行任何更改即可支持此功能,不過前提是這些應用遵循Android最佳實踐。具體要檢查的事項:
① 在屏幕寬度為 sw320dp 的設備上測試你的App,并確保其正常運行。
② 當設備Config發生變更時,更新任何與密度相關的緩存信息,例如緩存位圖或從網絡加載的資源。當應用從暫停狀態恢復運行時,檢查Config的變化。
注:如果你要緩存與配置相關的數據,則最好也包括相關元數據,例如該數據對應的屏幕尺寸或像素密度。保存這些元數據便于你在Config變更后決定是否需要刷新緩存數據。
③ 避免用像素單位指定尺寸,因為像素不會隨屏幕密度縮放。應改為使用dp等單位。
用戶可以在設置-顯示-顯示大小修改屏幕寬度,也可以在設置-開發人員選項-最小寬度隨意設置指定寬度,開發人員特別需要注意適配
NDK平臺庫
Android N 做了一些命名空間更改,阻止加載非公開API,會出現一些常見錯誤
如,UnsatisfiedLinkError
典型修復方法:
1. 使用標準 JNI 函數來替代使用 libandroid_runtime.so 中的 getJavaVM 和 getJNIEnv
2. 使用公開 alternative __system_property_get 來替代使用 libcutils.so 中的 property_get 符號
3. 使用應用本地版本來替代使用 libcrypto.so 中的 SSL_ctrl 符號
注解保留
Android 7.0在注解可見性被忽略時修復錯誤。這種問題將啟用本不應被允許的運行時訪問注解。 這些注解包括:
VISIBILITY_BUILD:僅應編譯時可見。
VISIBILITY_SYSTEM:運行時應可見,但僅限基本系統。 如果你的App依賴這種行為,請在注解中添加一項運行時必須可用的保留政策。你可通過使用@Retention(RetentionPolicy.RUNTIME)
這樣做。
其他重要說明
1. 如果一個針對較低API級別開發的App在Android 7.0上運行,那么在用戶更改顯示尺寸時,系統將終止此App進程。App必須能夠正常處理此情景。否則,當用戶從最近使用記錄中恢復運行App時,App將會出現崩潰現象。您應測試應用以確保不會發生此行為。要進行此測試,您可以通過DDMS手動終止應用,可以造成相同的崩潰現象。在屏幕密度發生更改時,系統不會自動終止針對Android 7.0及更高版本開發的App;不過這些App仍可能對配置變更做出不良響應。
2. Android 7.0上的應用應能夠正常處理配置變更,并且在后續啟動時不會出現崩潰現象。你可以通過更改字體大小 (Setting > Display > Font size) 并隨后從最近使用記錄中恢復運行應用,來驗證App行為。
3. 由于之前的Android版本中的一項錯誤,系統沒有對主線程上的一個TCP Socket的寫入操作嚴格檢查。Android 7.0修復了這個系統錯誤。之前有這種行為的App將會引發android.os.NetworkOnMainThreadException
。一般情況下,不建議在主線程上執行網絡操作,因為這些操作通常都有可能導致ANR和卡頓,這個應該是中所周知的,大家一般不會犯。
4. Debug.startMethodTracing()
方法族現在默認在你的共享的存儲空間上的軟件包特定目錄中存儲輸出,而非 SD卡頂級。這意味著應用不再需要請求WRITE_EXTERNAL_STORAGE權限就可以使用這些API。
5. 許多平臺API現在開始檢查在Binder事務間發送的大負載,系統現在會將TransactionTooLargeExceptions再次作為RuntimeExceptions引發,而不再只是默默記錄或不拋出這個錯誤。一個常見例子是在Activity.onSaveInstanceState())
上存儲過多數據,導致ActivityThread.StopInfo在你的App面向 Android 7.0時引發RuntimeException。
6. 如果應用向View post Runnable任務,并且View未附加到窗口,系統會用View為Runnable任務排隊;在 View附加到窗口之前,Runnable任務不會執行。 此行為會修復以下錯誤:
① 如果一個App是從并非預期Window UI線程的其他線程發布到View,則Runnable可能會因此運行錯誤。
② 如果Runnable任務是從并非looper thread的其他線程發布,則應用可能會曝光Runnable任務。
7. 如果Android 7.0上有DELETE_PACKAGES權限的應用嘗試刪除一個軟件包,但另一項應用已經安裝了這個軟件包,則系統可能要求用戶確認。在這種情況下,應用在調用PackageInstaller.uninstall())
時的返回狀態應為STATUS_PENDING_USER_ACTION。
更多關于Android相關內容感興趣的讀者可查看本站專題:《Android開發入門與進階教程》、《Android調試技巧與常見問題解決方法匯總》、《Android基本組件用法總結》、《Android視圖View技巧總結》、《Android布局layout技巧總結》及《Android控件用法總結》
希望本文所述對大家Android程序設計有所幫助。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。