Android数据存储——SharedPreferences及SDCard
来源:互联网 发布:淘宝帐号注册 编辑:程序博客网 时间:2024/04/28 11:40
一、数据存储选项:Data Storage ——Storage Options【重点】
- 1、Shared Preferences
- Store private primitive data in key-value pairs.
- 保存简单的键值对数据。
- 2、Internal Storage
- Store private data on the device memory.
- 在手机内存中保存不对外共享的信息。
- 3、External Storage
- Store public data on the shared external storage.
- 在外部存储设备上保存公共的数据信息。主要指保存在SDCard上。
- 4、SQLite Databases
- Store structured data in a private database.
- 将结构化的数据保存进数据库。
- 5、Network Connection
- Store data on the web with your own network server.
- 将数据保存到自己的远程服务器上。
- 【备注:】
- 内部存储空间十分有限,因而显得可贵,另外,它也是系统本身和系统应用程序主要的数据存储所在地,一旦内部存储空间耗尽,手机也就无法使用了。
- 所以对于内部存储空间,我们要尽量避免使用。Shared Preferences和SQLite数据库都是存储在内部存储空间上的。内部存储一般用Context来获取和操作。
- getFilesDir()获取你app的内部存储空间,相当于你的应用在内部存储上的根目录。
- 最容易混淆的是外部存储,如果说pc上区分出外部存储和内部存储的话,那么自带的硬盘算是内部存储,U盘或者移动硬盘算是外部存储,因此我们很容易带着这样的理解去看待安卓手机,认为机身固有存储是内部存储,而扩展的SDCard卡是外部存储。比如Nexus 4有16G的内部存储,普通消费者可以这样理解,但是安卓的编程中不能,这16GB仍然是外部存储。
- SharedPreferences:
(一)、概念:SharedPreferences是Android系统提供的一个通用的数据持久化框架,用于存储和读取key-value类型的原始基本数据类型对,目前支持string、int、long、float、boolean等基本类型的存储,对于自定义的对象数据类型,无法使用SharedPreferences来存储。SharedPreferences主要用于存储系统的配置信息。例如上次登录的用户名,上次最后设置的配置信息(如:是否打开音效、是否使用振动,小游戏的玩家积分等)。当再次启动程序后依然保持原有设置。SharedPreferences用键值对方式存储,方便写入和读取。(二)、使用SharedPreferences的步骤:1、获取SharedPreferences对象;SharedPreferences本身是一个接口,无法直接创建实例,通过Context的getSharedPreferences(String name, int mode)方法来获取实例。该方法的第二个参数有以下三个值:【文件读写的操作模式】- Context.MODE_PRIVATE: 指定该SharedPreferences的数据只能被本应用程序读、写;
- Context.MODE_APPEND:新内容追加到原内容后;
- Context.MODE_WORLD_READABLE: 指定 SharedPreferences数据能被其他应用程序读,但是不支持写;
- Context.MODE_WORLD_WRITEABLE: 指定 SharedPreferences数据能被其他应用程序读、写。会覆盖原数据。
- 可以使用 + 连接这些权限。
2、调用edit()方法获取SharedPreferences.Editor;3、通过SharedPreferences.Editor接口提供的put()方法对SharedPreferences进行更新;4、调用SharedPreferences.Editor的commit()方法,将更新提交到SharedPreferences中。(三)、核心代码:button_main_savedata.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { prefs = getSharedPreferences("myaccount", Context.MODE_PRIVATE); SharedPreferences.Editor editor = prefs.edit(); editor.putInt("age", 38); editor.putString("username", "wangxiangjun"); editor.putString("pwd", "123456"); editor.putString("username", "xiangjun"); editor.putString("age", "I'm 40 years old!"); editor.commit(); } }); button_main_readdata.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { prefs = getSharedPreferences("myaccount", Context.MODE_PRIVATE); String name = prefs.getString("username", "wxj"); String pwd = prefs.getString("pwd", "000"); int age = prefs.getInt("age", 20); System.out.println("====>" + name + ":" + pwd + ":" + age); } });
(四)、保存之后的SharedPreferences数据文件:SharedPreferences数据总是以xml格式保存在:/data/data/包名/shared_prefs目录下;例如:<?xml version='1.0' encoding='utf-8' standalone='yes' ?><map><string name="pwd">123456</string><string name="username">xiangjun</string><int name="age">20</int></map>(五)、SharedPreferences的设置Setting功能:1、引入:2、PreferenceActivity的简单用法:1)、步骤:- 将setting.xml文件放到res的xml目录下;
- 将arrays.xml文件放到values目录下;
- 写一个页面SettingActivity。
3)、核心代码://在SettingActivity中。不再需要setContentView(R.layout.activity_main)方法来加载布局了。
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // setContentView(R.layout.activity_main); addPreferencesFromResource(R.xml.setting);
//备注:This method was deprecated in API level 11. This function is not relevant for a modern fragment-based PreferenceActivity.这个方法在11版本以上就已经不推荐使用了。 }
(六)、借助SharedPreferences实现黑名单管理:1、示例代码:public class MainActivity extends Activity { private ListView listView_main_blockList; private EditText editText_main_number; private TextView textView_main_emptyinfo; private SharedPreferences prefs = null; private Editor editor = null; private ArrayAdapter<String> adapter = null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); editText_main_number = (EditText) findViewById(R.id.editText_main_number); listView_main_blockList = (ListView) findViewById(R.id.listView_main_blocklist); textView_main_emptyinfo = (TextView) findViewById(R.id.text_main_emptyinfo); prefs = getSharedPreferences("blocklist", Context.MODE_PRIVATE); editor = prefs.edit(); List<String> list = getBlocklist(); adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, list); // 注意setEmptyView()的用法。当适配器为空的时候,设置ListView中的展示内容。 listView_main_blockList.setEmptyView(textView_main_emptyinfo); listView_main_blockList.setAdapter(adapter); } public void clickButton(View view) { switch (view.getId()) { case R.id.button_main_add: String mpnumber = editText_main_number.getText().toString(); editor.putString(mpnumber, mpnumber); editor.commit(); fillListView(); break; case R.id.button_main_clear: editor.clear(); editor.commit(); fillListView(); break; default: break; } } /* * 获取SharedPreferences中的全部数据,放到List集合中。形成适配器的数据源 */ private List<String> getBlocklist() { List<String> list = new ArrayList<String>(); try { Map<String, ?> map = prefs.getAll(); // 增强for循环,实现对Map集合的遍历 for (Map.Entry<String, ?> entry : map.entrySet()) { list.add(entry.getKey()); } return list; } catch (Exception e) { return null; } } /* * 填充ListView控件,实现刷新显示数据的效果 */ private void fillListView() { adapter.clear(); adapter.addAll(getBlocklist()); } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.main, menu); return true; }}
三、External Storage之SDCard操作:(一)、引入:Android中提供了特有的两个方法来进行IO操作(openFileInput()和openFileOutput() ),但是毕竟手机内置存储空间很有限,为了更好地存储应用程序的大文件数据,需要读写SD卡上的文件。SD卡大大扩充了手机的存储能力。(二)、读写SD卡的步骤:1、先判断手机是否有sd卡;调用Environment的getExternalStorageState()方法判断手机是否插上sdcard。2、获取sdcard的路径;调用Environment的getExternalStorageDirectory()方法来获取外部存储器的目录。3、此外还可以获取SDCard可用磁盘空间的大小(借助StatFs类来实现);4、清单文件中设置读写sdcard的权限;<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/> 在sdcard中创建与删除文件的权限<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> 向sdcard写入权限5、执行读写操作(基本IO流操作)。【备注:】Environment.getExternalStorageDirectory().getPath()来获取sdcard路径,如果您需要往sdcard中保存特定类型的内容,可以考虑使用Environment.getExternalStoragePublicDirectory(String type)方法,该方法可以返回特定类型的目录,目前支持如下类型:- DIRECTORY_ALARMS //警报的铃声
- DIRECTORY_DCIM //相机拍摄的图片和视频保存的位置
- DIRECTORY_DOWNLOADS //下载文件保存的位置
- DIRECTORY_MOVIES //电影保存的位置, 比如 通过google play下载的电影
- DIRECTORY_MUSIC //音乐保存的位置
- DIRECTORY_NOTIFICATIONS //通知音保存的位置
- DIRECTORY_PICTURES //下载的图片保存的位置
- DIRECTORY_PODCASTS //用于保存podcast(博客)的音频文件
- DIRECTORY_RINGTONES //保存铃声的位置
【备注:】应用程序在运行的过程中如果需要向手机上保存数据,一般是把数据保存在SDcard中的。大部分应用是直接在SDCard的根目录下创建一个文件夹,然后把数据保存在该文件夹中。这样当该应用被卸载后,这些数据还保留在SDCard中,留下了垃圾数据。如果你想让你的应用被卸载后,与该应用相关的数据也清除掉,该怎么办呢?- 通过Context.getExternalFilesDir()方法可以获取到 SDCard/Android/data/应用的包名/files/ 目录,一般放一些长时间保存的数据 【设置->应用->应用详情里面的”清除数据 Clear Data“】
- 通过Context.getExternalCacheDir()方法可以获取到 SDCard/Android/data/应用包名/cache/目录,一般存放临时缓存数据 【设置->应用->应用详情里面的”清除缓存“ Clear Cache】
- 如果使用上面的方法,当你的应用在被用户卸载后,SDCard/Android/data/你的应用的包名/ 这个目录下的所有文件都会被删除,不会留下垃圾信息。
而且上面二个目录分别对应 设置->应用->应用详情里面的”清除数据“与”清除缓存“选项。当然如果要保存下载的内容,就不要放在以上目录下。(五)、案例:SDCard文件浏览器(三)、封装SDCard的工具类:SDCardHelper类public class SDCardHelper { private static String TAG = "SDCardHelper"; /* * 判断sdcard是否挂载 */ public static boolean isSDCardMounted() { return Environment.getExternalStorageState().equals( Environment.MEDIA_MOUNTED); } /* * 获取sdcard绝对物理路径 */ public static String getSDCardPath() { if (isSDCardMounted()) { return Environment.getExternalStorageDirectory().getAbsolutePath(); } else { return null; } } /* * 获取sdcard的全部的空间大小。返回MB字节 */ public static long getSDCardSize() { if (isSDCardMounted()) { StatFs fs = new StatFs(getSDCardPath()); long size = fs.getBlockSize(); long count = fs.getBlockCount(); return size * count / 1024 / 1024; } return 0; } /* * 获取sdcard的剩余的可用空间的大小。返回MB字节 */ public static long getSDCardFreeSize() { if (isSDCardMounted()) { StatFs fs = new StatFs(getSDCardPath()); long size = fs.getBlockSize(); long count = fs.getAvailableBlocks(); return size * count / 1024 / 1024; } return 0; } /* * 将文件(byte[])保存进sdcard指定的路径下 */ public static boolean saveFileToSDCard(byte[] data, String dir, String filename) { BufferedOutputStream bos = null; if (isSDCardMounted()) { Log.i(TAG, "==isSDCardMounted==TRUE"); File file = new File(getSDCardPath() + File.separator + dir); Log.i(TAG, "==file:" + file.toString() + file.exists()); if (!file.exists()) { boolean flags = file.mkdirs(); Log.i(TAG, "==创建文件夹:" + flags); } try { bos = new BufferedOutputStream(new FileOutputStream(new File( file, filename))); bos.write(data, 0, data.length); bos.flush(); return true; } catch (Exception e) { e.printStackTrace(); } finally {
try { bos.close(); } catch (IOException e) { e.printStackTrace(); } } } return false; } /* * 已知文件的路径,从sdcard中获取到该文件,返回byte[] */ public static byte[] loadFileFromSDCard(String filepath) { BufferedInputStream bis = null; ByteArrayOutputStream baos = null; if (isSDCardMounted()) { File file = new File(filepath); if (file.exists()) { try { baos = new ByteArrayOutputStream(); bis = new BufferedInputStream(new FileInputStream(file)); byte[] buffer = newbyte[1024 * 8]; int c = 0; while ((c = bis.read(buffer)) != -1) { baos.write(buffer, 0, c); baos.flush(); } return baos.toByteArray(); } catch (Exception e) { e.printStackTrace(); } finally { try { if (bis != null) { bis.close(); baos.close(); } } catch (IOException e) { e.printStackTrace(); } } } } return null; }}
四)、案例:
1、功能:点击按钮,实现从网络上访问图片,将图片保存进SDCard中。点击另外一按钮,可以获取到刚才保存进SDCard中的图片,将其加载的页面中的ImageView控件中。
2、示例代码:、示例代码:public class MainActivity extends Activity { private ImageView imageView_main_img; private String urlString = "http://t2.baidu.com/it/u=2,1891512358&fm=19&gp=0.jpg"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); imageView_main_img = (ImageView) findViewById(R.id.imageView_main_img); } public void clickButton(View view) { switch (view.getId()) { case R.id.button_main_save: new MyTask(this).execute(urlString); break; case R.id.button_main_show: String filepath = SDCardHelper.getSDCardPath() + File.separator + "mydir" + File.separator + "firstimg.jpg"; byte[] data = SDCardHelper.loadFileFromSDCard(filepath); if (data != null) { Bitmap bm = BitmapFactory.decodeByteArray(data, 0, data.length); imageView_main_img.setImageBitmap(bm); } else { Toast.makeText(this, "没有该图片!", Toast.LENGTH_LONG).show(); } break; default: break; } } class MyTask extends AsyncTask<String, Void, byte[]> { private Context context; private ProgressDialog pDialog; public MyTask(Context context) { this.context = context; pDialog = new ProgressDialog(context); pDialog.setIcon(R.drawable.ic_launcher); pDialog.setMessage("图片加载中..."); } @Override protected void onPreExecute() { super.onPreExecute(); pDialog.show(); } @Override protected byte[] doInBackground(String... params) { BufferedInputStream bis = null; ByteArrayOutputStream baos = new ByteArrayOutputStream(); try { URL url = new URL(params[0]); HttpURLConnection httpConn = (HttpURLConnection) url .openConnection(); httpConn.setDoInput(true); httpConn.connect(); if (httpConn.getResponseCode() == 200) { bis = new BufferedInputStream(httpConn.getInputStream()); byte[] buffer = newbyte[1024 * 8]; int c = 0; while ((c = bis.read(buffer)) != -1) { baos.write(buffer, 0, c); baos.flush(); } return baos.toByteArray(); } } catch (Exception e) { e.printStackTrace(); } return null; } @Override protected void onPostExecute(byte[] result) { super.onPostExecute(result); if (result == null) { Toast.makeText(context, "图片加载失败!", Toast.LENGTH_LONG).show(); } else { // 将字节数组转成Bitmap,然后将bitmap加载的imageview控件中 // Bitmap bitmap = BitmapFactory.decodeByteArray(result, 0, // result.length); // imageView_main_img.setImageBitmap(bitmap); if (SDCardHelper.saveFileToSDCard(result, "mydir", "firstimg.jpg")) { Toast.makeText(context, "图片保存OK!", Toast.LENGTH_LONG) .show(); } else { Toast.makeText(context, "图片保存失败!", Toast.LENGTH_LONG) .show(); } } pDialog.dismiss(); } } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.main, menu); return true; }}
2、原理:利用File对象的listFile()方法获得File[]数组。将数组产生的信息填充在listview中。核心代码中的重要方法:- listFiles()
- isFile()
- isDirectory()
- getAbsolutePath()
- getParentFile()
3、核心示例代码:public class MainActivity extends Activity { private TextView textView_main_currentpath; private ListView listView_main_fileList; private File currentFile = null; private File[] arrCurrentFiles = null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); textView_main_currentpath = (TextView) findViewById(R.id.text_main_currentpath); listView_main_fileList = (ListView) findViewById(R.id.listView_main_filelist); if (SDCardHelper.isSDCardMounted()) { currentFile = new File(SDCardHelper.getSDCardPath()); fillListView(currentFile); } else { Toast.makeText(MainActivity.this, "SDCARD不存在!", Toast.LENGTH_LONG) .show(); } listView_main_fileList .setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { if (arrCurrentFiles[position].isDirectory()) { File[] arrSubFiles = arrCurrentFiles[position] .listFiles(); if (arrSubFiles.length == 0) { Toast.makeText(MainActivity.this, "您点击的是空目录!", 2000).show(); } else { fillListView(arrCurrentFiles[position]); } } else { Toast.makeText(MainActivity.this, "您点击的不是目录!", Toast.LENGTH_LONG).show(); } } }); } public void clickButton(View view) { switch (view.getId()) { case R.id.imageView_main_back: if (!currentFile.getAbsolutePath().equals( SDCardHelper.getSDCardPath())) { fillListView(currentFile.getParentFile()); } break; default: break; } } public void fillListView(File file) { currentFile = file; arrCurrentFiles = currentFile.listFiles(); List<Map<String, Object>> list = new ArrayList<Map<String, Object>>(); for (int i = 0; i < arrCurrentFiles.length; i++) { Map<String, Object> map = new HashMap<String, Object>(); if (arrCurrentFiles[i].isDirectory()) { map.put("imgId", R.drawable.folder); } else { map.put("imgId", R.drawable.file); } map.put("filename", arrCurrentFiles[i].getName()); list.add(map); } SimpleAdapter adapter = new SimpleAdapter(MainActivity.this, list, R.layout.item_listview_main, new String[] { "imgId", "filename" }, newint[] { R.id.imageView_item_listview_type, R.id.text_item_listview_filename }); listView_main_fileList.setAdapter(adapter); textView_main_currentpath.setText(currentFile.getAbsolutePath()); }}
0 0
- Android数据存储——SharedPreferences及SDCard
- Android数据存储——SharedPreferences及SDCard
- Android数据存储——SharedPreferences及SDCard
- 15、Android数据存储——SharedPreferences及SDCard
- Android数据存储——SharedPreferences存储
- Android数据存储——SDcard
- Android——SdCard数据存储
- 用SharedPreferences数据存储到SDcard
- Android——SharedPreferences数据存储
- Android——数据存储之SharedPreferences
- Android数据存储——SharedPreferences
- Android存储数据方法——SharedPreferences
- Android数据存储 —— SharedPreferences
- Android——SharedPreferences存储数据方式
- Android数据存储——SharedPreferences
- Android数据存储之——SharedPreferences
- 【笔记】Android数据存储——SharedPreferences
- Android数据存储——1.使用SharedPreferences存储数据
- [转载]AE入门
- ArcGIS Engine 中线段的绘制方法
- python的学习资料汇总
- (转)ArcEngine根据点集rin…
- ArcGIS Desktop A…
- Android数据存储——SharedPreferences及SDCard
- 1分钟让别人喜欢你(一)
- 一切皆为JavaScript
- ArcGIS GP(Geoprocessing)…
- mac adb环境变量配置
- GIS规划应用——基于哈夫模型的GIS服…
- GIS:揭开你神秘的面纱
- ArcGIS夸张地图之Cartogram
- 基于ArcGIS Model Build…