2010-01-03 50 views
54

Tôi muốn thêm tính năng vào ứng dụng Android tự động sao lưu cơ sở dữ liệu SQLite vào SD card.Làm cách nào để sao lưu tệp cơ sở dữ liệu vào thẻ SD trên Android?

Cách tốt nhất để giải quyết vấn đề này là gì? Có bất kỳ ví dụ hoặc hướng dẫn nào có sẵn không?

+1

Lưu ý rằng nếu thẻ đó trên thẻ SD, thẻ sẽ không còn riêng tư với ứng dụng của bạn nữa. –

+3

@Mirko N: Tôi biết, nhưng mọi người muốn có một bản sao lưu cho những thứ như cài đặt lại, hư hỏng điện thoại, những thứ tương tự. – CodeFusionMobile

Trả lời

7

Cơ sở dữ liệu SQLite là các tệp hoàn toàn độc lập và di động — bạn chỉ có thể sao chép toàn bộ tệp thẳng vào thẻ SD.

Mặc dù trước tiên tôi sẽ kiểm tra xem thẻ SD có được lắp đặt trên thiết bị hay không và đường dẫn của thẻ là gì (sử dụng Environment.getExternalStorageDirectory()).

118

Mã này phù hợp với tôi!

try { 
     File sd = Environment.getExternalStorageDirectory(); 
     File data = Environment.getDataDirectory(); 

     if (sd.canWrite()) { 
      String currentDBPath = "//data//{package name}//databases//{database name}"; 
      String backupDBPath = "{database name}"; 
      File currentDB = new File(data, currentDBPath); 
      File backupDB = new File(sd, backupDBPath); 

      if (currentDB.exists()) { 
       FileChannel src = new FileInputStream(currentDB).getChannel(); 
       FileChannel dst = new FileOutputStream(backupDB).getChannel(); 
       dst.transferFrom(src, 0, src.size()); 
       src.close(); 
       dst.close(); 
      } 
     } 
    } catch (Exception e) { 
    } 

Có ai biết điều này sẽ hoạt động trên điện thoại không phải gốc không? Tôi đã chỉ thử nó trên một G1 bắt nguồn từ.

+18

Tôi có thể xác nhận điều này không hoạt động trên điện thoại không bắt nguồn từ. Chỉ cần chắc chắn rằng bạn thêm '' –

+0

currentDB.exists() returnign false .... có thể b cơ sở dữ liệu đó không hiện diện trên sys bộ nhớ nhưng tôi đã thành công chèn các hàng ... và m nhận được đường dẫn của String currentDBPath = db.getPath(); –

+10

Tôi sử dụng Tệp currentDB = getDatabasePath (DatabaseHelper.DATABASE_NAME); chứ không phải là tham chiếu tĩnh –

1

Tôi không biết những gì sẽ xảy ra nếu điện thoại được bắt rễ hay không nhưng bạn nên ghi tập tin của bạn để:

/Android/data/{package_name}/files/ 

này sẽ làm việc cho dù đó là bắt nguồn từ hay không.

+2

Sự cố với việc sao lưu vào vị trí này trên thẻ sd là sự cố sẽ bị xóa khi ứng dụng được gỡ cài đặt. Điều đó có thể không được mong muốn cho một bản sao lưu. – ZNS

2

I answered câu hỏi tương tự như vậy với phương pháp bạn có thể đặt trong SQLiteOpenHelper. Nó đơn giản như việc sao chép tệp db từ một số loại bộ nhớ ngoài, vào bộ nhớ ứng dụng nội bộ. Ngoài ra còn có một số mã phụ mở ra và đọc tệp db để đảm bảo rằng nó đang ở trạng thái thích hợp cho Android để thực hiện các cuộc gọi cơ sở dữ liệu đến nó.

+0

Tôi đã xem ví dụ của bạn và nó trông ngắn gọn, quá ngắn gọn. Thật khó cho tôi để tìm ra cách thích nghi nó với mã của tôi. Tôi không biết mã nào hiệu quả hơn, tất cả những gì tôi biết là logic/mã thừa hoặc quá đơn giản của mã khiến tôi khó hiểu và thích ứng với mã của mình hơn. Hầu hết mọi người tạo ra 4 "FILE" riêng biệt, trong khi bạn chỉ tạo 2 FILE. Tại sao chủ đề cụ thể này lại quá khó hiểu? – JamisonMan111

18
try { 
    File sd = Environment.getExternalStorageDirectory(); 
    File data = Environment.getDataDirectory(); 

    if (sd.canWrite()) { 
     String currentDBPath = "//data//"+ packageName +"//databases//"+dbList[0]; 
     String backupDBPath = dbList[0]; 
     File currentDB = new File(data, currentDBPath); 
     File backupDB = new File(sd, backupDBPath); 

     FileChannel src = new FileInputStream(currentDB).getChannel(); 
     FileChannel dst = new FileOutputStream(backupDB).getChannel(); 
     dst.transferFrom(src, 0, src.size()); 
     src.close(); 
     dst.close(); 
     Toast.makeText(getBaseContext(), backupDB.toString(), Toast.LENGTH_LONG).show(); 
    } 
} catch (Exception e) { 
    Toast.makeText(getBaseContext(), e.toString(), Toast.LENGTH_LONG).show(); 
} 

đó làm việc như trái ngược với các ví dụ trên, trong đó "/" chính là "\" lãng phí 20 phút của cuộc đời tôi tìm ra rằng, nhưng tôi thực sự nên đã thấy rằng sớm hơn. Toast sẽ cho bạn biết nơi tập tin đã được đặt hoặc cho bạn biết những gì sai khi nó không hoạt động.

+1

iif (sd.canWrite()) không hoạt động đối với tôi. Thay vào đó tôi đã sử dụng nếu (Environment.MEDIA_MOUNTED.equals (bang)) { – Archie

1

Bạn phải cấp quyền cho phép android.permission.WRITE_EXTERNAL_STORAGE trong đơn đăng ký của mình. Nó hoạt động tốt trên các thiết bị chưa được phát hành.

2
public static void BackupDatabase() throws IOException 
{ 
    boolean success =true; 
    File file = null; 
    file = new File(Environment.getExternalStorageDirectory() +"/M.O.L.S_Backup"); 

    if (file.exists()) 
    { 
     success =true; 
    } 
    else 
    { 
     success = file.mkdir(); 
    } 

    if (success) 
    { 
     String inFileName = "/data/data/com.sygic.sdk.demo/databases/MOLS_DB.s3db"; 
     File dbFile = new File(inFileName); 
     FileInputStream fis = new FileInputStream(dbFile); 

     String outFileName = Environment.getExternalStorageDirectory()+"/M.O.L.S_Backup/MOLS_DB.s3db"; 

     // Open the empty db as the output stream 
     OutputStream output = new FileOutputStream(outFileName); 

     // Transfer bytes from the inputfile to the outputfile 
     byte[] buffer = new byte[1024]; 
     int length; 
     while ((length = fis.read(buffer))>0) { 
      output.write(buffer, 0, length); 
     } 

     output.flush(); 
     output.close(); 
     fis.close(); 
    } 
} 
-2

Nếu khối thành công cho tôi một lỗi trên:

String inFileName = context.getDatabasePath(DB-Name); 
File dbFile = new File(inFileName); 
FileInputStream fis = new FileInputStream(dbFile); 
+3

Câu đầu tiên đó có ý nghĩa gì ???? –

+0

Đường dẫn cơ sở dữ liệu trung bình của nó – user1154390

0

Bạn tìm Tên cơ sở dữ liệu của bạn trong Adaptor Cơ sở dữ liệu nếu bạn là người mới vào này.

Lưu ý rằng bạn cũng có thể làm điều này cho SharedPreferences nhưng hãy nhớ thay đổi Context.MODE_PRIVATE thành Context.MODE_MULTI_PROCESS.

SharedPreferences_name sẽ trông như thế này = ExportSP("temp.xml");

String currentPathForSharedPreferences = "/data/"+ context.getPackageName() +"/shared_prefs/"+ SharedPreferences_name; 

Đối với xuất khẩu

exportDB("MyDbName"); 

private void exportDB(String db_name){ 

File sd = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + 
       File.separator + "Your Backup Folder"+ 
       File.separator); 

      boolean success = true; 
      if (!sd.exists()) { 
       success = sd.mkdir(); 
      } 
      if (success) { 

     File data = Environment.getDataDirectory(); 
     FileChannel source=null; 
     FileChannel destination=null; 
     String currentDBPath = "/data/"+ context.getPackageName() +"/databases/"+db_name; 
     String backupDBPath = db_name; 
     File currentDB = new File(data, currentDBPath); 
     File backupDB = new File(sd, backupDBPath); 
     try { 
      source = new FileInputStream(currentDB).getChannel(); 
      destination = new FileOutputStream(backupDB).getChannel(); 
      destination.transferFrom(source, 0, source.size()); 
      source.close(); 
      destination.close(); 
      Toast.makeText(this, "Please wait", Toast.LENGTH_SHORT).show(); 
     } catch(IOException e) { 
      e.printStackTrace(); 
     } 
      }} 

Đối với nhập khẩu

importDB("MyDbName"); 

private void importDB(String db_name){ 
     File sd = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + 
       File.separator + "Your Backup Folder"+ 
       File.separator); 
     File data = Environment.getDataDirectory(); 
     FileChannel source=null; 
     FileChannel destination=null; 
     String backupDBPath = "/data/"+ context.getPackageName() +"/databases/"+db_name; 
     String currentDBPath = db_name; 
     File currentDB = new File(sd, currentDBPath); 
     File backupDB = new File(data, backupDBPath); 
     try { 
      source = new FileInputStream(currentDB).getChannel(); 
      destination = new FileOutputStream(backupDB).getChannel(); 
      destination.transferFrom(source, 0, source.size()); 
      source.close(); 
      destination.close(); 
      Toast.makeText(this, "Please wait", Toast.LENGTH_SHORT).show(); 
     } catch(IOException e) { 
      e.printStackTrace(); 
     } 
} 
-1
@Override 
protected void onCreate(Bundle savedInstanceState) { 
    try { 
     File sd = Environment.getExternalStorageDirectory(); 
     File data = Environment.getDataDirectory(); 

     if (sd.canWrite()) { 
      String currentDBPath = "//data//"+getPackageName()+"//databases//"+DATABASE_NAME+""; 
      String backupDBPath = "backup.db"; 
      File currentDB = new File(data, currentDBPath); 
      File backupDB = new File(sd, backupDBPath); 

      FileChannel src = new FileInputStream(currentDB).getChannel(); 
      FileChannel dst = new FileOutputStream(backupDB).getChannel(); 
      dst.transferFrom(src, 0, src.size()); 
      src.close(); 
      dst.close(); 
      Toast.makeText(getBaseContext(), backupDB.toString(), Toast.LENGTH_LONG).show(); 
     } 
    } catch (Exception e) { 
     Toast.makeText(getBaseContext(), e.toString(), Toast.LENGTH_LONG).show(); 
    } 
} 
0

@ đang skeniver của việc cho tôi.Tôi chỉ muốn thêm như sau:

Sử dụng:

String currentDbPath = getApplicationContext().getDatabasePath("{database name}"); 

Nó sẽ cho bạn con đường cơ sở dữ liệu của bạn. Tốt hơn là sử dụng thay vì mã hóa cứng Chuỗi, như:

String currentDbPath = "//data//{package name}//databases//{database name}"; 
Các vấn đề liên quan