resources资源可以存储声音文件,但当处理多个音乐文件时,效率会很低。
assets可以被看作随应用打包的微型文件系统,支持任意层次的文件目录结构。类似游戏这样需要加载大量图片和声音资源的应用通常都会使用它
1. 导入assets
在app模块下创建assets目录,然后建立需要的资源文件夹并放入资源。
2. 处理assets
assets导入后,我们还要能在应用中进行定位,管理记录,以及播放,这需要新建一个名为 BeatBox 的资源管理类。代码如下:
1 public class BeatBox { 2 3 //用于日志记录 4 private static final String TAG = "BeatBox"; 5 6 //用于存储声音资源文件目录名 7 private static final String SOUNDS_FOLDER = "sample_sounds"; 8 9 //访问assets需要用到AssetManager类,可以从context中获取到它,这里添加一个带Contex参数的构造函数获取并留存它。 10 private AssetManager mAssets; 11 12 public BeatBox(Context context){ 13 /* 14 * 访问assets时,可以不用关心究竟使用哪个Contex对象, 15 * 而且在实际开发的任何场景下,所有Context中的AssetManager管理的都是同一套assets资源。 16 */ 17 mAssets = context.getAssets(); 18 loadSounds(); 19 } 20 21 private void loadSounds(){ 22 String[] soundNames; 23 try{ 24 //list(S)方法取得assets中的资源清单。能够列出指定目录中的所有文件名。 25 //只要传入声音资源所在的目录,就能看到其中所有的.wav文件。 26 soundNames = mAssets.list(SOUNDS_FOLDER); 27 Log.i(TAG, "Found "+ soundNames.length + " sounds"); 28 }catch (IOException ioe){ 29 Log.e(TAG, "Could not list assets",ioe ); 30 return; 31 } 32 } 33 }
3. 使用Assets
获取到资源文件名之后,要讲其展示给用户,最终还需要播放这些声音文件,所以,我们得创建一个对象,让它管理资源文件名,用户应该看到的文件名以及其他一些相关信息。
创建一个Sound管理类。
1 public class BeatBox { 2 3 //用于日志记录 4 private static final String TAG = "BeatBox"; 5 6 //用于存储声音资源文件目录名 7 private static final String SOUNDS_FOLDER = "sample_sounds"; 8 9 //访问assets需要用到AssetManager类,可以从context中获取到它,这里添加一个带Contex参数的构造函数获取并留存它。 10 private AssetManager mAssets; 11 12 //创建一个Sound列表 13 private List<Sound> mSounds = new ArrayList<>(); 14 15 public BeatBox(Context context){ 16 /* 17 * 访问assets时,可以不用关心究竟使用哪个Contex对象, 18 * 而且在实际开发的任何场景下,所有Context中的AssetManager管理的都是同一套assets资源。 19 */ 20 mAssets = context.getAssets(); 21 loadSounds(); 22 } 23 24 private void loadSounds(){ 25 String[] soundNames; 26 try{ 27 //list(S)方法取得assets中的资源清单。能够列出指定目录中的所有文件名。 28 //只要传入声音资源所在的目录,就能看到其中所有的.wav文件。 29 soundNames = mAssets.list(SOUNDS_FOLDER); 30 Log.i(TAG, "Found "+ soundNames.length + " sounds"); 31 }catch (IOException ioe){ 32 Log.e(TAG, "Could not list assets",ioe ); 33 return; 34 } 35 36 for(String fileName : soundNames){ 37 String assetPath = SOUNDS_FOLDER + "/" + fileName; 38 Sound sound = new Sound(assetPath); 39 mSounds.add(sound); 40 } 41 } 42 43 public List<Sound> getSounds(){ 44 return mSounds; 45 } 46 }
4. 访问Assets
Sound对象定义了assets文件路径,尝试使用File对象打开资源文件是行不通的,正确的方式是使用AssetManager:
String assetPath = sound.getAssetPath();
InputStream sounData = mAssets.open(assetPath); //这样就得到了标准的InputStream数据流,随后,和java中的其他InputStream一样,该怎么用就怎么用。
不过有些API可能还会需要FileDescriptor。只需要改为调用AddetManager.openFd(String)方法就行了。
String assetPath = sound.getAssetPath();
AssetFileDescriptor assetFd = mAssets.openFd(assetPath);
FileDescriptor fd = assetFd.getFileDescriptor();