1 权限
从DDMS的File Explorer中的Permissions可以看出Android文件目录的权限。
与Linux下的文件权限表示方式相同,共用10位代表用户权限,
第1位:代表文件类型
- 文件
l 链接或快捷方式link
d 目录dir
第2~4位:代表当前用户的权限
r readable
w writeable
x 可执行
--- 即不可读也不可写
第5~7位:代表用户所在组的权限
r readable
w writeable
x 可执行
--- 即不可读也不可写
第8~10位:代表其他用户
r readable
w writeable
x 可执行
--- 即不可读也不可写
在Android中为每个应用程序创建一个独立的用户,并为该用户创建一个独立的用户组。
2 手机内部文件的存取
在Android下的文件存取操作和Windows下的操作基本上没有区别,都可以通过绝对路径访问文件,区别在于Android下的某些路径有权限问题。Android为每个应用程序都创建了单独的文件存取路径,该路径为Android系统根目录下data\data\[pakageName]文件夹。应用程序包名即为文件夹名。
在应用程序中通过Context的getDir (String name, int mode)方法便可获取到该路径。此外还有getFilesDir()、getCacheDir()等方法。
下面代码可以向data\data\files\save.txt保存字符串str
File file = new File(getFilesDir(), "save.txt");
try {
FileOutputStreamfos = new FileOutputStream(file);
//或使用
//FileOutputStreamfos = openFileOutput("save.txt", Context.MODE_PRIVATE);
fos.write(str.getBytes());
fos.flush();
fos.close();
} catch (FileNotFoundException e) {
// TODO Auto-generatedcatch block
e.printStackTrace();
} catch (IOException e) {
// TODOAuto-generated catch block
e.printStackTrace();
}
文件读取:
File file = new File(getFilesDir(),"save.txt");
try {
FileReaderfileReader = new FileReader(file);
BufferedReaderbufferedReader = new BufferedReader(fileReader);
String str= bufferedReader.readLine();
tvRead.setText(str);
fileReader.close();
bufferedReader.close();
} catch (FileNotFoundException e) {
// TODOAuto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODOAuto-generated catch block
e.printStackTrace();
}
用上面方式创建的文件,权限为默认,即私有权限。要想创建带有指定权限的文件,可使用openFileOutput(String name, int mode)在data\data\[PakageName]\files下创建一个权限为mode的文件name。mode的值可为Context.MODE_PRIVATE、Context.MODE_WORLD_READABLE、Context.MODE_WORLD_WRITEABLE。
FileOutputStream fos =openFileOutput("save.txt", Context.MODE_PRIVATE);
3 获取存储空间大小及剩余空间
要想获取到存储空间的大小,可以先获取到存储器的簇大小,然后获取到簇的数量,两者相乘即可获得存储空间大小。
首先是SDcard:
// 判断是否有SDcard
if (Environment.MEDIA_MOUNTED.equals(Environment
.getExternalStorageState())){
File path= Environment.getExternalStorageDirectory();
StatFsstatFs = new StatFs(path.getPath());
// 获取簇大小(单位:B)
longblockSize = statFs.getBlockSize();
// 获取总簇数
longblockCount = statFs.getBlockCount();
// 获取可用簇数
longavailableBlockCount = statFs.getAvailableBlocks();
// 计算SDcard总大小
longsdMemory = blockSize * blockCount;
System.out.println(sdMemory);
// 计算SDcard剩余大小
longsdAvailableMemory = blockSize * availableBlockCount;
// 格式化显示
StringsdMemoryStr = Formatter.formatFileSize(
MainActivity.this,sdMemory);
StringsdAvailableMemoryStr = Formatter.formatFileSize(
MainActivity.this,sdAvailableMemory);
System.out.println("总大小:" + sdMemoryStr + "\n剩余空间:"
+sdAvailableMemoryStr);
}
机身存储空间大小和SDcard大小的获取方法几乎相同,将File替换为getDataDirectory()即可。
File path = Environment.getDataDirectory();
4 SDcard文件的存取
由于Android可以通过绝对路径访问文件,所以可以使用/sdcard或/mnt/sdcard访问到SDcard,也可以使用Environment.getExternalStorageDirectory()获取到SDcard的路径/mnt/sdcard。通常在对SDcard进行访问前先检查SDcard是否存在,如果写入的文件较大,应增加对剩余空间的检查。
向SDcard写入文件:
//判断是否有SDcard
if(Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())){
String str= etWriteSDcard.getText().toString();
File file= new File("/sdcard/save.txt");
//或者使用
//Filefile = new File(Environment.getExternalStorageDirectory() +"/save.txt");
try {
FileOutputStreamfos = new FileOutputStream(file);
fos.write(str.getBytes());
fos.flush();
fos.close();
} catch(FileNotFoundException e) {
// TODOAuto-generated catch block
e.printStackTrace();
} catch(IOException e) {
// TODOAuto-generated catch block
e.printStackTrace();
}
}
从SDcard读取文件:
File file = new File("/sdcard/save.txt");
try {
FileReaderfileReader = new FileReader(file);
BufferedReaderbufferedReader = new BufferedReader(fileReader);
String str= bufferedReader.readLine();
tvReadSDcard.setText(str);
} catch (FileNotFoundException e) {
// TODOAuto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODOAuto-generated catch block
e.printStackTrace();
}
注意:在对SDcard进行写入数据时需要权限WRITE_EXTERNAL_STORAGE
<uses-permissionandroid:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
在Android4.0后增加了对SDcard进行读取权限的设置,因此最好加入READ_EXTERNAL_STORAGE权限
<uses-permissionandroid:name="android.permission.READ_EXTERNAL_STORAGE"/>
5 SharedPreferences
使用SharedPreferences可以实现以键值对的形式存取任意类型数据,如使用putBoolean(String key, boolean value)保存布尔数据,使用putInt(String key, int value)保存整型数据等。SharedPreferences文件在/data/data/[PackageName]/shared_prefs下以xml文件存储。
写入:
SharedPreferences sp =getSharedPreferences("spName", MODE_PRIVATE);
//应用程序只有一个sp文件时可以不使用文件名
//SharedPreferences sp =getPreferences(MODE_PRIVATE);
Editor editor = sp.edit();
editor.putString("keyName", str);
//必须使用commit()提交才能更改
editor.commit();
读取:
SharedPreferences sp =getSharedPreferences("spName", MODE_PRIVATE);
//第二个参数为取不到key对应的value时默认的value值
String str = sp.getString("keyName","defValue");
6 SQLite数据库
在Activity中创建一个数据库非常简单,直接使用openOrCreateDatabase(String name, int mode, CursorFactory factory)即可打开或创建一个名为DB_NAME的数据库。
private static final String DB_NAME ="mydb";
private SQLiteDatabase db = null;
db = openOrCreateDatabase(DB_NAME, MODE_PRIVATE,null);
使用获取到的SQLiteDatabase对象的execSQL(String sql)方法可以执行一条标准SQL语句,可以用来创建表及其他操作。
String sql = "create table user(uid integerprimary key autoincrement, username varchar(20), password varchar(20))";
db.execSQL(sql);
插入数据:
sql = "insert into user values (?, '张三', 'password')";
db.execSQL(sql);
//或使用ContentValues
ContentValues cv = new ContentValues();
cv.put("username", "李四");
cv.put("password", "pwd12345");
db.insert("user", null, cv);
由于execSQL(String sql)没有返回值,所以不能使用该方法进行数据查询。SQLiteDatabase类提供了query()方法,query()方法有多种重载形式,可依据需要进行选择。query()方法返回一个游标cursor,可以通过该游标取得查询结果。
//select * form user
Cursor cursor = db.query("user", newString[] { "uid", "username",
"password"}, null, null, null, null, null);
while(cursor.moveToNext()) {
System.out.println("uid:\t"+ cursor.getInt(0));
System.out.println("username:\t"+ cursor.getString(1));
System.out.println("password:\t"+ cursor.getString(2));
cursor.moveToNext();
}
数据更新:
//update user set password='12345pwd' whereusername='李四';
sql = "update user set password='12345pwd'where username='李四'";
db.execSQL(sql);
//或使用ContentValues
ContentValues cv = new ContentValues();
cv.put("password", "12345pwd");
db.update("user", cv,"username=?", new String[] {"李四"});
数据删除:
//delete from user where username='李四'
sql = "delete from user where username='李四'";
db.execSQL(sql);
//或使用delete()
db.delete("user", "username=?",new String[] {"张三"});
使用rawQuery()简化SQL语句拼接
//使用?作为占位符
sql = "select * from user where username=? andpassword like ?";
//String[]内字符串按顺序对应sql语句中的占位符
Cursor cursor = db.rawQuery(sql, newString[]{"张三", "%word%"});
此外Android还提供了对事务的支持,
db.beginTransaction();
try {
//数据库操作
db.setTransactionSuccessful();
} finally {
db.endTransaction();
}
数据库操作完毕要使用close()方法将数据库关闭。
db.close();
7 使用SQLiteOpenHelper操纵SQLite数据库
Android还提供了数据库的帮助类,提供了一套自动执行的机制帮助开发者操作数据库。使用SQLiteOpenHelper需新建一个继承SQLiteOpenHelper的子类。
public classDBSQLiteOpenHelper extends SQLiteOpenHelper {
private static final int DB_VERSION = 1;
private static final String DB_NAME = "mydb";
/**
* 构造方法
* @param context
*/
publicDBSQLiteOpenHelper(Context context) {
super(context,DB_NAME, null, DB_VERSION);
}
/**
* 数据库第一次创建时自动调用该方法
*/
@Override
publicvoid onCreate(SQLiteDatabase db) {
String sql = "create table user(uid integer primary keyautoincrement, username varchar(20), password varchar(20))";
db.execSQL(sql);
}
/**
* 版本更新时自动调用该方法,进行新数据表的创建或者旧数据表的删除或其他更新操作
*/
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, intnewVersion) {
Stringsql = "alter table user add age integer";
db.execSQL(sql);
}
}
在应用中需要操作数据库时,先新建一个DBSQLiteOpenHelper实例,再通过getWritableDatabase()获取到一个可写的数据库或者通过getReadableDatabase()获取到一个只读的数据库进行增删改查等操作。
DBSQLiteOpenHelper dbHelper = newDBSQLiteOpenHelper(getContext());
SQLiteDatabase db = dbHelper.getWritableDatabase();
db.close();
8 Content Provider
使用ContentProvider可以对其他应用程序共享私有数据库。
首先在AndroidManifest.xml的Application中声明Provider标签
<!-- name标签为完整类名 -->
<!-- authorities标签随意填写,一般为<apppackagename>.provider. -->
<provider
android:name="com.weizi.provider.DBProvider"
android:authorities="com.weizi.provider">
</provider>
新建一个自己的Provider继承ContentProvider
public class DBProvider extendsContentProvider {
//匹配指定操作URI成功时的返回值
privatestatic final int INSERT = 1;
privatestatic final int DELETE = 2;
privatestatic final int UPDATE = 3;
privatestatic final int QUERY = 4;
privatestatic final int QUERY_TABLE_USER = 5;
privatestatic final int DELETE_BY_UID =6;
//URI匹配器,匹配失败返回UriMatcher.NO_MATCH
privatestatic UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);
//增加匹配成功时的返回值
static{
//AndroidManifest.xml中配置的authorities
finalString AUTHORITY = "com.weizi.provider";
//insert操作的URIcontent://com.weizi.provider/insert
matcher.addURI(AUTHORITY,"insert", INSERT);
//delete操作的URIcontent://com.weizi.provider/delete
matcher.addURI(AUTHORITY,"delete", DELETE);
//URI也可包含要操作记录的编号或者其他数字信息content://com.weizi.provider/delete/123344
//#表示通配所有数字,可以通过ContentUris.parseId(uri)获得该数字
matcher.addURI(AUTHORITY,"delete/#", DELETE_BY_UID);
//update操作的URIcontent://com.weizi.provider/update
matcher.addURI(AUTHORITY,"update", UPDATE);
//query操作的URIcontent://com.weizi.provider/query
matcher.addURI(AUTHORITY,"query", QUERY);
//URI也可包含要操作的表名content://com.weizi.provider/query/tablename
matcher.addURI(AUTHORITY,"query/user", QUERY_TABLE_USER);
}
privateDBSQLiteOpenHelper helper;
//Provivder被初始化时自动调用该方法
@Override
publicboolean onCreate() {
//初始化SQLiteOpenHelper
helper= new DBSQLiteOpenHelper(getContext());
returntrue;
}
@Override
publicCursor query(Uri uri, String[] projection, String selection,
String[]selectionArgs, String sortOrder) {
Cursorcursor = null;
//根据传入的uri进行匹配,以确定是否为指定操作
switch(matcher.match(uri)) {
caseQUERY:
//根据传入的参数对数据库进行查询操作,并返回查询得到的Cursor
SQLiteDatabasedb = helper.getReadableDatabase();
cursor= db.query("user", projection, selection, selectionArgs,
null,null, sortOrder);
//查询完毕不要用db.close()进行关闭
break;
default:
//不能匹配Uri时抛出非法参数异常
thrownew IllegalArgumentException("Unknown Uri : " + uri);
}
returncursor;
}
@Override
publicString getType(Uri uri) {
Stringtype;
switch(matcher.match(uri)) {
caseINSERT:
type= "vnd.android.cursor.item/user";
break;
caseDELETE:
type= "vnd.android.cursor.item/user";
default:
type= null;
break;
}
returntype;
}
@Override
publicUri insert(Uri uri, ContentValues values) {
UriinsertUri;
//根据传入的uri进行匹配,以确定是否为指定操作
switch(matcher.match(uri)) {
caseINSERT:
//插入数据记录ContentValues
SQLiteDatabasedb = helper.getWritableDatabase();
longrowId = db.insert("user", null, values);
//Uri insertUri = Uri.parse("content://" + AUTHORITY +"/user" +
//"/" + rowId);
insertUri= ContentUris.withAppendedId(uri, rowId);
break;
default:
thrownew IllegalArgumentException("Unknown Uri : " + uri);
}
returninsertUri;
}
@Override
public int delete(Uri uri, String selection, String[]selectionArgs) {
int num = 0;
// 根据传入的uri进行匹配,以确定是否为指定操作
switch (matcher.match(uri)) {
case DELETE:
// 删除指定数据记录
SQLiteDatabase db = helper.getWritableDatabase();
num= db.delete("user", selection, selectionArgs);
break;
default:
throw new IllegalArgumentException("Unknown Uri :" + uri);
}
return num;
}
@Override
public int update(Uri uri, ContentValues values, Stringselection,
String[] selectionArgs) {
intnum = 0;
//根据传入的uri进行匹配,以确定是否为指定操作
switch(matcher.match(uri)) {
caseUPDATE:
//更新数据记录
SQLiteDatabasedb = helper.getWritableDatabase();
num = db.update("user", values,selection, selectionArgs);
break;
default:
thrownew IllegalArgumentException("Unknown Uri : " + uri);
}
returnnum;
}
}
在其他应用中获取到ContentResolver的实例,然后调用其insert、update、delete、query方法并传入对应的Uri便可访问Provider提供的数据。
ContentResolver contentResolver= getContentResolver();
contentResolver.insert(url,values);
contentResolver.delete(url,where, selectionArgs);
contentResolver.update(uri,values, where, selectionArgs);
contentResolver.query(uri,projection, selection, selectionArgs, sortOrder);