Wysyłanie aplikacji z bazą danych

Jeśli Twoja aplikacja wymaga bazy danych i zawiera wbudowane dane, jaki jest najlepszy sposób wysłania tej aplikacji? Powinienem:

  1. Wstępnie utworzyć bazę danych SQLite i dołączyć ją do .apk?

  2. Dołącz polecenia SQL z aplikacją i czy utworzyć bazę danych i wstawić dane przy pierwszym użyciu?

Wady jakie widzę to:

  1. Możliwe niedopasowania wersji SQLite mogą powodować problemy i obecnie nie wiedzieć, gdzie powinna znajdować się baza danych i jak do niej uzyskać dostęp.

  2. Tworzenie i wypełnianie bazy danych na urządzeniu może zająć naprawdę dużo czasu.

Jakieś sugestie? Wskazówki do dokumentacji dotyczące wszelkich problemów będą bardzo mile widziane.
Author: Razor, 2009-02-04

16 answers

Właśnie znalazłem sposób na to w blogu ReignDesign w artykule zatytułowanym Korzystanie z własnej bazy danych SQLite w aplikacjach na Androida . Zasadniczo można wstępnie utworzyć bazę danych, umieścić go w katalogu zasobów w apk, a na pierwszym użyciu skopiować do katalogu" /data/data/YOUR_PACKAGE/databases/".

 442
Author: Heikki Toivonen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-03-06 19:23:44

Istnieją dwie opcje tworzenia i aktualizacji baz danych.

Jednym z nich jest utworzenie bazy danych na zewnątrz, a następnie umieszczenie jej w folderze zasobów projektu, a następnie skopiowanie stamtąd całej bazy danych. Jest to znacznie szybsze, jeśli baza danych zawiera wiele tabel i innych komponentów. aktualizacje są wyzwalane przez zmianę numeru wersji bazy danych w res / values / strings.plik xml. uaktualnienia będą następnie realizowane poprzez utworzenie nowej bazy danych zewnętrznie, zastąpienie starej bazy danych w folderze assets nową bazą danych, zapisanie starej bazy danych w pamięci wewnętrznej pod inną nazwą, skopiowanie nowej bazy danych z folderu assets do pamięci wewnętrznej, przeniesienie wszystkich danych ze starej bazy danych (która została wcześniej zmieniona) do nowej bazy danych i ostatecznie usunięcie starej bazy danych. Możesz utworzyć bazę danych oryginalnie za pomocą SQLite Manager FireFox plugin aby wykonać tworzenie SQL Oświadczenia.

Inną opcją jest utworzenie wewnętrznej bazy danych z pliku sql. Nie jest to tak szybkie, ale opóźnienie prawdopodobnie byłoby niezauważalne dla użytkowników, jeśli baza danych ma tylko kilka tabel. aktualizacje są wyzwalane przez zmianę numeru wersji bazy danych w res / values / strings.plik xml. uaktualnienia będą następnie realizowane przez przetwarzanie pliku SQL aktualizacji. Dane w bazie danych pozostaną niezmienione, chyba że zostanie usunięty kontener, dla przykład upuszczania tabeli.

Poniższy przykład pokazuje, jak korzystać z jednej z metod.

Oto przykładowa baza create_database.plik sql. Należy go umieścić w folderze assets projektu dla wewnętrznej metody lub skopiować do "Execute SQL" SQLite Manager, aby utworzyć bazę danych dla zewnętrznej metody. (Uwaga: zwróć uwagę na komentarz dotyczący tabeli wymaganej przez system 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"; 

Oto przykładowa baza update_database.plik sql. To ma być umieszczony w folderze zasobów projektu dla wewnętrznej metody lub skopiowany do "Execute SQL" SQLite Manager, aby utworzyć bazę danych dla zewnętrznej metody. (Uwaga: zauważ, że wszystkie trzy typy komentarzy SQL będą ignorowane przez parser sql, który jest zawarty w tym przykładzie.)

--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');

Tutaj jest wpis do/res/values / strings.plik xml dla numeru wersji bazy danych.

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

Oto działanie, które uzyskuje dostęp do bazy danych, a następnie używa go. (Uwaga: możesz chcieć uruchomić kod bazy danych w osobnym wątku, jeśli wykorzystuje on dużo zasobów.)

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

    }
}

Tutaj znajduje się Klasa pomocnicza bazy danych, w której baza danych jest tworzona lub aktualizowana w razie potrzeby. (Uwaga: Android wymaga utworzenia klasy rozszerzającej SQLiteOpenHelper do pracy z bazą danych 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.
     */

}

Oto Klasa FileHelper, która zawiera metody do kopiowania plików i parsowania sql pliki.

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
Author: Danny Remington - OMS,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-02-02 02:45:27

Biblioteka SQLiteAssetHelper sprawia, że to zadanie jest naprawdę proste.

Jest łatwy do dodania jako zależność gradle (ale Jar jest również dostępny dla Ant / Eclipse), a wraz z dokumentacją można go znaleźć na:
https://github.com/jgilfelt/android-sqlite-asset-helper

Jak wyjaśniono w dokumentacji:

  1. Dodaj zależność do pliku gradle build twojego modułu:

    dependencies {
        compile 'com.readystatesoftware.sqliteasset:sqliteassethelper:+'
    }
    
  2. Skopiuj bazę danych do katalogu zasobów, w podkatalog o nazwie assets/databases. Na przykład:
    assets/databases/my_database.db

    (opcjonalnie możesz skompresować bazę danych w pliku zip, takim jak assets/databases/my_database.zip. Nie jest to potrzebne, ponieważ APK jest już skompresowany jako całość.)

  3. Utwórz klasę, na przykład:

    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
Author: DavidEG,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-22 10:47:08

Myślę, że najlepszym i najnowszym sposobem do dziś jest użycie klasy SQLiteAssetHelper.

Ten samouczek poprowadzi cię doskonale przez importowanie i używanie zewnętrznej bazy danych w Androidzie

Biblioteka Android SQLiteAssetHelper pozwala na zbudowanie SQLite bazy danych w komputerze stacjonarnym, a do importowania i używania jej w Aplikacja na Androida. Stwórzmy prostą aplikację do zademonstrowania zastosowanie tej biblioteki.

Krok 1: Tworzenie cudzysłowów bazy danych.db używając swojego ulubionego SQLite aplikacji bazodanowej (DB Browser dla SQLite to przenośny krzyż Platforma freeware, która może być używana do tworzenia i edycji SQLite bazy danych). Utwórz tabelę "cudzysłów" z pojedynczą kolumną "cudzysłów". Wstaw losowe cudzysłowy do tabeli 'cudzysłowy'.

Krok 2 : Baza Danych może być importowana do projektu bezpośrednio jako jest, lub jako skompresowany plik. Skompresowany plik jest zalecany, jeśli Twój baza danych jest zbyt duża. Możesz utworzyć ZIP kompresja lub GZ kompresja.

Nazwa pliku skompresowanego pliku db musi być quotes.db.zip, jeśli używasz kompresji ZIP lub quotes.db.gz, Jeśli używasz GZ kompresja.

Krok 3 : Utwórz nową aplikację External Database Demo z Nazwa pakietu com.javahelps.com.javahelps.externaldatabasedemo.

Krok 4: Otwórz plik build.gradle (Module: app) i dodaj następujący zależność.

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

Gdy masz zapisany plik build.gradle kliknij na 'Synchronizuj teraz' link do aktualizacji projektu. Możesz zsynchronizować build.gradle, przez kliknij prawym przyciskiem myszy plik build.gradle i wybierz opcję Synchronize build.gradle.

Krok 5: kliknij prawym przyciskiem myszy folder aplikacji i utwórz nowy folder zasobów.

Krok 6: Utwórz nowy folder "bazy danych" wewnątrz folderu zasoby.

Krok 7: skopiuj i wklej plik quotes.db.zip wewnątrz assets/databases folder.

Krok 8 : Utwórz nową klasę 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.

Krok 9: Utwórz nową klasę DatabaseAccess i wprowadź kod, jak pokazano poniżej. Więcej szczegółów na temat tej klasy można znaleźć na stronie Advanced Android Samouczek bazy danych.

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,

Aktualizuj i usuwaj wiersze w bazie danych jak zwykle. Więcej szczegółów, pod tym linkiem zaawansowana baza danych Androida.

Wszystkie konfiguracje związane z bazą danych zostały zakończone i teraz musimy Utwórz ListView, aby wyświetlić cytaty.

Krok 10: Dodaj ListView w swoim 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>  

Krok 11: Znajdź obiekt ListView w metodzie onCreate MainActivity i podaj cytaty, które są odczytywane utworzyć bazę danych.

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

Krok 12 : Zapisz wszystkie zmiany i uruchom aplikację.

Oprócz tego artykułu można pobrać SQLiteAssetHelper tutaj

 24
Author: Alex Jolig,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-21 08:01:07

Moje rozwiązanie nie używa żadnej biblioteki innej firmy ani nie zmusza do wywoływania niestandardowych metod na podklasie SQLiteOpenHelper, Aby zainicjować bazę danych podczas tworzenia. Zajmuje się również aktualizacjami baz danych. Wszystko, co należy zrobić, to podklasa SQLiteOpenHelper.

Warunek wstępny:

  1. baza danych, którą chcesz wysłać za pomocą aplikacji. powinna zawierać tabelę 1x1 o nazwie android_metadata z atrybutem locale o wartości en_US oprócz tabel unikalnych dla Twojego app.

Podklasa SQLiteOpenHelper:

  1. podklasa SQLiteOpenHelper.
  2. Utwórz metodę private w podklasie SQLiteOpenHelper. Metoda ta zawiera logikę kopiowania zawartości bazy danych z pliku bazy danych w folderze 'assets' do bazy danych utworzonej w kontekście pakietu aplikacji.
  3. Override onCreate, onUpgrade oraz onOpen metody SQLiteOpenHelper.
Wystarczy. Oto podklasa SQLiteOpenHelper:
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:
        }
    }
}

Wreszcie, aby uzyskać bazę danych connection, wystarczy wywołać getReadableDatabase() lub getWritableDatabase() na podklasie SQLiteOpenHelper i zajmie się utworzeniem db, kopiowaniem zawartości db z podanego pliku w folderze' assets', jeśli baza danych nie istnieje.

W skrócie, możesz użyć podklasy SQLiteOpenHelper, Aby uzyskać dostęp do bazy danych dostarczonej w folderze assets, tak jak w przypadku bazy danych inicjowanej za pomocą zapytań SQL w metodzie onCreate().

 12
Author: Vaishak Nair,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-26 14:56:20

[[8]}wysyłanie aplikacji z plikiem bazy danych, w Android Studio 3.0

Wysyłanie aplikacji z plikiem bazy danych jest dla mnie dobrym pomysłem. Zaletą jest to, że nie musisz wykonywać skomplikowanej inicjalizacji, co czasami kosztuje dużo czasu, jeśli zestaw danych jest ogromny.

Krok 1: Przygotuj plik bazy danych

Przygotuj plik bazy danych. Może to być albo a .plik db lub a .plik sqlite. Jeśli używasz a .plik sqlite, wszystko, co musisz zrobić, to zmienić nazwy rozszerzeń plików. Kroki są takie same.

W tym przykładzie przygotowałem plik o nazwie testDB.db. Ma jedną tabelę i kilka przykładowych danych w niej w ten sposób Tutaj wpisz opis obrazka

Krok 2: zaimportuj plik do projektu

Utwórz folder zasobów, jeśli go nie masz. Następnie skopiuj i wklej plik bazy danych do tego folderu

Tutaj wpisz opis obrazka

Krok 3: Skopiuj plik do folderu danych aplikacji

Musisz skopiować bazę danych plik do folderu danych aplikacji w celu dalszej interakcji z nim. Jest to jednorazowa akcja (inicjalizacja) do skopiowania pliku bazy danych. Jeśli wywołasz ten kod wiele razy, plik bazy danych w folderze data zostanie nadpisany przez plik w folderze assets. Ten proces nadpisywania jest przydatny, gdy chcesz zaktualizować bazę danych w przyszłości podczas aktualizacji aplikacji.

Należy pamiętać, że podczas aktualizacji aplikacji plik bazy danych nie zostanie zmieniony w folderze danych aplikacji. Tylko Odinstaluj będzie usuń to.

Plik bazy danych musi zostać skopiowany do folderu /databases. Otwórz Eksplorator Plików Urządzenia. Wpisz data/data/<YourAppName>/ położenie. Jest to domyślny folder danych aplikacji wymieniony powyżej. Domyślnie plik bazy danych zostanie umieszczony w innym folderze o nazwie bazy danych w tym katalogu

Tutaj wpisz opis obrazka

Teraz proces kopiowania plików jest podobny do tego, co robi Java. Użyj poniższego kodu, aby wykonać kopiuj wklej. To jest kod inicjacyjny. Może być również używany do zaktualizuj (przez nadpisanie) plik bazy danych w przyszłości.

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

Następnie odśwież folder, Aby zweryfikować proces kopiowania

Tutaj wpisz opis obrazka

Krok 4: Utwórz bazę danych open helper

Utwórz podklasę dla SQLiteOpenHelper, z connect, close, path, itd. Nazwałem go 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) {
    }
}

Krok 5: Utwórz klasę najwyższego poziomu do interakcji z bazą danych

Będzie to klasa, która odczytuje i zapisuje plik bazy danych. Istnieje również próbka zapytanie, aby wydrukować wartość w bazie danych.

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

Krok 6: bieg testowy

Przetestuj kod, uruchamiając następujące linie kodów.

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

Naciśnij przycisk run i Kibicuj!

Tutaj wpisz opis obrazka

 9
Author: Fangming,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-07 20:23:00

W listopadzie 2017 roku Google udostępniło bibliotekę Room Persistence Library

Z dokumentacji:

Biblioteka trwałości pokoju zapewnia warstwę abstrakcji nad SQLite aby umożliwić płynny dostęp do bazy danych przy jednoczesnym wykorzystaniu pełnej mocy SQLite.

Biblioteka pomaga utworzyć pamięć podręczną danych aplikacji na urządzeniu to działa na Twoją aplikację. Ta pamięć podręczna, która służy jako pojedyncza aplikacja źródło prawdy, pozwala użytkownikom na przeglądanie spójnej kopii of key informacje w aplikacji, niezależnie od tego, czy użytkownicy mają połączenie z Internetem.

Baza Danych pokoju ma wywołanie zwrotne, gdy baza danych jest utworzona lub otwarta po raz pierwszy. Możesz użyć create callback, aby wypełnić bazę danych.

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

Kod z tego posta na blogu .

 8
Author: LordRaydenMK,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-28 17:21:34

Z tego co widziałem powinieneś wysyłać bazę danych, która ma już ustawienia tabel i danych. Jeśli jednak chcesz (i w zależności od typu aplikacji, którą posiadasz), możesz zezwolić na "opcję Uaktualnij bazę danych". Następnie należy pobrać najnowszą wersję SQLite, pobrać najnowszą Wstaw/Utwórz instrukcje pliku tekstowego hostowanego online, wykonać instrukcje i wykonać transfer danych ze starego db do nowego.

 5
Author: masfenix,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-02-04 20:14:43

W końcu to zrobiłem!! Użyłem tego linku pomoc przy użyciu własnej bazy danych SQLite w aplikacjach na Androida, ale musiałem go trochę zmienić.

  1. Jeśli masz wiele pakietów, powinieneś umieścić tutaj nazwę pakietu głównego:

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

  2. Zmieniłem metodę kopiowania bazy danych z folderu lokalnego do folderu emulatora! Miał jakiś problem, gdy ten folder nie istniał. Więc przede wszystkim powinien sprawdzić ścieżkę, a jeśli jej nie ma, powinien utwórz folder.

  3. W poprzednim kodzie metoda copyDatabase nigdy nie została wywołana, gdy baza danych nie istniała, a Metoda checkDataBase spowodowała wyjątek. więc zmieniłem trochę kod.

  4. Jeśli twoja baza danych nie ma rozszerzenia pliku, nie używaj nazwy pliku z nim.

It works nice for me, I hope it whould be usefull for u too

    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
Author: afsane,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-04-03 15:16:20

Obecnie nie ma możliwości precreate bazy danych SQLite do wysyłki z apk. Najlepsze, co możesz zrobić, to zapisać odpowiedni SQL jako zasób i uruchomić je z aplikacji. Tak, prowadzi to do powielania danych (ta sama informacja istnieje jako resrouce i jako baza danych), ale nie ma obecnie innego sposobu. Jedynym czynnikiem łagodzącym jest skompresowany plik apk. Moje doświadczenie to 908kb kompresuje do mniej niż 268kb.

Poniższy wątek ma najlepszą dyskusję/rozwiązanie I znalazłem z dobrym kodem przykładowym.

Http://groups.google.com/group/android-developers/msg/9f455ae93a1cf152

Zapisałem moją instrukcję CREATE jako zasób łańcuchowy do odczytu z kontekstem.getString () i uruchomił go za pomocą SQLiteDatabse.execSQL ().

Dane dla moich wstawek zapisałem w res / raw / inserts.sql (stworzyłem plik sql, 7000 + linii). Korzystając z techniki z linku powyżej wprowadziłem pętlę, odczytałem plik linia po linii i połączyłem dane na " INSERT Do wartości tbl " i zrobił kolejny SQLiteDatabase.execSQL (). Nie ma sensu zapisywać 7000 "wstaw do wartości tbl", gdy można je po prostu połączyć.

Trwa to około dwudziestu sekund na emulatorze, Nie wiem, jak długo zajęłoby to na prawdziwym telefonie, ale zdarza się to tylko raz, gdy użytkownik po raz pierwszy uruchamia aplikację.

 4
Author: Will,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-02-04 23:32:28

Wysłanie bazy danych wewnątrz apk, a następnie skopiowanie jej do /data/data/... podwoi rozmiar bazy danych (1 w apk, 1 w data/data/...) i zwiększy rozmiar apk (oczywiście). Więc twoja baza danych nie powinna być zbyt duża.

 4
Author: Hiep,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-06-30 15:43:03

Android już zapewnia podejście oparte na wersji zarządzania bazami danych. To podejście zostało wykorzystane w BARACUS framework dla aplikacji Android.

Umożliwia zarządzanie bazą danych w całym cyklu życia wersji aplikacji, będąc w stanie zaktualizować bazę danych sqlite z dowolnej wcześniejszej wersji do bieżącej.

Ponadto pozwala na uruchamianie kopii zapasowych na gorąco i odzyskiwanie na gorąco SQLite.

Nie jestem w 100% pewien, ale gorący powrót do zdrowia dla konkretnego urządzenia może umożliwić wysyłanie przygotowanej bazy danych w aplikacji. Ale nie jestem pewien co do formatu binarnego bazy danych, który może być specyficzny dla niektórych urządzeń, dostawców lub generacji urządzeń.

Ponieważ jest to Licencja Apache 2, możesz ponownie użyć dowolnej części kodu, , którą można znaleźć na github

EDIT:

Jeśli chcesz tylko wysyłać dane, możesz rozważyć utworzenie i utrzymywanie Pojo przy pierwszym uruchomieniu aplikacji. BARACUS ma wbudowane wsparcie dla tego (Wbudowany magazyn wartości klucza dla informacji konfiguracyjnych, np. "APP_FIRST_RUN" plus hook after-context-bootstrap w celu uruchomienia operacji po uruchomieniu na tym kontekście). Umożliwia to przesyłanie ściśle powiązanych danych z aplikacją; w większości przypadków jest to dopasowane do moich przypadków użycia.

 3
Author: gorefest,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-11-24 12:05:39

Jeśli wymagane dane nie są zbyt duże (limity Nie wiem, zależy od wielu rzeczy), można również pobrać dane (w XML, JSON, cokolwiek) ze strony internetowej/webapp. Po otrzymaniu polecenia SQL wykonaj na podstawie odebranych danych tworząc tabele i wstawiając dane.

Jeśli aplikacja mobilna zawiera dużo danych, później może być łatwiej zaktualizować dane w zainstalowanych aplikacjach z dokładniejszymi danymi lub zmianami.

 3
Author: Jaco,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-27 17:19:25

Napisałem bibliotekę Aby uprościć ten proces.

dataBase = new DataBase.Builder(context, "myDb").
//        setAssetsPath(). // default "databases"
//        setDatabaseErrorHandler().
//        setCursorFactory().
//        setUpgradeCallback()
//        setVersion(). // default 1
build();

Utworzy bazę danych z pliku assets/databases/myDb.db. Dodatkowo otrzymasz wszystkie te funkcjonalności:

  • załaduj bazę danych z pliku
  • zsynchronizowany dostęp do bazy danych
  • używanie SQLite-android przez requery, specyficzną dla Androida dystrybucję najnowszych wersji SQLite.

Sklonuj go z github .

 2
Author: Ilya Gazman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-07-10 05:41:59

Używam ORMLite i poniższy kod zadziałał dla mnie

public class DatabaseProvider extends OrmLiteSqliteOpenHelper {
    private static final String DatabaseName = "DatabaseName";
    private static final int DatabaseVersion = 1;
    private final Context ProvidedContext;

    public DatabaseProvider(Context context) {
        super(context, DatabaseName, null, DatabaseVersion);
        this.ProvidedContext= context;
        SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
        boolean databaseCopied = preferences.getBoolean("DatabaseCopied", false);
        if (databaseCopied) {
            //Do Nothing
        } else {
            CopyDatabase();
            SharedPreferences.Editor editor = preferences.edit();
            editor.putBoolean("DatabaseCopied", true);
            editor.commit();
        }
    }

    private String DatabasePath() {
        return "/data/data/" + ProvidedContext.getPackageName() + "/databases/";
    }

    private void CopyDatabase() {
        try {
            CopyDatabaseInternal();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private File ExtractAssetsZip(String zipFileName) {
        InputStream inputStream;
        ZipInputStream zipInputStream;
        File tempFolder;
        do {
            tempFolder = null;
            tempFolder = new File(ProvidedContext.getCacheDir() + "/extracted-" + System.currentTimeMillis() + "/");
        } while (tempFolder.exists());

        tempFolder.mkdirs();

        try {
            String filename;
            inputStream = ProvidedContext.getAssets().open(zipFileName);
            zipInputStream = new ZipInputStream(new BufferedInputStream(inputStream));
            ZipEntry zipEntry;
            byte[] buffer = new byte[1024];
            int count;

            while ((zipEntry = zipInputStream.getNextEntry()) != null) {
                filename = zipEntry.getName();
                if (zipEntry.isDirectory()) {
                    File fmd = new File(tempFolder.getAbsolutePath() + "/" + filename);
                    fmd.mkdirs();
                    continue;
                }

                FileOutputStream fileOutputStream = new FileOutputStream(tempFolder.getAbsolutePath() + "/" + filename);
                while ((count = zipInputStream.read(buffer)) != -1) {
                    fileOutputStream.write(buffer, 0, count);
                }

                fileOutputStream.close();
                zipInputStream.closeEntry();
            }

            zipInputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }

        return tempFolder;
    }

    private void CopyDatabaseInternal() throws IOException {

        File extractedPath = ExtractAssetsZip(DatabaseName + ".zip");
        String databaseFile = "";
        for (File innerFile : extractedPath.listFiles()) {
            databaseFile = innerFile.getAbsolutePath();
            break;
        }
        if (databaseFile == null || databaseFile.length() ==0 )
            throw new RuntimeException("databaseFile is empty");

        InputStream inputStream = new FileInputStream(databaseFile);

        String outFileName = DatabasePath() + DatabaseName;

        File destinationPath = new File(DatabasePath());
        if (!destinationPath.exists())
            destinationPath.mkdirs();

        File destinationFile = new File(outFileName);
        if (!destinationFile.exists())
            destinationFile.createNewFile();

        OutputStream myOutput = new FileOutputStream(outFileName);

        byte[] buffer = new byte[1024];
        int length;
        while ((length = inputStream.read(buffer)) > 0) {
            myOutput.write(buffer, 0, length);
        }

        myOutput.flush();
        myOutput.close();
        inputStream.close();
    }

    @Override
    public void onCreate(SQLiteDatabase sqLiteDatabase, ConnectionSource connectionSource) {
    }

    @Override
    public void onUpgrade(SQLiteDatabase sqLiteDatabase, ConnectionSource connectionSource, int fromVersion, int toVersion) {

    }
}

Proszę zauważyć, że kod wyodrębnia plik bazy danych z pliku zip w zasobach

 2
Author: Homayoun Behzadian,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-12 06:27:28

Zmodyfikowałem klasę i odpowiedzi na pytanie i napisałem klasę, która umożliwia aktualizację bazy danych poprzez DB_VERSION.

public class DatabaseHelper extends SQLiteOpenHelper {
    private static String DB_NAME = "info.db";
    private static String DB_PATH = "";
    private static final int DB_VERSION = 1;

    private SQLiteDatabase mDataBase;
    private final Context mContext;
    private boolean mNeedUpdate = false;

    public DatabaseHelper(Context context) {
        super(context, DB_NAME, null, DB_VERSION);
        if (android.os.Build.VERSION.SDK_INT >= 17)
            DB_PATH = context.getApplicationInfo().dataDir + "/databases/";
        else
            DB_PATH = "/data/data/" + context.getPackageName() + "/databases/";
        this.mContext = context;

        copyDataBase();

        this.getReadableDatabase();
    }

    public void updateDataBase() throws IOException {
        if (mNeedUpdate) {
            File dbFile = new File(DB_PATH + DB_NAME);
            if (dbFile.exists())
                dbFile.delete();

            copyDataBase();

            mNeedUpdate = false;
        }
    }

    private boolean checkDataBase() {
        File dbFile = new File(DB_PATH + DB_NAME);
        return dbFile.exists();
    }

    private void copyDataBase() {
        if (!checkDataBase()) {
            this.getReadableDatabase();
            this.close();
            try {
                copyDBFile();
            } catch (IOException mIOException) {
                throw new Error("ErrorCopyingDataBase");
            }
        }
    }

    private void copyDBFile() throws IOException {
        InputStream mInput = mContext.getAssets().open(DB_NAME);
        //InputStream mInput = mContext.getResources().openRawResource(R.raw.info);
        OutputStream mOutput = new FileOutputStream(DB_PATH + DB_NAME);
        byte[] mBuffer = new byte[1024];
        int mLength;
        while ((mLength = mInput.read(mBuffer)) > 0)
            mOutput.write(mBuffer, 0, mLength);
        mOutput.flush();
        mOutput.close();
        mInput.close();
    }

    public boolean openDataBase() throws SQLException {
        mDataBase = SQLiteDatabase.openDatabase(DB_PATH + DB_NAME, null, SQLiteDatabase.CREATE_IF_NECESSARY);
        return mDataBase != null;
    }

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

    @Override
    public void onCreate(SQLiteDatabase db) {

    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        if (newVersion > oldVersion)
            mNeedUpdate = true;
    }
}

Używanie klasy.

W klasie activity deklaruj zmienne.

private DatabaseHelper mDBHelper;
private SQLiteDatabase mDb;

W metodzie onCreate wpisz następujący kod.

mDBHelper = new DatabaseHelper(this);

try {
    mDBHelper.updateDataBase();
} catch (IOException mIOException) {
    throw new Error("UnableToUpdateDatabase");
}

try {
    mDb = mDBHelper.getWritableDatabase();
} catch (SQLException mSQLException) {
    throw mSQLException;
}

Jeśli dodasz plik bazy danych do folderu res / raw, użyj następującej modyfikacji klasy.

public class DatabaseHelper extends SQLiteOpenHelper {
    private static String DB_NAME = "info.db";
    private static String DB_PATH = "";
    private static final int DB_VERSION = 1;

    private SQLiteDatabase mDataBase;
    private final Context mContext;
    private boolean mNeedUpdate = false;

    public DatabaseHelper(Context context) {
        super(context, DB_NAME, null, DB_VERSION);
        if (android.os.Build.VERSION.SDK_INT >= 17)
            DB_PATH = context.getApplicationInfo().dataDir + "/databases/";
        else
            DB_PATH = "/data/data/" + context.getPackageName() + "/databases/";
        this.mContext = context;

        copyDataBase();

        this.getReadableDatabase();
    }

    public void updateDataBase() throws IOException {
        if (mNeedUpdate) {
            File dbFile = new File(DB_PATH + DB_NAME);
            if (dbFile.exists())
                dbFile.delete();

            copyDataBase();

            mNeedUpdate = false;
        }
    }

    private boolean checkDataBase() {
        File dbFile = new File(DB_PATH + DB_NAME);
        return dbFile.exists();
    }

    private void copyDataBase() {
        if (!checkDataBase()) {
            this.getReadableDatabase();
            this.close();
            try {
                copyDBFile();
            } catch (IOException mIOException) {
                throw new Error("ErrorCopyingDataBase");
            }
        }
    }

    private void copyDBFile() throws IOException {
        //InputStream mInput = mContext.getAssets().open(DB_NAME);
        InputStream mInput = mContext.getResources().openRawResource(R.raw.info);
        OutputStream mOutput = new FileOutputStream(DB_PATH + DB_NAME);
        byte[] mBuffer = new byte[1024];
        int mLength;
        while ((mLength = mInput.read(mBuffer)) > 0)
            mOutput.write(mBuffer, 0, mLength);
        mOutput.flush();
        mOutput.close();
        mInput.close();
    }

    public boolean openDataBase() throws SQLException {
        mDataBase = SQLiteDatabase.openDatabase(DB_PATH + DB_NAME, null, SQLiteDatabase.CREATE_IF_NECESSARY);
        return mDataBase != null;
    }

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

    @Override
    public void onCreate(SQLiteDatabase db) {

    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        if (newVersion > oldVersion)
            mNeedUpdate = true;
    }
}

Http://blog.harrix.org/article/6784

 2
Author: Harrix,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-07 15:06:57