Android(安卓)Uri获取资源文件(多种方式)
16lz
2022-04-26
在Android中少不了去获取资源文件,在Android里封装了几种获取固定Resource文件的方式,今天不讲这个。
如果你要获取资源文件夹raw目录下的视频文件,那你会怎么做? 这时候Uri就排上用场了
我在这先设个疑问,通过Uri去拿raw文件夹下的mbg_unlock资源,以下哪种是正确的Uri呢?
- Uri uri = Uri.parse("android.resource://" + getPackageName() + "/raw/mbg_unlock" );
- Uri uri = Uri.parse("android.resource://" + getPackageName() + "/raw/" +R.raw.mbg_unlock);
- Uri uri = Uri.parse("android.resource://" + getPackageName() + "/" +R.raw.mbg_unlock);
- Uri uri = Uri.parse("android.resource://" + getPackageName() + "/xxxx/mbg_unlock" );
当你尝试以后你会发现,这四种都可以!是不是很神奇、很惊讶、是不是得说一句妈卖批,哈哈
读者可能会问了,前三种我还稍微可以理解,第四种也太无语了吧!别着急,我来给你解释为什么这四张都可以。
在Android中涉及Uri的操作一定少不了ContentResolver.java 这个类,而这个类就是我们所要找的那个关键类,如果不懂这个类是做什么的读者可以自己查一下。
通过debug在ContentResolver.java 中找到 getResourceId() 方法的这段代码,就是问题的关键。我来带大家解读一下
/** * Resolves an android.resource URI to a {@link Resources} and a resource id. * * @hide */ public OpenResourceIdResult getResourceId(Uri uri) throws FileNotFoundException { String authority = uri.getAuthority(); Resources r; if (TextUtils.isEmpty(authority)) { throw new FileNotFoundException("No authority: " + uri); } else { try { r = mContext.getPackageManager().getResourcesForApplication(authority); } catch (NameNotFoundException ex) { throw new FileNotFoundException("No package found for authority: " + uri); } } List path = uri.getPathSegments(); //对Uri包名后面根据 '/' 进行切割 if (path == null) { throw new FileNotFoundException("No path: " + uri); } int len = path.size(); int id; if (len == 1) { //如果包名后面的 '/'只有一个,就直接看看是不是int型的 id ,后面代码就直接根绝这个id调用native方法进行了资源查找。这也就解释了例3可以通过。 try { id = Integer.parseInt(path.get(0)); } catch (NumberFormatException e) { throw new FileNotFoundException("Single path segment is not a resource ID: " + uri); } } else if (len == 2) { //如果有两个,则调用了这个方法。下面有这个代码源码 id = r.getIdentifier(path.get(1), path.get(0), authority); } else { //如果是其他数量,则直接抛异常 throw new FileNotFoundException("More than two path segments: " + uri); } if (id == 0) { throw new FileNotFoundException("No resource found for: " + uri); } OpenResourceIdResult res = new OpenResourceIdResult(); res.r = r; res.id = id; return res; }
下面的是getIdentifier(path.get(1), path.get(0), authority)的源码:
int getIdentifier(String name, String defType, String defPackage) { if (name == null) { throw new NullPointerException("name is null"); } try { return Integer.parseInt(name); //直接对包名后面的的第二个'/'后面的部分进行判断是不是int型,如果是的话直接返回,然后进行native方法取资源。这也解释了为什么例2和例4都可以通过。 } catch (Exception e) { // Ignore } return mAssets.getResourceIdentifier(name, defType, defPackage); //这段代码是个native方法,系统根绝资源文件名进行查找到资源所对应的id,然后返回。这也说明了例1为什么能通过了。 }
在上面代码里面注释部分,对上满的问题进行了一一解答。应该可以解决读者的疑惑了吧,如果还是不是很懂可以自己动手debug试试~
更多相关文章
- Android应用开发中的风格和主题(style,themes)
- Android中可以做的两件坏事---破解锁屏密码和获取Wifi密码
- Android换肤功能设计与实现(5)——网络加载及图片内存管理
- Android仿淘宝首页UI(附代源代码及示例图片)
- 領航桌面App一秒鐘把你的 Android(安卓)手機換成 iPhone 介面
- Android(安卓)React Native加载图片资源的正确姿势
- Android中可以做的两件坏事---破解锁屏密码和获取Wifi密码
- 原来这样就可以开发出一个百万量级的Android相机
- 持续更新的Android(安卓)& Android(安卓)Jetpack & Material Des