Pregunta

Si su aplicación requiere una base de datos y viene con datos integrados, ¿cuál es la mejor manera de enviar esa aplicación?Debería:

  1. Cree previamente la base de datos SQLite e inclúyala en el .apk?

  2. ¿Incluir los comandos SQL con la aplicación y hacer que cree la base de datos e inserte los datos en el primer uso?

Los inconvenientes que veo son:

  1. Posibles discrepancias en la versión de SQLite pueden causar problemas y actualmente no sé dónde debería ir la base de datos ni cómo acceder a ella.

  2. Puede llevar mucho tiempo crear y completar la base de datos en el dispositivo.

¿Alguna sugerencia?Se agradecerían enormemente sugerencias sobre la documentación sobre cualquier problema.

¿Fue útil?

Solución

Acabo de encontrar una manera de hacer esto en ReignDesign blog en un artículo titulado Uso de su propia base de datos SQLite en aplicaciones Android . Básicamente que crear previamente su base de datos, lo puso en su directorio de activos en su apk, y en la primera copia de uso a /data/data/YOUR_PACKAGE/databases/ directorio.

Otros consejos

Hay dos opciones para la creación y actualización de bases de datos.

Una es crear una base de datos externa, luego se coloca en la carpeta de los activos del proyecto y luego copiar la base de datos a partir de ahí. Esto es mucho más rápido si la base de datos tiene una gran cantidad de tablas y otros componentes. Las actualizaciones son provocados por el cambio del número de versión de la base de datos en el / los valores de archivo res / strings.xml. Actualizaciones serían entonces llevarse a cabo mediante la creación de una nueva base de datos externa, en sustitución de la antigua base de datos en los activos de la carpeta con la nueva base de datos, el ahorro de la antigua base de datos en el almacenamiento interno con otro nombre, la copia de la nueva base de datos a partir de los activos carpeta en la memoria interna, la transferencia de todos los datos de la antigua base de datos (que pasó a llamarse antes) en el nuevo base de datos y, finalmente, la supresión de la antigua base de datos. Puede crear una base de datos originalmente por el uso de la Administrador de SQLite plugin de Firefox para ejecutar las sentencias SQL de creación.

La otra opción es crear una base de datos interna de un archivo sql. Esto no es tan rápido, pero el retraso probablemente sería imperceptible para los usuarios si la base de datos tiene sólo unas pocas mesas. Las actualizaciones son provocados por el cambio del número de versión de la base de datos en el / los valores de archivo res / strings.xml. Actualizaciones serían entonces llevarse a cabo mediante el procesamiento de un archivo de actualización SQL. Los datos en la base de datos permanecerán sin cambios, excepto cuando su recipiente se retira, por ejemplo dejar caer una mesa.

El siguiente ejemplo muestra cómo utilizar cualquiera de los métodos.

Este es un archivo de ejemplo create_database.sql. Es para ser colocado en la carpeta de los activos del proyecto para el método interno o copiado en el SQL "Ejecutar' del Administrador de SQLite para crear la base de datos para el método externo (NOTA:. Observe el comentario acerca de la tabla requerida por 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"; 

Este es un archivo de ejemplo update_database.sql. Es para ser colocado en la carpeta de los activos del proyecto para el método interno o copiado en el SQL "Ejecutar' del Administrador de SQLite para crear la base de datos para el método externo . (Nota: Tenga en cuenta que los tres tipos de SQL comentarios serán ignorados por el analizador de SQL que se incluye en este ejemplo.)

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

Esta es una entrada para añadir al archivo /res/values/strings.xml para el número de versión de la base de datos.

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

Esta es una actividad que tiene acceso a la base de datos y luego lo utiliza. ( Nota:. Es posible que desee ejecutar el código de base de datos en un hilo separado si se utiliza una gran cantidad de recursos )

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

    }
}

Esta es la clase de ayuda base de datos donde se crea o se actualiza la base de datos si es necesario. (NOTA:. Android requiere la creación de una clase que se extiende SQLiteOpenHelper con el fin de trabajar con una base de datos 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.
     */

}

Esta es la clase FileHelper que contiene métodos para copiar archivos de flujo de bytes y analizar archivos 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(";");
    }

}

La biblioteca SQLiteAssetHelper hace esta tarea muy simple.

Es muy fácil añadir una dependencia Gradle (pero un tarro también está disponible para la hormiga / Eclipse), y junto con la documentación que se puede encontrar en:
https://github.com/jgilfelt/android-sqlite-asset-helper

Nota:. Este proyecto ya no se mantiene como se indica en el enlace de arriba Github

Como se explica en la documentación:

  1. Añadir a la dependencia fichero de construcción Gradle de su módulo:

    dependencies {
        compile 'com.readystatesoftware.sqliteasset:sqliteassethelper:+'
    }
    
  2. Copiar la base de datos en el directorio de activos, en un subdirectorio llamado assets/databases. Por ejemplo:
    assets/databases/my_database.db

    (Opcionalmente, se puede comprimir la base de datos en un archivo zip como assets/databases/my_database.zip. Esto no es necesario, ya que el APK se comprime en su conjunto ya.)

  3. Crea una clase, por ejemplo:

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

Supongo que la mejor y más nueva forma hasta hoy es usar SQLiteAssetHelper clase.

este tutorial te guía perfectamente a través Importación y uso de bases de datos externas en Android

El androide SQLiteAssetHelper La biblioteca le permite construir su SQLitebase de datos en su computadora de escritorio y para importarla y usarla en su aplicación Android.Creemos una aplicación simple para demostrar la aplicación de esta biblioteca.

Paso 1:Cree una base de datos cotizaciones.db utilizando su aplicación favorita de la base de datos SQLite (el navegador DB para SQLite es un software libre de plataforma portátil, que se puede utilizar para crear y editar bases de datos SQLite).Cree una tabla 'cotizaciones' con una sola columna 'cotización'.Inserte algunas citas aleatorias en la tabla 'citas'.

Paso 2:La base de datos se puede importar al proyecto directamente como está o como un archivo comprimido.Se recomienda el archivo comprimido, si su base de datos tiene un tamaño demasiado grande.Puedes crear un ZIPcompresión o un GZ compresión.

El nombre del archivo db comprimido debe ser quotes.db.zip, si está utilizando la compresión zip o quotes.db.gz, si está utilizando la compresión GZ.

Paso 3:Crear una nueva aplicación External Database Demo con un nombre de paquete com.javahelps.com.javahelps.externaldatabasedemo.

Etapa 4:Abre el build.gradle (Módulo:APP) Archivo y agregue la siguiente dependencia.

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

Una vez que haya guardado el build.gradle Archivo Haga clic en el enlace 'Sync Now' para actualizar el proyecto.Puedes sincronizar el build.gradle, haciendo clic derecho en el build.gradle archivo y seleccionando Synchronize build.gradle opción también.

Paso 5:Haga clic derecho en la carpeta de la aplicación y cree una nueva carpeta de activos.

Paso 6:Cree una nueva carpeta 'bases de datos' dentro de la carpeta de activos.

Paso 7:Copia y pega el quotes.db.zip archivo dentro del assets/databases carpeta.

Paso 8:Crear una nueva clase 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.

Paso 9:Crear una nueva clase DatabaseAccess e ingrese el código como se muestra a continuación.Más detalles sobre esta clase están disponibles en el tutorial avanzado de la base de datos de 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,

actualice y elimine las filas de la base de datos como de costumbre.Para obtener más detalles, siga este enlace una base de datos avanzada de Android.

Todas las configuraciones relacionadas con la base de datos se completan y ahora necesitamos crear un ListView para mostrar las cotizaciones.

Paso 10:Agrega un ListView en tus 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>  

Paso 11:Encuentra el objeto de ListView en el onCreate método de MainActivity y alimentar las citas que se leen forman la base de datos.

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

Paso 12:Guarde todos los cambios y ejecute la aplicación.

Además de este artículo puedes descargar SQLiteAssetHelper aquí

Mi solución no utiliza ninguna biblioteca de terceros ni fuerzas que llame a métodos personalizados en SQLiteOpenHelper subclase para inicializar la base de datos en la creación. También se encarga de las actualizaciones de bases de datos también. Todo lo que hay que hacer es subclase android_metadata.

Requisito:

  1. La base de datos que desea enviar con la aplicación. Debe contener una tabla de 1x1 llamado locale con un atributo que tiene el valor en_US private además de las mesas únicas para su aplicación.

subclases onCreate:

  1. Subclase onUpgrade.
  2. Crear un método onOpen dentro de la subclase getReadableDatabase(). Este método contiene la lógica para copiar el contenido de bases de datos desde el archivo de base de datos en la carpeta de los 'activos' a la base de datos creada en el contexto paquete de aplicación.
  3. Override getWritableDatabase(), onCreate() y <=> métodos de <=>.

dicho suficiente. Aquí va la <=> subclase:

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

Por último, para obtener una conexión de base de datos, simplemente llame o <=> <=> en el <=> subclase y se hará cargo de la creación de una base de datos, copiar el contenido db desde el archivo especificado en la carpeta 'activos', Si la base de datos no existe.

En resumen, se puede usar la subclase <=> acceder a la base de datos enviado en la carpeta los activos del mismo modo que se uso para una base de datos que se inicializa mediante consultas SQL en el método <=>.

Envío de la aplicación con un archivo de base de datos, en Android Studio 3.0

Enviar la aplicación con un archivo de base de datos es una buena idea para mí.La ventaja es que no necesita realizar una inicialización compleja, que a veces cuesta mucho tiempo, si su conjunto de datos es enorme.

Paso 1:Preparar archivo de base de datos

Tenga listo su archivo de base de datos.Puede ser un archivo .db o un archivo .sqlite.Si utiliza un archivo .sqlite, todo lo que necesita hacer es cambiar los nombres de las extensiones del archivo.Los pasos son los mismos.

En este ejemplo, preparé un archivo llamado testDB.db.Tiene una tabla y algunos datos de muestra como este.enter image description here

Paso 2:Importa el archivo a tu proyecto

Cree la carpeta de activos si no ha tenido una.Luego copie y pegue el archivo de la base de datos en esta carpeta.

enter image description here

Paso 3:Copie el archivo a la carpeta de datos de la aplicación.

Debe copiar el archivo de la base de datos a la carpeta de datos de la aplicación para poder interactuar más con él.Esta es una acción única (inicialización) para copiar el archivo de base de datos.Si llama a este código varias veces, el archivo de base de datos en la carpeta de datos será sobrescrito por el de la carpeta de activos.Este proceso de sobrescritura es útil cuando desea actualizar la base de datos en el futuro durante la actualización de la aplicación.

Tenga en cuenta que durante la actualización de la aplicación, este archivo de base de datos no se modificará en la carpeta de datos de la aplicación.Sólo la desinstalación lo eliminará.

El archivo de la base de datos debe copiarse a /databases carpeta.Abra el Explorador de archivos del dispositivo.Ingresar data/data/<YourAppName>/ ubicación.Esta es la carpeta de datos predeterminada de la aplicación mencionada anteriormente.Y de forma predeterminada, el archivo de la base de datos se colocará en otra carpeta llamada bases de datos en este directorio.

enter image description here

Ahora, el proceso de copiar archivos es muy parecido a lo que hace Java.Utilice el siguiente código para copiar y pegar.Este es el código de iniciación.También se puede utilizar para actualizar (sobrescribiendo) el archivo de base de datos en el futuro.

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

Luego actualice la carpeta para verificar el proceso de copia.

enter image description here

Etapa 4:Crear ayuda abierta de base de datos

Crear una subclase para SQLiteOpenHelper, con conectar, cerrar, ruta, etc.lo nombré 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) {
    }
}

Paso 5:Crear una clase de nivel superior para interactuar con la base de datos.

Esta será la clase que lea y escriba su archivo de base de datos.También hay una consulta de muestra para imprimir el valor en la base de datos.

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

Paso 6:Prueba en ejecución

Pruebe el código ejecutando las siguientes líneas de códigos.

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

¡Pulsa el botón de ejecutar y anímate!

enter image description here

En noviembre de 2017 Google lanzó el habitación Persistencia Biblioteca

A partir de la documentación:

  

La biblioteca de la persistencia de habitaciones proporciona una capa de abstracción sobre SQLite   para permitir el acceso de base de datos con fluidez, mientras que el aprovechamiento de la potencia de   SQLite.

     

La biblioteca le ayuda a crear una memoria caché de datos de la aplicación en un dispositivo   que se está ejecutando la aplicación. Esta caché, que sirve como de su aplicación única   fuente de verdad, permite a los usuarios ver una copia consistente de la llave   información dentro de su aplicación, independientemente de si los usuarios tienen una   conexión a Internet.

La base de datos de habitaciones tiene una devolución de llamada cuando la base de datos se crea o se abre por primera vez. Puede usar la devolución de llamada crear para poblar su base de datos.

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

entrada de blog .

Por lo que he visto que debe ser envío de una base de datos que ya tiene la configuración de tablas y datos. Sin embargo, si usted quiere (y dependiendo del tipo de aplicación que tienen) puede permitir que "la opción de base de datos de actualización". Entonces lo que se hace es descargar la última versión de SQLite, obtener la última Insertar / Crear declaraciones de un fichero de texto alojado en línea, ejecutar las instrucciones y hacer una transferencia de datos desde el antiguo db a la nueva.

Finalmente lo hice !! He utilizado este enlace ayuda para utilizar su propio SQLite base de datos en aplicaciones Android , pero tuvo que cambiar un poco.

  1. Si usted tiene muchos paquetes que usted debe poner el nombre del paquete maestro aquí:

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

  2. Me cambió el método que copia la base de datos de la carpeta local a la carpeta emulador! Tenía un poco de problema cuando no existiera esa carpeta. Así que en primer lugar, es necesario comprobar la ruta y si no está ahí, se debe crear la carpeta.

  3. En el código anterior, el método copyDatabase nunca fue llamado cuando la base de datos no existe y el método checkDataBase causó una excepción. así que cambié el código un poco.

  4. Si su base de datos no tiene una extensión de archivo, no utilice el nombre del archivo con uno.

funciona bien para mí, espero que sea útil para whould u demasiado

    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.

}

En la actualidad no hay ninguna manera de crear previamente una base de datos SQLite con el envío del apk. Lo mejor que puede hacer es guardar el SQL adecuado como un recurso y ejecutarlos desde la aplicación. Sí, esto lleva a la duplicación de datos (existe misma información que una resrouce y como una base de datos), pero no hay otra manera en este momento. El único factor de mitigación es el archivo apk se comprime. Mi experiencia es 908KB comprime a menos de 268KB.

El hilo de abajo es la mejor discusión / solución que he encontrado con un buen código de ejemplo.

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

Me guardaron mi sentencia CREATE como un recurso de cadena para ser leído con Context.getString () y corrió con SQLiteDatabse.execSQL ().

Me almacenan los datos de mis insertos en res / prima / inserts.sql (he creado el archivo sql, 7000+ líneas). Utilizando la técnica desde el enlace anterior entré en un bucle, leer el archivo línea por línea y concactenated los datos en "INSERT INTO VALOR TBL" e hizo otra SQLiteDatabase.execSQL (). No tiene sentido en el ahorro de 7000 "INSERT INTO TBL VALUE" s cuando sólo se pueden concactenated sucesivamente.

Se tarda unos veinte segundos en el emulador, no sé cuánto tiempo tardaría en un teléfono real, pero sólo ocurre una vez, cuando el usuario inicia por primera vez la aplicación.

Envío de la base de datos dentro de la apk y luego copiarlo en /data/data/... se duplicará el tamaño de la base de datos (1 en apk, 1 en data/data/...), y aumentará el tamaño apk (por supuesto). Por lo que su base de datos no debe ser demasiado grande.

Android ya ofrece un enfoque versión consciente de gestión de base de datos. Este enfoque ha sido aprovechado en el marco Baracus para aplicaciones de Android.

Se le permite administrar la base de datos a lo largo de todo el ciclo de vida de la versión de una aplicación, beeing capaz de actualizar la base de datos SQLite desde cualquier versión anterior a la actual.

Además, le permite ejecutar caliente -backups y caliente-recuperación de la SQLite.

No estoy 100% seguro, pero un hot-recuperación para un específica dispositivo puede permitirle enviar una base de datos preparada en su aplicación. Pero no estoy seguro acerca de la base de datos de formato binario que podrían ser específicos para determinados dispositivos, proveedores o generaciones de dispositivos.

Dado que la materia es Apache License 2, no dude en volver a utilizar cualquier parte del código, que se puede encontrar en github

EDIT:

Si sólo quiere enviar datos, podría considerar crear instancias POJO y persistiendo en las aplicaciones de la primera puesta. Baracus tiene un soporte incorporado para esto (Built-in del almacén de claves de valor para informaciones de configuración, por ejemplo, "APP_FIRST_RUN" además de un servicio post-contexto-arranque gancho con el fin de ejecutar las operaciones posteriores al lanzamiento del contexto). Esto le permite tener los datos enviados apretado junto con su aplicación; en la mayoría de los casos se ajustaba a mis casos de uso.

Si los datos requeridos no es demasiado grande (límites No sé, dependerá de muchas cosas), también puede descargar los datos (en XML, JSON, lo que sea) de un sitio web / aplicación web. Después de recibir, ejecutar las sentencias SQL utilizando los datos recibidos que crean las tablas e insertar los datos.

Si su aplicación móvil contiene una gran cantidad de datos, que podría ser más fácil después de actualizar los datos de las aplicaciones instaladas con los datos más precisos o cambios.

para simplificar este proceso.

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

Se va a crear una base de datos de assets/databases/myDb.db archivo. Además obtendrá todos aquellos funcionalidad:

  • base de datos de la carga del archivo
  • acceso sincronizado a la base de datos
  • sqlite-android nueva consulta, Android distribución específica de las últimas versiones de SQLite.

Clonar desde github .

Estoy usando ORMLite y por debajo de código que funcionó para mí

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

    }
}

Tenga en cuenta, el código extrae archivo de base de datos desde un archivo zip en activos

He modificado la clase y las respuestas a la pregunta y escribí una clase que permite actualizar la base de datos a través de 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;
    }
}

El uso de una clase.

En la clase de actividad, declarar variables.

private DatabaseHelper mDBHelper;
private SQLiteDatabase mDb;

En el método onCreate, escribir el siguiente código.

mDBHelper = new DatabaseHelper(this);

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

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

Si se agrega un archivo de base de datos para la res carpeta / prima a continuación, utilizar la siguiente modificación de la clase.

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

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top