zoukankan      html  css  js  c++  java
  • Android中使用SQLiteOpenHelper管理SD卡中的数据库

    使用Android中自带的SQLiteOpenHelper可以完成数据库的创建与管理,但有两点局限:
    (1)数据库创建在内存卡中,大小受限,创建位置位于/data/data/应用程序名/databases中(可使用Eclispe的DDMS查看)。
    (2)如果无法获取Root权限,则无法直接查看创建的数据库。
     
    鉴于上述限制及实际需要,打算使用SQLiteOpenHelper管理SD卡上的数据库,通过研究SQLiteOpenHelper的源码,发现其创建或打开数据库的代码位于getWritableDatabase()函数中(getReadableDatabase本身也是调用了getWritableDatabase):
     if (mName == null) {
         db = SQLiteDatabase.create(null);
         } 
    else {
         db = mContext.openOrCreateDatabase(mName, 0, mFactory);
         }

     分析上述代码发现,当数据库名字为非空时,创建数据库或打开由mContext完成,这个mContext由SQLiteOpenHelper的构造函数传入:SQLiteOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version)。那么我们对于传入的context,重载其

    import android.content.Context;
    import android.database.SQLException;
    import android.database.sqlite.SQLiteDatabase;
    import android.database.sqlite.SQLiteOpenHelper;
    import android.util.Log;

    /**
    * 数据库管理和维护类
    **/
    public class SdCardDBHelper extends SQLiteOpenHelper{

    public static final String TAG = "SdCardDBHelper";
    /**
    * 数据库名称
    **/
    public static String DATABASE_NAME = "sddb.db";

    /**
    * 数据库版本
    **/
    public static int DATABASE_VERSION = 1;

    /**
    * 构造函数
    *
    * @param context 上下文环境
    **/
    public SdCardDBHelper(Context context){
    super(context, DATABASE_NAME, null, DATABASE_VERSION);
    }

    /**
    * 创建数据库时触发,创建离线存储所需要的数据库表
    *
    * @param db
    **/
    @Override
    public void onCreate(SQLiteDatabase db) {
    Log.e(TAG, "开始创建数据库表");
    try{
    //创建用户表(user)
    db.execSQL("create table if not exists user" +
    "(_id integer primary key autoincrement,name varchar(20),password varchar(20),role varchar(10),updateTime varchar(20))");
    Log.e(TAG, "创建离线所需数据库表成功");
    }
    catch(SQLException se){
    se.printStackTrace();
    Log.e(TAG, "创建离线所需数据库表失败");
    }
    }

    /** 更新数据库时触发,
    *
    * @param db
    * @param oldVersion
    * @param newVersion
    **/
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    //db.execSQL("ALTER TABLE person ADD COLUMN other STRING");
    }
    }

    重载的openOrCreateDatabase在sd卡上创建数据库的Context

    import java.io.File;
    import java.io.IOException;

    import android.content.Context;
    import android.content.ContextWrapper;
    import android.database.DatabaseErrorHandler;
    import android.database.sqlite.SQLiteDatabase;
    import android.database.sqlite.SQLiteDatabase.CursorFactory;
    import android.util.Log;

    /**
    * 用于支持对存储在SD卡上的数据库的访问
    **/
    public class DatabaseContext extends ContextWrapper {

    /**
    * 构造函数
    * @param base 上下文环境
    */
    public DatabaseContext(Context base){
    super(base);
    }

    /**
    * 获得数据库路径,如果不存在,则创建对象对象
    * @param name
    * @param mode
    * @param factory
    */
    @Override
    public File getDatabasePath(String name) {
    //判断是否存在sd卡
    boolean sdExist = android.os.Environment.MEDIA_MOUNTED.equals(android.os.Environment.getExternalStorageState());
    if(!sdExist){//如果不存在,
    Log.e("SD卡管理:", "SD卡不存在,请加载SD卡");
    return null;
    }
    else{//如果存在
    //获取sd卡路径
    String dbDir=android.os.Environment.getExternalStorageDirectory().getAbsolutePath();
    dbDir += "/database";//数据库所在目录
    String dbPath = dbDir+"/"+name;//数据库路径
    //判断目录是否存在,不存在则创建该目录
    File dirFile = new File(dbDir);
    if(!dirFile.exists())
    dirFile.mkdirs();

    //数据库文件是否创建成功
    boolean isFileCreateSuccess = false;
    //判断文件是否存在,不存在则创建该文件
    File dbFile = new File(dbPath);
    if(!dbFile.exists()){
    try {
    isFileCreateSuccess = dbFile.createNewFile();//创建文件
    } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    }
    else
    isFileCreateSuccess = true;

    //返回数据库文件对象
    if(isFileCreateSuccess)
    return dbFile;
    else
    return null;
    }
    }

    /**
    * 重载这个方法,是用来打开SD卡上的数据库的,android 2.3及以下会调用这个方法。
    *
    * @param name
    * @param mode
    * @param factory
    */
    @Override
    public SQLiteDatabase openOrCreateDatabase(String name, int mode,
    SQLiteDatabase.CursorFactory factory) {
    SQLiteDatabase result = SQLiteDatabase.openOrCreateDatabase(getDatabasePath(name), null);
    return result;
    }

    /**
    * Android 4.0会调用此方法获取数据库。
    *
    * @see android.content.ContextWrapper#openOrCreateDatabase(java.lang.String, int,
    * android.database.sqlite.SQLiteDatabase.CursorFactory,
    * android.database.DatabaseErrorHandler)
    * @param name
    * @param mode
    * @param factory
    * @param errorHandler
    */
    @Override
    public SQLiteDatabase openOrCreateDatabase(String name, int mode, CursorFactory factory,
    DatabaseErrorHandler errorHandler) {
    SQLiteDatabase result = SQLiteDatabase.openOrCreateDatabase(getDatabasePath(name), null);
    return result;
    }
    }

     调用程序:

    DatabaseContext dbContext = new DatabaseContext(this);
    SdCardDBHelper dbHelper = new SdCardDBHelper(dbContext);

    这里尤其值得注意的是,不同版本的android API会调用不同的openOrCreateDatabase函数。

    当然也可直接使用SQLiteDatabase创建SD卡上的数据库,或者直接修改SQLiteOpenHelper的源码重新编译,不过前者没有对数据库进行一些检验容错处理,也不及SQLiteOpenHelper对数据库操作方便。后者工作量较大,不建议采用。
     
    最后注意记得加入对SD卡的读写权限
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
     
    SQLite桌面查看工具:sqlite administrator、sqlite man或者firefox插件sqlite manager等。
     
    参考资料:
  • 相关阅读:
    英语46级CET外语大学词汇
    TOEFL词汇笔记英语托福英语
    19道常见的JS面试算法题
    Vue.js---指令与事件、语法糖
    Qt--多线程间的互斥
    const关键字总结
    Numpy和Pandas的使用入门
    python爬虫爬取天气数据并图形化显示
    JCEF-鼠标右键菜单
    JCEF-tab形式展示浏览器
  • 原文地址:https://www.cnblogs.com/zhuzhengwen1983/p/3624667.html
Copyright © 2011-2022 走看看