Android 资源获取和表示方式

原创
2014/12/08 10:31
阅读数 2.6W

前言:

在某些应用中,为了实现应用apk资源放入重复利用,或者使用反射得到本应用的资源,需要使用反射反射方式获得,但Resources类中也自带了这种获取方式,并且功能更加强大的方式。此外,在特殊情况下,我们还时不时需要获取系统资源,因此有必要了解资源的表示和获取方式。

 

你可以获取string、color、drawable、raw、xml等文件,因此也就意味着,这里可以获取的资源是res中已定义的资源,对于控件id的获取,暂时无法做到

android.content.res.Resources.class

 public int getIdentifier(String name, String defType, String defPackage) {
        if (name == null) {
            throw new NullPointerException("name is null");
        }
        try {
            return Integer.parseInt(name);
        } catch (Exception e) {
            // Ignore
        }
        return mAssets.getResourceIdentifier(name, defType, defPackage);
    }

 

一、 获取资源的id

1.如下,我们可以获取当前应用的资源id

 int drawableId = mContext.getResources().getIdentifier("ic_launcher","drawable", mContext.getPackageName());
 mImageView.setImageResource(drawableId);

2.我们也可以获取其他应用的资源id

Resources resources = context.getResources();
int indentify= getResources().getIdentifier("icon", "drawable", "org.anddev.android.testproject");

int resId = getResources().getIdentifier("background", "color", getPackageName());
startBtn.setTextColor(getResources().getColor(resId));

对于这种方式,我们也可以这么做

表达方式
getResources().getIdentifier(packageName+":"+ resType+"/"+ resourceName,null,null)

举例:
int indentify = getResources().getIdentifier("org.loveandroid.androidtest:drawable/icon",null,null);

注意:这里需要注意,除了系统内置资源,如果你的apk中对文件夹名称有压缩(如利用AndResGuard),显然这种获取资源的方式不适合使用

 

3.进行封装一下

public static int getResourceId(Context context,String name,String type,String packageName){
        Resources themeResources=null;
        PackageManager pm=context.getPackageManager();
        try {
            themeResources=pm.getResourcesForApplication(packageName);
            return themeResources.getIdentifier(name, type, packageName);
        } catch (NameNotFoundException e) {

            e.printStackTrace();
        }
        return 0;
 }

 

二、 uri资源标识和读取

uri资源一般分为3类

public static final String SCHEME_CONTENT = "content";
public static final String SCHEME_ANDROID_RESOURCE = "android.resource";
public static final String SCHEME_FILE = "file";

参考ImageView中的实现,我们先熟悉一下大致用法

private Drawable getDrawableFromUri(Uri uri) {
    final String scheme = uri.getScheme();
    if (ContentResolver.SCHEME_ANDROID_RESOURCE.equals(scheme)) {
        try {
            // Load drawable through Resources, to get the source density information
            ContentResolver.OpenResourceIdResult r =
                    mContext.getContentResolver().getResourceId(uri);
            return r.r.getDrawable(r.id, mContext.getTheme());
        } catch (Exception e) {
            Log.w(LOG_TAG, "Unable to open content: " + uri, e);
        }
    } else if (ContentResolver.SCHEME_CONTENT.equals(scheme)
            || ContentResolver.SCHEME_FILE.equals(scheme)) {
        try {
            Resources res = sCompatUseCorrectStreamDensity ? getResources() : null;
            ImageDecoder.Source src = ImageDecoder.createSource(mContext.getContentResolver(),
                    uri, res);
            return ImageDecoder.decodeDrawable(src, (decoder, info, s) -> {
                decoder.setAllocator(ImageDecoder.ALLOCATOR_SOFTWARE);
            });
        } catch (IOException e) {
            Log.w(LOG_TAG, "Unable to open content: " + uri, e);
        }
    } else {
        return Drawable.createFromPath(uri.toString());
    }
    return null;
}

 

由于content://和file:// 作为经常使用的方式,我们不做太多赘述,重点说一下android.resource

android系统中,应用的资源存储时也通常会被存入 数据库,也可以被共享,因此来说资源会获得应用的uri

Uri uri = Uri.parse("android.resource://"+getPackageName()+"/"+R.raw.xinyueshenhua);
Uri uri = Uri.parse("android.resource://"+getPackageName()+"/"+R.drawable.ic_launcher);

我们也可以进一步封装

public static  Uri getResourceUri(int resId,String packageName){
    return Uri.parse("android.resource://"+packageName+"/"+resId);
}

 

对于Content:// 而言,一般需要再特定的ContentProvider中获取资源

Uri mImageCaptureUri = data.getData();
Bitmap photoBmp = null;
if (mImageCaptureUri != null) {
    photoBmp = MediaStore.Images.Media.getBitmap(ac.getContentResolver(), mImageCaptureUri);
}

 

当然,也有些情况,file、content、android.resource都可以使用

或如下方式

/** 
     * 通过uri获取图片并进行压缩 
     * 
     * @param uri 
     */  
    public static Bitmap getBitmapFormUri(Activity ac, Uri uri) throws FileNotFoundException, IOException {  
        InputStream input = ac.getContentResolver().openInputStream(uri);  
        BitmapFactory.Options onlyBoundsOptions = new BitmapFactory.Options();  
        onlyBoundsOptions.inJustDecodeBounds = true;  
        onlyBoundsOptions.inDither = true;//optional  
        onlyBoundsOptions.inPreferredConfig = Bitmap.Config.ARGB_8888;//optional  
        BitmapFactory.decodeStream(input, null, onlyBoundsOptions);  
        input.close();  
        int originalWidth = onlyBoundsOptions.outWidth;  
        int originalHeight = onlyBoundsOptions.outHeight;  
        if ((originalWidth == -1) || (originalHeight == -1))  
            return null;  
        //图片分辨率以480x800为标准  
        float hh = 800f;//这里设置高度为800f  
        float ww = 480f;//这里设置宽度为480f  
        //缩放比。由于是固定比例缩放,只用高或者宽其中一个数据进行计算即可  
        int be = 1;//be=1表示不缩放  
        if (originalWidth > originalHeight && originalWidth > ww) {//如果宽度大的话根据宽度固定大小缩放  
            be = (int) (originalWidth / ww);  
        } else if (originalWidth < originalHeight && originalHeight > hh) {//如果高度高的话根据宽度固定大小缩放  
            be = (int) (originalHeight / hh);  
        }  
        if (be <= 0)  
            be = 1;  
        //比例压缩  
        BitmapFactory.Options bitmapOptions = new BitmapFactory.Options();  
        bitmapOptions.inSampleSize = be;//设置缩放比例  
        bitmapOptions.inDither = true;//optional  
        bitmapOptions.inPreferredConfig = Bitmap.Config.ARGB_8888;//optional  
        input = ac.getContentResolver().openInputStream(uri);  
        Bitmap bitmap = BitmapFactory.decodeStream(input, null, bitmapOptions);  
        input.close();  
   
        return compressImage(bitmap);//再进行质量压缩  
    }  

 

三、asset资源

实际上asset比较特殊,android中提供了android_asset标识,但它仅仅是host,而不是scheme,不要再使用中混淆了。

file:///android_asset/win8_Demo/index.html

四、Android 获取系统资源Id

int indentify = getResources().getIdentifier("actionbar_bg", "drawable","android");  //注意,最后一个参数必须是“android”

 

展开阅读全文
加载中
点击加入讨论🔥(4) 发布并加入讨论🔥
4 评论
0 收藏
2
分享
返回顶部
顶部