在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实现计时与倒计时(限时抢购)的几种方法
  2. 安卓视频播放器 一行代码快速实现视频播放,Android视频播放,Androi
  3. Android Zip文件解压缩代码
  4. (20120722)(笔记004)android开发应用程序资源
  5. Android如何完全调试framework层代码
  6. Android自定义View的实现方法,带你一步步深入了解View(三) 。
  7. android studio如何生成混淆代码的jar
  8. Android React Native加载图片资源的正确姿势
  9. 【移动开发】Android中图片过大造成内存溢出,OOM(OutOfMemory)异常

随机推荐

  1. 【转】Android(安卓)--Google Market
  2. android系统学习笔记二
  3. android中checkbox自定义样式
  4. MT6573默认锁屏界面修改
  5. android xml
  6. android获取手机型号和系统版本号
  7. 自定义圆形进度条ProgressBar的三种方式
  8. Android去掉标题,强制设置横屏或竖屏
  9. Android(安卓)HorizontalScrollView 水平
  10. Android设置权限问题