在Android中少不了去获取资源文件,在Android里封装了几种获取固定Resource文件的方式,今天不讲这个。

如果你要获取资源文件夹raw目录下的视频文件,那你会怎么做?  这时候Uri就排上用场了

 

我在这先设个疑问,通过Uri去拿raw文件夹下的mbg_unlock资源,以下哪种是正确的Uri呢?

  1. Uri uri = Uri.parse("android.resource://" + getPackageName() + "/raw/mbg_unlock" );
  2. Uri uri = Uri.parse("android.resource://" + getPackageName() + "/raw/" +R.raw.mbg_unlock);
  3. Uri uri = Uri.parse("android.resource://" + getPackageName() + "/" +R.raw.mbg_unlock);
  4. 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试试~

 

 

 

更多相关文章

  1. Android应用开发中的风格和主题(style,themes)
  2. Android中可以做的两件坏事---破解锁屏密码和获取Wifi密码
  3. Android换肤功能设计与实现(5)——网络加载及图片内存管理
  4. Android仿淘宝首页UI(附代源代码及示例图片)
  5. 領航桌面App一秒鐘把你的 Android(安卓)手機換成 iPhone 介面
  6. Android(安卓)React Native加载图片资源的正确姿势
  7. Android中可以做的两件坏事---破解锁屏密码和获取Wifi密码
  8. 原来这样就可以开发出一个百万量级的Android相机
  9. 持续更新的Android(安卓)& Android(安卓)Jetpack & Material Des

随机推荐

  1. Elasticsearch 最佳运维实践 - 总结(一)
  2. 踩坑CBO,解决那些坑爹的SQL优化问题
  3. Intel Thunderbolt曝出7个漏洞,影响过去9
  4. Sentence-BERT: 一种能快速计算句子相似
  5. 【MOS】Limitations of the Oracle Cost
  6. memcached程序端口监控脚本
  7. PKG_COLLECTION_LHR 存储过程或函数返回
  8. cront计划任务的详细讲解
  9. 【MOS】RAC 环境中 gc block lost 和私网
  10. Iptables 规则用法小结