Pergunta

Se a sua aplicação requer um banco de dados e vem com construído em dados, qual é a melhor maneira de enviar essa aplicação? Should I:

  1. PreCreate o banco de dados SQLite e incluí-lo no .apk?

  2. Inclua os comandos SQL com a aplicação e tê-lo criar o banco de dados e inserir os dados no primeiro uso?

As desvantagens que eu vejo são:

  1. possíveis incompatibilidades versão SQLite pode causar problemas e atualmente não sei onde o banco de dados deve ir e como acessá-lo.

  2. Pode demorar muito tempo para criar e preencher o banco de dados no dispositivo.

Todas as sugestões? Ponteiros para a documentação sobre quaisquer questões seria muito apreciada.

Foi útil?

Solução

Eu encontrei uma maneira de fazer isso em ReignDesign blog em um artigo intitulado Usando o seu próprio banco de dados SQLite em aplicações Android . Basicamente você PreCreate seu banco de dados, colocá-lo em seu diretório ativo em sua apk, e na cópia da primeira utilização para o diretório /data/data/YOUR_PACKAGE/databases/.

Outras dicas

Há duas opções para a criação e atualização de bases de dados.

Uma é criar um banco de dados externamente, em seguida, colocá-lo no ativo pasta do projeto e, em seguida, copiar todo o banco de dados de lá. Isto é muito mais rápido se o banco de dados tem um monte de tabelas e outros componentes. Upgrades são acionados, alterando o número da versão do banco de dados na valores / arquivo res / strings.xml. Atualizações, então, ser conseguido através da criação de um novo banco de dados externamente, substituindo o antigo banco de dados no ativo pasta com o novo banco de dados, salvando o antigo banco de dados no armazenamento interno com outro nome, copiando o novo banco de dados a partir dos activos pasta para armazenamento interno, a transferência de todos os dados do banco de dados antigo (que foi renomeado anteriormente) para a nova banco de dados e, finalmente, eliminar o banco de dados antigo. Você pode criar um banco de dados originalmente usando o SQLite Manager FireFox plug-in para executar suas instruções SQL de criação.

A outra opção é criar um banco de dados interno de um arquivo sql. Isto não é tão rápido, mas o atraso provavelmente seria imperceptível para os usuários se o banco de dados tem apenas algumas mesas. Upgrades são acionados, alterando o número da versão do banco de dados na valores / arquivo res / strings.xml. Atualizações, então, ser realizado pelo processamento de um arquivo sql upgrade. Os dados na base de dados permanecerá inalterada, excepto quando o recipiente é removido, por exemplo deixando cair de uma mesa.

O exemplo a seguir demonstra como usar o método.

Aqui está um exemplo de arquivo create_database.sql. É para ser colocado no ativo pasta do projeto para o método interno ou copiado para o "Executar SQL' do SQLite Manager para criar o banco de dados para o método externo (NOTA:. Observe o comentário sobre a mesa exigido pelo 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"; 

Aqui está um exemplo de arquivo update_database.sql. É para ser colocado no ativo pasta do projeto para o método interno ou copiado para o "Executar SQL' do SQLite Manager para criar o banco de dados para o método externo . (Nota: Observe que todos os três tipos de SQL comentários serão ignorados pelo analisador sql que está incluído neste exemplo.)

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

Aqui está uma entrada para adicionar ao arquivo de /res/values/strings.xml para o número da versão do banco de dados.

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

Aqui é uma atividade que acessa o banco de dados e, em seguida, usa-lo. ( Nota:. Você pode querer executar o código de banco de dados em um segmento separado se ele usa um monte 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();
            }
        }

    }
}

Aqui está a classe auxiliar de banco de dados onde o banco de dados é criado ou atualizado, se necessário. (NOTA:. Android requer que você crie uma classe que estende SQLiteOpenHelper, a fim de trabalhar com um banco de dados 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.
     */

}

Aqui está a classe FileHelper que contém métodos para fluxo de bytes copiar arquivos e analisar arquivos 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(";");
    }

}

A biblioteca SQLiteAssetHelper torna essa tarefa muito simples.

É fácil adicionar como uma dependência Gradle (mas um frasco também está disponível para Ant / Eclipse) e, juntamente com a documentação pode ser encontrada em:
https://github.com/jgilfelt/android-sqlite-asset-helper

Nota:. Este projeto não é mais mantido como indicado no link acima Github

Como explicado na documentação:

  1. Adicionar a dependência de arquivo de construção Gradle do seu módulo:

    dependencies {
        compile 'com.readystatesoftware.sqliteasset:sqliteassethelper:+'
    }
    
  2. Copiar o banco de dados no diretório de ativos, em um subdiretório chamado assets/databases. Por exemplo:
    assets/databases/my_database.db

    (Opcionalmente, você pode compactar o banco de dados em um arquivo zip, como assets/databases/my_database.zip. Isso não é necessário, uma vez que o APK é comprimido como já todo.)

  3. Crie uma classe, por exemplo:

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

Eu acho que o melhor e da maneira mais novo até hoje está usando classe SQLiteAssetHelper.

Este tutorial guias perfeitamente através de importar e usar banco de dados externos no Android

A biblioteca SQLiteAssetHelper Android permite que você construa o seu SQLite banco de dados em seu computador desktop, e para importação e usá-lo em sua aplicação Android. Vamos criar uma aplicação simples para demonstrar a aplicação desta biblioteca.

Passo 1 : Criar um quotes.db banco de dados usando o SQLite favorito aplicação de banco de dados (DB navegador para SQLite é um cruzamento portátil gratuito plataforma, que pode ser usado para criar e editar SQLite bases de dados). Criar uma tabela 'aspas' com uma única coluna 'Citação'. Inserir algumas citações aleatórias no 'citações' da tabela.

Passo 2 : O banco de dados pode ser importado para o projecto, quer directamente como ela é, ou como um arquivo compactado. O arquivo compactado é recomendado, se seu banco de dados é muito grande em tamanho. Você pode criar um ZIP compressão ou uma compressão GZ.

O nome do arquivo db arquivo compactado deve ser quotes.db.zip, se você está usando a compressão ZIP ou quotes.db.gz, se você estiver usando GZ compressão.

Passo 3 : Criar um novo External Database Demo aplicativo com um nome do pacote com.javahelps.com.javahelps.externaldatabasedemo.

Passo 4

: arquivo e adicione a seguinte: Abra o build.gradle (app Module) dependência.

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

Uma vez que você salvou o arquivo build.gradle clique no botão 'Sync Now' link para atualizar o projeto. Você pode sincronizar o build.gradle, por botão direito sobre o arquivo build.gradle e opção de selecionar Synchronize build.gradle também.

Passo 5 :. Botão direito do mouse na pasta do aplicativo e criar uma nova pasta ativos

Passo 6 :. Criar uma nova pasta 'bancos de dados' dentro da pasta ativos

Passo 7 : Copie e cole o arquivo quotes.db.zip dentro do assets/databases pasta.

Passo 8 : Criar uma nova classe 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.

Passo 9 : Criar um novo DatabaseAccess classe e digite o código como mostrado abaixo. Mais detalhes sobre esta classe está disponível em Avançada Android Banco de dados tutorial.

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,

atualizar e excluir todas as linhas no banco de dados como de costume. Para mais detalhes, siga este link Advanced Database Android.

Todas as configurações de banco de dados relacionados são concluídos e agora precisamos criar um ListView para exibir as aspas.

Passo 10 :. Adicionar um ListView em sua 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>  

Passo 11 : Encontre o objeto de ListView no método onCreate de MainActivity e alimentam as citações que são lidas formar o banco de dados.

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

Passo 12 :. Salve todas as alterações e executar o aplicativo

Além de este artigo você pode baixar SQLiteAssetHelper aqui

A minha solução não usa qualquer biblioteca de terceiros, nem obriga a chamar métodos personalizados na subclasse SQLiteOpenHelper para inicializar o banco de dados sobre a criação. Ele também cuida de atualizações do banco de dados também. Tudo o que precisa ser feito é SQLiteOpenHelper subclasse.

Pré-requisito:

  1. O banco de dados que você deseja enviar com o aplicativo. Ele deve conter uma tabela 1x1 android_metadata nomeado com um locale atributo ter a en_US valor além das tabelas únicas para a sua aplicação.

Subclassing SQLiteOpenHelper:

  1. subclasse SQLiteOpenHelper.
  2. Crie um método private dentro da subclasse SQLiteOpenHelper. Este método contém a lógica para copiar o conteúdo do banco de dados a partir do arquivo de banco de dados na pasta 'ativos' para o banco de dados criado no contexto pacote de aplicativos.
  3. onCreate Override, onUpgrade e métodos onOpen de SQLiteOpenHelper.

dito o suficiente. Aqui vai a subclasse 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:
        }
    }
}

Finalmente, para obter uma conexão de banco de dados, basta ligar getReadableDatabase() ou getWritableDatabase() na subclasse SQLiteOpenHelper e ele vai cuidar de criar um db, copiar conteúdos db a partir do arquivo especificado na pasta 'ativos', se o banco de dados não existe .

Em suma, você pode usar a subclasse SQLiteOpenHelper ao acesso db enviado no ativo pasta assim como você usaria para um banco de dados que é inicializado usando consultas SQL no método onCreate().

Envio o aplicativo com um arquivo de banco de dados, no Android Studio 3.0

O transporte da aplicação com um arquivo de banco de dados é uma boa idéia para mim. A vantagem é que você não precisa fazer uma inicialização complexa, que às vezes custa muito tempo, se o conjunto de dados é enorme.

Passo 1: Prepare arquivo de banco de dados

Tenha o seu arquivo de banco de dados pronto. Ela pode ser tanto um arquivo db ou um arquivo .sqlite. Se você usar um arquivo .sqlite, tudo que você precisa fazer é mudar nomes de extensão de arquivo. Os passos são os mesmos.

Neste exemplo, eu preparei um arquivo chamado testDB.db. Tem uma mesa e alguns dados de exemplo nele como este enter descrição da imagem aqui

Passo 2: Importe o arquivo em seu projeto

Criar os ativos da pasta, se você ainda não teve um. Em seguida, copie e cole o arquivo de banco de dados para esta pasta

 enter descrição da imagem aqui

Passo 3: Copie o arquivo de dados do aplicativo pasta

Você precisa copiar o arquivo de banco de dados para a pasta de dados do aplicativo, a fim de fazer mais interação com ele. Esta é uma ação uma vez (inicialização) para copiar o arquivo de banco de dados. Se você chamar este código várias vezes, o arquivo de banco de dados em dados de pasta será substituído por um em pasta ativos. Este processo de substituição é útil quando você deseja atualizar o banco de dados no futuro durante a atualização do aplicativo.

Note-se que durante a atualização do aplicativo, este arquivo de banco de dados não será alterado na pasta de dados do aplicativo. Apenas desinstalação irá excluí-lo.

O arquivo de banco de dados precisa ser copiados para a pasta /databases. Abrir Dispositivo File Explorer. Introduza a localização data/data/<YourAppName>/. Estes são dados padrão do aplicativo pasta mencionados acima. E, por padrão, o arquivo de banco de dados será colocado em uma outra pasta chamada bases de dados sob este diretório

 enter descrição da imagem aqui

Agora, o processo de arquivo de cópia é muito parecido com o que Java está fazendo. Use o seguinte código para fazer a pasta de cópia. Este é o código de iniciação. Ele também pode ser usado para atualização (sobrescrevendo) o arquivo de banco de dados no 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
}

Em seguida, atualizar a pasta para verificar o processo de cópia

 enter descrição da imagem aqui

Etapa 4: Criar banco de dados ajudante aberta

Criar uma subclasse para SQLiteOpenHelper, com conexão, fechar, caminho, etc. I nomeou-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) {
    }
}

Etapa 5: Criar classe de nível superior para interagir com o banco de dados

Esta será a classe que ler e escrever seu arquivo de banco de dados. Também há uma consulta de exemplo para imprimir o valor no banco de dados.

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

Passo 6: Teste de execução

Test o código executando as seguintes linhas de códigos.

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

Aperte o botão de execução e alegria!

 enter descrição da imagem aqui

Em novembro 2017 o Google lançou o quarto Persistência Biblioteca

A partir da documentação:

O quarto persistência biblioteca fornece uma camada de abstração sobre SQLite para permitir o acesso de banco de dados fluente enquanto aproveitando o poder cheio de SQLite.

A biblioteca ajuda a criar um cache de dados de seu aplicativo em um dispositivo que está executando o aplicativo. Esta cache, que serve como seu aplicativo está solteiro fonte da verdade, permite aos usuários visualizar uma cópia consistente de chave informação dentro de seu aplicativo, independentemente dos usuários têm uma conexão de internet.

O banco de dados quarto tem uma chamada de retorno quando o banco de dados é criado ou aberto. Você pode usar o callback criar para preencher o banco de dados.

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

código deste blog .

Pelo que tenho visto você deve estar enviando um banco de dados que já tem a configuração e dados de tabelas. No entanto, se você quiser (e, dependendo do tipo de aplicação que você tem) você pode permitir que "a opção de banco de dados upgrade". Então o que você faz é baixar a versão mais recente sqlite, pegar as últimas Inserir / criar instruções de um arquivo de texto hospedados on-line, executar as instruções e fazer uma transferência de dados a partir da antiga db para o novo.

Finalmente eu fiz isso !! Eu tenho usado este link Usando seu próprio SQLite banco de dados em aplicações Android , mas teve que mudá-lo um pouco.

  1. Se você tem muitos pacotes que você deve colocar o nome do pacote mestre aqui:

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

  2. Eu mudei o método que copia o banco de dados da pasta local para a pasta emulador! Ele tinha algum problema quando essa pasta não existia. Então, primeiro de tudo, deve verificar o caminho e se ele não estiver lá, ele deve criar a pasta.

  3. No código anterior, o método copyDatabase nunca foi chamado quando o banco de dados não existe e o método checkDataBase exceção causada. então eu mudei o código um pouco.

  4. Se o seu banco de dados não tem uma extensão de arquivo, não use o nome do arquivo com um.

funciona bom para mim, eu espero que whould ser útil para 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.

}

Atualmente não há nenhuma maneira de PreCreate um banco de dados SQLite para navio com o seu apk. O melhor que você pode fazer é salvar o SQL apropriado como um recurso e executá-los a partir de sua aplicação. Sim, isso leva a duplicação de dados (mesma informação existe como um resrouce e, como um banco de dados), mas não há outra maneira agora. O único fator mitigação é o arquivo apk é comprimido. Minha experiência é 908KB compressas para menos de 268KB.

O fio abaixo tem a melhor discussão / solução que eu encontrei com um bom código de exemplo.

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

I valor minha instrução CREATE como um recurso de cadeia para ser lido com Context.getString () e ele correu com SQLiteDatabse.execSQL ().

Eu armazenados os dados para os meus inserções em res / / inserts.sql raw (eu criei o arquivo sql, 7000 + linhas). Usando a técnica a partir do link acima entrei em um loop, ler o arquivo linha por linha e concactenated os dados para "INSERT INTO tbl VALUE" e fez outra SQLiteDatabase.execSQL (). Não há sentido em economia de 7000 "INSERT INTO VALOR tbl" é quando eles podem apenas ser concactenated diante.

É preciso cerca de vinte segundos no emulador, eu não sei quanto tempo isso levaria em um telefone real, mas isso só acontece uma vez, quando o usuário inicia pela primeira vez o aplicativo.

O transporte da base de dados dentro do apk e depois copiá-lo para /data/data/... vai dobrar o tamanho do banco de dados (1 em apk, 1 em data/data/...), e irá aumentar o tamanho apk (é claro). Portanto, o seu banco de dados não deve ser muito grande.

Android já fornece uma abordagem versão consciente de gerenciamento de banco de dados. Esta abordagem tem sido aproveitado no âmbito baracus para aplicações Android.

Ele permite gerenciar o banco de dados ao longo todo o ciclo versão de um aplicativo, beeing capaz de atualizar o banco de dados SQLite a partir de qualquer versão anterior ao atual.

Além disso, ele permite que você execute quente -backups e hot-recuperação do SQLite.

Eu não estou 100% de certeza, mas um hot-recuperação para um específica dispositivo pode permitir-lhe enviar um banco de dados preparado em seu aplicativo. Mas não estou certo sobre o formato binário de banco de dados que podem ser específicos para determinados dispositivos, fornecedores ou gerações de dispositivos.

Uma vez que o material é Apache License 2, sinta-se livre para reutilizar qualquer parte do código, que pode ser encontrado no github

EDIT:

Se você só quer enviar dados, você pode considerar instanciar e persistindo POJOs nas aplicações primeiro começar. Baracus tem um suporte embutido para esta (Built-in de armazenamento de chaves de valor para informações sobre configuração, por exemplo "APP_FIRST_RUN" mais um gancho de pós-context-inicialização, a fim de operações de prazo pós-lançamento do contexto). Isto permite-lhe ter dados apertado juntamente fornecidas com o aplicativo; na maioria dos casos esta equipado para os meus casos de uso.

Se os dados requeridos não é muito grande (limites não sei, vai depender de um monte de coisas), você também pode fazer o download dos dados (em XML, JSON, qualquer que seja) de um site / webapp. Depois de receber, executar as instruções SQL usando os dados recebidos criando suas tabelas e inserindo os dados.

Se o seu aplicativo móvel contém muitos dados, pode ser mais fácil, mais tarde, para atualizar os dados nos aplicativos instalados com dados mais precisos ou alterações.

Eu escrevi um biblioteca para simplificar este processo.

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

Ele vai criar um banco de dados a partir do arquivo assets/databases/myDb.db. Além disso, você receberá todas as funcionalidades:

  • banco de dados de carga de arquivo
  • Acesso sincronizado com o banco de dados
  • sqlite-android por requery, distribuição específica Android das últimas versões do SQLite.

Clone-lo a partir github .

Eu estou usando ORMLite e abaixo código funcionou para mim

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

    }
}

Por favor, note que o arquivo de banco de extratos de código de um arquivo zip em ativos

Eu modifiquei a classe e as respostas para a pergunta e escreveu uma classe que permite a atualização do banco de dados via 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;
    }
}

Usando uma classe.

Na classe de atividade, as variáveis ??de declaração.

private DatabaseHelper mDBHelper;
private SQLiteDatabase mDb;

No método onCreate, escrever o seguinte 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;
}

Se você adicionar um arquivo de banco de dados para os res pasta / raw, em seguida, usar a seguinte modificação da classe.

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 em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top