【Android API Guides 简译(三)】Data Storage--Storage Options

Android提供了几种永久储存手机数据的选项,而我们选择存储的方式依据于我们存储的不同的特定需求,比如你的数据是否需要只对自己公开,数据是否可以被其他应用得到或者你想要储存多大的数据。

数据存储的方式如下:

Shared Preferences

通过xml类型的键值对,存储私密的原始数据。

Internal Storage 内部存储

通过手机内存存储私密数据

External Storage 外部存储

在设备外部共享里存储公开的数据

SQLite Databases Android 原生内部数据库

在私有数据库里存储结构化的数据

Network Connection 网络连接

在网络服务器上存储数据

Android 还提供了一种将私有的数据公开化的组件–Content-providers,详见Content-providers参考文档。

一、使用Shared Preferences

SharedPreferences类提供了一个完整的框架用来通过键值对的形式,永久地储存私有信息。我们可以使用SharedPreferences类储存任意一种类型的数据,包括booleans, floats, ints, longs, and strings。而且这些数据将会在整个会话阶段一直保存,即使你的应用被关闭。

得到SharedPreferences对象的两种方式:

1、getSharedPreferences() - 如果你想要得到一个通过键名来区分的笼统的Preferences对象,使用这种方法。

2、getPreferences(int) - 如果你的整个Activity只需要一个Preferences,因此你不需要提供键名。使用这种方法。

写入Value值的方式:

1、使用edit()方法得到一个 SharedPreferences.Editor对象。

2、通过类似putBoolean() 和 putString() 的方法添加值。

3、将编辑器的值和SharedPreferences对象的值相关联。

读取Value值,通过SharedPreferences类的方法,比如getBoolean() 和 getString() 。

示例代码:

public class Calc extends Activity {
    public static final String PREFS_NAME = "MyPrefsFile";

    @Override
    protected void onCreate(Bundle state){
       super.onCreate(state);
       . . .

       // Restore preferences
       SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);
       boolean silent = settings.getBoolean("silentMode", false);
       setSilent(silent);
    }

    @Override
    protected void onStop(){
       super.onStop();

      // We need an Editor object to make preference changes.
      // All objects are from android.context.Context
      SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);
      SharedPreferences.Editor editor = settings.edit();
      editor.putBoolean("silentMode", mSilentMode);

      // Commit the edits!
      editor.commit();
    }
}

二、使用Internal Storage

你可以直接将数据存储在内部存储里,但一般情况下,内部存储的数据对于本程序是私有的,其他程序是无法访问到的,也就是说当本程序被卸载时,该数据会一起被移除。我们一般将内部文件放在Data/data/相应的应用目录。

创建或者向内部存储写入一个文档的过程如下:

1、调用openFileOutput()方法,参数是文件名字和类型,返回一个FileOutputStream对象。

2、用write()写入文档

3、用close()关闭文档

示例代码:

String FILENAME = "hello_file";
String string = "hello world!";

FileOutputStream fos = openFileOutput(FILENAME, Context.MODE_PRIVATE);
fos.write(string.getBytes());
fos.close();

MODE_PRIVATE将会创建或者取代相同名字的文件,而且这个文件只对本程序可用。其他的模式有:MODE_APPEND, MODE_WORLD_READABLE, 和 MODE_WORLD_WRITEABLE。

如果我们有读取一个内容固定不变的文件,可以在编译的时候,在R.raw目录下保存你想要访问的文件,然后调用 openRawResource(),参数是R.raw.,返回一个 InputStream 对象,通过这个流,读取你想要读取的内容。(但是你不可以对这个文件进行写入操作。)

保存临时文件

如果你并不想永久的保存某些数据,你可以通过调用getCaheDir()方法,在系统目录里创建打开一个文件,用来保存临时数据。方法返回值是保存临时文件的路径。

当系统的内部存储快满了时,系统会自动清理临时文件,但是你不能依靠系统自动来清理临时文件,需要自己设置临时文件的大小上限,定时删除临时文件。当使用者卸载应用时,临时数据都会被删除。

其他有用的方法

getFilesDir()

得到保存文件的绝对路径。

getDir()

创建或者打开一个存在的内部存储文件。

deleteFile()

删除一个保存在内部存储的文件。

fileList()

返回应用的目录下的文件的清单。

三、使用外部存储

任何一个Android兼容性的手机都支持共享你保存在“外部存储”的文件。所谓”外部存储“,既可以保存在可移除的SD卡,也包含不可移除的内部存储里。而且当我们通过USB连接电脑时,我们可以修改这些文件。

注意:当我们在电脑上加载外部存储时,手机内不可访问相应的文件。存储在外部存储的文件不受安全性保护,用户可以任意的增加修改或者删除该文件。

访问到外部存储

你必须拥有 READ_EXTERNAL_STORAGE 或 WRITE_EXTERNAL_STORAGE 权限,才能访问或写入外部存储的文件。

在工程的Manifest.xml里修改:

<manifest ...>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    ...
</manifest>

当我们既想读取又想写入时,只需要得到 WRITE_EXTERNAL_STORAGE 权限就可以。

注意:从4.4版本后,如果只是访问和写入对本应用私有的文件,不需要获得上述权限。

检查媒体的可用性

在我们使用外部存储的文件之前,都必须检查文件的可用性,即文件是否只读,隐藏或者其他状态。我们会用getExternalStorageState(),返回一个String对象。通过将String值与MEDIA_MOUNTED,MEDIA_MOUNTED_READ_ONLY等来确认当前文件的状态。下面提供了两种检查文件的可用性的方法:

/* Checks if external storage is available for read and write */
public boolean isExternalStorageWritable() {
    String state = Environment.getExternalStorageState();
    if (Environment.MEDIA_MOUNTED.equals(state)) {
        return true;
    }
    return false;
}

/* Checks if external storage is available to at least read */
public boolean isExternalStorageReadable() {
    String state = Environment.getExternalStorageState();
    if (Environment.MEDIA_MOUNTED.equals(state) ||
        Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
        return true;
    }
    return false;
}

保存可被其他应用共享的文件

我们通常把想要共享的文件放在具有共享属性的文件目录下,那么怎么创建具有共享属性的文件目录呢?调用getExternalStoragePublicDirectory()创建一个文件目录,通过参数目录类型和目录名称,设置文件目录的属性和名称。

实例代码:

public File getAlbumStorageDir(String albumName) {
    // Get the directory for the user‘s public pictures directory.
    File file = new File(Environment.getExternalStoragePublicDirectory(
            Environment.DIRECTORY_PICTURES), albumName);
    if (!file.mkdirs()) {
        Log.e(LOG_TAG, "Directory not created");
    }
    return file;
}

保存私有文件

你可以通过调用getExternalFilesDir()方法来创建隐藏文件目录,同时可以通过设置参数的值来标示该目录的类型,比如DIRECTORY_MOVIES,标明该文件目录里的文件是视频类型的。

上文提到过,4.4以后无需设置权限即可访问外部存储的文件。低版本的需要如下设置,类似前面:

<manifest ...>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
                     android:maxSdkVersion="18" />
    ...
</manifest>

注意:当用户将应用卸载后,该文件会一起被移除。因为该文件不会被文件系统扫描到,所以通过content provider组件是无法访问到这些文件的。因此,如果当用户在此程序生成的文件不能保存在私有目录下,否则用户无法通过其他应用找到这些文件。

有时候,设备会将内部存储划分一部分当做外部存储使用,于是在4.3及以下版本时,调用 getExternalFilesDir() 方法不能访问到被划作外部存储的内部存储的文件,但在4.4版本以后,调用getExternalFilesDir() 方法,我们可以访问到两部分的文件。这时候getExternalFilesDir() 方法返回一个文件名条目,第一个条目就是被划作外部存储的目录。而且此目录是基本目录,除非在该目录已满或者无法访问的情况下,否则优先使用这部分存储。

当然如果你不喜欢这种设计的API,你可以使用support library里的静态方法ContextCompat.getExternalFilesDirs()。

注意:尽管私有目录下的文件不可被content provider组件使用,但是如果想要完全保密的话,还是要存储在内部存储里,因为私有目录里文件可以被具有 READ_EXTERNAL_STORAGE权限的应用访问到。

保存临时文件

同内部存储里保存临时文件一样,可以调用getExternalCacheDir()创建临时文件。也同样的,被卸载时会被移除。

四、使用数据库

Android自带 SQLite 数据库,但只能在创建该数据库的应用中使用,其他应用不能使用。

创建数据库的推荐方法是创建继承SQLiteOpenHelper的类,并重写OnCreate()方法。

示例如下:

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() and getReadableDatabase()方法来得到 SQLiteDatabase对象,通过对这个对象进行操作来完成数据库的功能。

SQLiteDatabase对象可以通过调用query()进行大部分的查询,更复杂的查询比如得到列名,可以通过 SQLiteQueryBuilder对象进行查询。

每个SQLite查询都会得到Cursor。Cursor即索引,只想每一个想要查询的数据。

数据库调试

Android SDK包含一个叫作 sqlite3的数据库,我们可以进行试操作。

五、使用网络连接

我们还可以通过网上的服务器储存和恢复数据,这里不再详述。

时间: 2024-12-13 14:12:53

【Android API Guides 简译(三)】Data Storage--Storage Options的相关文章

【Android API Guides 简译(一)】App Resourses--Overview

将数据与程序分开的原因,表面是为了独立的管理数据,深层原因是使App兼容不同的环境即使你的数据支持不同语言或者不同屏幕大小的特殊设备.这是非常且越来越重要的! 对于各种各样的资源,我们统一分成两种: 默认资源和针对不同环境的备选资源 举个例子,默认资源存放在res/layout/ directory下,针对于横摆方向的设备的备选资源存放在res/layout-land/ directory(横摆方向的设备的具体方式见图).当只有默认资源时,见图1.当设置了备选资源时,见图二,Android系统会

【Android API Guides简译(四)】使用Service还是使用线程?

一个服务是一个组件,这个组件可以在Android后台运行,即使你的这个应用被关闭,它依然在运行.所以说只有你需要一个和当前程序无关的后台程序时,才去创建它. 而如果你只是想让你的App在主线程外工作,而且操作限定在当前程序中时,只需要在在里面创建另一个线程. 比如你只是想在你的Activity在运行时,放一首音乐,那么你应该在onCreat()方法里创建另一个线程,在onStart()里开始线程,在onStop()里结束这个线程,同时你也要考虑到使用AsyncTask orHandlerThre

android API Guides学习--Introduction(1)

android介绍: android提供了丰富的应用程序开发框架,它允许你在java语言环境中为移动设备创建独特的应用程序与环境. 1android应用程序提供多个入口点 android 应用程序是由不同的组件组合而成的,每个组件都被单独调用.activity组件提供一块屏幕作为使用者的界面.service独立的在幕后执行. 你可以使用intent类来实现组件的切换.也可以在一个app中多次调用同一个组件.例如在一个地图应用程序中显示地址的activity组件.该模型为一个单一的应用程序提供了多

Android API Guides – Introduction to Android

Android介绍 声明: 本文由Gordon翻译 发布于www.dlvoice.com 欢迎转载,但请保留此声明 原文地址:http://developer.android.com/guide/index.html Android提供了丰富的应用框架以便用户能够创建使用Java的环境来在移动设备上开发有创新性的应用和游戏.Android API Guides文档将会详细描述如何使用Android不同API来开发应用. 假如你是Android开发的新手,最好首先了解一下下面列出的Android

翻译Android API Guides: App Manifest

原文在这里:http://developer.android.com/guide/topics/manifest/manifest-intro.html *Manifest译作"清单",这里沿用英文便于理解,其它术语同理. **文中链接都会跳转到android开发者网站. App Manifest 每一个应用都必须在它的根目录有一份AndroidManifest.xml文件(必须使用这个名字).Android系统必须在运行应用的任何代码之前了解一些重要信息,这些信息就来自于这份mani

Android API Guides –Device Compatibility

设备的兼容性 声明: 本文由Gordon翻译 发布于www.dlvoice.com 欢迎转载,但请保留此声明 原文地址:http://developer.android.com/guide/practices/compatibility.html Android可以运行在不同类型的设备上,从手机到平板以及电视都可以运行.这些不同的设备将为开发者提供大量的潜在用户.那么为了能够让你的应用在所有的设备上运行良好,你就需要接受一些特性的多样性以及提供一个不同屏幕配置的友好的用户接口. 为了达到这样的目

Android API Guides – Application Fundamentals

应用基础 声明: 本文由Gordon翻译 发布于www.dlvoice.com 欢迎转载,但请保留此声明 原文地址:http://developer.android.com/guide/components/fundamentals.html Android应用是用Java语言来开发的.Android的SDK工具将会把你的代码和数据以及资源文件编译到APK中,所谓的APK就是一个Android包,它是以.apk结尾的压缩包文件.APK文件包含了Android应用的所有部分,一个真正的Androi

android API Guides学习--Introduction(2)

应用程序基本原理: android应用程序是用java语言编写的,android SDK工具在APK(Android package)里编译代码(数据文件和资源文件).apk是一个后缀为.apk的档案文件,1个apk文件包含了android应用程序的所有内容,apk是用来安装应用程序的基于android的设备.一旦安装了apk文件,每个app运行在自己安全的沙盒中. android操作系统是一个多用户的Linux操作系统,每一个app有一个不同的用户. 系统默认给各自的app分配一个唯一的Lin

android API Guides学习--Intent and Intent Filters

Intent是一个消息传递类,同时可以启动一些组件 作用: 1启动一个activity组件. 通过Context类的 startActivity()/ startActivity ()方法启动activity组件. 2启动一个service组件 通过Context类的startService()方法启动此组件,只能执行一次性操作(例如下载文件). 通过Context类的 bindService()方法 3发送一条广播 通过Context类的sendBroadcast(), sendOrdered