使用外部存储
每个Android兼容的设备都支持用于保存文件的一个共享的外部存储器。这个存储器能够是一种可移动的存储介质(如SD卡)或是内部的(不可移动的)存储器。被保存在外部存储器上的文件是完全共享的,并且在启用了USB存储把文件传输到计算机上时,用户能够修改这些文件。
警告:如果应用把外部存储器挂载到计算机上或者移除这个存储介质,那么外部文件就不能够显示了,并且这些保存在外部存储器上的文件没有任何安全可言。所有的应用程序都能够读/写放在外部存储器上的文件,并且用户也能够删除它们。
检查存储介质的可用性
在用外部存储器工作之前,应该始终调用getExternalStorageState()方法来检查存储介质是否可用。存储介质可能被挂载在一个丢失的、或是只读等其他状态的计算机上。以下是检查可用性的方法:
boolean mExternalStorageAvailable = false;
boolean mExternalStorageWriteable = false;
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state)) {
// We can read and write the media
mExternalStorageAvailable = mExternalStorageWriteable = true;
} else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
// We can only read the media
mExternalStorageAvailable = true;
mExternalStorageWriteable = false;
} else {
// Something else is wrong. It may be one of many other states, but all we need
// to know is we can neither read nor write
mExternalStorageAvailable = mExternalStorageWriteable = false;
}
这个例子检查了外部存储器是否可用于读写。你可能还想要检查getExternalStorageState()方法的其他状态,如存储介质是否是共享的(被连接到一个计算机上),是否完全丢失、是否被恶意的删除等等。使用这些状态,在应用程序需要访问存储介质时,以便给用户提供更多的通知信息。
访问外部存储器上的文件
如果使用API级别8或更高的版本,可以使用getExternalFilesDir()方法来打开一个File对象,它代表了应该保存文件的外部存储器目录。这个方法需要一个type参数,它指定了想要的子目录的类型,如DIRECTORY_MUSIC和DIRECTORY_RINGTONES(如果传递null,则会得到应用程序的文件目录的根目录)。如果需要,这个方法会创建合适的目录。通过指定目录的类型,确保Android的介质扫描器把文件正确的分类到系统中(例如,铃声被标识为铃声,而不是音乐)。如果用户卸载了应用程序,应用对应的目录和目录中所有的内容将会被删除。
如果使用API级别7或更低的版本,使用getExternalStorageDirectory()方法来打开一个File对象,它代表了外部存储器的根目录,然后应该把数据写到下列目录中:
/Android/data/<package_name>/files/
<package_name>是Java样式的包名,如:com.example.android.app。如果用户的设备正在运行API级别8或更高的版本,并且卸载了应用程序,那么这个目录和其所有的内容将会被删除。
保存应该共享的文件
如果保存的文件不是应用程序所专有的,并且在应用程序被卸载时,不删除这些文件,那么就要把它们保存到外部存储器上的一个公共的目录上。这些目录位于外部存储器的根目录,如Music/、Pictures/、Ringtones/等等。
在API级别8或更高的版本中,使用getExternalStoragePublicDirectory()方法,把需要的公共目录类型传递给这个方法,如DIRECTORY_MUSIC、DIRECTORY_PICTURES、DIRECTORY_RINGTONES或其他的类型。如果需要,这个方法会创建适当的目录。
如果使用API级别7或更低的版本,使用getExternalStorageDirectory()方法来打开一个File对象,它代表了外部存储器的根,然后把共享文件保存到下列目录之一中:
Music/---媒体扫描器把在这个目录中找到所有媒体文件作为用户音乐。
Podcasts/---媒体扫描器把在这个目录中找到的所有媒体文件作为音/视频的剪辑片段。
Ringtones/---媒体扫描器把在这个目录中找到的所有媒体文件作为铃声。
Alarms/---媒体扫描器把在这个目录中找到的所有媒体文件作为闹钟的声音。
Pictures/---所有的图片(不包括那些用照相机拍摄的照片)。
Movies/---所有的电影(不包括那些用摄像机拍摄的视频)。
Download/---其他下载的内容。
保存缓存文件
如果使用API级别8或更高的版本,使用getExternalCacheDir()来打开一个File对象,它代表了保存缓存文件的外部存储器目录。如果卸载应用程序,这些文件会自动的被删除。但是,在应用的生存期间,应该自己管理这些缓存文件,并且为了保留存储空间,应在不需要的时候删除这些缓存文件。
如果使用API级别7或更低的版本,就要使用getExternalStorageDirectory()方法来打开一个File对象,它代表了外部存储器的根目录,然后把缓存数据写入下列目录中:
/Android/data/<package_name>/cache/
<package_name>是Java样式的包名,如:com.example.android.app。
使用数据库
Android提供了对SQLite数据的完全支持。应用中创建的任何数据库都能够通过类名来访问,但在应用程序的外部不能访问。
推荐创建一个新的SQLite数据的方法是,创建一个SQLiteOpenHelper类的子类,并且要覆写onCreate()方法,在这个方法中能够执行SQLite命令来创建数据库中的表,例如:
public class DictionaryOpenHelper extends SQLiteOpenHelper {
private static final int DATABASE_VERSION = 2;
private static final String DICTIONARY_TABLE_NAME = "dictionary";
private static final String DICTIONARY_TABLE_CREATE =
"CREATE TABLE " + DICTIONARY_TABLE_NAME + " (" +
KEY_WORD + " TEXT, " +
KEY_DEFINITION + " TEXT);";
DictionaryOpenHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(DICTIONARY_TABLE_CREATE);
}
}
然后,用SQLiteOpenHelper的实现类的构造器来获取一个实例。分别调用getWritableDatabase()方法和getReadableDatabase()方法来分别读写数据库。它们都会返回一个SQLiteDatabase对象,它代表了数据库,并提供了操作SQLite的方法。
使用SQLiteDatabase.query()来执行SQLite的查询操作,它接收各种查询参数,如要查询的表、投影、选择条件、列、分组等等。对于复杂的查询,如要求列别名的查询,应该使用SQLiteQueryBuilder类,它为构建查询提供了几种便利的方法。
每个SQLite查询都会返回一个Cursor对象,它指向查询结果的所有行。Cursor对象始终能够在数据库的查询结果中导航,并且能够读取当前行和列的数据。
数据库调试
Android SDK包括了sqlite3数据库工具,可以用这些工具来浏览表的内容,运行SQL命令,以及执行其他的SQLite数据上的功能。
使用网络连接
在网络可用时,可以基于Web服务来保存和获取数据。使用下列包中的类来进行网络操作。
java.net.*;
android.net.*