游戏编程肯定不光只是用手机内存还要访问外部存储空间,主要是访问SD卡。先从读取资源文件开始。
我们知道assets/和res/文件夹用于存放可在应用程序中的使用文件。
assets/用于存储各种应用程序中需要的文件(例如配置文件或音频文件等),这些文件会打包在Android应用程序中。
res/包含应用程序所需的各种资源文件,如icons、用于国际化的字符串文件和用于界面布局的XML文件。它们同样打包于应用文件中。
在这里我们不使用res/文件夹,因为它对我们构造文件集存在限制。而assets/目录才是我们存放的地方,无论如何层次结构的文件夹都可以。
Assets/文件夹中的文件通过一个AssetManager类显示出来,我们可以在应用程序中引用该管理器,如下所示:
AssetManager assetManager = context.getAssets();
一旦我们得到AssetManager,就可以容易地打开文件:
InputStream inputStream = assetManager.open("dir/dir2/filename.txt");
该方法将返回一个普通Java输入流InputStream,通过它我们可以读取任何类型的文件。AssetManager.open()方法的唯一参数是相对于asset目录的文件名,如果路径为dir/dir2/filename.txt,那么在Eclipse里就是assets/dir/dir2/filename.txt。
现在我们从assets/目录下的一个texts子目录来加载txt文件并将其显示在TextView中。
代码如下:
package org.example.ch04_android_basics; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import android.app.Activity; import android.content.res.AssetManager; import android.os.Bundle; import android.widget.TextView; public class AssetsTest extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); TextView textView = new TextView(this); setContentView(textView); AssetManager assetManager = getAssets(); InputStream inputStream = null; try{ inputStream = assetManager.open("texts/myawesometext.txt"); String text = loadTextFile(inputStream); textView.setText(text); }catch(IOException e){ textView.setText("Couldn't load file"); }finally{ if(inputStream != null) try{ inputStream.close(); }catch(IOException e){ textView.setText("Couldn't close file"); } } } public String loadTextFile(InputStream inputStream) throws IOException{ ByteArrayOutputStream byteStream = new ByteArrayOutputStream(); byte[] bytes = new byte[4096]; int len = 0; while((len = inputStream.read(bytes)) > 0) byteStream.write(bytes, 0, len); return new String(byteStream.toByteArray(), "UTF-8"); } }
运行效果如下:
这里用了一个小方法loadTextFile(),用于从InputStream中读取所有字节并将所有字节转换成字符串返回,并采用UTF-8编码。
接下来该访问外部存储文件了,有时候我们需要持久保存一些信息并在随后重新加载它们。
首先要做的是请求实际访问外部存储空间的权限,需要在清单文件的<uses-permission>元素中添加该权限,关于这些权限可以参考Android游戏编程Manifest文件准备,接下来我们需要检查一下所用设备是否存在有用的外部存储空间。
String state = Environment.getExternalStorageState();
我们得到一个字符串。Environment类中定义了很多常量,其中一个叫Environment.MEDIA_MOUNTED,它也是一个字符串。如果返回的字符串等于该常量,我们就具有读写外部存储空间的全部权限。注意这里需要用equals()方法来比较这两个字符串,而引用等式在任何情况下是无法工作的。关于String使用equals()方法和==的区别可以参考。
一旦我们确定可以访问外部存储空间,就需要获取其根目录的名称。如果我们想访问一个特定的文件,就需要相对于根目录去指定它。
File externalDir = Environment.getExternalStorageDirectory(); 获取根目录
现在可以在SD卡上写入一个文件,并把它读出来显示在TextView上了,然后再将该文件删除,代码如下:
package org.example.ch04_android_basics; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import android.app.Activity; import android.os.Bundle; import android.os.Environment; import android.widget.TextView; public class ExternalStorageTest extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); TextView textView = new TextView(this); setContentView(textView); String state = Environment.getExternalStorageState(); if(!state.equals(Environment.MEDIA_MOUNTED)){ textView.setText("No external storage mounted"); }else{ File externalDir = Environment.getExternalStorageDirectory(); File textFile = new File(externalDir.getAbsolutePath() + File.separator + "text.txt"); try{ writeTextFile(textFile, "This is test. Roger"); String text = readTextFile(textFile); textView.setText(text); if(!textFile.delete()){ textView.setText("Couldn't remove temporary file"); } }catch(IOException e){ textView.setText("Something went wrong! " + e.getMessage()); } } } private void writeTextFile(File file, String text) throws IOException{ BufferedWriter writer = new BufferedWriter(new FileWriter(file)); writer.write(text); writer.close(); } private String readTextFile(File file) throws IOException{ BufferedReader reader = new BufferedReader(new FileReader(file)); StringBuilder text = new StringBuilder(); String line; while((line = reader.readLine()) != null){ text.append(line); text.append("\n"); } reader.close(); return text.toString(); } }
运行效果如下:
从这里我们可以看出,我们很容易删除外部设备上的所有文件,因此从安卓市场下载并安装那些需要SD卡权限的应用程序时,一定要三思而后行。一旦安装了该应用程序,它将能完全控制你的文件