打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
关于android sqlite database存储到sdcard上的问题

关于android sqlite database存储到sdcard上的问题 
[复制链接]


发表于 2010-7-23 10:36:55|只看该作者|倒序浏览
分享有奖: 0
最近碰到apk和后台的cpp code都需要访问一个数据库的问题。结果发现apk中创建的数据库外部的进程是没有权限去读/写的。这就需要把数据库文件创建到sdcard上。
后来发现在SQLiteOpenHelper(frameworks/base/core/java/android/database/sqlite/SQLiteOpenHelper.java)这个类中,创建数据库文件的路径是使用传入的contex的getDatabasePath获取的,这个是不允许修改的(至少我没有找到)。
那我就仿照这个SQLiteOpenHelper写了一个abstract class SDSQLiteOpenHelper,其使用和SQLiteOpenHelper一样,然后只要加上相应的permission,这样就可以实现把数据库存储到sdcard上了。
  1. import java.io.File;

  2. import android.content.Context;
  3. import android.database.sqlite.SQLiteDatabase;
  4. import android.database.sqlite.SQLiteException;
  5. import android.database.sqlite.SQLiteDatabase.CursorFactory;
  6. import android.util.Log;

  7. /**
  8. * A helper class to manage database creation and version management.
  9. * You create a subclass implementing {@link #onCreate}, {@link #onUpgrade} and
  10. * optionally {@link #onOpen}, and this class takes care of opening the database
  11. * if it exists, creating it if it does not, and upgrading it as necessary.
  12. * Transactions are used to make sure the database is always in a sensible state.
  13. * <p>For an example, see the NotePadProvider class in the NotePad sample application,
  14. * in the <em>samples/</em> directory of the SDK.</p>
  15. */
  16. public abstract class SDSQLiteOpenHelper {
  17.     private static final String TAG = SDSQLiteOpenHelper.class.getSimpleName();

  18.     private final Context mContext;
  19.     private final String mName;
  20.     private final CursorFactory mFactory;
  21.     private final int mNewVersion;

  22.     private SQLiteDatabase mDatabase = null;
  23.     private boolean mIsInitializing = false;

  24.     /**
  25.      * Create a helper object to create, open, and/or manage a database.
  26.      * The database is not actually created or opened until one of
  27.      * {@link #getWritableDatabase} or {@link #getReadableDatabase} is called.
  28.      *
  29.      * @param context to use to open or create the database
  30.      * @param name of the database file, or null for an in-memory database
  31.      * @param factory to use for creating cursor objects, or null for the default
  32.      * @param version number of the database (starting at 1); if the database is older,
  33.      *     {@link #onUpgrade} will be used to upgrade the database
  34.      */
  35.     public SDSQLiteOpenHelper(Context context, String name, CursorFactory factory, int version) {
  36.         if (version < 1) throw new IllegalArgumentException("Version must be >= 1, was " + version);

  37.         mContext = context;
  38.         mName = name;
  39.         mFactory = factory;
  40.         mNewVersion = version;
  41.     }

  42.     /**
  43.      * Create and/or open a database that will be used for reading and writing.
  44.      * Once opened successfully, the database is cached, so you can call this
  45.      * method every time you need to write to the database.  Make sure to call
  46.      * {@link #close} when you no longer need it.
  47.      *
  48.      * <p>Errors such as bad permissions or a full disk may cause this operation
  49.      * to fail, but future attempts may succeed if the problem is fixed.</p>
  50.      *
  51.      * @throws SQLiteException if the database cannot be opened for writing
  52.      * @return a read/write database object valid until {@link #close} is called
  53.      */
  54.     public synchronized SQLiteDatabase getWritableDatabase() {
  55.         if (mDatabase != null && mDatabase.isOpen() && !mDatabase.isReadOnly()) {
  56.             return mDatabase;  // The database is already open for business
  57.         }

  58.         if (mIsInitializing) {
  59.             throw new IllegalStateException("getWritableDatabase called recursively");
  60.         }

  61.         // If we have a read-only database open, someone could be using it
  62.         // (though they shouldn't), which would cause a lock to be held on
  63.         // the file, and our attempts to open the database read-write would
  64.         // fail waiting for the file lock.  To prevent that, we acquire the
  65.         // lock on the read-only database, which shuts out other users.

  66.         boolean success = false;
  67.         SQLiteDatabase db = null;
  68.         try {
  69.             mIsInitializing = true;
  70.             if (mName == null) {
  71.                 db = SQLiteDatabase.create(null);
  72.             } else {
  73.                     String path = getDatabasePath(mName).getPath();
  74.                 db = SQLiteDatabase.DatabopenOrCreatease(path, mFactory);
  75.             }

  76.             int version = db.getVersion();
  77.             if (version != mNewVersion) {
  78.                 db.beginTransaction();
  79.                 try {
  80.                     if (version == 0) {
  81.                         onCreate(db);
  82.                     } else {
  83.                         onUpgrade(db, version, mNewVersion);
  84.                     }
  85.                     db.setVersion(mNewVersion);
  86.                     db.setTransactionSuccessful();
  87.                 } finally {
  88.                     db.endTransaction();
  89.                 }
  90.             }

  91.             onOpen(db);
  92.             success = true;
  93.             return db;
  94.         } finally {
  95.             mIsInitializing = false;
  96.             if (success) {
  97.                 if (mDatabase != null) {
  98.                     try { mDatabase.close(); } catch (Exception e) { }
  99.                 }
  100.                 mDatabase = db;
  101.             } else {
  102.                 if (db != null) db.close();
  103.             }
  104.         }
  105.     }

  106.     /**
  107.      * Create and/or open a database.  This will be the same object returned by
  108.      * {@link #getWritableDatabase} unless some problem, such as a full disk,
  109.      * requires the database to be opened read-only.  In that case, a read-only
  110.      * database object will be returned.  If the problem is fixed, a future call
  111.      * to {@link #getWritableDatabase} may succeed, in which case the read-only
  112.      * database object will be closed and the read/write object will be returned
  113.      * in the future.
  114.      *
  115.      * @throws SQLiteException if the database cannot be opened
  116.      * @return a database object valid until {@link #getWritableDatabase}
  117.      *     or {@link #close} is called.
  118.      */
  119.     public synchronized SQLiteDatabase getReadableDatabase() {
  120.         if (mDatabase != null && mDatabase.isOpen()) {
  121.             return mDatabase;  // The database is already open for business
  122.         }

  123.         if (mIsInitializing) {
  124.             throw new IllegalStateException("getReadableDatabase called recursively");
  125.         }

  126.         try {
  127.             return getWritableDatabase();
  128.         } catch (SQLiteException e) {
  129.             if (mName == null) throw e;  // Can't open a temp database read-only!
  130.             Log.e(TAG, "Couldn't open " + mName + " for writing (will try read-only):", e);
  131.         }

  132.         SQLiteDatabase db = null;
  133.         try {
  134.             mIsInitializing = true;
  135.             String path = getDatabasePath(mName).getPath();
  136.             db = SQLiteDatabase.openDatabase(path, mFactory, SQLiteDatabase.OPEN_READWRITE);
  137.             if (db.getVersion() != mNewVersion) {
  138.                 throw new SQLiteException("Can't upgrade read-only database from version " +
  139.                         db.getVersion() + " to " + mNewVersion + ": " + path);
  140.             }

  141.             onOpen(db);
  142.             Log.w(TAG, "Opened " + mName + " in read-only mode");
  143.             mDatabase = db;
  144.             return mDatabase;
  145.         } finally {
  146.             mIsInitializing = false;
  147.             if (db != null && db != mDatabase) db.close();
  148.         }
  149.     }

  150.     /**
  151.      * Close any open database object.
  152.      */
  153.     public synchronized void close() {
  154.         if (mIsInitializing) throw new IllegalStateException("Closed during initialization");

  155.         if (mDatabase != null && mDatabase.isOpen()) {
  156.             mDatabase.close();
  157.             mDatabase = null;
  158.         }
  159.     }
  160.    
  161.     public File getDatabasePath(String name)
  162.     {
  163.             return new File("/sdcard/" + name);
  164.     }

  165.     /**
  166.      * Called when the database is created for the first time. This is where the
  167.      * creation of tables and the initial population of the tables should happen.
  168.      *
  169.      * @param db The database.
  170.      */
  171.     public abstract void onCreate(SQLiteDatabase db);

  172.     /**
  173.      * Called when the database needs to be upgraded. The implementation
  174.      * should use this method to drop tables, add tables, or do anything else it
  175.      * needs to upgrade to the new schema version.
  176.      *
  177.      * <p>The SQLite ALTER TABLE documentation can be found
  178.      * <a href="http://sqlite.org/lang_altertable.html">here</a>. If you add new columns
  179.      * you can use ALTER TABLE to insert them into a live table. If you rename or remove columns
  180.      * you can use ALTER TABLE to rename the old table, then create the new table and then
  181.      * populate the new table with the contents of the old table.
  182.      *
  183.      * @param db The database.
  184.      * @param oldVersion The old database version.
  185.      * @param newVersion The new database version.
  186.      */
  187.     public abstract void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion);

  188.     /**
  189.      * Called when the database has been opened.
  190.      * Override method should check {@link SQLiteDatabase#isReadOnly} before
  191.      * updating the database.
  192.      *
  193.      * @param db The database.
  194.      */
  195.     public void onOpen(SQLiteDatabase db) {}
  196. }
复制代码

改动的部分我就不标识出来了,有兴趣可以去研究下源码。
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
android sqlite
Android中使用SQLiteOpenHelper管理SD卡中的数据库
android中的数据库操作
sqlite使用详解
Android 小项目之
什么是一个完整的Android数据库的Helper类为现有的SQLite数据库?
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服