kniost

谁怕,一蓑烟雨任平生

0%

Android编程权威指南(第二版)学习笔记(十八)—— 第18章 Assets

本章介绍了 assets。assets 是有别于 resources 的另一种资源打包方式,可以被看作随应用打包的微型文件系统,支持任意层次的文件目录结构。因为这个优点,类似游戏这样需要加载大量图片和声音资源的应用通常都会使用它。

GitHub 地址:
完成18章

这章需要用到一个 RecyclerView,其中每个 ViewHolder 对应一个音频文件。如果使用 resources 来管理声音文件,那么 Android 一个一个处理效率将极其低下(毕竟声音是时间敏感的),所以我们使用 Assets 来处理。

1 导入 Assets

在模块的根目录下新建 assets 文件(或者右键点击模块的根目录新建),然后建立需要的资源文件夹并放入资源。

2 处理 Assets

assets 导入后,我们还要能在应用中进行定位、管理记录以及播放。这需要新建一个名为 BeatBox 的资源管理类,代码和相应注释如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public class BeatBox {
// TAG 变量用于记录日志
private static final String TAG = "BeatBox";

// 用于存储声音资源文件目录名
private static final String SOUNDS_FOLDER = "sample_sounds";

// 访问 assets 需要用到 AssetManager 对象
private AssetManager mAssets;

public BeatBox(Context context) {
// 在初始化的时候获取 assets 的管理对象
// 不用在意 Context 是哪个,因为
// 所有的 AssetManager 管理的都是一套 assets 资源
mAssets = context.getAssets();
loadSounds();
}

private void loadSounds() {
String[] soundNames = new String[]{};
try {
// 获取所有文件的名字
soundNames = mAssets.list(SOUNDS_FOLDER);
Log.i(TAG, "Found " + soundNames.length + " sounds");
} catch (IOException ioe) {
Log.e(TAG, "Could not list assets", ioe);
}
}
}

3 使用 Assets

获取到资源文件名之后,要将其展示给用户,最终还需要播放这些声音文件。所以,我们得创建一个对象,让它管理资源文件名、用户应该看到的文件名以及其他一些相关信息。在这里,我们创建了一个叫 Sound 的类用来管理一个声音:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class Sound {
private String mAssetPath;
private String mName;

public Sound(String assetPath) {
mAssetPath = assetPath;
// 将文件路径用"/"分割
String[] components = assetPath.split("/");
// 取最后一个,即文件名
String filename = components[components.length - 1];
// 在知道文件名结尾是 .wav 的情况下,直接将 .wav 替换为空
mName = filename.replace(".wav", "");
}

public String getAssetPath() {
return mAssetPath;
}

public String getName() {
return mName;
}
}

然后在 BeatBox 类中获取所有的 Sound 对象,这样我们就有了 RecyclerView 的数据集,然后就能够绑定声音和 ViewHolder 了。

4 访问 Assets

Sound 对象定义了 assets 文件路径。但是尝试使用 File 对象打开资源文件是行不通的;
正确的方式是使用 AssetManager:

1
2
String assetPath = sound.getAssetPath();
InputStream soundData = mAssets.open(assetPath);

这样才能得到标准的 InputStream 数据流。随后,和 Java 中的其他 InputStream 一样,该怎么用就怎么用。
不过,有些 API 可能还会需要 FileDescriptor。(下一章的 SoundPool 类会用到。)这也好办, 如下列代码所示,改调用 AssetManager.openFd(String)方法就行了。

1
2
3
4
5
String assetPath = sound.getAssetPath();
// AssetFileDescriptors are different from FileDescriptors,
AssetFileDescriptor assetFd = mAssets.openFd(assetPath);
// but you get can a regular FileDescriptor easily if you need to.
FileDescriptor fd = assetFd.getFileDescriptor();

GitHub Page: kniost.github.io
简书:http://www.jianshu.com/u/723da691aa42