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

最近碰到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. }
复制代码


改动的部分我就不标识出来了,有兴趣可以去研究下源码。

 

转帖:http://www.eoeandroid.com/thread-26188-1-1.html

感谢作者分享:sandersshen

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值