[問題] 關於Uri

看板AndroidDev作者 (非常念舊)時間7年前 (2017/06/19 23:31), 7年前編輯推噓1(1050)
留言51則, 4人參與, 最新討論串1/1
我是抓取 nordic nrftoolbox 的 source code。 https://goo.gl/5WxUPB 任務是利用這 code 抓取 bin file 來做 firmware 更新,客戶嫌麻煩說還要loader 去選擇檔案,想要寫死路徑。 dfuActivity 主要是在 663 行 final Intent intent = new Intent(Intent.ACTION_GET_CONTENT); 最後在 433 行回傳,可以看到裡面大部分就只是利用 loader 選取的 data來獲取 uri 分析uri對以下填值 mFileType = mFileTypeTmp; mFilePath = null; mFileStreamUri = null; 接著我會經過 452 行的 else if,最後準備要更新時要執行的地方是 743行 裡面的參數就是這些變數。 我用官方沒改的 code ,在449行用 Log.d("",""+uri.toString);印出已經load下的檔案uri content://com.android.externalstorage.documents/document/primary%3ANordic%20Semiconductor%2Fnrf52832_xxaa_s132.bin 接著我開始改 code 我就直接用上面這串 利用 Uri.parser("xxxxx") 來丟到 743行的 mFileStreamUri 最後APK卻說找不到檔案,我懷疑是 URI的轉換問題讓APK無法找到bin file,另 一個可能就是464行的restartLoader的問題,我把455~464 663~665 mark掉了。 也就是不透過其他APP例如檔案管理APK來載入檔案,直接寫死要上傳的檔案的uri 既然客戶希望按個 button,就可以不用開啟 loader 選取檔案,那麼有沒有辦法是 下了 Intent intent = new Intent(Intent.ACTION_GET_CONTENT); startActivity(intent, SELECT_FILE_REQ)); 可以不用由客戶去選檔,就指定給他路徑了呢? 還有我的URI可以這樣 assign嗎...?-->主要還是想知道為啥找不到檔案 如果有甚麼資訊或指教請不吝說明,謝謝。 ----------------------------------------------------------------------------- 更新1: 查看了 logcat 出現了權限相關訊息 6-20 11:49:38.395 19930 19941 E DatabaseUtils: Writing exception to parcel 06-20 11:49:38.395 19930 19941 E DatabaseUtils: java.lang.SecurityException: Permission Denial: reading com.android.externalstorage.ExternalStorageProvider uri content://com.android.externalstorage.documents/document/primary%3ANordic%20Semiconductor%2Fnrf52832_xxaa_s132.bin from pid=20023, uid=10259 requires android.permission.MANAGE_DOCUMENTS, or grantUriPermission() 更新2: 他下面還有關於 DfuBaseService 一樣權限的問題..,我下個步驟是要抓這個 DfuBaseService 的 code 在 mainifest.xml加上權限看看 6-20 12:20:55.858 21818 21831 E DatabaseUtils: java.lang.SecurityException: Permission Denial: reading com.android.externalstorage.ExternalStorageProvider uri content://com.android.externalstorage.documents/document/primary%3ANordic%20Semiconductor%2Fnrf52832_xxaa_s132.bin from pid=21436, uid=10259 requires android.permission.MANAGE_DOCUMENTS, or grantUriPermission() 06-20 12:20:55.858 21818 21831 E DatabaseUtils: at android.content.ContentProvider.enforceReadPermissionInner(ContentProvider.java:608) 06-20 12:20:55.858 21818 21831 E DatabaseUtils: at android.content.ContentProvider$Transport.enforceReadPermission(ContentProvider.java:483) 06-20 12:20:55.858 21818 21831 E DatabaseUtils: at android.content.ContentProvider$Transport.enforceFilePermission(ContentProvider.java:474) 06-20 12:20:55.858 21818 21831 E DatabaseUtils: at android.content.ContentProvider$Transport.openTypedAssetFile(ContentProvider.java:419) 06-20 12:20:55.858 21818 21831 E DatabaseUtils: at android.content.ContentProviderNative.onTransact(ContentProviderNative.java:319) 06-20 12:20:55.858 21818 21831 E DatabaseUtils: at android.os.Binder.execTransact(Binder.java:565) 06-20 12:20:55.859 21436 21845 E DfuBaseService: A security exception occurred while opening file 06-20 12:20:55.859 21436 21845 E DfuBaseService: java.lang.SecurityException: Permission Denial: reading com.android.externalstorage.ExternalStorageProvider uri content://com.android.externalstorage.documents/document/primary%3ANordic%20Semiconductor%2Fnrf52832_xxaa_s132.bin from pid=21436, uid=10259 requires android.permission.MANAGE_DOCUMENTS, or grantUriPermission() 更新3: 我將 DFU library 抓下來,在mainifest.xml加上 <uses-permission android:name="android.permission.MANAGE_DOCUMENT 無效... 有沒有啥解法...?感謝 更新4: 這是某段註解,就像s大說的可以用file或者content。 * The URI returned from application may be in 'file' or 'content' schema. 'File' schema allows us to create a File object and read details from if * directly. Data from 'Content' schema must be read by Content Provider. To do that we are using a Loader.*/ 我的APP 獲得到的 content,最後給 dfu library內的 DfuBaseService來讀取,讀取不了 的原因是因為沒有權限。我可以理解為- DfuBaseService 沒有那個權限,而這個權限 是由系統的Loader提供的嗎? ACTION_GET_CONTENT一發出,會可以讓我選擇適合的 檔案管理APK來載入檔案,所以說這個權限是由這個檔案管理的APK提供的嗎? 這個權限到底是 loader 給的還是檔案管理apk給的~"~? 是系統的loader吧? 所以我的app才需要實作loader相關的function? -- ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 58.115.110.197 ※ 文章網址: https://www.ptt.cc/bbs/AndroidDev/M.1497886262.A.A02.html ※ 編輯: gn00618777 (61.220.69.181), 06/20/2017 10:17:43 ※ 編輯: gn00618777 (61.220.69.181), 06/20/2017 12:01:05

06/20 12:57, , 1F
就沒權限存取那個位置的檔案啊
06/20 12:57, 1F

06/20 13:03, , 2F
這個URI是個content uri,是跟系統的DocumentProvider取
06/20 13:03, 2F
※ 編輯: gn00618777 (61.220.69.181), 06/20/2017 13:30:52 ※ 編輯: gn00618777 (61.220.69.181), 06/20/2017 14:57:31

06/20 15:12, , 3F
或是我可以設定 ACTION_GET_CONTENT後可以直接存取
06/20 15:12, 3F

06/20 15:13, , 4F
某個特定的檔案嗎,不用經由客戶來選?
06/20 15:13, 4F

06/20 15:13, , 5F
setDataAndType好像也不能直接選取到我要的檔案..
06/20 15:13, 5F

06/20 15:14, , 6F
MANAGE_DOCUMENTS不是第三方App可以要的權限
06/20 15:14, 6F

06/20 15:18, , 7F
問題不是在用ACTION_GET_CONTENT要,而是你要到的這個URI
06/20 15:18, 7F

06/20 15:20, , 8F
是content uri。你現在要存取的這個檔案是你可以控制的? 直
06/20 15:20, 8F

06/20 15:20, , 9F
接看它放在哪然後用file://的URI就可以了吧
06/20 15:20, 9F

06/20 15:33, , 10F
s大感謝你的回覆。 你說可以控制的是指檔案格式還是
06/20 15:33, 10F

06/20 15:34, , 11F
存放位址還是 URI 的 scheme?
06/20 15:34, 11F

06/20 15:37, , 12F
從S大的回覆是指這個 bin 我可以用 file://的URI去設?
06/20 15:37, 12F

06/20 15:44, , 13F
經你一說我有看DfuActivity 有關於判斷得到的uri是屬
06/20 15:44, 13F

06/20 15:44, , 14F
於 sheme 是 file 或是 content的設置
06/20 15:44, 14F

06/20 15:48, , 15F
content是找某個ContentProvider要,必須符合該Provider的
06/20 15:48, 15F

06/20 15:48, , 16F
限制,例如現在這個com.android.externalstorage.documents
06/20 15:48, 16F

06/20 15:50, , 17F
要求app必須就是當初用ACTION_GET_CONTENT跟它要的那個app
06/20 15:50, 17F

06/20 15:52, , 18F
file是看如果是app自己的目錄就沒任何限制,如果是共用的目
06/20 15:52, 18F

06/20 15:53, , 19F
錄要READ_EXTERNAL_STORAGE權限,如果是系統目錄就不能存取
06/20 15:53, 19F

06/20 15:54, , 20F
用content的可能還是對應到某個檔案,但是用content去存取
06/20 15:54, 20F

06/20 15:54, , 21F
跟直接用file存取,遇到的限制就會不同
06/20 15:54, 21F

06/20 15:57, , 22F
如果你能控制那檔案放哪,就放在能取的地方然後用file
06/20 15:57, 22F
※ 編輯: gn00618777 (61.220.69.181), 06/20/2017 16:17:40

06/20 16:18, , 23F
s大,我有更新4,請您看一下我的理解對不對?
06/20 16:18, 23F
※ 編輯: gn00618777 (61.220.69.181), 06/20/2017 16:21:17 ※ 編輯: gn00618777 (61.220.69.181), 06/20/2017 16:25:02

06/20 16:32, , 24F
不知道你說的loader是指哪個...
06/20 16:32, 24F

06/20 16:32, , 25F
ACTION_GET_CONTENT回來的uri的權限是檔案管理app給的,但
06/20 16:32, 25F

06/20 16:34, , 26F
是檔案管理app裡面實作當然有可能是再跟別人取的
06/20 16:34, 26F

06/20 16:35, , 27F
重點是你到底能不能直接存取那個檔案? 還是除了那個content
06/20 16:35, 27F

06/20 16:35, , 28F
URI以外你現在根本不知道那個檔案在哪?
06/20 16:35, 28F

06/20 16:59, , 29F
那個檔案存放的地方我可以決定,事實上我剛剛在搜尋
06/20 16:59, 29F

06/20 17:00, , 30F
怎樣將我要load的檔案轉成用file://表示的URI
06/20 17:00, 30F

06/20 17:01, , 31F
目前我用 File file = new File(Runtime.getExternal)
06/20 17:01, 31F

06/20 17:02, , 32F
StorageDirectory().toString() + "/Download/", name
06/20 17:02, 32F

06/20 17:02, , 33F
再用file.exists()先確認有沒有存在
06/20 17:02, 33F

06/20 17:03, , 34F
再用 Uri uri = Uri.fromFile(tmpFile);
06/20 17:03, 34F

06/20 17:04, , 35F
還不確定能不能用此Uri來更新 firmware,稍後測試
06/20 17:04, 35F

06/20 17:45, , 36F
我工作上是惡搞啦 ASSETS複製出去後在指定那位置更新
06/20 17:45, 36F

06/20 17:46, , 37F
更新成功後在onTransferCompleted階段刪檔
06/20 17:46, 37F

06/20 17:47, , 38F
這樣就不太用大改程式了....只是要多要讀寫權限就是了
06/20 17:47, 38F

06/20 17:47, , 39F
反正跟客戶說 因為更新設備 所以要讀寫檔案就呼嚨過去了..
06/20 17:47, 39F

06/20 17:47, , 40F
這是不好的示範就是了.....
06/20 17:47, 40F

06/20 18:05, , 41F
天啊 我成功了>"<<>"< 太感謝了.....真的是很感謝..
06/20 18:05, 41F

06/20 18:06, , 42F
不太懂P大說的內容..
06/20 18:06, 42F

06/20 18:07, , 43F
那這樣content的使用時機是啥,file://比較好用阿..
06/20 18:07, 43F

06/20 18:32, , 44F
asset如果在同個app不用複製,用file:///android_assets/可
06/20 18:32, 44F

06/20 18:33, , 45F
以直接存取
06/20 18:33, 45F

06/20 18:35, , 46F
content是跟ContentProvider要,ContentProvider的實作不一
06/20 18:35, 46F

06/20 18:36, , 47F
定是取檔案,可能從任何地方來,跟file是不同的概念
06/20 18:36, 47F

06/20 18:47, , 48F
Android N上uri有限制file://的使用,要注意一下
06/20 18:47, 48F

06/20 18:53, , 49F
p大以啥限制?我目前就是在N上開發
06/20 18:53, 49F

06/20 18:57, , 50F
N之後不能share file uri給別的app,在同一個app裡沒關係
06/20 18:57, 50F

06/21 16:00, , 51F
了解,謝謝分享
06/21 16:00, 51F
文章代碼(AID): #1PH-use2 (AndroidDev)
文章代碼(AID): #1PH-use2 (AndroidDev)