Корабль приложения с базой данных

голоса
870

Если приложение требует базы данных и поставляется с встроенной данных, что является лучшим способом, чтобы отправить это приложение? Нужно ли мне:

  1. Базу данных предварительно создать SQLite и включить его в .apk?

  2. Включите команды SQL с приложением и его создать базу данных и вставки данных при первом использовании?

К недостаткам я вижу, являются:

  1. Возможные SQLite версии несовпадения может вызвать проблемы, и я в настоящее время не знаю, где база данных должна идти и как получить к нему доступ.

  2. Это может занять очень много времени для создания и заполнения базы данных на устройстве.

Какие-либо предложения? Указатели на документацию по любым вопросам, было бы весьма признателен.

Задан 04/02/2009 в 21:11
источник пользователем
На других языках...                            


16 ответов

голоса
440

Я только что нашел способ сделать это в ReignDesign блоге в статье под названием Использование собственной базы данных SQLite в Android приложений . В основном вы предварительно создать свою базу данных, поместите его в каталоге активов в вашем APK, и при первом использовании копии на «/ данные / данные / YOUR_PACKAGE / базы данных /» каталог.

Ответил 06/03/2009 d 20:23
источник пользователем

голоса
193

Есть два варианта для создания и обновления баз данных.

Одним из них является создание базы данных извне, а затем поместить его в папку активов проекта , а затем скопировать всю базу данных оттуда. Это гораздо быстрее , если база данных содержит много таблиц и других компонентов. Обновления инициируются изменения номера версии базы данных в Резе / значениях / файл strings.xml. Обновление затем будет достигнуто за счет создания новой базы данных извне, заменяя старую базу данных в папке активов с новой базой данных, сохраняя старую базу данных во внутренней памяти под другим именем, скопировав новую базу данных активов папку на внутренней памяти, передавая все данные из старой базы данных (который был переименован ранее) в новую базу данных и , наконец , удалить старую базу данных. Вы можете создать базу данных первоначально используяSQLite Manager FireFox плагин для выполнения ваших операторов создания.

Другой вариант заключается в создании базы данных внутри из файла SQL. Это не так быстро , но задержка, вероятно , будет незаметна для пользователей , если база данных имеют только несколько таблиц. Обновления инициируются изменения номера версии базы данных в Резе / значениях / файл strings.xml. Обновление затем будет достигнуто путем обработки обновления SQL файла. Данные в базе данных остаются неизменными , за исключением , когда его контейнер удаляется, например , капельной таблицу.

В приведенном ниже примере показано, как использовать любой метод.

Вот пример create_database.sql файл. Он должен быть размещен в папке активов проекта для внутреннего метода или скопирована в «Execute SQL» из SQLite Manager , чтобы создать базу данных для внешнего метода. (ПРИМЕЧАНИЕ. Обратите внимание , что комментарий о таблице , требуемой Android)

--Android requires a table named 'android_metadata' with a 'locale' column
CREATE TABLE "android_metadata" ("locale" TEXT DEFAULT 'en_US');
INSERT IGNORE  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"; 

Вот пример update_database.sql файл. Он должен быть размещен в папке активов проекта для внутреннего метода или скопирована в «Execute SQL» в SQLite Manager , чтобы создать базу данных для внешнего метода. (Примечание: Обратите внимание , что будут игнорироваться все три типа SQL комментарии по SQL синтаксический анализатор , который включен в данном примере.)

--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 IGNORE  INTO "picnic_table" VALUES ('paper');

Вот запись, чтобы добавить в файл /res/values/strings.xml для номера версии базы данных.

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

Вот это деятельность , которая обращается к базе данных , а затем использует его. ( Примечание: Вы можете запустить код базы данных в отдельном потоке , если он использует много ресурсов. )

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

    }
}

Вот вспомогательный класс базы данных , где база данных создается или обновляется , если это необходимо. (Примечание: Android требует , чтобы вы создали класс , который расширяет SQLiteOpenHelper для работы с базой данных 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.
     */

}

Вот класс FileHelper, который содержит методы для байтов копирования файлов и синтаксического анализа 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(";");
    }

}
Ответил 26/01/2011 d 22:22
источник пользователем

голоса
124

Библиотека SQLiteAssetHelper делает эту задачу очень просто.

Легко добавить как Gradle зависимость (но Jar также доступна для Ant / Eclipse), и вместе с документацией можно найти по адресу:
https://github.com/jgilfelt/android-sqlite-asset-helper

Как объяснено в документации:

  1. Добавьте зависимость к Gradle файла сборки вашего модуля:

    dependencies {
        compile 'com.readystatesoftware.sqliteasset:sqliteassethelper:+'
    }
    
  2. Скопируйте базу данных в каталог активов, в подкаталоге assets/databases. Например:
    assets/databases/my_database.db

    ( При желании, можно сжать базу данных в виде архива , таких как assets/databases/my_database.zip. Это не требуется, так как APK сжимается в целом уже.)

  3. Создайте класс, например:

    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);
        }
    }
    
Ответил 03/08/2012 d 22:08
источник пользователем

голоса
23

Я думаю , самый лучший и самый новый путь до сегодняшнего дня используется SQLiteAssetHelperкласс.

Этот учебник поможет вам отлично через импорт и использование внешних баз данных в Android

Android SQLiteAssetHelperбиблиотека позволяет строить свою SQLite базу данных на настольном компьютере, а также импортировать и использовать его в Android приложения. Давайте создадим простое приложение , чтобы продемонстрировать применение этой библиотеки.

Шаг 1 : Создание quotes.db базы данных с помощью вашего любимых приложений баз данных SQLite (DB Browser для SQLite является портативной кроссплатформенной бесплатным программным обеспечением , которое может быть использовано для создания и редактирования баз данных SQLite). Создайте таблицу «кавычки» с одной колонкой «цитатой». Вставьте некоторые случайные кавычки в таблицу «цитирует».

Шаг 2 : База данных может быть импортирована в проект либо непосредственно , как это, или в виде сжатого файла. Сжатый файл рекомендуется, если ваша база данных слишком велики по размеру. Вы можете создать либо ZIP сжатие или GZсжатие.

Имя файла сжатого файла БД должно быть quotes.db.zip, если вы используете сжатие ZIP или quotes.db.gz, если вы используете сжатие GZ.

Шаг 3 : Создание нового приложения External Database Demoс именем пакета com.javahelps.com.javahelps.externaldatabasedemo.

Шаг 4 : Откройте build.gradle: файл (модуль приложения) и добавьте следующую зависимость.

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

После того, как вы сохранили build.gradleфайл , нажмите на ссылку «Синхронизировать» , чтобы обновить проект. Вы можете синхронизировать build.gradle, щелкнув правой кнопкой мыши на build.gradleфайле и выберите Synchronize build.gradleопцию , а также.

Шаг 5 : Нажмите правой кнопкой мыши на папке приложения и создать новую папку активов.

Шаг 6 : Создание новой папки «базы данных» внутри папки активов.

Шаг 7 : Скопируйте и вставьте quotes.db.zipфайл внутри assets/databasesпапки.

Шаг 8 : Создайте новый класс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.

Шаг 9 : Создайте новый класс DatabaseAccessи введите код , как показано ниже. Более подробно об этом классе можно найти на базы данных учебника Advanced Android.

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,

обновлять и удалять строки в базе данных, как обычно. Для получения более подробной информации по этой ссылке Advanced Android базы данных.

Все регулировки базы данных , связанные завершены , и теперь нам нужны создать , ListViewчтобы отобразить котировки.

Шаг 10 : Добавьте ListViewв вашей 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>  

Шаг 11 : Найдите объект ListViewв onCreateметоде MainActivityи покормить цитаты , которые считываются из базы данных.

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

Шаг 12 : Сохраните все изменения и запустить приложение.

В дополнение к этой статье вы можете скачать SQLiteAssetHelper здесь

Ответил 21/01/2016 d 08:01
источник пользователем

голоса
11

Мое решение ни использует любую стороннюю библиотеку , ни силы вы назвать пользовательские методы на SQLiteOpenHelperподкласс , чтобы инициализировать базу данных при создании. Он также берет на себя обновление базы данных , а также. Все , что нужно сделать , это подкласс SQLiteOpenHelper.

Необходимое условие:

  1. Базы данных , которые вы хотите отправить с приложением. Он должен содержать таблицу 1x1 имени android_metadataс атрибутом , localeимеющим значение en_USв дополнение к таблицам , уникальным для вашего приложения.

Наследование SQLiteOpenHelper:

  1. Подкласс SQLiteOpenHelper.
  2. Создать privateметод в SQLiteOpenHelperподклассе. Этот метод содержит логику для копирования содержимого базы данных из файла базы данных в папке "активов в базу данных , созданных в рамках пакета прикладных программ.
  3. Override onCreate, onUpgrade и onOpen методы SQLiteOpenHelper.

Достаточно сказано. Здесь идет 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:
        }
    }
}

Наконец, чтобы получить соединение с базой данных, просто позвоните getReadableDatabase()или getWritableDatabase()наSQLiteOpenHelper подклассу , и он будет заботиться о создании БД, копирование содержимого БД из указанного файла в папке "активов, если база данных не существует.

Короче говоря, вы можете использовать SQLiteOpenHelperподкласс для доступа к БД погружена в папке активов так же , как вы бы использовать для базы данных , которая инициализируется с помощью запросов SQL в onCreate()методе.

Ответил 26/03/2015 d 14:56
источник пользователем

голоса
7

Доставки приложения с помощью файла базы данных, в Android Studio 3.0

Доставки приложения с файлом базы данных является хорошей идеей для меня. Преимущество заключается в том, что вам не нужно делать сложную инициализацию, которая иногда стоит много времени, если набор данных огромен.

Шаг 1: Подготовка файла базы данных

Есть файл базы данных готовы. Это может быть либо .db файл или .sqlite файл. Если вы используете .sqlite файл, все, что вам нужно сделать, это изменить имена расширений файлов. Эти шаги одинаковы.

В этом примере, я подготовил файл с именем testDB.db. Она имеет одну таблицу и некоторые выборочные данные в нем, как это введите описание изображения здесь

Шаг 2: Импорт файла в проект

Создайте папку активов, если не был один. Затем скопируйте и вставьте файл базы данных в эту папку

введите описание изображения здесь

Шаг 3: Скопируйте файл в папку данных в приложении

Вам необходимо скопировать файл базы данных в каталоге данных приложения для того, чтобы сделать дальнейшее взаимодействие с ним. Это один раз действие а (инициализация), чтобы скопировать файл базы данных. Если вы вызываете этот код несколько раз, файл базы данных в папке данных будут перезаписаны один в папке активов. Этот перезапись процесс полезен, если вы хотите, чтобы обновить базу данных в будущем при обновлении приложения.

Обратите внимание, что при обновлении приложения, этот файл базы данных не будет изменен в папке данных приложения. Только удалить удалит его.

Файл базы данных должен быть скопирован в /databasesпапку. Откройте Проводник Device File. Введите data/data/<YourAppName>/местоположение. Это папка данных по умолчанию для приложения упомянутой выше. И по умолчанию, файл базы данных будет место в другой папке под названием базы данных в этом каталоге

введите описание изображения здесь

Теперь, процесс копирования файлов в значительной степени как и то, что делает Java. Используйте следующий код, чтобы сделать копию пасты. Это код инициации. Он также может быть использован для обновления (путем перезаписи) файл базы данных в будущем.

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

Затем обновить папку для проверки процесса копирования

введите описание изображения здесь

Шаг 4: Создание базы данных с открытым помощником

Создайте подкласс SQLiteOpenHelperс Подключайтесь, близко, путь и т.д. Я назвал его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) {
    }
}

Шаг 5: Создание высшего класса уровня для взаимодействия с базой данных

Это будет класс, прочитать и записать файл базы данных. Также есть пример запрос для вывода значения в базе данных.

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

Шаг 6: Проверка работы

Проверьте код, выполнив следующие строки кодов.

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

Нажмите кнопку запуска и поболеть!

введите описание изображения здесь

Ответил 07/11/2017 d 20:23
источник пользователем

голоса
5

В ноябре 2017 года Google выпустила номер Persistence Library

Из документации:

Библиотека номеров живучести обеспечивает уровень абстракции над SQLite, чтобы свободно доступ к базе данных, одновременно используя всю мощь SQLite.

Библиотека позволяет создавать кэш данных вашего приложения на устройстве, которое работает ваше приложение. Этот кэш, который служит в качестве единственного источника вашего приложения истины, позволяет пользователям просматривать последовательную копию ключевой информации в вашем приложении, независимо от того, есть ли у пользователей подключение к Интернету.

База данных номеров имеет функцию обратного вызова, когда база данных создается первый или открыт. Вы можете использовать создать функцию обратного вызова для заполнения базы данных.

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

Код из этого сообщения в блоге .

Ответил 28/11/2017 d 17:21
источник пользователем

голоса
5

В конце концов я сделал это !! Я использовал эту ссылку помощи Используя собственную базу данных SQLite в Android приложений , но пришлось изменить его немного.

  1. Если у вас есть много пакетов, которые вы должны поставить имя мастера-пакет здесь:

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

  2. Я изменил метод, который копирует базу данных из локальной папки в папке Emulator! Это была какая-то проблема, когда эта папка не существует. Поэтому в первую очередь, он должен проверить путь, и если его нет, то нужно создать папку.

  3. В предыдущем коде, copyDatabaseметод никогда не вызывается , когда база данных не существует , и checkDataBaseметод вызывается исключение. поэтому я изменил код немного.

  4. Если база данных не имеет расширение имени файла, не используйте имя файла с одним.

это работает хорошо для меня, я надеюсь, что это whould быть полезным для и слишком

    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.

}
Ответил 14/02/2014 d 10:03
источник пользователем

голоса
5

Из того, что я видел, как вы должны грузить базу данных, которая уже имеет настройки таблиц и данных. Однако, если вы хотите (и в зависимости от типа приложения, у вас есть), вы можете позволить «обновить параметр базы данных». Тогда что вы делаете, это загрузить последнюю версию SQLite, получить последнюю Вставку / Создать заявления в текстовом файле размещенного в Интернете, выполнять операторы и сделать перенос данных из старой БД в новом.

Ответил 04/02/2009 d 21:14
источник пользователем

голоса
4

Доставка базы данных внутри APK , а затем скопировать его /data/data/...удвоит размер базы данных (1 в APK, 1 в data/data/...), и увеличит размер АПК (конечно). Так что ваша база данных не должна быть слишком большой.

Ответил 12/08/2012 d 21:28
источник пользователем

голоса
4

В настоящее время не существует никакого способа предварительно создать базу данных SQLite отгружать с APK. Лучшее, что вы можете сделать, это сохранить соответствующий SQL в качестве ресурса и запускать их из вашего приложения. Да, это приводит к дублированию данных (та же информация существует как resrouce и в качестве базы данных), но нет другого пути, прямо сейчас. Единственный смягчающий фактор является файл APK сжимается. Мой опыт показывает, 908KB компрессы менее 268KB.

Нить ниже имеет лучший дискуссионный / решение я нашел с хорошим примером кода.

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

Я сохранил мою CREATE заявления как строка ресурс для чтения с Context.getString () и побежал с SQLiteDatabse.execSQL ().

Я хранятся данные для моих вставок в Рез / сырой / inserts.sql (я создал файл SQL, 7000 + линии). Используя технику по ссылке выше, я вошел в петлю, прочитать файл построчно и concactenated данные на «INSERT INTO ИГНОРИРУЙТЕ TBL VALUE» и сделал еще один SQLiteDatabase.execSQL (). Нет смысла в сохранении 7000 «Вставляйте ИГНОРИРУЙТЕ INTO TBL VALUE» S, когда они только могут быть concactenated на.

Она занимает около двадцати секунд на эмуляторе, я не знаю, как долго это будет брать на реальный телефон, но это происходит только один раз, когда пользователь запускает приложение.

Ответил 05/02/2009 d 00:32
источник пользователем

голоса
3

Android уже содержит версии Осведомленного подхода управления базами данных. Этот подход был заемные средства в рамках Baracus для Android приложений.

Это позволяет управлять базой данных по всей версии жизненного цикла приложения, неоспоримым возможность обновлять базу данных SQLite с любой предыдущей версии до текущей.

Кроме того, он позволяет запускать горячие резервные копии и горячее восстановление SQLite.

Я не уверен на 100%, а горячее восстановление для конкретного устройства может дать возможности отправить готовую базу данных в приложении. Но я не уверен в базе данных двоичного формате , которые могут быть специфическими для определенных устройств, поставщиков или поколений устройств.

Поскольку материал Лицензия Apache 2, не стесняйтесь использовать любую часть коды, который можно найти на GitHub

РЕДАКТИРОВАТЬ :

Если вы хотите, чтобы отправить данные, вы можете рассмотреть инстанцирование и сохраняющийся POJOs в приложениях первый запуска. Baracus получил встроенную поддержку этого (встроенный в хранилище ключей значения для Infos конфигурации, например, «APP_FIRST_RUN» плюс после контекста начальной загрузки крюка для запуска операции после запуска от контекста). Это позволяет иметь плотно соединенные данные погруженные с приложением; в большинстве случаев это устанавливается в моих случаях использования.

Ответил 28/10/2014 d 06:41
источник пользователем

голоса
3

Если требуемые данные не слишком велик (пределы Я не знаю, будет зависеть от многих вещей), вы также можете загрузить данные (в формате XML, JSON, что угодно) с веб-сайта / веб-приложение. После приема, выполнять операторы, используя полученные данные, создавая свои таблицы и вставки данных.

Если ваше мобильное приложение содержит много данных, это может быть проще в дальнейшем обновлять данные в установленных приложениях с более точными данными или изменениями.

Ответил 21/12/2009 d 11:12
источник пользователем

голоса
2

Я использую ORMLite и ниже код работает для меня

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

    }
}

Обратите внимание, что код извлекает файл базы данных из архива в активах

Ответил 12/07/2017 d 06:27
источник пользователем

голоса
2

Я написал библиотеку , чтобы упростить этот процесс.

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

Это позволит создать базу данных из assets/databases/myDb.dbфайла. Кроме того , вы получите все эти функции:

  • База данных Загрузить из файла
  • Синхронный доступ к базе данных
  • Использование SQLite-андроида по Requery, Android конкретное распределение последних версий SQLite.

Клон его из GitHub .

Ответил 10/07/2016 d 05:41
источник пользователем

голоса
1

Я изменил класс и ответы на этот вопрос и написал класс, который позволяет обновлять базу данных с помощью DB_VERSION.

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

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

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

Использование класса.

В классе деятельности, объявлять переменные.

private DatabaseHelper mDBHelper;
private SQLiteDatabase mDb;

В OnCreate метод, написать следующий код.

mDBHelper = new DatabaseHelper(this);

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

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

Если добавить файл базы данных в разрешении папку / сырец затем используют следующую модификацию класса.

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

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

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

Ответил 12/04/2017 d 17:14
источник пользователем

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more