日期:2014-05-16  浏览次数:20477 次

[Android]关于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上了。

import java.io.File;

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

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

??? private final Context mContext;
??? private final String mName;
??? private final CursorFactory mFactory;
??? private final int mNewVersion;

??? private SQLiteDatabase mDatabase = null;
??? private boolean mIsInitializing = false;

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

??????? mContext = context;
??????? mName = name;
??????? mFactory = factory;
??????? mNewVersion = version;
??? }

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

??????? }

??????? if (mIsInitializing) {
??????????? throw new IllegalStateException("getWritableDatabase called recursively");
??????? }

??????? // If we have a read-only database open, someone could be using it

??????? // (though they shouldn't), which would cause a lock to be held on

??????? //