设为首页 收藏本站
查看: 2127|回复: 0

[经验分享] 理解 Android 本地数据存储 API 利用首选项、SQLite 和内部及外部内存 API

[复制链接]

尚未签到

发表于 2016-12-2 06:43:39 | 显示全部楼层 |阅读模式
  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;     
}

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-308283-1-1.html 上篇帖子: 解决:sqlite数据库含有\n的值或者sax解析xml有\n的值付给TextView,显示却不会换行 下篇帖子: [原创,转载请注明来源]android中sqlite数据库的中文数据的插入(insert)和查询(select)
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表