android 五种存储

简介: 引用:http://www.2cto.com/kf/201204/125798.html     Android提供的数据持久化存储方式有以下几种。 1.Shared Preferences:以Key-Value形式存储数据 2.Internal Storage:数据文件存储在内存卡 3.External Storage:数据存储在外部设备,如SD卡等 4.SQLite Databases:SQLite存储方式 5.Network Connection:通过WebService等网络通信方式存储数据。

引用:http://www.2cto.com/kf/201204/125798.html

 

 

Android提供的数据持久化存储方式有以下几种。

1.Shared Preferences:以Key-Value形式存储数据


2.Internal Storage:数据文件存储在内存卡


3.External Storage:数据存储在外部设备,如SD卡等


4.SQLite Databases:SQLite存储方式


5.Network Connection:通过WebService等网络通信方式存储数据。

 

一、Shared Preferences

常用来存储应用中的用户偏好设置,例如应用的默认皮肤设置、记录用户上次登录信息等。数据的存储格式为Key-Value。

下面通过案例,记录用户信息来了解如何使用Shared Preferences。

介绍将使用到的Android SDK API:

SharedPreferences类:提供了一批读取、遍历数据的API。

Editor类:提供修改、保存数据API。
getSharedPreferences(String name, int mode):指定存储文件的文件名,并设置访问权限


getPreferences(int mode):如果你的Activity中只需要一个喜好文件,则可以不提供存储文件名,只需要设置访问权限


更多介绍可以访问:http://android.toolib.net/guide/topics/data/data-storage.html#pref

1、新建Android项目

项目名称Shared Preferences,主Activity名称为MainActivity。

2、设计主界面XML描述


[html] <?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android
    android:orientation="vertical" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" 
    > 
<TextView   
    android:layout_width="fill_parent"  
    android:layout_height="wrap_content"  
    android:text="@string/name" 
    /> 
  
<EditText 
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:id="@+id/name" 
    /> 
 
<TextView 
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:text="@string/age"  
    /> 
     
<EditText 
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:id="@+id/age" 
    /> 
 
<Button 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:text="@string/save"  
    android:onClick="save" 
    /> 
</LinearLayout> 
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
<TextView 
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:text="@string/name"
    />
 
<EditText
 android:layout_width="fill_parent"
 android:layout_height="wrap_content"
 android:id="@+id/name"
 />

<TextView
 android:layout_width="fill_parent"
 android:layout_height="wrap_content"
 android:text="@string/age"
 />
 
<EditText
 android:layout_width="fill_parent"
 android:layout_height="wrap_content"
 android:id="@+id/age"
 />

<Button
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:text="@string/save"
 android:onClick="save"
 />
</LinearLayout>界面效果:




 

3、定义“保存”按钮的save事件处理方法


[java] package mr.jin.shared; 
 
import android.app.Activity; 
import android.content.Context; 
import android.content.SharedPreferences; 
import android.content.SharedPreferences.Editor; 
import android.os.Bundle; 
import android.view.View; 
import android.widget.EditText; 
import android.widget.Toast; 
 
public class MainActivity extends Activity { 
    private EditText nameEdit; 
    private EditText ageEdit; 
    private String USERINFO="userInfo"; 
     
    @Override 
    public void onCreate(Bundle savedInstanceState) { 
        super.onCreate(savedInstanceState); 
        setContentView(R.layout.main); 
         
        nameEdit = (EditText) findViewById(R.id.name);//应用打开后,即查找到姓名、年龄的文本框对象。  
        ageEdit = (EditText) findViewById(R.id.age); 
 
        init(); 
    } 
     
    public void save(View v){ 
        try{ 
            SharedPreferences perference = getSharedPreferences(USERINFO, Context.MODE_PRIVATE); 
            Editor editor = perference.edit(); 
            editor.putString("name", nameEdit.getText().toString()); 
            editor.putString("age", ageEdit.getText().toString()); 
            editor.commit();//未调用commit前,数据实际是没有存储进文件中的。 调用后,存储存储  
             
            Toast.makeText(this, R.string.success, Toast.LENGTH_LONG).show(); 
             
        }catch(Exception e){ 
            Toast.makeText(this, R.string.error, Toast.LENGTH_LONG).show(); 
        } 
    } 
     
    /*第一次打开应用时,读取本地用户信息设置*/ 
    public void init(){ 
        SharedPreferences perference = getSharedPreferences(USERINFO, Context.MODE_PRIVATE); 
        nameEdit.setText(perference.getString("name", "")); 
        ageEdit.setText(perference.getString("age", "")); 
    } 

package mr.jin.shared;

import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;

public class MainActivity extends Activity {
 private EditText nameEdit;
 private EditText ageEdit;
 private String USERINFO="userInfo";
 
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
       
        nameEdit = (EditText) findViewById(R.id.name);//应用打开后,即查找到姓名、年龄的文本框对象。
        ageEdit = (EditText) findViewById(R.id.age);

        init();
    }
   
    public void save(View v){
     try{
      SharedPreferences perference = getSharedPreferences(USERINFO, Context.MODE_PRIVATE);
      Editor editor = perference.edit();
      editor.putString("name", nameEdit.getText().toString());
      editor.putString("age", ageEdit.getText().toString());
      editor.commit();//未调用commit前,数据实际是没有存储进文件中的。 调用后,存储存储
      
      Toast.makeText(this, R.string.success, Toast.LENGTH_LONG).show();
         
     }catch(Exception e){
      Toast.makeText(this, R.string.error, Toast.LENGTH_LONG).show();
     }
    }
   
    /*第一次打开应用时,读取本地用户信息设置*/
    public void init(){
     SharedPreferences perference = getSharedPreferences(USERINFO, Context.MODE_PRIVATE);
     nameEdit.setText(perference.getString("name", ""));
     ageEdit.setText(perference.getString("age", ""));
    }
}


4、部署应用

第一次打开应用,两个输入框都为空。在输入信息后,点击保存。退出应用,再次打开应用,将显示之前保存的用户信息。

 


二、Internal Storage

可以将文件存储在内部存储设备,默认文件访问权限是私有的,除了当前应用,其他应用无法访问。当用户卸载您的应用程序,这些文件将被删除。

来看看Android SDK提供的文件存储权限:

Context.MODE_APPEND;//追加方式存储
Context.MODE_PRIVATE;//私有方式存储,其他应用无法访问
Context.MODE_WORLD_READABLE;//允许其他应用读取数据
Context.MODE_WORLD_WRITEABLE;//允许其他应用写入、读取数据


1.建立项目

项目名称InternalStorage,主Activity类名称MainActivity。

2.定义界面及XML描述




 

print?<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android
    android:orientation="vertical" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" 
    > 
<TextView   
    android:layout_width="fill_parent"  
    android:layout_height="wrap_content"  
    android:text="输入文字" 
    /> 
  
 <EditText 
    android:minLines="3" 
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:id="@+id/editText" 
    /> 
  
 <Button 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:text="保存" 
    android:onClick="save" 
    /> 
     
 <TextView 
    android:id="@+id/showText" 
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    /> 
     
 <Button 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:text="显示保存的数据" 
    android:onClick="showData" 
    /> 
</LinearLayout> 
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
<TextView 
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:text="输入文字"
    />
 
 <EditText
  android:minLines="3"
  android:layout_width="fill_parent"
  android:layout_height="wrap_content"
  android:id="@+id/editText"
  />
 
 <Button
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:text="保存"
  android:onClick="save"
  />
  
 <TextView
  android:id="@+id/showText"
  android:layout_width="fill_parent"
  android:layout_height="wrap_content"
  />
  
 <Button
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:text="显示保存的数据"
  android:onClick="showData"
  />
</LinearLayout>
3.定义“保存”按钮的save、“显示保存的数据”按钮的事件处理


[java] package mr.jin.internal; 
 
import java.io.ByteArrayOutputStream; 
import java.io.FileInputStream; 
import java.io.FileOutputStream; 
 
import android.app.Activity; 
import android.content.Context; 
import android.os.Bundle; 
import android.view.View; 
import android.widget.EditText; 
import android.widget.TextView; 
import android.widget.Toast; 
 
public class MainActivity extends Activity { 
    private EditText editText; 
    private TextView showText; 
     
    @Override 
    public void onCreate(Bundle savedInstanceState) { 
        super.onCreate(savedInstanceState); 
        setContentView(R.layout.main); 
         
        editText = (EditText) findViewById(R.id.editText); 
        showText = (TextView) findViewById(R.id.showText); 
    } 
     
    public void save(View v){ 
        String content = editText.getText().toString(); 
         
        try { 
            FileOutputStream outfile = openFileOutput("current_file", Context.MODE_PRIVATE); 
            outfile.write(content.getBytes()); 
            outfile.close(); 
            Toast.makeText(this, "保存成功", 3000).show(); 
        } catch (Exception e) { 
            Toast.makeText(this, "保存失败", 3000).show(); 
            e.printStackTrace(); 
        } 
    } 
     
    public void showData(View v){ 
        try { 
            FileInputStream showfile = openFileInput("current_file"); 
            ByteArrayOutputStream out = new ByteArrayOutputStream(); 
            byte[] data = new byte[1024]; 
            int len = 0; 
             
            while( (len=showfile.read(data))  != -1){ 
                out.write(data, 0, len); 
            } 
             
            String content = new String(out.toByteArray()); 
             
            showText.setText(content); 
             
            Toast.makeText(this, "显示成功", 3000).show(); 
        } catch (Exception e) { 
            Toast.makeText(this, "显示失败", 3000).show(); 
            e.printStackTrace(); 
        } 
    } 

package mr.jin.internal;

import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;

import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends Activity {
    private EditText editText;
    private TextView showText;
   
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
       
        editText = (EditText) findViewById(R.id.editText);
        showText = (TextView) findViewById(R.id.showText);
    }
   
    public void save(View v){
     String content = editText.getText().toString();
     
     try {
   FileOutputStream outfile = openFileOutput("current_file", Context.MODE_PRIVATE);
   outfile.write(content.getBytes());
   outfile.close();
   Toast.makeText(this, "保存成功", 3000).show();
  } catch (Exception e) {
   Toast.makeText(this, "保存失败", 3000).show();
   e.printStackTrace();
  }
    }
   
    public void showData(View v){
     try {
   FileInputStream showfile = openFileInput("current_file");
   ByteArrayOutputStream out = new ByteArrayOutputStream();
   byte[] data = new byte[1024];
   int len = 0;
   
   while( (len=showfile.read(data))  != -1){
    out.write(data, 0, len);
   }
   
   String content = new String(out.toByteArray());
   
   showText.setText(content);
   
   Toast.makeText(this, "显示成功", 3000).show();
  } catch (Exception e) {
   Toast.makeText(this, "显示失败", 3000).show();
   e.printStackTrace();
  }
    }
}

 


4.部署测试。

 

三、External Storage

扩展存储,例如常见扩展存储有SD卡,可以将大容量的数据存储在外部存储中。

因为SD卡是可以由用户自由装载、卸载的,所以在使用SD卡上的文件之前,应该先检测设备是否已经装载成功。

通过判断Environment.getExternalStorageState()的返回值,可以知道目前SD卡的状态。

 

 

1、访问SD卡上文件

a.如果使用API级别大于等于8,可以使用getExternalFilesDir(String type),参数要求提供一个子目录名称,若传递null即为根目录,返回指定目录路径的File对象。

这里手册上建议使用有意义的子目录名称,便于Android媒体扫描器,正确的将文件分类。

[java] public class Environment { 
    public static String DIRECTORY_MUSIC = "Music"; //音频文件  
    public static String DIRECTORY_PODCASTS = "Podcasts";   //广播  
    public static String DIRECTORY_RINGTONES = "Ringtones"; //铃声  
    public static String DIRECTORY_ALARMS = "Alarms";   //警报  
    public static String DIRECTORY_NOTIFICATIONS = "Notifications"; //通知  
    public static String DIRECTORY_PICTURES = "Pictures";   //图片  
    public static String DIRECTORY_MOVIES = "Movies";   //电影  
    public static String DIRECTORY_DOWNLOADS = "Download";  //下载  
    public static String DIRECTORY_DCIM = "DCIM";   //照片  
    //...不完整的Environment类内容  

public class Environment {
 public static String DIRECTORY_MUSIC = "Music"; //音频文件
 public static String DIRECTORY_PODCASTS = "Podcasts"; //广播
 public static String DIRECTORY_RINGTONES = "Ringtones"; //铃声
 public static String DIRECTORY_ALARMS = "Alarms"; //警报
 public static String DIRECTORY_NOTIFICATIONS = "Notifications"; //通知
 public static String DIRECTORY_PICTURES = "Pictures"; //图片
 public static String DIRECTORY_MOVIES = "Movies"; //电影
 public static String DIRECTORY_DOWNLOADS = "Download"; //下载
 public static String DIRECTORY_DCIM = "DCIM"; //照片
 //...不完整的Environment类内容
}

 


b.API级别小于等于7,可以使用getExternalStorageDirectory(),将返回文件路径为/Android/data/<package_name>/files/的File对象,这里的<package_name>就是
AndroidManifest.xml中<manifest>标签中定义package。


这两种方法创建的文件,在应用被卸载时,文件也随之删除。

 


2、如果不希望创建的文件在应用卸载后被删除,可以使用下面的方法

以共享文件的方式存储,任何应用都将可以访问这些文件。

a.API大于等于8,getExternalStoragePublicDirectory (String type),参数与getExternalFilesDir(String type)中的参数一样,指定子目录。

b.API小于等于7,getExternalStorageDirectory(),返回外部存储的根目录的File对象。然后将文件存储在:

Music/ - 媒体扫描仪划分为用户的音乐在这里发现的所有媒体。
Podcasts/ - 媒体扫描仪的分类在这里找到一个podcast的所有媒体。
Ringtones/ - 媒体扫描器分类作为铃声,在这里发现所有的媒体。
Alarms/ - 媒体扫描仪发出报警声,这里发现的所有媒体分类。
Notifications/ - 媒体扫描仪的分类作为通知的声音在这里发现的所有媒体。
Pictures/ - 所有照片(不包括那些用相机拍摄)。
Movies/ - 所有电影(不包括用摄像机拍摄的)。
Download/ - 杂项下载。

 

 

四、SQLite存储

Android提供了对SQLite全面支持,无需考虑数据库连接、连接池等问题。

只需要集成SQLiteOpenHelper类,它提供了访问数据库、事务等API。

[java] package mr.jin.service; 
 
import android.content.Context; 
import android.database.sqlite.SQLiteDatabase; 
import android.database.sqlite.SQLiteOpenHelper; 
 
public class DBOpenHelper extends SQLiteOpenHelper { 
 
    public DBOpenHelper(Context context) { 
        //第一个参数:传递上下文对象  
        //第二个参数:数据库保存的文件名  
        //第三个参数:null使用默认的创建游标对象工厂  
        //第四个参数:最重要,表示数据库版本号,最小值1。每次运行应用前  
        //      会与当前应用的数据库版本做比较,如果大于当前版本号  
        //      将调用onUpgrade方法。  
        super(context, "dbfile.db", null, 1); 
    } 
 
    @Override 
    public void onCreate(SQLiteDatabase db) {//只在第一次运行应用时调用,这里可以运行创建数据库结构的代码  
        db.execSQL("CREATE TABLE person(personid integer primary key autoincrement, name varchar(20))"); 
    } 
 
    @Override 
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {//只在数据库版本发生改变时调用  
        db.execSQL("ALTER TABLE person ADD amount integer NULL"); 
    } 
 

package mr.jin.service;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

public class DBOpenHelper extends SQLiteOpenHelper {

 public DBOpenHelper(Context context) {
  //第一个参数:传递上下文对象
  //第二个参数:数据库保存的文件名
  //第三个参数:null使用默认的创建游标对象工厂
  //第四个参数:最重要,表示数据库版本号,最小值1。每次运行应用前
  //  会与当前应用的数据库版本做比较,如果大于当前版本号
  //  将调用onUpgrade方法。
  super(context, "dbfile.db", null, 1);
 }

 @Override
 public void onCreate(SQLiteDatabase db) {//只在第一次运行应用时调用,这里可以运行创建数据库结构的代码
  db.execSQL("CREATE TABLE person(personid integer primary key autoincrement, name varchar(20))");
 }

 @Override
 public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {//只在数据库版本发生改变时调用
  db.execSQL("ALTER TABLE person ADD amount integer NULL");
 }

}
SQLiteOpenHelper提供了两个API来获得数据库连接对象SQLiteDatabase:


getWritableDatabase():返回可读、写对象


getReadableDatabase():返回可读、写对象。仅当无法写时,返回只读对象。


具体一些操作数据库的方法,可以参看SQLiteDatabase API手册,提供的方法已经足够多了。http://android.toolib.net/reference/android/database/sqlite/SQLiteDatabase.html

相关文章
|
6月前
|
存储 安全 Java
Android DataStore:安全存储和轻松管理数据
Android DataStore:安全存储和轻松管理数据
|
9月前
|
存储 编解码 Android开发
如何使用 VMware 安装安卓虚拟机,如何配置虚拟机的网络和存储?
如何使用 VMware 安装安卓虚拟机,如何配置虚拟机的网络和存储?
791 0
|
存储 XML 缓存
Android 初代 K-V 存储框架 SharedPreferences,旧时代的余晖?
SharedPreferences 是 Android 平台上轻量级的 K-V 存储框架,亦是初代 K-V 存储框架,至今被很多应用沿用。 有的小伙伴会说,SharedPreferences 是旧时代的产物,现在已经有 DataStore 或 MMKV 等新时代的 K-V 框架,没有学习意义。但我认为,虽然 SharedPreference 这个方案已经过时,但是并不意味着 SharedPreference 中使用的技术过时。做技术要知其然,更要知其所以然,而不是人云亦云,如果要你解释为什么 SharedPreferences 会过时,你能说到什么程度?
114 0
|
存储 Java Android开发
Android 7.1 设置-存储信息显示不正确
Android 7.1 设置-存储信息显示不正确
210 0
Android 7.1 设置-存储信息显示不正确
|
存储 Shell Android开发
【Android 逆向】获取安装在手机中的应用的 APK 包 ( 进入 adb shell | 获取 root 权限 | 进入 /data/app/ 目录 | 拷贝 base.apk 到外置存储 )
【Android 逆向】获取安装在手机中的应用的 APK 包 ( 进入 adb shell | 获取 root 权限 | 进入 /data/app/ 目录 | 拷贝 base.apk 到外置存储 )
436 0
【Android 逆向】获取安装在手机中的应用的 APK 包 ( 进入 adb shell | 获取 root 权限 | 进入 /data/app/ 目录 | 拷贝 base.apk 到外置存储 )
|
存储 API 文件存储
Android | 作用域存储适配
Android | 作用域存储适配
|
存储 数据库 Android开发
【Android 文件管理】分区存储 ( 创建与查询图片文件 )(一)
【Android 文件管理】分区存储 ( 创建与查询图片文件 )(一)
345 0
【Android 文件管理】分区存储 ( 创建与查询图片文件 )(一)
|
存储 XML API
Android调用相机拍照录视频录音以及存储,7.0以上及以下都可使用。
Android调用相机拍照录视频录音以及存储,7.0以上及以下都可使用。
296 0
|
存储 缓存 Linux
Android内、外存储分区&常用存储目录,getExternalStorageDirectory获取的是storage/emulated/0/
Android内、外存储分区&常用存储目录,getExternalStorageDirectory获取的是storage/emulated/0/
1336 0
|
SQL 存储 Oracle
【Android】7.0复杂数据的存储SQLite(内置数据库)Room框架
常用的数据库 sqlserver oracle mysql Android嵌入式数据库SQLite SQLite数据库支持SQL语法和ACID事务,适用于存储大量的关系型数据 eg:qq的聊天列表 学习强国的新闻
512 0