首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Android 應用開發:將 SQLite 資料庫與 APK 一同打包的完整指南

     編輯:Java 相關知識

在 Android 開發中,預先準備好資料庫(如字典、離線地圖、預設設定)並隨 APK 發布,是常見需求。本文詳細說明如何將 SQLite 資料庫檔案放入 assets 目錄,並在首次啟動時自動複製到應用專屬資料目錄,附帶完整程式碼與進階方案(支援 SD 卡備份)。

方案一:標準流程 — assets → /data/data/包名/databases/

1. 專案結構準備

  • 在 src/main/assets/ 下建立資料庫檔案,例如 test.db。
  • 確認資料庫結構(資料表、索引)已建立完成。

2. 核心複製邏輯

public class DbTestActivity extends Activity {
    private static final String DB_NAME = "test.db";
    private static final String DB_PATH = "/data/data/com.test.db/databases/"; // 依包名調整

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        copyDatabaseIfNeeded();
        testDatabase();
    }

    private void copyDatabaseIfNeeded() {
        File dbFile = new File(DB_PATH + DB_NAME);
        if (!dbFile.exists()) {
            // 確保目錄存在
            new File(DB_PATH).mkdirs();
            try (InputStream is = getAssets().open(DB_NAME);
                 OutputStream os = new FileOutputStream(dbFile)) {
                byte[] buffer = new byte[1024];
                int length;
                while ((length = is.read(buffer)) > 0) {
                    os.write(buffer, 0, length);
                }
                os.flush();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    private void testDatabase() {
        SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(DB_PATH + DB_NAME, null);
        Cursor cursor = db.rawQuery("SELECT * FROM test", null);
        if (cursor.moveToFirst()) {
            byte[] blob = cursor.getBlob(0);
            String text = new String(blob, StandardCharsets.UTF_8).trim();
            Log.d("DB_TEST", "資料讀取成功: " + text);
        }
        cursor.close();
        db.close();
    }
}

關鍵點說明

  • 路徑固定:/data/data/包名/databases/ 為 Android 預設資料庫目錄,應用解除安裝時自動清理。
  • 只複製一次:啟動時檢查檔案是否存在,避免重複覆蓋使用者資料。
  • 編碼處理:讀取 BLOB/TEXT 時指定 StandardCharsets.UTF_8 防止亂碼。

方案二:進階 — 支援外部儲存 (SD 卡) 備份與還原

適用於資料庫較大、或需讓使用者手動備份/匯出的場景。

public class ReleaseDatabaseHelper {
    private final Context context;
    private final String dbName;
    private final File dbDir; // 例如 Environment.getExternalStorageDirectory() + "/myapp/db/"

    public ReleaseDatabaseHelper(Context context, String dbName, File dbDir) {
        this.context = context;
        this.dbName = dbName;
        this.dbDir = dbDir;
    }

    public SQLiteDatabase openOrCopyDatabase() {
        if (!dbDir.exists()) dbDir.mkdirs();
        File target = new File(dbDir, dbName);

        if (!target.exists()) {
            copyFromAssetsOrRaw(target);
        }
        return SQLiteDatabase.openOrCreateDatabase(target, null);
    }

    private void copyFromAssetsOrRaw(File target) {
        try (InputStream is = context.getAssets().open(dbName); // 或 getResources().openRawResource(R.raw.db_name)
             FileOutputStream fos = new FileOutputStream(target)) {
            byte[] buffer = new byte[8192];
            int count;
            while ((count = is.read(buffer)) > 0) {
                fos.write(buffer, 0, count);
            }
        } catch (IOException e) {
            Log.e("DB_HELPER", "複製資料庫失敗", e);
        }
    }
}

常見問題與避坑指南

問題原因解決方案
資料庫複製後讀取報 "no such table"assets 中的 .db 檔案其實是空的或結構錯誤用 DB Browser for SQLite 開啟確認結構與資料
檔案過大 (>1MB) 導致 assets 打包失敗舊版 Android Gradle Plugin 對單一 asset 檔有限制升級 AGP、或改用 split APK / raw 資源 / 網路下載
中文亂碼資料庫建立時編碼非 UTF-8,或讀取時未指定字集建表時指定 CHARSET=utf8;讀取時用 new String(bytes, "UTF-8")
Android 10+ Scoped Storage 導致無法寫入外部儲存權限模型變更優先用內部儲存;外部儲存需請求 MANAGE_EXTERNAL_STORAGE 或用 MediaStore

最佳實踐總結

  1. 小型唯讀資料庫:走 assets → 內部儲存,最簡單、相容性最好。
  2. 大型/可寫入資料庫:首次啟動下載至內部儲存,或使用 Room + Pre-packaged Database (Room 2.2+ 支援 createFromAsset)。
  3. 版本升級:實作 SQLiteOpenHelper.onUpgrade() 或 Room Migration,避免覆蓋使用者資料。
  4. 測試:在模擬器與真機 (Android 7~14) 完整跑一次「安裝→開啟→關閉→重開→升級 App→再開」流程。

掌握這套流程,即可輕鬆實現「預置資料庫隨 APK 發布、首次自動部署、升級平滑遷移」的完整生命週期管理。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved