作者gn00618777 (非常念旧)
看板AndroidDev
标题[问题] 关於Uri
时间Mon Jun 19 23:30:57 2017
我是抓取 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://webptt.com/cn.aspx?n=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
1F:→ ssccg: 就没权限存取那个位置的档案啊 06/20 12:57
2F:→ ssccg: 这个URI是个content uri,是跟系统的DocumentProvider取 06/20 13:03
※ 编辑: gn00618777 (61.220.69.181), 06/20/2017 13:30:52
※ 编辑: gn00618777 (61.220.69.181), 06/20/2017 14:57:31
3F:→ gn00618777: 或是我可以设定 ACTION_GET_CONTENT後可以直接存取 06/20 15:12
4F:→ gn00618777: 某个特定的档案吗,不用经由客户来选? 06/20 15:13
5F:→ gn00618777: setDataAndType好像也不能直接选取到我要的档案.. 06/20 15:13
6F:→ ssccg: MANAGE_DOCUMENTS不是第三方App可以要的权限 06/20 15:14
7F:→ ssccg: 问题不是在用ACTION_GET_CONTENT要,而是你要到的这个URI 06/20 15:18
8F:→ ssccg: 是content uri。你现在要存取的这个档案是你可以控制的? 直 06/20 15:20
9F:→ ssccg: 接看它放在哪然後用file://的URI就可以了吧 06/20 15:20
10F:→ gn00618777: s大感谢你的回覆。 你说可以控制的是指档案格式还是 06/20 15:33
11F:→ gn00618777: 存放位址还是 URI 的 scheme? 06/20 15:34
12F:→ gn00618777: 从S大的回覆是指这个 bin 我可以用 file://的URI去设? 06/20 15:37
13F:→ gn00618777: 经你一说我有看DfuActivity 有关於判断得到的uri是属 06/20 15:44
14F:→ gn00618777: 於 sheme 是 file 或是 content的设置 06/20 15:44
15F:→ ssccg: content是找某个ContentProvider要,必须符合该Provider的 06/20 15:48
16F:→ ssccg: 限制,例如现在这个com.android.externalstorage.documents 06/20 15:48
17F:→ ssccg: 要求app必须就是当初用ACTION_GET_CONTENT跟它要的那个app 06/20 15:50
18F:→ ssccg: file是看如果是app自己的目录就没任何限制,如果是共用的目 06/20 15:52
19F:→ ssccg: 录要READ_EXTERNAL_STORAGE权限,如果是系统目录就不能存取 06/20 15:53
20F:→ ssccg: 用content的可能还是对应到某个档案,但是用content去存取 06/20 15:54
21F:→ ssccg: 跟直接用file存取,遇到的限制就会不同 06/20 15:54
22F:→ ssccg: 如果你能控制那档案放哪,就放在能取的地方然後用file 06/20 15:57
※ 编辑: gn00618777 (61.220.69.181), 06/20/2017 16:17:40
23F:→ gn00618777: s大,我有更新4,请您看一下我的理解对不对? 06/20 16:18
※ 编辑: gn00618777 (61.220.69.181), 06/20/2017 16:21:17
※ 编辑: gn00618777 (61.220.69.181), 06/20/2017 16:25:02
24F:→ ssccg: 不知道你说的loader是指哪个... 06/20 16:32
25F:→ ssccg: ACTION_GET_CONTENT回来的uri的权限是档案管理app给的,但 06/20 16:32
26F:→ ssccg: 是档案管理app里面实作当然有可能是再跟别人取的 06/20 16:34
27F:→ ssccg: 重点是你到底能不能直接存取那个档案? 还是除了那个content 06/20 16:35
28F:→ ssccg: URI以外你现在根本不知道那个档案在哪? 06/20 16:35
29F:→ gn00618777: 那个档案存放的地方我可以决定,事实上我刚刚在搜寻 06/20 16:59
30F:→ gn00618777: 怎样将我要load的档案转成用file://表示的URI 06/20 17:00
31F:→ gn00618777: 目前我用 File file = new File(Runtime.getExternal) 06/20 17:01
32F:→ gn00618777: StorageDirectory().toString() + "/Download/", name 06/20 17:02
33F:→ gn00618777: 再用file.exists()先确认有没有存在 06/20 17:02
34F:→ gn00618777: 再用 Uri uri = Uri.fromFile(tmpFile); 06/20 17:03
35F:→ gn00618777: 还不确定能不能用此Uri来更新 firmware,稍後测试 06/20 17:04
36F:推 paulku: 我工作上是恶搞啦 ASSETS复制出去後在指定那位置更新 06/20 17:45
37F:→ paulku: 更新成功後在onTransferCompleted阶段删档 06/20 17:46
38F:→ paulku: 这样就不太用大改程式了....只是要多要读写权限就是了 06/20 17:47
39F:→ paulku: 反正跟客户说 因为更新设备 所以要读写档案就呼咙过去了.. 06/20 17:47
40F:→ paulku: 这是不好的示范就是了..... 06/20 17:47
41F:→ gn00618777: 天啊 我成功了>"<<>"< 太感谢了.....真的是很感谢.. 06/20 18:05
42F:→ gn00618777: 不太懂P大说的内容.. 06/20 18:06
43F:→ gn00618777: 那这样content的使用时机是啥,file://比较好用阿.. 06/20 18:07
44F:→ ssccg: asset如果在同个app不用复制,用file:///android_assets/可 06/20 18:32
45F:→ ssccg: 以直接存取 06/20 18:33
46F:→ ssccg: content是跟ContentProvider要,ContentProvider的实作不一 06/20 18:35
47F:→ ssccg: 定是取档案,可能从任何地方来,跟file是不同的概念 06/20 18:36
48F:→ bukiya: Android N上uri有限制file://的使用,要注意一下 06/20 18:47
49F:→ gn00618777: p大以啥限制?我目前就是在N上开发 06/20 18:53
50F:→ ssccg: N之後不能share file uri给别的app,在同一个app里没关系 06/20 18:57
51F:→ gn00618777: 了解,谢谢分享 06/21 16:00