XML DOM 獲取節點值
1523
2025-04-01
從android7.0開始強制啟用StrictMode“嚴苛模式”。StrictMode是在android2.3引進的類。當時它的作用是作為一個開發工具用的,開發者可以開發者選項中打開它,它可以捕捉到在主線程序發生的磁盤IO讀寫、網絡訪問發生的意外,通常這個意外都是ANR(android not response),當時可以用這個工具檢測出這些意外,代碼就可以做調整:將磁盤讀寫、網絡訪問等耗時操作寫到非主線程中,以提供更好的體驗。但是在android7.0以后,這項功能被強制使用了。
在App之間共享文件
對于android7.0以后的系統,android框架強制使用StrictMode API 策略。這個策略禁止在app外暴露 “file://“URI。如果一個intent包含一個文件URI(以file://開頭)離開你的app,那么這個app就報告FileUriExposedException異常。安裝apk的功能實際上是系統提供的。Intent會帶著我們的意圖(包括apk的位置信息)離開我們的app,進入系統中,讓系統中的應用來處理。這意味著apk文件需要在app間共享。
為了與其他應用共享文件,你應該發送"content://"URI ,并授予臨時訪問權限。授予這個臨時訪問權限的最簽單方法就是使用FileProvider類。
注意:當然少不了android6.0之后要動態申請權限這一步。
使用FileProvider輔助完成安裝任務
第一步:在manifest.xml申請以下權限,特別是第二個權限,如果缺少的話,在android8.0的手機上安裝apk會失敗。
1
2
第二步:動態申請android.permission.READ_EXTERNAL_STORAGE權限。在android6.0之后,這個權限要動態申請,具體請看Github上的代碼。
第三步:在manifest.xml中聲明FileProvider:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
android:name:provider可以直接使用v4包提供的FileProvider,或者自定義,但是自定義的provider一定要繼承FileProvider,一般使用系統的就足夠了。
android:authorities:這個值將會發布在content://下,即其他app通過content://com.wong.myapp.UPDATE_APP_FILE_PROVIDER來訪問apk文件等信息,稍后將在代碼中用到。
**android:exported:“false”**表示我們的provider不需要對外開放。
android:grantUriPermissions:“true”,此值為true,app才能獲得臨時共享權限。
元數據meta-data中:
**android:name=“android.support.FILE_PROVIDER_PATHS”**必須是這個名字。因為在
android.support.v4.content.FileProvider類里,要用這個key,獲取我們的xml文件路徑。
XmlResourceParser in = info.loadXmlMetaData(context.getPackageManager(), "android.support.FILE_PROVIDER_PATHS");
1
2
android:resource="@xml/file_provider_paths"指定配置可訪問路徑的xml的文件地址。
第四步:res/xml中定義對外暴露的文件夾路徑
首先,在res資源目錄入創建xml文件夾,然后在xml創建一份名為file_provider_paths.xml的文件,內容如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
注意:
在android8.0以上的手機上,讀取共享文件時,如apk更新的編程中,我們把apk下載后,要安裝時,去讀取這個apk文件就出現如下錯誤:
Failed to find configured root that contains ...
1
2
所以一定要在file_provider_paths.xml文件中添加root-path 標簽,即:
1
第五步:生成content://類型的Uri
使用以下代碼只能生成格式為file://xxx的Uri,如果是android7.0之前的就用file://形式訪問,獲取Uri方式如下:
File picFile = xxx; Uri picUri = Uri.fromFile(picFile);
1
2
android7.0以后的必須通過FileProvider.getUriForFile方法來生成content://xxx類型的Uri:
File apkFile = new File(Environment.getExternalStorageDirectory(), "update_folder/update.apk"); Uri fileUri = FileProvider.getUriForFile(MainActivity.this, "com.wong.myapp.UPDATE_APP_FILE_PROVIDER", apkFile);
1
2
3
4
getUriForFile:第一個參數是Context;第二個參數,就是我們之前在manifest#provider中定義的android:authorities屬性的值;第三個參數是File。
第六步:給Uri授予臨時權限
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
1
2
第七步:使用Intent傳遞Uri
intent.setDataAndType(fileUri, "application/vnd.android.package-archive"); startActivityForResult(intent, 100);
1
2
安裝apk的核心代碼:
private void installApk() { Intent intent = new Intent(Intent.ACTION_VIEW); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.addCategory(Intent.CATEGORY_DEFAULT); //重新構造Uri:content:// Uri fileUri; File apkFile = new File(Environment.getExternalStorageDirectory(), "update_folder/update.apk"); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { fileUri = FileProvider.getUriForFile(MainActivity.this, "com.wong.myapp.UPDATE_APP_FILE_PROVIDER", apkFile); //授予目錄臨時共享權限 intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); } else { fileUri = Uri.fromFile(apkFile); } intent.setDataAndType(fileUri, "application/vnd.android.package-archive"); //使用Intent傳遞Uri startActivity(intent); }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
完整代碼
Android HTTP
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。