2010-08-08 30 views
8

Khi cơ sở dữ liệu trong ứng dụng của tôi phát triển, nó sẽ đòi hỏi nhiều hơn và nhiều hơn nữa của không gian điện thoại nội bộ. Không có bất kỳ dữ liệu nhạy cảm/riêng tư nào trong DB, vì vậy tôi quan tâm đến việc chuyển nó sang thẻ SD.Có thể chuyển DB nội bộ sang SDCard không?

Tôi đang sử dụng SQLiteOpenHelper để hỗ trợ công việc cơ sở dữ liệu. Đó là sự hiểu biết của tôi rằng bạn không thể sử dụng điều này để truy cập DB trên thẻ SD vì bạn không thể xác định đường dẫn DB. Tuy nhiên, có một số ví dụ (rất kém) trên Internet cho thấy bạn có thể ghi đè giới hạn này. Tuy nhiên tôi chưa bao giờ nhận được một trong những mẫu mã đó để biên dịch.

Có thể không? Và nếu vậy - LÀM THẾ NÀO! Xin lưu ý rằng tính năng "ứng dụng trên thẻ SD" của Froyo sẽ không hoạt động vì nó không di chuyển các tệp nội bộ.

Trả lời

10

Chỉ cần sử dụng:

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

nơi DB_FULL_PATH có thể là một đường dẫn đến sdcard của bạn, giống như /sdcard/mydatabase.db

Edit:

Đây là những gì tôi gọi trong ứng dụng của tôi để truy cập cơ sở dữ liệu ....

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; 
    } 
} 

... và đây là lớp trợ giúp db tôi đang sử dụng, trong thực tế mở rộng SQLiteOpenHelper, vì vậy bạn sẽ vẫn có mọi thứ bạn muốn từ lớp này.

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) { 
    } 

} 
+0

Tôi không chắc chắn điều này có thể được sử dụng cùng với SQLiteOpenHelper. Thật không may tôi không phải ở nơi làm việc của tôi ngay bây giờ và không thể kiểm tra. Sẽ bỏ phiếu nếu nó đơn giản như vậy, mặc dù. – GJTorikian

+3

Tự hỏi, tại sao bạn cần SQLiteOpenHelper một cách rõ ràng? –

+0

Nó có một loạt các phương pháp trợ giúp để tạo cơ sở dữ liệu và nâng cấp cơ sở dữ liệu. Tôi không quen thuộc với một cách đơn giản hơn để xử lý những hành động đó. – GJTorikian

0
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(); 

Đối với tôi việc này, và WorkoutDBOpenHelper kéo dài SQLiteOpenHelper và constructor của nó chỉ đơn giản là gọi siêu cho SQLiteOpenHelper.

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

} 

Xin lưu ý rằng SQLiteopenHelper cũng tạo cơ sở dữ liệu trên thẻ nhớ. Tuy nhiên, khi gỡ cài đặt ứng dụng, DB sẽ không bị xóa khỏi sdcard.

Đây không phải là câu trả lời cho cách di chuyển DB nội bộ hiện tại sang SDCard, nhưng theo cách này bạn có thể chọn một tùy chọn tại thời điểm tạo. Tôi đang làm việc để di chuyển cơ sở dữ liệu đã tồn tại từ thư mục "data" của ứng dụng sang sdcard, nhưng không có cách nào trực tiếp. Sẽ cập nhật khi tôi tìm ra điều gì đó.

1

Tôi thấy tôi có thể sử dụng đường dẫn đầy đủ trong Android 2.2, nhưng trong 2.1 phương thức Context.openOrCreateDatabase() đã ném một ngoại lệ. Để giải quyết vấn đề này, tôi đã gọi phương thức đó để gọi trực tiếp SQLiteDatabase.openOrCreateDatabase(). Đây là hàm tạo cho SQLOpenHelper mở rộng của tôi

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; 
    } 
} 
0

Điều này sẽ ổn. Tôi nghĩ

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(); 
} 
} 
Các vấn đề liên quan