是否可以将内部数据库移动到SDCard?

随着我的应用程序数据库的增长,这将需要越来越多的内部电话空间。 数据库中没有任何敏感/隐私的数据,所以我有兴趣把它移到SD卡上。

我正在使用SQLiteOpenHelper来协助数据库工作。 这是我的理解,你不能使用这个在SD卡上的DB访问,因为你不能定义数据库path。 但是,互联网上有一些(非常差)的例子表明你可以覆盖这个限制。 然而,我从来没有得到这些代码示例之一编译。

可能吗? 如果是这样 – 怎么样! 请注意,Froyo的“SD卡上的应用程序”function将无法正常工作,因为它不会移动内部文件。

Solutions Collecting From Web of "是否可以将内部数据库移动到SDCard?"

只要使用:

SQLiteDatabase.openDatabase(DB_FULL_PATH, null, SQLiteDatabase.OPEN_READONLY); 

其中DB_FULL_PATH可以是您的SD卡的path,例如/sdcard/mydatabase.db

编辑:

这是我在我的应用程序访问数据库中调用….

 private static DBUtil dbHelper = null; public void openDatabase() { if(dbHelper == null) { dbHelper = new DBUtil(this.context); dbHelper.openDataBase(SQLiteDatabase.OPEN_READWRITE); } } public void closeDatabase() { if(dbHelper != null) { dbHelper.close(); dbHelper = null; } } 

…这是我使用的数据库帮助类,它实际上扩展SQLiteOpenHelper,所以你仍然拥有你想要从这个类的一切。

 package com.myapp.android.db; import android.content.Context; import android.database.SQLException; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteException; import android.database.sqlite.SQLiteOpenHelper; import android.util.Log; import com.myapp.android.MyApp; import java.io.IOException; /** * Standard database utility class. * * TODO: Refactor. */ public class DBUtil extends SQLiteOpenHelper { /** * Database directory. * * <p> * Example: "/sdcard/myapp/db/" * </p> */ public static String DB_DIRECTORY = null; /** * Name of the database file. * * <p> * Example: "mydatabase.db" * </p> * */ public static String DB_NAME = null; /** * Full absolute path of the database. * * <p> * Example: "/sdcard/myapp/db/mydatabase.db" * </p> */ public static String DB_FULL_PATH = null; static { DB_DIRECTORY = MyApp.DATA_REPOSITORY_URI + "/myapp/db/"; DB_NAME = "mydatabase.db"; DB_FULL_PATH = DB_DIRECTORY + DB_NAME; } private SQLiteDatabase myDataBase; /** * Constructor Takes and keeps a reference of the passed context in order to * access to the application assets and resources. * * @param context */ public DBUtil(Context context) { super(context, DB_NAME, null, 1); try { this.createDataBase(); } catch (IOException ioe) { throw new Error("Unable to create database"); } } /** * Creates a empty database on the system and rewrites it with your own * database. * */ public void createDataBase() throws IOException { if (!checkDataBase()) this.getWritableDatabase(); } /** * Check if the database already exist to avoid re-copying the file each * time you open the application. * * @return true if it exists, false if it doesn't */ private boolean checkDataBase() { SQLiteDatabase checkDB = null; try { checkDB = SQLiteDatabase.openDatabase(DB_FULL_PATH, null, SQLiteDatabase.OPEN_READONLY); } catch (SQLiteException e) { // database does't exist yet. } if (checkDB != null) { checkDB.close(); } return checkDB != null ? true : false; } public void openDataBase(int mode) throws SQLException { try { myDataBase = SQLiteDatabase.openDatabase(DB_FULL_PATH, null, mode); } catch(IllegalStateException e) { // Sometimes, esp. after application upgrade, the database will be non-closed, raising a IllegalStateException // below. Try to avoid by simply opening it again. Log.d(MyApp.APP, "Database non-closed. Reopening."); myDataBase = SQLiteDatabase.openDatabase(DB_FULL_PATH, null, mode); } } public void openDataBase() throws SQLException { openDataBase(SQLiteDatabase.OPEN_READWRITE); } public SQLiteDatabase getDb() { return myDataBase; } @Override public synchronized void close() { if (myDataBase != null) myDataBase.close(); super.close(); } @Override public void onCreate(SQLiteDatabase db) { } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { } } 

我发现我可以在Android 2.2中使用完整path,但在2.1中,Context.openOrCreateDatabase()方法引发了exception。 为了解决这个问题,我直接调用了SQLiteDatabase.openOrCreateDatabase()方法。 这是我的扩展SQLOpenHelper的构造函数

 public class Database extends SQLiteOpenHelper { public Database(Context context) { super(new ContextWrapper(context) { @Override public SQLiteDatabase openOrCreateDatabase(String name, int mode, SQLiteDatabase.CursorFactory factory) { // allow database directory to be specified File dir = new File(DIR); if(!dir.exists()) { dir.mkdirs(); } return SQLiteDatabase.openDatabase(DIR + "/" + NAME, null, SQLiteDatabase.CREATE_IF_NECESSARY); } }, NAME, null, VERSION); this.context = context; } } 
  String dbPath = DATABASE_NAME; File sdcard = Environment.getExternalStorageDirectory(); if (sdcard != null && sdcard.canWrite()){ dbPath = sdcard.getAbsolutePath() + "/mypath/onsdcard/" + DATABASE_NAME; } else { dbPath = DATABASE_NAME; } mDBHelper = new WorkoutDBOpenHelper(context, dbPath); if(null != mDBHelper) mDB = mDBHelper.getWritableDatabase(); 

对我来说这个工作,和WorkoutDBOpenHelper扩展SQLiteOpenHelper和它的构造函数简单地调用SQLiteOpenHelper的超级。

 WorkoutDBOpenHelper(Context context, String dbPath) { super(context, dbPath, null, DATABASE_VERSION); } 

请注意,SQLiteopenHelper也在存储卡上创build数据库。 但是,在应用程序卸载时,数据库不会从SD卡中删除。

这不是如何将现有的内部数据库移动到SDCard的答案,但是这样您可以在创build时select一个选项。 我正在将现有的数据库从应用程序的“数据”目录移动到SD卡,但没有直接的方法。 一旦我找出一些东西,将会更新。

这将是确定的。 我想

 public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Log.i("DATABASE EXIST : ", ""+checkDataBase()); if(!checkDataBase()) copyDataBase(); DatabaseHandler dbhandler = new DatabaseHandler(MainActivity.this); Cursor cursor = dbhandler.getAllContacts(); ListView list = (ListView) findViewById(R.id.datalist); CustomCursorAdapter cursoradapter = new CustomCursorAdapter(MainActivity.this, cursor); list.setAdapter(cursoradapter); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); if (id == R.id.action_settings) { return true; } return super.onOptionsItemSelected(item); } private void copyDataBase() { ContextWrapper cw =new ContextWrapper(getApplicationContext()); String DB_PATH = "/data/data/com.example.copydatabase/databases/"; String DB_NAME = "testing"; Log.i("Database", "New database is being copied to device!"); byte[] buffer = new byte[1024]; OutputStream myOutput = null; int length; // Open your local db as the input stream InputStream myInput = null; try { myInput = MainActivity.this.getAssets().open(DB_NAME); // transfer bytes from the inputfile to the // outputfile myOutput =new FileOutputStream(DB_PATH+ DB_NAME); while((length = myInput.read(buffer)) > 0) { myOutput.write(buffer, 0, length); } myOutput.close(); myOutput.flush(); myInput.close(); Log.i("Database", "New database has been copied to device!"); } catch(IOException e) { e.printStackTrace(); } } public boolean checkDataBase() { String DB_PATH = "/data/data/com.example.copydatabase/databases/"; String DB_NAME = "testing"; File dbFile = new File(DB_PATH + DB_NAME); return dbFile.exists(); } }