android数据存储的途径

译自android.com

安卓为你是实现持久化数据提供了几种选择。具体的方案选择取决于你的特定需要,比如存储的数据是应用私有的还是对其他应用程序也是可见的,存储你的数据需要多大的空间。

你存储数据的选择如下:

Shared Preferences

以键值对的形式保持私有的原始数据

Internal Storage

在设备的内存内保存私有的数据

External Storage

在外部存储器保存公开的数据

SQLite Databases

在私有化的表中保存具备结构的数据

Network Connection

将数据保存在你的个人的网络服务器

安卓通过content provider为你提供了一种向其他应用暴露你的隐私数据的方案。content provider是一个可以选择实现的帮助你暴露你的应用数据的读写权限的组件,是一个subject to whatever restrictions you want to impose.

Using Shared Preferences

SharedPreferences这个类提供了一个允许你以保存和索取键值对类型的私密数据的框架。你可以使用SharedPreferences保存任何私密数据,比如布尔类型、浮点型、整型、长整型和字符串数据。这些数据会一直被持久化保存在整个用户期间(即使你的应用进程已经被杀死)

为了获得一个SharedPreferences对象,你可以使用下面任何一种方法:

1、getSharedPreferences()使用这个方法,你可以通过指定文件的名字获得一个特定的配置文件(这种情况下,应用内会存在多个不同名字的配置文件)

2、getPreferences()使用这个方法如果你只需要为你的activity获得唯一一个配置文件的对象。

你可以通过以下的步骤将数据写进文件:

1、调用edit()这个方法获取一个SharedPreferences.Editor.对象

2、通过诸如putBoolean()andputString()的方法添加数据

3、使用commit()方法提交数据

下面是一个具体的例子

publicclassCalcextendsActivity{

publicstaticfinalStringPREFS_NAME="MyPrefsFile";

@Override

protectedvoidonCreate(Bundlestate){

super.onCreate(state);

...

// Restore preferences

SharedPreferencessettings=getSharedPreferences(PREFS_NAME,0);

booleansilent=settings.getBoolean("silentMode",false);

setSilent(silent);

}

@Override

protectedvoidonStop(){

super.onStop();

// We need an Editor object to make preference changes.

// All objects are from android.context.Context

SharedPreferencessettings=getSharedPreferences(PREFS_NAME,0);

SharedPreferences.Editoreditor=settings.edit();

editor.putBoolean("silentMode",mSilentMode);

// Commit the edits!

editor.commit();

}

}

Using the Internal Storage

你可以直接直接将数据保存在设备的内部存储器。默认的情况下,保存在内部存储设备的文件是隐秘的,即只有你自己的应用可以使用,其他应用,包括用户没有权限读写这些文件。当你的应用被卸载的时候,这些文件也会被移除。

你可以通过以下步骤创建一个文件并将其保存到你的内部存储设备:

1、调用openFileOutput()这个方法,并将文件的名字以及操作的模式作为参数传入,这个方法会返回一个FileOutputStream

2、利用write()将数据写入文件

3、利用close()这个方法关闭输入流

例如:

StringFILENAME="hello_file";

Stringstring="hello world!";

FileOutputStreamfos=openFileOutput(FILENAME,Context.MODE_PRIVATE);

fos.write(string.getBytes());

fos.close();

MODE_PRIVATE将会创建一个文件(或者取代原来的同名文件),并且文件只有应用本书可以操作。其他有效的操作模式包括:MODE_APPEND,MODE_WORLD_READABLE, andMODE_WORLD_WRITEABLE

你可以通过以下步骤读取内部存储的文件数据:

1、调用openFileInput()方法并将文件名字作为参数传入。这个方法会返回一个FileInputStream.

2、利用read()按字节读取文件中的内容

3、利用close()关闭输出流

Tip:If you want to save a static file in your application at compile time, save the file in your projectres/raw/directory. You can open it withopenRawResource(), passing theR.raw.resource ID. This method returns anInputStreamthat you can use to read the file (but you cannot write to the original file).

Saving cache files

如果你只是想保存临时文件而并不是将数据持久化保存,你可以使用getCacheDir()的方法打开一个目录,这是一个保存你的应用的临时的缓存文件的目录。

当你的设备的内部存储容量不足的时候,安卓系统会自动的删除这些缓存文件以便于回收空间。尽管如此,你不应该依赖于系统的自动回收功能,你应该自己控制这些缓存文件并维持一个合理的内存占用显示,比如1mb。当你的应用被卸载的时候,这些文件就会被移除。

Other useful methods

getFilesDir()

获取内部文件保存的绝对路径

getDir()

在内部存储系统中创建(存在的时候就直接打开)一个目录

deleteFile()

删除保存在内部文件系统的文件

fileList()

返回当前应用保存的文件

Using the External Storage

每一个安卓设备都支持外部存储器,因此你可以用来保存你的文件。这可以是一个可移除的存储器(比如sd卡),也可以是内置的(不可移除)存储器。存储在外部存储器的文件是全局可读的并且用户可以修改这些文件当他们通过usb大容量数据与电脑连接的时候。

Caution:External storage can become unavailable if the user mounts the external storage on a computer or removes the media, and there's no security enforced upon files you save to the external storage. All applications can read and write files placed on the external storage and the user can remove them.

为了读写外部存储设备的文件,你的应用需要获得这些权限:READ_EXTERNAL_STORAGEWRITE_EXTERNAL_STORAGE

...

在你使用外部存储设备的时候,你应该调用方法检测外部存储设备是否可用。外部存储设备有可能正被挂载到电脑、缺失、只读或者其他的状态,例如:

/* Checks if external storage is available for read and write */

publicbooleanisExternalStorageWritable(){

Stringstate=Environment.getExternalStorageState();

if(Environment.MEDIA_MOUNTED.equals(state)){

returntrue;

}

returnfalse;

}

/* Checks if external storage is available to at least read */

publicbooleanisExternalStorageReadable(){

Stringstate=Environment.getExternalStorageState();

if(Environment.MEDIA_MOUNTED.equals(state)||

Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)){

returntrue;

}

returnfalse;

}

一般情况下,用户能够通过你的应用打开的文件应该被存储在一个公共的路径下并且其他应用可以访问,并且用户可以轻易的在设备上拷贝这些文件。当你这样做的时候,你应该使用任意一个共享的目录,比如:Music/,Pictures/, andRingtones/.

为了获得一个合适的公共目录的file对象,你可以调用getExternalStoragePublicDirectory()这个方法并将路径的类型作为参数传入,比如DIRECTORY_MUSIC,DIRECTORY_PICTURES,DIRECTORY_RINGTONES或者其他。通过将文件保存在直接的媒体类型的目录内,系统的多媒体扫描器可以将你的文件进行合适的分类。比如:

publicFilegetAlbumStorageDir(StringalbumName){

// Get the directory for the user's public pictures directory.

Filefile=newFile(Environment.getExternalStoragePublicDirectory(

Environment.DIRECTORY_PICTURES),albumName);

if(!file.mkdirs()){

Log.e(LOG_TAG,"Directory not created");

}

returnfile;

}

Saving files that are app-private

如果你正在处理一些文件你并不打算向其他应用程序公开,你应该通过调用方法getExternalFilesDir().使用外部存储器中的隐私目录。这个方法也可以指定一个类型参数作为子目录。如果你并不需要一个指定的路径,你可以传一个空值获取你应用的隐私目录的根目录。

从安卓4.4开始,读写本应用的隐私目录并不需要提供READ_EXTERNAL_STORAGEorWRITE_EXTERNAL_STORAGE这两个权限,所以你可以通过添加maxSdkVersion这个属性声明只有在低版本的系统中才需要加入权限:

android:maxSdkVersion="18"/>

...

Note:When the user uninstalls your application, this directory and all its contents are deleted. Also, the system media scanner does not read files in these directories, so they are not accessible from theMediaStorecontent provider. As such, youshould not use these directoriesfor media that ultimately belongs to the user, such as photos captured or edited with your app, or music the user has purchased with your app—those files should besaved in the public directories.

有时候,设备已经从内部存储器中分割一部分内存作为外部存储并且同时又提供了一个sd卡的拓展卡槽。当这样的设备搭载的系统低于安卓4.3(包括4.3)的时候,方法getExternalFilesDir()只提供了读写内部存储的权限并且你的应用并不可以对sd卡进行读写操作。然而,从安卓4.4开始,你可以通过调用方法getExternalFilesDir()获取内部和外部的读写权限,这时候方法会返回一个包含两个路径的file数组。第一个数组元素是最主要的外部存储设备的路径,你应该使用这一个路径除非它的存储空间已满或者不可用。如果你想要在系统为4.3及以下的设备上获取两个路径的权限。你可以使用支持库的静态方法ContextCompat.getExternalFilesDirs()。这个方法会返回一个file的数组,但是通常情况下,在4.3及以下的系统只会得到一个元素。

CautionAlthough the directories provided bygetExternalFilesDir()andgetExternalFilesDirs()are not accessible by theMediaStorecontent provider, other apps with theREAD_EXTERNAL_STORAGEpermission can access all files on the external storage, including these. If you need to completely restrict access for your files, you should instead write your files to theinternal storage.

Saving cache files

你可以调用方法getExternalCacheDir()获得内部存储器的一个用于存储缓存文件的file对象。如果你的应用被卸载的话,这写文件也会被移除。

与上面提及到的方法ContextCompat.getExternalFilesDirs()相类似,你可以获得第二存储器中的缓存目录通过调用方法ContextCompat.getExternalCacheDirs()

Tip:To preserve file space and maintain your app's performance, it's important that you carefully manage your cache files and remove those that aren't needed anymore throughout your app's lifecycle.

Using Databases

安卓提供了对sqlite数据库的全部支持。并且通过你创建的数据库的名字可以在应用的每一个类中使用,但是不会超出你的应用。

推荐你使用继承SQLiteOpenHelper并重写onCreate()这个方法来创建一个新的数据库。在onCreate()方法中你可以执行一个sqlite命令在数据库中创建一张表,例如:

publicclassDictionaryOpenHelperextendsSQLiteOpenHelper{

privatestaticfinalintDATABASE_VERSION=2;

privatestaticfinalStringDICTIONARY_TABLE_NAME="dictionary";

privatestaticfinalStringDICTIONARY_TABLE_CREATE=

"CREATE TABLE "+DICTIONARY_TABLE_NAME+" ("+

KEY_WORD+" TEXT, "+

KEY_DEFINITION+" TEXT);";

DictionaryOpenHelper(Contextcontext){

super(context,DATABASE_NAME,null,DATABASE_VERSION);

}

@Override

publicvoidonCreate(SQLiteDatabasedb){

db.execSQL(DICTIONARY_TABLE_CREATE);

}

}

你可以获得一个你已经实现的SQLiteOpenHelper的实例通过你已经定义好的构造器。你可以调用getWritableDatabase()andgetReadableDatabase()这两个方法分别获取可读和可写的数据库对象。

你可以通过调用SQLiteDatabasequery()方法执行sqlite 的查询操作。query()方法乐意接受多个参数,包括要查询的表的名字、要查询的列名、分组列名等。对于那些复杂的查询操作,比如需要列的同义名的,你可以使用SQLiteQueryBuilderSQLiteQueryBuilder,它可以提供多种便捷的方法执行查询操作。

每一个sqlite的查询操作会返回一个指向所有查询到的行数据的指针。你可以利用这个指针实现查询结果的导航并且读取相关的行列信息。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,835评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,598评论 1 295
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,569评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,159评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,533评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,710评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,923评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,674评论 0 203
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,421评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,622评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,115评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,428评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,114评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,097评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,875评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,753评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,649评论 2 271

推荐阅读更多精彩内容