Backlight87
11/17/2017 - 12:45 PM

Android res/raw 和 assets 使用

Android res/raw 和 assets 使用

今天在研究通知栏的时候,不想用系统默认的提示音,就想着自定义提示音,了解到可以可以在项目中添加raw文件夹或者assets文件夹来存放音频,使用raw的话是放在res下面的,也就是说可以直接用过R.raw.xxx.mp3,获取到该音频。 注意:但是该文件夹下的音频会被编译成二进制文件,不能直接打开

音频

具体的新建方法:

下面是代码,说明下,我是为了图方便直接在BroadcastReceiver的onReceive方法里面发送Notification的,最好不要在onReceive方法里面做耗时操作。

public class Receiver1 extends BroadcastReceiver {

NotificationManager manager;
int notificationId = 0;

@Override
public void onReceive(Context context, Intent intent) {
    Intent intent1 = new Intent(context,MainActivity.class);//启动Activity的Intent
    PendingIntent pintent = PendingIntent.getActivity(context,0,intent1,0);
    Notification.Builder builder = new Notification.Builder(context);
    builder.setSmallIcon(R.mipmap.ic_launcher);
    builder.setTicker("Hello");//手机状态栏的提示
    builder.setWhen(System.currentTimeMillis());//设置时间
    builder.setContentTitle("通知栏通知");
    builder.setContentText("练习Notification");
    builder.setContentIntent(pintent);//点击之后的意图
    builder.setSound(Uri.parse("android.resource://" + context.getPackageName() + "/"+R.raw.sound));//自定义声音

// builder.setDefaults(Notification.DEFAULT_SOUND);//设置声音 builder.setDefaults(Notification.DEFAULT_LIGHTS);//设置指示灯,,,,,指示灯个震动都需要配置权限 builder.setDefaults(Notification.DEFAULT_VIBRATE);//设置震动效果 // builder.setDefaults(Notification.DEFAULT_ALL);//设置上面的三种效果

    //Android4.1以上的版本用Notification notification = builder.build();
    //Android4.1以下的版本用builder.getNotification();
    manager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
    Notification notification  = builder.build();
    manager.notify(notificationId,notification);
}

} 文件

在如下位置新建 assets 文件夹:

然后里面用到了一个 error.html 的 html 文件,用于在加载 webView 失败的时候展示给用户。

使用:

webView.loadUrl("file:///android_asset/error.html"); 1 这种方式可以加载assets目录下的网页,并且与网页有关的css,js,图片等文件也会的加载。

这样就可以使用了,是不是很简单呢?

后续

相同点

两者目录下的文件在打包后会原封不动的保存在apk包中,不会被编译成二进制,这些文件将被打包到APK中应用使用。

不同点

区别 一

可能有的朋友会问了,既然两种方式都是不会被编译成二进制文件,而我们在引用音频文件的时候,使用的是 R.raw.xxx.mp3 这种方式,为什么在使用文件的时候要使用 webView.loadUrl("file:///android_asset/error.html"); 这种方式?难道不能也使用 R.assets.errpr.html 这种方式来引用文件吗?

要弄清这个问题,首先要明白第一个不同点:

res/raw 中的文件会被映射到 R.java 文件中,访问的时候直接使用资源 ID 即 R.raw.xxx.mp3; assets 文件夹下的文件不会被映射到 R.java 中,访问的时候需要 AssetManager 类。 那么我们既然不能通过使用 R 文件的方式引用,我们可以通过使用绝对路径的方式去引用吗?

答案是否定的!

因为 apk 文件安装之后会放在 /data/app/ 目录下,以 apk 形式存在, asset/res 被绑定在 apk 里,并不会解压到 /data/data/你的应用包名 目录下去,所以我们无法直接获取到 assets 的绝对路径,因为它们根本就没有。 注意:下面的只能在已经 Root 的手机或者模拟器中可以看到

首先我们看下我们的手机在没安装 app 的情况下,data/app 文件夹下面有什么文件?

现在我们来安装一下简书 App :

我们发现,我们安装的 app 确实是出现在了 /data/app 文件夹下面。

这个时候如果你点开 /data/data/你的应用包名 文件夹查看的话,是看不到 assets 文件夹的,说明并没有解压到这里,所以就不能使用绝对路径去引用了。

system/app 系统自带的应用程序,无法删除。 data/app 用户程序安装的目录,有删除权限。安装时把apk文件复制到此目录。 data/data 存放应用程序的数据。 data/dalvik-cache 将 apk 中的 dex 文件安装到 dalvik-cache 目录下( dex 文件是 dalvik 虚拟机的可执行文件,其大小约为原始 apk 文件大小的四分之一)。 APP安装过程:复制APK安装包到data/app目录下,解压并扫描安装包,把dex文件(Dalvik字节码)保存到dalvik-cache目录,并data/data目录下创建对应的应用数据目录。

附录:

res/anim/ XML文件,它们被编译进逐帧动画(frame by frame animation)或补间动画(tweened animation)对象 res/drawable/

.png、.9.png、.jpg文件,它们被编译进以下的Drawable资源子类型中: 要获得这种类型的一个资源,可以使用Resource.getDrawable(id) 位图文件 9-patches(可变尺寸的位图) 为了获取资源类型,使用mContext.getResources().getDrawable(R.drawable.imageId) 注意:放在这里的图像资源可能会被aapt工具自动地进行无损压缩优化。比如,一个真彩色但并不需要256色的PNG可能会被转换为一个带调色板的8位PNG。这使得同等质量的图片占用更少的资源。所以我们得意识到这些放在该目录下的二进制图像在生成时可能会发生变化。如果你想读取一个图像位流并转换成一个位图(bitmap),请把图像文件放在res/raw/目录下,这样可以避免被自动优化。 res/layout/ 被编译为屏幕布局(或屏幕的一部分)的XML文件。参见布局声明(Declaring Layout)

res/values/ 可以被编译成很多种类型的资源的XML文件。注意: 不像其他的res/文件夹,它可以保存任意数量的文件,这些文件保存了要创建资源的描述,而不是资源本身。XML元素类型控制这些资源应该放在R类的什么地方,尽管这个文件夹里的文件可以任意命名,不过下面使一些比较典型的文件(文件命名的惯例是将元素类型包含在该名称之中): array.xml 定义数组 colors.xml 定义color drawable和颜色的字符串值(color string values)。使用Resource.getDrawable()和Resources.getColor()分别获得这些资源。 dimens.xml定义尺寸值(dimension value)。使用Resources.getDimension()获得这些资源。 strings.xml定义字符串(string)值。使用Resources.getString()或者Resources.getText()获取这些资源。getText()会保留在UI字符串上应用的丰富的文本样式。 styles.xml 定义样式(style)对象。 res/xml/ 任意的XML文件,在运行时可以通过调用Resources.getXML()读取。 res/raw/ 直接复制到设备中的任意文件。它们无需编译,添加到你的应用程序编译产生的压缩文件中。要使用这些资源,可以调用Resources.openRawResource(),参数是资源的ID,即R.raw.somefilename。 区别 二

另外需要我们注意的是:

res/raw 不可以有目录结构,也就是说只能存放一级目录,不能再下面建立文件夹。 而 assets 则可以有目录结构,也就是 assets 目录下可以再建立任意深度和数量的文件夹 assets 下面文件的使用

html文件

如上面例子所示

其他文件

获取 AssetManager

AssetManager assetManager =getAssets();
InputStream is = assetManager.open("filename");  

1 2 补充一下:在未知目录下有哪些文件,该去和获取这些文件的名称并把文件拷贝到目标目录中呢?(用于内置文件但不知道文件名称,需要筛选出想要的文件然后拷贝到目标目录中,推荐内置在assets文件夹中)

  1. res/raw目录: 通过反射的方式得到R.java里面raw内部类里面所有的资源ID的名称,然后通过名称获取资源ID的值来读取我们想要的文件。(这个方法我没试过,有用过的同学麻烦发一段代码看看)。
  2. assets目录: getAssets().list(“”);来获取assets目录下所有文件夹和文件的名称,再通过这些名称再读取我们想要的文件。