理解 Android 本地数据存储 API 利用首选项、SQLite 和内部及外部内存 API

http://www.ibm.com/developerworks/cn/xml/x-androidstorage/

 

存储应用程序首选项

本节介绍 Preferences API 和屏幕。Android API 提供很多方式处理首选项。其中一种方式是直接使用 SharedPreferences,并使用您自己的屏幕设计和首选项管理。第二种方法是使用 PreferenceActivity。PreferenceActivity 自动负责首选项如何呈现在屏幕上(默认情况下,看起来跟系统首选项一样),并通过使用 SharedPreferences 在用户与每个首选项交互时自动存储或保存首选项。

 

Preferences 屏幕的 XML 声明

<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/prefs_screen"
        android:key="preferencescreen"
    >
    <PreferenceCategory android:title="Assets">
        <EditTextPreference 
            android:key="@string/prefs_assetname_friendslist_key"
            android:title="Friends List" 
            android:summary="Please enter filename"
            android:defaultValue="friends.txt"
        />
        <EditTextPreference 
            android:key="@string/prefs_assetname_picture_key"
            android:title="Picture" 
            android:summary="Please enter filename"
            android:defaultValue="pict2.jpg"
        />
    </PreferenceCategory>

    <PreferenceCategory android:title="Auto Settings">
        <CheckBoxPreference
            android:key="@string/prefs_autodelete_key"
            android:title="Delete at Startup" 
            android:summary="Check to clear at startup"
            android:defaultValue="false"
        />
    </PreferenceCategory>
</PreferenceScreen>

  PreferenceScreen 包含 EditTextPreference 的两个实例、一个 CheckBoxPreference 和两个由 PreferenceCategory 定义的类别组(一个用于 Asset,另一个用于 Auto Settings)。

使用 SharedPreferences

 

/
// The following methods show how to use the SharedPreferences
/

/**
 * Retrieves the Auto delete preference
 * @return the value of auto delete
 */
public boolean prefsGetAutoDelete() {
    boolean v = false;
    SharedPreferences sprefs = 
       PreferenceManager.getDefaultSharedPreferences(appContext); 
    String key = appContext.getString(R.string.prefs_autodelete_key);
    try {
        v = sprefs.getBoolean(key, false);
    } catch (ClassCastException e) {
    }
    return v;
}   

/**
 * Sets the auto delete preference
 * @param v the value to set
 */
public void  prefsSetAutoDelete(boolean v) {
    SharedPreferences sprefs = 
    PreferenceManager.getDefaultSharedPreferences(appContext); 
    Editor e = sprefs.edit();
    String key = appContext.getString(R.string.prefs_autodelete_key);               
    e.putBoolean(key, v);
    e.commit();
}

 

MainActivity 插入到数据库中

String fname = prefsGetFilename();
if (fname != null && fname.length() > 0) {
    buffer = getAsset(fname);
    // Parse the JSON file
    String friendslist = new String(buffer);
    final JSONObject json = new JSONObject(friendslist);
    JSONArray d = json.getJSONArray("data");
    int l = d.length();
    for (int i2=0; i2<l; i2++) {
        JSONObject o = d.getJSONObject(i2);
        String n = o.getString("name");
        String id = o.getString("id");
        dbHelper.insert(id, n);
    }
    // Only the original owner thread can touch its views                           
    MainActivity.this.runOnUiThread(new Runnable() {
        public void run() {
            friendsArrayAdapter.notifyDataSetChanged();
        }
    });         
}

MainActivity Select All 和将数据绑定到 ListView

final ArrayList<Friend> dbFriends = dbHelper.listSelectAll();
if (dbFriends != null) {
    // Only the original owner thread can touch its views                           
    MainActivity.this.runOnUiThread(new Runnable() {
        public void run() {
            friendsArrayAdapter = 
            new FriendsArrayAdapter(
                MainActivity.this, R.layout.rowlayout, dbFriends);
            listView.setAdapter(friendsArrayAdapter);
            friendsArrayAdapter.notifyDataSetChanged();
        }
    });
}   

 从本地私有存储器读取数据   

/**
 * Writes content to internal storage making the content private to 
 * the application. The method can be easily changed to take the MODE 
 * as argument and let the caller dictate the visibility: 
 * MODE_PRIVATE, MODE_WORLD_WRITEABLE, MODE_WORLD_READABLE, etc.
 * 
 * @param filename - the name of the file to create
 * @param content - the content to write
 */
public void writeInternalStoragePrivate(
        String filename, byte[] content) {
    try {
        //MODE_PRIVATE creates/replaces a file and makes 
        //  it private to your application. Other modes:
        //    MODE_WORLD_WRITEABLE
        //    MODE_WORLD_READABLE
        //    MODE_APPEND
        FileOutputStream fos = 
           openFileOutput(filename, Context.MODE_PRIVATE);
        fos.write(content);
        fos.close();
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

 从内部私有存储器读取数据

				
/**
 * Reads a file from internal storage
 * @param filename the file to read from
 * @return the file content
 */
public byte[] readInternalStoragePrivate(String filename) {
    int len = 1024;
    byte[] buffer = new byte[len];
    try {
        FileInputStream fis = openFileInput(filename);
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        int nrb = fis.read(buffer, 0, len); // read up to len bytes
        while (nrb != -1) {
            baos.write(buffer, 0, nrb);
            nrb = fis.read(buffer, 0, len);
        }
        buffer = baos.toByteArray();
        fis.close();
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
    return buffer;
}

 

从本地私有存储器删除数据

/**
 * Delete internal private file 
 * @param filename - the filename to delete
 */
public void deleteInternalStoragePrivate(String filename) {
    File file = getFileStreamPath(filename);
    if (file != null) {
        file.delete();
    }
}

 为公共数据使用设备的外部存储器

有了数据存储 API,您可以使用外部存储器存储数据。信息可以是私有的,您可以有选择地让其他应用程序对之具有读或写的访问权限。本节您将对此 API 进行编程,以便使用包括 getExternalStorageState()、getExternalFilesDir()、getExternalStorageDirectory() 和 getExternalStoragePublicDirectory() 在内的很多 API 来存储公共数据。您为公共数据使用下面的路径:/Android/data/<package_name>/files/。

在使用外部存储器之前,必须看看它是否可用,是否可写。下面两个代码片段展示了测试这些条件的帮助器方法。清单 23 测试外部存储器是否可用。

测试外部存储器是否可用   

/**
 * Helper Method to Test if external Storage is Available
 */
public boolean isExternalStorageAvailable() {
    boolean state = false;
    String extStorageState = Environment.getExternalStorageState();
    if (Environment.MEDIA_MOUNTED.equals(extStorageState)) {
        state = true;
    }
    return state;
}

 测试外部存储器是否只可读

/**
 * Helper Method to Test if external Storage is read only
 */
public boolean isExternalStorageReadOnly() {
    boolean state = false;
    String extStorageState = Environment.getExternalStorageState();
    if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(extStorageState)) {
        state = true;
    }
    return state;
}

 写到外部内存

/**
 * Write to external public directory
 * @param filename - the filename to write to
 * @param content - the content to write 
 */
public void writeToExternalStoragePublic(String filename, byte[] content) {

    // API Level 7 or lower, use getExternalStorageDirectory() 
    //  to open a File that represents the root of the external 
    // storage, but writing to root is not recommended, and instead 
    // application should write to application-specific directory, as shown below.

    String packageName = this.getPackageName();
    String path = "/Android/data/" + packageName + "/files/";

    if (isExternalStorageAvailable() && 
       !isExternalStorageReadOnly()) {
        try {
            File file = new File(path, filename);
            file.mkdirs();
            FileOutputStream fos = new FileOutputStream(file);
            fos.write(content);
            fos.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

 从外部内存读取数据

/**
 * Reads a file from internal storage
 * @param filename - the filename to read from
 * @return the file contents
 */
public byte[] readExternallStoragePublic(String filename) {
    int len = 1024;
    byte[] buffer = new byte[len];
    String packageName = this.getPackageName();
    String path = "/Android/data/" + packageName + "/files/";

    if (!isExternalStorageReadOnly()) {     
        try {
            File file = new File(path, filename);            
            FileInputStream fis = new FileInputStream(file);
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            int nrb = fis.read(buffer, 0, len); //read up to len bytes
            while (nrb != -1) {
                baos.write(buffer, 0, nrb);
                nrb = fis.read(buffer, 0, len);
            }
            buffer = baos.toByteArray();
            fis.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    return buffer;
}

外部内存删除文件

/**
 * Delete external public file 
 * @param filename - the filename to write to
 */
void deleteExternalStoragePublicFile(String filename) {
    String packageName = this.getPackageName();
    String path = "/Android/data/" + packageName + "/files/"+filename;
    File file = new File(path, filename);
    if (file != null) {
        file.delete();
    }
}

  处理外部存储器需要特殊的权限 WRITE_EXTERNAL_STORAGE,它通过 AndroidManifest.xml 请求得到

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

 

外部存储 API 通过根据文件类型(比如 Pictures、Ringtones)将文件存储在预先确定的目录中,允许您公共地存储文件。本文没有介绍这种方法,但是您应该熟悉它。此外,记住外部存储器中的文件任何时候都可能消失。

如果您具有不需要长期永久保存的临时文件,那么可以将这些文件存储在高速缓存中。高速缓存是一种特殊的内存,可以用于存储中小型数据(少于兆字节),但是您一定要知道,取决于有多少内存可用,高速缓存的内容任何时候都可能被清除。

检索到内部内存高速缓存的路径

/**
 * Helper method to retrieve the absolute path to the application 
 * specific internal cache directory on the file system. These files 
 * will be ones that get deleted when the application is uninstalled or when 
 * the device runs low on storage. There is no guarantee when these 
 * files will be deleted.
 * 
 * Note: This uses a Level 8+ API.
 * 
 * @return the absolute path to the application specific cache 
 * directory
 */
public String getInternalCacheDirectory() {
    String cacheDirPath = null;
    File cacheDir = getCacheDir();
    if (cacheDir != null) {
        cacheDirPath = cacheDir.getPath();
    }
    return cacheDirPath;        
}

检索到外部内存高速缓存的路径

/**
 * Helper method to retrieve the absolute path to the application 
 * specific external cache directory on the file system. These files 
 * will be ones that get deleted when the application is uninstalled or when 
 * the device runs low on storage. There is no guarantee when these 
 * files will be deleted.
 * 
 * Note: This uses a Level 8+ API.
 * 
 * @return the absolute path to the application specific cache 
 * directory
 */
public String getExternalCacheDirectory() {
    String extCacheDirPath = null;
    File cacheDir = getExternalCacheDir();
    if (cacheDir != null) {
        extCacheDirPath = cacheDir.getPath();
    }
    return extCacheDirPath;     
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值