Pertanyaan Kirimkan aplikasi dengan basis data


Jika aplikasi Anda membutuhkan database dan dilengkapi dengan data bawaan, apa cara terbaik untuk mengirim aplikasi itu? Haruskah saya:

  1. Precreate database SQLite dan sertakan dalam .apk?

  2. Sertakan perintah SQL dengan aplikasi dan membuatnya membuat database dan memasukkan data pada penggunaan pertama?

Kekurangan yang saya lihat adalah:

  1. Kemungkinan ketidakcocokan versi SQLite mungkin menyebabkan masalah dan saat ini saya tidak tahu kemana database harus pergi dan bagaimana cara mengaksesnya.

  2. Mungkin butuh waktu sangat lama untuk membuat dan mengisi database pada perangkat.

Ada saran? Penunjuk ke dokumentasi tentang masalah apa pun akan sangat dihargai.


882
2018-02-04 20:11


asal


Jawaban:


Saya baru saja menemukan cara untuk melakukan ini di blog ReignDesign dalam sebuah artikel berjudul Menggunakan database SQLite Anda sendiri di aplikasi Android. Pada dasarnya Anda membebani database Anda, memasukkannya ke dalam direktori aset Anda di apk Anda, dan pada penggunaan pertama salin ke direktori "/ data / data / YOUR_PACKAGE / databases /".


441
2018-03-06 19:23



Ada dua opsi untuk membuat dan memperbarui basis data. 

Salah satunya adalah membuat database secara eksternal, lalu menempatkannya di folder aset proyek dan kemudian menyalin seluruh database dari sana. Ini lebih cepat jika database memiliki banyak tabel dan komponen lainnya. Peningkatan dipicu dengan mengubah nomor versi basis data di file res / values ​​/ strings.xml. Peningkatan kemudian akan dicapai dengan membuat database baru secara eksternal, menggantikan database lama dalam folder aset dengan database baru, menyimpan database lama di penyimpanan internal dengan nama lain, menyalin database baru dari folder aset ke penyimpanan internal, mentransfer semua dari data dari database lama (yang diganti namanya sebelumnya) menjadi database baru dan akhirnya menghapus database lama. Anda dapat membuat database awalnya dengan menggunakan Plugin SQLite Manager FireFox untuk mengeksekusi pernyataan sql kreasi Anda.

Pilihan lainnya adalah membuat database secara internal dari file sql. Ini tidak secepat tetapi penundaan mungkin tidak akan terlihat oleh pengguna jika database hanya memiliki beberapa tabel. Peningkatan dipicu dengan mengubah nomor versi basis data di file res / values ​​/ strings.xml.  Peningkatan kemudian akan dicapai dengan memproses file upgrade sql. Data dalam database akan tetap tidak berubah kecuali ketika wadahnya dihapus, misalnya menjatuhkan tabel.

Contoh di bawah ini menunjukkan cara menggunakan salah satu metode.

Berikut ini contoh file create_database.sql. Ini harus ditempatkan dalam folder aset proyek untuk metode internal atau disalin ke dalam "Execute SQL" dari SQLite Manager untuk membuat database untuk metode eksternal. (CATATAN: Perhatikan komentar tentang tabel yang dibutuhkan oleh Android.)

--Android requires a table named 'android_metadata' with a 'locale' column
CREATE TABLE "android_metadata" ("locale" TEXT DEFAULT 'en_US');
INSERT INTO "android_metadata" VALUES ('en_US');

CREATE TABLE "kitchen_table";
CREATE TABLE "coffee_table";
CREATE TABLE "pool_table";
CREATE TABLE "dining_room_table";
CREATE TABLE "card_table"; 

Berikut ini contoh file update_database.sql. Ini harus ditempatkan dalam folder aset proyek untuk metode internal atau disalin ke dalam "Execute SQL" dari SQLite Manager untuk membuat database untuk metode eksternal. (CATATAN: Perhatikan bahwa ketiga jenis komentar SQL akan diabaikan oleh parser sql yang disertakan dalam contoh ini.)

--CREATE TABLE "kitchen_table";  This is one type of comment in sql.  It is ignored by parseSql.
/*
 * CREATE TABLE "coffee_table"; This is a second type of comment in sql.  It is ignored by parseSql.
 */
{
CREATE TABLE "pool_table";  This is a third type of comment in sql.  It is ignored by parseSql.
}
/* CREATE TABLE "dining_room_table"; This is a second type of comment in sql.  It is ignored by parseSql. */
{ CREATE TABLE "card_table"; This is a third type of comment in sql.  It is ignored by parseSql. }

--DROP TABLE "picnic_table"; Uncomment this if picnic table was previously created and now is being replaced.
CREATE TABLE "picnic_table" ("plates" TEXT);
INSERT INTO "picnic_table" VALUES ('paper');

Ini adalah entri untuk ditambahkan ke file /res/values/strings.xml untuk nomor versi database.

<item type="string" name="databaseVersion" format="integer">1</item>

Berikut ini adalah aktivitas yang mengakses database dan kemudian menggunakannya. (Catatan: Anda mungkin ingin menjalankan kode basis data dalam untaian terpisah jika menggunakan banyak sumber daya.)

package android.example;

import android.app.Activity;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;

/**
 * @author Danny Remington - MacroSolve
 * 
 *         Activity for demonstrating how to use a sqlite database.
 */
public class Database extends Activity {
     /** Called when the activity is first created. */
     @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        DatabaseHelper myDbHelper;
        SQLiteDatabase myDb = null;

        myDbHelper = new DatabaseHelper(this);
        /*
         * Database must be initialized before it can be used. This will ensure
         * that the database exists and is the current version.
         */
         myDbHelper.initializeDataBase();

         try {
            // A reference to the database can be obtained after initialization.
            myDb = myDbHelper.getWritableDatabase();
            /*
             * Place code to use database here.
             */
         } catch (Exception ex) {
            ex.printStackTrace();
         } finally {
            try {
                myDbHelper.close();
            } catch (Exception ex) {
                ex.printStackTrace();
            } finally {
                myDb.close();
            }
        }

    }
}

Di sini adalah kelas pembantu basis data di mana database dibuat atau diperbarui jika diperlukan. (CATATAN: Android mengharuskan Anda membuat kelas yang memperluas SQLiteOpenHelper agar dapat bekerja dengan database Sqlite.)

package android.example;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

/**
 * @author Danny Remington - MacroSolve
 * 
 *         Helper class for sqlite database.
 */
public class DatabaseHelper extends SQLiteOpenHelper {

    /*
     * The Android's default system path of the application database in internal
     * storage. The package of the application is part of the path of the
     * directory.
     */
    private static String DB_DIR = "/data/data/android.example/databases/";
    private static String DB_NAME = "database.sqlite";
    private static String DB_PATH = DB_DIR + DB_NAME;
    private static String OLD_DB_PATH = DB_DIR + "old_" + DB_NAME;

    private final Context myContext;

    private boolean createDatabase = false;
    private boolean upgradeDatabase = false;

    /**
     * Constructor Takes and keeps a reference of the passed context in order to
     * access to the application assets and resources.
     * 
     * @param context
     */
    public DatabaseHelper(Context context) {
        super(context, DB_NAME, null, context.getResources().getInteger(
                R.string.databaseVersion));
        myContext = context;
        // Get the path of the database that is based on the context.
        DB_PATH = myContext.getDatabasePath(DB_NAME).getAbsolutePath();
    }

    /**
     * Upgrade the database in internal storage if it exists but is not current. 
     * Create a new empty database in internal storage if it does not exist.
     */
    public void initializeDataBase() {
        /*
         * Creates or updates the database in internal storage if it is needed
         * before opening the database. In all cases opening the database copies
         * the database in internal storage to the cache.
         */
        getWritableDatabase();

        if (createDatabase) {
            /*
             * If the database is created by the copy method, then the creation
             * code needs to go here. This method consists of copying the new
             * database from assets into internal storage and then caching it.
             */
            try {
                /*
                 * Write over the empty data that was created in internal
                 * storage with the one in assets and then cache it.
                 */
                copyDataBase();
            } catch (IOException e) {
                throw new Error("Error copying database");
            }
        } else if (upgradeDatabase) {
            /*
             * If the database is upgraded by the copy and reload method, then
             * the upgrade code needs to go here. This method consists of
             * renaming the old database in internal storage, create an empty
             * new database in internal storage, copying the database from
             * assets to the new database in internal storage, caching the new
             * database from internal storage, loading the data from the old
             * database into the new database in the cache and then deleting the
             * old database from internal storage.
             */
            try {
                FileHelper.copyFile(DB_PATH, OLD_DB_PATH);
                copyDataBase();
                SQLiteDatabase old_db = SQLiteDatabase.openDatabase(OLD_DB_PATH, null, SQLiteDatabase.OPEN_READWRITE);
                SQLiteDatabase new_db = SQLiteDatabase.openDatabase(DB_PATH,null, SQLiteDatabase.OPEN_READWRITE);
                /*
                 * Add code to load data into the new database from the old
                 * database and then delete the old database from internal
                 * storage after all data has been transferred.
                 */
            } catch (IOException e) {
                throw new Error("Error copying database");
            }
        }

    }

    /**
     * Copies your database from your local assets-folder to the just created
     * empty database in the system folder, from where it can be accessed and
     * handled. This is done by transfering bytestream.
     * */
    private void copyDataBase() throws IOException {
        /*
         * Close SQLiteOpenHelper so it will commit the created empty database
         * to internal storage.
         */
        close();

        /*
         * Open the database in the assets folder as the input stream.
         */
        InputStream myInput = myContext.getAssets().open(DB_NAME);

        /*
         * Open the empty db in interal storage as the output stream.
         */
        OutputStream myOutput = new FileOutputStream(DB_PATH);

        /*
         * Copy over the empty db in internal storage with the database in the
         * assets folder.
         */
        FileHelper.copyFile(myInput, myOutput);

        /*
         * Access the copied database so SQLiteHelper will cache it and mark it
         * as created.
         */
        getWritableDatabase().close();
    }

    /*
     * This is where the creation of tables and the initial population of the
     * tables should happen, if a database is being created from scratch instead
     * of being copied from the application package assets. Copying a database
     * from the application package assets to internal storage inside this
     * method will result in a corrupted database.
     * <P>
     * NOTE: This method is normally only called when a database has not already
     * been created. When the database has been copied, then this method is
     * called the first time a reference to the database is retrieved after the
     * database is copied since the database last cached by SQLiteOpenHelper is
     * different than the database in internal storage.
     */
    @Override
    public void onCreate(SQLiteDatabase db) {
        /*
         * Signal that a new database needs to be copied. The copy process must
         * be performed after the database in the cache has been closed causing
         * it to be committed to internal storage. Otherwise the database in
         * internal storage will not have the same creation timestamp as the one
         * in the cache causing the database in internal storage to be marked as
         * corrupted.
         */
        createDatabase = true;

        /*
         * This will create by reading a sql file and executing the commands in
         * it.
         */
            // try {
            // InputStream is = myContext.getResources().getAssets().open(
            // "create_database.sql");
            //
            // String[] statements = FileHelper.parseSqlFile(is);
            //
            // for (String statement : statements) {
            // db.execSQL(statement);
            // }
            // } catch (Exception ex) {
            // ex.printStackTrace();
            // }
    }

    /**
     * Called only if version number was changed and the database has already
     * been created. Copying a database from the application package assets to
     * the internal data system inside this method will result in a corrupted
     * database in the internal data system.
     */
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        /*
         * Signal that the database needs to be upgraded for the copy method of
         * creation. The copy process must be performed after the database has
         * been opened or the database will be corrupted.
         */
        upgradeDatabase = true;

        /*
         * Code to update the database via execution of sql statements goes
         * here.
         */

        /*
         * This will upgrade by reading a sql file and executing the commands in
         * it.
         */
        // try {
        // InputStream is = myContext.getResources().getAssets().open(
        // "upgrade_database.sql");
        //
        // String[] statements = FileHelper.parseSqlFile(is);
        //
        // for (String statement : statements) {
        // db.execSQL(statement);
        // }
        // } catch (Exception ex) {
        // ex.printStackTrace();
        // }
    }

    /**
     * Called everytime the database is opened by getReadableDatabase or
     * getWritableDatabase. This is called after onCreate or onUpgrade is
     * called.
     */
    @Override
    public void onOpen(SQLiteDatabase db) {
        super.onOpen(db);
    }

    /*
     * Add your public helper methods to access and get content from the
     * database. You could return cursors by doing
     * "return myDataBase.query(....)" so it'd be easy to you to create adapters
     * for your views.
     */

}

Inilah kelas FileHelper yang berisi metode untuk file streaming aliran byte dan parsing file sql.

package android.example;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.Reader;
import java.nio.channels.FileChannel;

/**
 * @author Danny Remington - MacroSolve
 * 
 *         Helper class for common tasks using files.
 * 
 */
public class FileHelper {
    /**
     * Creates the specified <i><b>toFile</b></i> that is a byte for byte a copy
     * of <i><b>fromFile</b></i>. If <i><b>toFile</b></i> already existed, then
     * it will be replaced with a copy of <i><b>fromFile</b></i>. The name and
     * path of <i><b>toFile</b></i> will be that of <i><b>toFile</b></i>. Both
     * <i><b>fromFile</b></i> and <i><b>toFile</b></i> will be closed by this
     * operation.
     * 
     * @param fromFile
     *            - InputStream for the file to copy from.
     * @param toFile
     *            - InputStream for the file to copy to.
     */
    public static void copyFile(InputStream fromFile, OutputStream toFile) throws IOException {
        // transfer bytes from the inputfile to the outputfile
        byte[] buffer = new byte[1024];
        int length;

        try {
            while ((length = fromFile.read(buffer)) > 0) {
                toFile.write(buffer, 0, length);
            }
        }
        // Close the streams
        finally {
            try {
                if (toFile != null) {
                    try {
                        toFile.flush();
                    } finally {
                        toFile.close();
                    }
            }
            } finally {
                if (fromFile != null) {
                    fromFile.close();
                }
            }
        }
    }

    /**
     * Creates the specified <i><b>toFile</b></i> that is a byte for byte a copy
     * of <i><b>fromFile</b></i>. If <i><b>toFile</b></i> already existed, then
     * it will be replaced with a copy of <i><b>fromFile</b></i>. The name and
     * path of <i><b>toFile</b></i> will be that of <i><b>toFile</b></i>. Both
     * <i><b>fromFile</b></i> and <i><b>toFile</b></i> will be closed by this
     * operation.
     * 
     * @param fromFile
     *            - String specifying the path of the file to copy from.
     * @param toFile
     *            - String specifying the path of the file to copy to.
     */
    public static void copyFile(String fromFile, String toFile) throws IOException {
        copyFile(new FileInputStream(fromFile), new FileOutputStream(toFile));
    }

    /**
     * Creates the specified <i><b>toFile</b></i> that is a byte for byte a copy
     * of <i><b>fromFile</b></i>. If <i><b>toFile</b></i> already existed, then
     * it will be replaced with a copy of <i><b>fromFile</b></i>. The name and
     * path of <i><b>toFile</b></i> will be that of <i><b>toFile</b></i>. Both
     * <i><b>fromFile</b></i> and <i><b>toFile</b></i> will be closed by this
     * operation.
     * 
     * @param fromFile
     *            - File for the file to copy from.
     * @param toFile
     *            - File for the file to copy to.
     */
    public static void copyFile(File fromFile, File toFile) throws IOException {
        copyFile(new FileInputStream(fromFile), new FileOutputStream(toFile));
    }

    /**
     * Creates the specified <i><b>toFile</b></i> that is a byte for byte a copy
     * of <i><b>fromFile</b></i>. If <i><b>toFile</b></i> already existed, then
     * it will be replaced with a copy of <i><b>fromFile</b></i>. The name and
     * path of <i><b>toFile</b></i> will be that of <i><b>toFile</b></i>. Both
     * <i><b>fromFile</b></i> and <i><b>toFile</b></i> will be closed by this
     * operation.
     * 
     * @param fromFile
     *            - FileInputStream for the file to copy from.
     * @param toFile
     *            - FileInputStream for the file to copy to.
     */
    public static void copyFile(FileInputStream fromFile, FileOutputStream toFile) throws IOException {
        FileChannel fromChannel = fromFile.getChannel();
        FileChannel toChannel = toFile.getChannel();

        try {
            fromChannel.transferTo(0, fromChannel.size(), toChannel);
        } finally {
            try {
                if (fromChannel != null) {
                    fromChannel.close();
                }
            } finally {
                if (toChannel != null) {
                    toChannel.close();
                }
            }
        }
    }

    /**
     * Parses a file containing sql statements into a String array that contains
     * only the sql statements. Comments and white spaces in the file are not
     * parsed into the String array. Note the file must not contained malformed
     * comments and all sql statements must end with a semi-colon ";" in order
     * for the file to be parsed correctly. The sql statements in the String
     * array will not end with a semi-colon ";".
     * 
     * @param sqlFile
     *            - String containing the path for the file that contains sql
     *            statements.
     * 
     * @return String array containing the sql statements.
     */
    public static String[] parseSqlFile(String sqlFile) throws IOException {
        return parseSqlFile(new BufferedReader(new FileReader(sqlFile)));
    }

    /**
     * Parses a file containing sql statements into a String array that contains
     * only the sql statements. Comments and white spaces in the file are not
     * parsed into the String array. Note the file must not contained malformed
     * comments and all sql statements must end with a semi-colon ";" in order
     * for the file to be parsed correctly. The sql statements in the String
     * array will not end with a semi-colon ";".
     * 
     * @param sqlFile
     *            - InputStream for the file that contains sql statements.
     * 
     * @return String array containing the sql statements.
     */
    public static String[] parseSqlFile(InputStream sqlFile) throws IOException {
        return parseSqlFile(new BufferedReader(new InputStreamReader(sqlFile)));
    }

    /**
     * Parses a file containing sql statements into a String array that contains
     * only the sql statements. Comments and white spaces in the file are not
     * parsed into the String array. Note the file must not contained malformed
     * comments and all sql statements must end with a semi-colon ";" in order
     * for the file to be parsed correctly. The sql statements in the String
     * array will not end with a semi-colon ";".
     * 
     * @param sqlFile
     *            - Reader for the file that contains sql statements.
     * 
     * @return String array containing the sql statements.
     */
    public static String[] parseSqlFile(Reader sqlFile) throws IOException {
        return parseSqlFile(new BufferedReader(sqlFile));
    }

    /**
     * Parses a file containing sql statements into a String array that contains
     * only the sql statements. Comments and white spaces in the file are not
     * parsed into the String array. Note the file must not contained malformed
     * comments and all sql statements must end with a semi-colon ";" in order
     * for the file to be parsed correctly. The sql statements in the String
     * array will not end with a semi-colon ";".
     * 
     * @param sqlFile
     *            - BufferedReader for the file that contains sql statements.
     * 
     * @return String array containing the sql statements.
     */
    public static String[] parseSqlFile(BufferedReader sqlFile) throws IOException {
        String line;
        StringBuilder sql = new StringBuilder();
        String multiLineComment = null;

        while ((line = sqlFile.readLine()) != null) {
            line = line.trim();

            // Check for start of multi-line comment
            if (multiLineComment == null) {
                // Check for first multi-line comment type
                if (line.startsWith("/*")) {
                    if (!line.endsWith("}")) {
                        multiLineComment = "/*";
                    }
                // Check for second multi-line comment type
                } else if (line.startsWith("{")) {
                    if (!line.endsWith("}")) {
                        multiLineComment = "{";
                }
                // Append line if line is not empty or a single line comment
                } else if (!line.startsWith("--") && !line.equals("")) {
                    sql.append(line);
                } // Check for matching end comment
            } else if (multiLineComment.equals("/*")) {
                if (line.endsWith("*/")) {
                    multiLineComment = null;
                }
            // Check for matching end comment
            } else if (multiLineComment.equals("{")) {
                if (line.endsWith("}")) {
                    multiLineComment = null;
                }
            }

        }

        sqlFile.close();

        return sql.toString().split(";");
    }

}

194
2018-01-26 21:22



Pustaka SQLiteAssetHelper membuat tugas ini sangat sederhana.

Sangat mudah untuk menambahkan sebagai dependensi gradle (tetapi Jar juga tersedia untuk Ant / Eclipse), dan bersama dengan dokumentasi itu dapat ditemukan di:
https://github.com/jgilfelt/android-sqlite-asset-helper

Sebagaimana dijelaskan dalam dokumentasi:

  1. Tambahkan dependensi ke file build gradle modul Anda:

    dependencies {
        compile 'com.readystatesoftware.sqliteasset:sqliteassethelper:+'
    }
    
  2. Salin database ke dalam direktori aset, dalam subdirektori yang disebut assets/databases. Contohnya:
    assets/databases/my_database.db

    (Opsional, Anda dapat memampatkan basis data dalam file zip seperti assets/databases/my_database.zip. Ini tidak diperlukan, karena APK dikompresi secara keseluruhan.)

  3. Buat kelas, misalnya:

    public class MyDatabase extends SQLiteAssetHelper {
    
        private static final String DATABASE_NAME = "my_database.db";
        private static final int DATABASE_VERSION = 1;
    
        public MyDatabase(Context context) {
            super(context, DATABASE_NAME, null, DATABASE_VERSION);
        }
    }
    

126
2017-08-03 21:08



Saya rasa yang terbaik dan cara terbaru sampai hari ini adalah menggunakan SQLiteAssetHelper kelas.

Tutorial ini membimbing Anda dengan sempurna Mengimpor dan Menggunakan Database Eksternal di Android

Android SQLiteAssetHelper perpustakaan memungkinkan Anda membangun SQLite   database di komputer desktop Anda, dan untuk mengimpor dan menggunakannya di Anda   Aplikasi Android. Mari buat aplikasi sederhana untuk mendemonstrasikan   aplikasi perpustakaan ini.

Langkah 1: Buat quotes.db database menggunakan SQLite favorit Anda   aplikasi database (DB Browser untuk SQLite adalah persilangan portabel   freeware platform, yang dapat digunakan untuk membuat dan mengedit SQLite   database). Buat 'kutipan' tabel dengan satu kolom 'kutipan'.   Masukkan beberapa tanda kutip acak ke dalam tabel 'tanda kutip'.

Langkah 2: Database dapat diimpor ke dalam proyek baik secara langsung sebagai   itu, atau sebagai file terkompresi. File yang dikompresi direkomendasikan, jika   database Anda terlalu besar ukurannya. Anda dapat membuat a ZIP   kompresi atau a GZ kompresi.

Nama file dari file db terkompresi harus quotes.db.zip, jika kamu   menggunakan kompresi ZIP atau quotes.db.gz, jika Anda menggunakan GZ   kompresi.

Langkah 3: Buat aplikasi baru External Database Demo dengan   nama paket com.javahelps.com.javahelps.externaldatabasedemo.

Langkah 4: Buka build.gradle (Modul: aplikasi) file dan tambahkan berikut ini   ketergantungan.

dependencies {
    compile 'com.readystatesoftware.sqliteasset:sqliteassethelper:+'
}

Setelah Anda menyimpan file build.gradle file klik pada 'Sync Now'   tautan untuk memperbarui proyek. Anda dapat menyinkronkan build.gradle, oleh   mengklik kanan pada build.gradlefile dan memilih Synchronize build.gradle pilihan juga.

Langkah 5: Klik kanan pada folder aplikasi dan buat folder aset baru.

Langkah 6: Buat 'database' folder baru di dalam folder aset.

Langkah 7: Salin dan tempel quotes.db.zip file di dalam    assets/databases map.

Langkah 8: Buat kelas baru DatabaseOpenHelper

package com.javahelps.externaldatabasedemo;

import android.content.Context;

import com.readystatesoftware.sqliteasset.SQLiteAssetHelper;

public class DatabaseOpenHelper extends SQLiteAssetHelper {
    private static final String DATABASE_NAME = "quotes.db";
    private static final int DATABASE_VERSION = 1;

    public DatabaseOpenHelper(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
    }
}  Notice that rather than extending SQLiteOpenHelper, the DatabaseOpenHelper extends  SQLiteAssetHelper class.

Langkah 9: Buat kelas baru DatabaseAccess dan masukkan kode seperti yang ditunjukkan   di bawah. Detail lebih lanjut tentang kelas ini tersedia di Android Lanjutan   Tutorial basis data.

package com.javahelps.externaldatabasedemo;

import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

import java.util.ArrayList;
import java.util.List;

public class DatabaseAccess {
    private SQLiteOpenHelper openHelper;
    private SQLiteDatabase database;
    private static DatabaseAccess instance;

    /**
     * Private constructor to aboid object creation from outside classes.
     *
     * @param context
     */
    private DatabaseAccess(Context context) {
        this.openHelper = new DatabaseOpenHelper(context);
    }

    /**
     * Return a singleton instance of DatabaseAccess.
     *
     * @param context the Context
     * @return the instance of DabaseAccess
     */
    public static DatabaseAccess getInstance(Context context) {
        if (instance == null) {
            instance = new DatabaseAccess(context);
        }
        return instance;
    }

    /**
     * Open the database connection.
     */
    public void open() {
        this.database = openHelper.getWritableDatabase();
    }

    /**
     * Close the database connection.
     */
    public void close() {
        if (database != null) {
            this.database.close();
        }
    }

    /**
     * Read all quotes from the database.
     *
     * @return a List of quotes
     */
    public List<String> getQuotes() {
        List<String> list = new ArrayList<>();
        Cursor cursor = database.rawQuery("SELECT * FROM quotes", null);
        cursor.moveToFirst();
        while (!cursor.isAfterLast()) {
            list.add(cursor.getString(0));
            cursor.moveToNext();
        }
        cursor.close();
        return list;
    }
}  In this class only the `getQuotes` method is implemented to read the data from the database. You have the full freedom to insert,

perbarui dan hapus setiap baris dalam database seperti biasa. Untuk lebih jelasnya,   ikuti tautan ini Advanced Android Database.

Semua pengaturan terkait database selesai dan sekarang kita perlu   membuat ListView untuk menampilkan tanda kutip.

Langkah 10: Tambah sebuah ListView di dalam kamu activity_main.xml.

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity">

    <ListView
        android:id="@+id/listView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_gravity="center" />
</FrameLayout>  

Langkah 11: Temukan objek ListView dalam onCreate metode dari MainActivity dan memberi makan tanda kutip yang dibaca   membentuk database.

package com.javahelps.externaldatabasedemo;

import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.widget.ArrayAdapter;
import android.widget.ListView;

import java.util.List;


public class MainActivity extends ActionBarActivity {
    private ListView listView;

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

        this.listView = (ListView) findViewById(R.id.listView);
        DatabaseAccess databaseAccess = DatabaseAccess.getInstance(this);
        databaseAccess.open();
        List<String> quotes = databaseAccess.getQuotes();
        databaseAccess.close();

        ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1,
quotes);
        this.listView.setAdapter(adapter);
    }
}

Langkah 12: Simpan semua perubahan dan jalankan aplikasi.

Selain artikel ini, Anda dapat mengunduh SQLiteAssetHelper  sini


23
2018-01-21 08:01



Solusi saya tidak menggunakan pustaka pihak ketiga atau memaksa Anda untuk memanggil metode khusus SQLiteOpenHelper subkelas untuk menginisialisasi basis data tentang pembuatan. Ini juga mengurus upgrade database juga. Yang perlu dilakukan adalah subkelas SQLiteOpenHelper.

Prasyarat:

  1. Database yang ingin Anda kirimkan dengan aplikasi. Itu harus mengandung sebuah meja bernama 1x1 android_metadata dengan atribut locale memiliki nilai en_US selain tabel unik untuk aplikasi Anda.

Subclassing SQLiteOpenHelper:

  1. Subkelas SQLiteOpenHelper.
  2. Membuat private metode dalam SQLiteOpenHelper subkelas. Metode ini berisi logika untuk menyalin isi basis data dari file database di folder 'aset' ke database yang dibuat dalam konteks paket aplikasi.
  3. Mengesampingkan onCreate, onUpgrade  dan  onOpen metode SQLiteOpenHelper.

Cukup berkata. Ini dia SQLiteOpenHelper subkelas:

public class PlanDetailsSQLiteOpenHelper extends SQLiteOpenHelper {
    private static final String TAG = "SQLiteOpenHelper";

    private final Context context;
    private static final int DATABASE_VERSION = 1;
    private static final String DATABASE_NAME = "my_custom_db";

    private boolean createDb = false, upgradeDb = false;

    public PlanDetailsSQLiteOpenHelper(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
        this.context = context;
    }

    /**
     * Copy packaged database from assets folder to the database created in the
     * application package context.
     * 
     * @param db
     *            The target database in the application package context.
     */
    private void copyDatabaseFromAssets(SQLiteDatabase db) {
        Log.i(TAG, "copyDatabase");
        InputStream myInput = null;
        OutputStream myOutput = null;
        try {
            // Open db packaged as asset as the input stream
            myInput = context.getAssets().open("path/to/shipped/db/file");

            // Open the db in the application package context:
            myOutput = new FileOutputStream(db.getPath());

            // Transfer db file contents:
            byte[] buffer = new byte[1024];
            int length;
            while ((length = myInput.read(buffer)) > 0) {
                myOutput.write(buffer, 0, length);
            }
            myOutput.flush();

            // Set the version of the copied database to the current
            // version:
            SQLiteDatabase copiedDb = context.openOrCreateDatabase(
                DATABASE_NAME, 0, null);
            copiedDb.execSQL("PRAGMA user_version = " + DATABASE_VERSION);
            copiedDb.close();

        } catch (IOException e) {
            e.printStackTrace();
            throw new Error(TAG + " Error copying database");
        } finally {
            // Close the streams
            try {
                if (myOutput != null) {
                    myOutput.close();
                }
                if (myInput != null) {
                    myInput.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
                throw new Error(TAG + " Error closing streams");
            }
        }
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        Log.i(TAG, "onCreate db");
        createDb = true;
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        Log.i(TAG, "onUpgrade db");
        upgradeDb = true;
    }

    @Override
    public void onOpen(SQLiteDatabase db) {
        Log.i(TAG, "onOpen db");
        if (createDb) {// The db in the application package
            // context is being created.
            // So copy the contents from the db
            // file packaged in the assets
            // folder:
            createDb = false;
            copyDatabaseFromAssets(db);

        }
        if (upgradeDb) {// The db in the application package
            // context is being upgraded from a lower to a higher version.
            upgradeDb = false;
            // Your db upgrade logic here:
        }
    }
}

Akhirnya, untuk mendapatkan koneksi database, panggil saja getReadableDatabase() atau getWritableDatabase() pada SQLiteOpenHelper subclass dan akan mengurus pembuatan db, menyalin isi db dari file yang ditentukan dalam folder 'assets', jika database tidak ada.

Singkatnya, Anda dapat menggunakan SQLiteOpenHelper subclass untuk mengakses db yang dikirim dalam folder aset seperti yang akan Anda gunakan untuk database yang diinisialisasi menggunakan query SQL di onCreate() metode.


12
2018-03-26 14:56



Mengirim aplikasi dengan file database, di Android Studio 3.0

Mengirim aplikasi dengan file database adalah ide yang bagus untuk saya. Keuntungannya adalah Anda tidak perlu melakukan inisialisasi yang rumit, yang terkadang menghabiskan banyak waktu, jika kumpulan data Anda sangat besar.

Langkah 1: Persiapkan file database

Sudah siapkan file database Anda. Ini bisa berupa file .db atau file .sqlite. Jika Anda menggunakan file .sqlite, semua yang perlu Anda lakukan adalah mengubah nama ekstensi file. Langkahnya sama.

Dalam contoh ini, saya menyiapkan file bernama testDB.db. Ini memiliki satu tabel dan beberapa contoh data di dalamnya seperti ini enter image description here

Langkah 2: Impor file ke dalam proyek Anda

Buat folder aset jika Anda belum memilikinya. Kemudian salin dan tempel file database ke folder ini

enter image description here

Langkah 3: Salin file ke folder data aplikasi

Anda perlu menyalin file database ke folder data aplikasi untuk melakukan interaksi lebih lanjut dengan itu. Ini adalah tindakan satu kali (inisialisasi) untuk menyalin file database. Jika Anda memanggil kode ini beberapa kali, file database di folder data akan ditimpa oleh yang ada di folder aset. Proses penimpaan ini berguna saat Anda ingin memperbarui basis data di masa mendatang selama pembaruan aplikasi.

Perhatikan bahwa selama pembaruan aplikasi, file database ini tidak akan diubah dalam folder data aplikasi. Hanya uninstall yang akan menghapusnya.

File database perlu disalin ke /databases map. Buka File Explorer Perangkat. Memasukkan data/data/<YourAppName>/ lokasi. Ini adalah folder data default aplikasi yang disebutkan di atas. Dan secara default, file database akan ditempatkan di folder lain yang disebut database di bawah direktori ini

enter image description here

Sekarang, proses menyalin file hampir sama seperti apa yang dilakukan Java. Gunakan kode berikut untuk melakukan copy paste. Ini adalah kode inisiasi. Ini juga dapat digunakan untuk memperbarui (dengan menimpa) file database di masa depan.

//get context by calling "this" in activity or getActivity() in fragment
//call this if API level is lower than 17  String appDataPath = "/data/data/" + context.getPackageName() + "/databases/"
String appDataPath = context.getApplicationInfo().dataDir;

File dbFolder = new File(appDataPath + "/databases");//Make sure the /databases folder exists
dbFolder.mkdir();//This can be called multiple times.

File dbFilePath = new File(appDataPath + "/databases/testDB.db");

try {
    InputStream inputStream = context.getAssets().open("testDB.db");
    OutputStream outputStream = new FileOutputStream(dbFilePath);
    byte[] buffer = new byte[1024];
    int length;
    while ((length = inputStream.read(buffer))>0)
    {
        outputStream.write(buffer, 0, length);
    }
    outputStream.flush();
    outputStream.close();
    inputStream.close();
} catch (IOException e){
    //handle
}

Kemudian segarkan folder untuk memverifikasi proses penyalinan

enter image description here

Langkah 4: Buat pembantu basis data terbuka

Buat subclass untuk SQLiteOpenHelper, dengan menghubungkan, menutup, jalan, dll. Aku menamakannya DatabaseOpenHelper

import android.content.Context;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

public class DatabaseOpenHelper extends SQLiteOpenHelper {
    public static final String DB_NAME = "testDB.db";
    public static final String DB_SUB_PATH = "/databases/" + DB_NAME;
    private static String APP_DATA_PATH = "";
    private SQLiteDatabase dataBase;
    private final Context context;

    public DatabaseOpenHelper(Context context){
        super(context, DB_NAME, null, 1);
        APP_DATA_PATH = context.getApplicationInfo().dataDir;
        this.context = context;
    }

    public boolean openDataBase() throws SQLException{
        String mPath = APP_DATA_PATH + DB_SUB_PATH;
        //Note that this method assumes that the db file is already copied in place
        dataBase = SQLiteDatabase.openDatabase(mPath, null, SQLiteDatabase.OPEN_READWRITE);
        return dataBase != null;
    }

    @Override
    public synchronized void close(){
        if(dataBase != null) {dataBase.close();}
        super.close();
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    }
}

Langkah 5: Buat kelas tingkat atas untuk berinteraksi dengan database

Ini akan menjadi kelas yang membaca & menulis file database Anda. Juga ada contoh permintaan untuk mencetak nilai dalam database.

import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log;

public class Database {
    private final Context context;
    private SQLiteDatabase database;
    private DatabaseOpenHelper dbHelper;

    public Database(Context context){
        this.context = context;
        dbHelper = new DatabaseOpenHelper(context);
    }

    public Database open() throws SQLException
    {
        dbHelper.openDataBase();
        dbHelper.close();
        database = dbHelper.getReadableDatabase();
        return this;
    }

    public void close()
    {
        dbHelper.close();
    }

    public void test(){
        try{
            String query ="SELECT value FROM test1";
            Cursor cursor = database.rawQuery(query, null);
            if (cursor.moveToFirst()){
                do{
                    String value = cursor.getString(0);
                    Log.d("db", value);
                }while (cursor.moveToNext());
            }
            cursor.close();
        } catch (SQLException e) {
            //handle
        }
    }
}

Langkah 6: Uji coba

Uji kode dengan menjalankan baris kode berikut.

Database db = new Database(context);
db.open();
db.test();
db.close();

Tekan tombol lari dan bersorak!

enter image description here


8
2017-11-07 20:23



Pada bulan November 2017 Google merilis Perpustakaan Ruang Persistensi

Dari dokumentasi:

Perpustakaan persistensi ruang menyediakan lapisan abstraksi atas SQLite   untuk memungkinkan akses database lancar sambil memanfaatkan kekuatan penuh   SQLite.

Perpustakaan membantu Anda membuat cache data aplikasi Anda di perangkat   yang menjalankan aplikasi Anda. Cache ini, yang berfungsi sebagai single aplikasi Anda   sumber kebenaran, memungkinkan pengguna untuk melihat salinan kunci yang konsisten   informasi dalam aplikasi Anda, terlepas dari apakah pengguna memiliki   koneksi internet.

Database Kamar memiliki callback ketika database pertama kali dibuat atau dibuka. Anda dapat menggunakan callback buat untuk mengisi database Anda.

Room.databaseBuilder(context.applicationContext,
        DataDatabase::class.java, "Sample.db")
        // prepopulate the database after onCreate was called
        .addCallback(object : Callback() {
            override fun onCreate(db: SupportSQLiteDatabase) {
                super.onCreate(db)
                // moving to a new thread
                ioThread {
                    getInstance(context).dataDao()
                                        .insert(PREPOPULATE_DATA)
                }
            }
        })
        .build()

Kode dari ini posting blog.


7
2017-11-28 17:21



Dari apa yang saya lihat, Anda harus mengirimkan database yang sudah memiliki pengaturan dan data tabel. Namun jika Anda ingin (dan tergantung pada jenis aplikasi yang Anda miliki) Anda dapat memperbolehkan "upgrade opsi database". Kemudian apa yang Anda lakukan adalah mengunduh versi sqlite terbaru, dapatkan pernyataan Insert / Create terbaru dari textfile yang di-host secara online, jalankan pernyataan dan lakukan transfer data dari db lama ke yang baru.


5
2018-02-04 20:14



Akhirnya saya melakukannya !! Saya telah menggunakan tautan ini bantuan Menggunakan basis data SQLite Anda sendiri di aplikasi Android, tetapi harus mengubahnya sedikit.

  1. Jika Anda memiliki banyak paket, Anda harus memasukkan nama paket master di sini:

    private static String DB_PATH = "data/data/masterPakageName/databases";

  2. Saya mengubah metode yang menyalin database dari folder lokal ke folder emulator! Ada masalah ketika folder itu tidak ada. Jadi pertama-tama, harus memeriksa jalur dan jika tidak ada, itu harus membuat folder.

  3. Pada kode sebelumnya, copyDatabase metode tidak pernah dipanggil ketika database tidak ada dan checkDataBase metode menyebabkan pengecualian. jadi saya mengubah kode sedikit.

  4. Jika database Anda tidak memiliki ekstensi file, jangan gunakan nama file dengan satu.

itu bekerja baik untuk saya, saya berharap itu bisa berguna untuk Anda juga

    package farhangsarasIntroduction;


import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;

import android.content.Context;
import android.database.Cursor;

import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
import android.database.sqlite.SQLiteOpenHelper;

import android.util.Log;


    public class DataBaseHelper extends SQLiteOpenHelper{

    //The Android's default system path of your application database.
    private static String DB_PATH = "data/data/com.example.sample/databases";

    private static String DB_NAME = "farhangsaraDb";

    private SQLiteDatabase myDataBase;

    private final Context myContext;

    /**
      * Constructor
      * Takes and keeps a reference of the passed context in order to access to the application assets and resources.
      * @param context
      */
    public DataBaseHelper(Context context) {

        super(context, DB_NAME, null, 1);
            this.myContext = context;

    }   

    /**
      * Creates a empty database on the system and rewrites it with your own database.
      * */
    public void createDataBase() {

        boolean dbExist;
        try {

             dbExist = checkDataBase();


        } catch (SQLiteException e) {

            e.printStackTrace();
            throw new Error("database dose not exist");

        }

        if(dbExist){
        //do nothing - database already exist
        }else{

            try {

                copyDataBase();


            } catch (IOException e) {

                e.printStackTrace();
                throw new Error("Error copying database");

            }
    //By calling this method and empty database will be created into the default system path
    //of your application so we are gonna be able to overwrite that database with our database.
        this.getReadableDatabase();


    }

    }

    /**
      * 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{
        String myPath = DB_PATH +"/"+ DB_NAME;

        checkDB = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY);
    }catch(SQLiteException e){

    //database does't exist yet.
        throw new Error("database does't exist yet.");

    }

    if(checkDB != null){

    checkDB.close();

    }

    return checkDB != null ? true : false;
    }

    /**
      * Copies your database from your local assets-folder to the just created empty database in the
      * system folder, from where it can be accessed and handled.
      * This is done by transfering bytestream.
      * */
    private void copyDataBase() throws IOException{



            //copyDataBase();
            //Open your local db as the input stream
            InputStream myInput = myContext.getAssets().open(DB_NAME);

            // Path to the just created empty db
            String outFileName = DB_PATH +"/"+ DB_NAME;
            File databaseFile = new File( DB_PATH);
             // check if databases folder exists, if not create one and its subfolders
            if (!databaseFile.exists()){
                databaseFile.mkdir();
            }

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

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

            //Close the streams
            myOutput.flush();
            myOutput.close();
            myInput.close();



    }



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

    }

     you to create adapters for your views.

}

5
2018-02-14 09:03