Question

Si votre application nécessite une base de données et il est livré avec construit dans les données, ce qui est la meilleure façon d'expédier cette application? Dois-je:

  1. PreCreate la base de données SQLite et l'inclure dans le .apk?

  2. Inclure les commandes SQL avec l'application et l'ont créer la base de données et insérer les données de la première utilisation?

Les inconvénients que je vois sont:

  1. discordances version SQLite possibles pourraient causer des problèmes et je ne sais pas actuellement où la base de données devrait aller et comment y accéder.

  2. Il peut prendre un temps très long pour créer et alimenter la base de données sur le périphérique.

Toutes les suggestions? Pointeurs à la documentation concernant toutes les questions seraient grandement appréciés.

Était-ce utile?

La solution

Je viens de trouver une façon de le faire dans ReignDesign blog dans un article intitulé Utilisation de votre propre base de données SQLite dans les applications Android . Fondamentalement, vous PreCreate votre base de données, mettez-le dans votre répertoire actif dans votre apk, et sur la première copie à usage répertoire /data/data/YOUR_PACKAGE/databases/.

Autres conseils

Il y a deux options pour la création et la mise à jour des bases de données.

La première consiste à créer une base de données externe, puis placez-le dans le dossier actif du projet, puis copier la base de données complète à partir de là. Cela est beaucoup plus rapide si la base de données a beaucoup de tables et d'autres composants. Mises à niveau sont déclenchées en modifiant le numéro de version de base de données dans la résolution / valeurs / fichier strings.xml. Mises à niveau seraient alors accompli en créant une nouvelle base de données externe, en remplacement de l'ancienne base de données dans les actifs dossier avec la nouvelle base de données, sauvegarde de la vieille base de données dans le stockage interne sous un autre nom, la copie de la nouvelle base de données à partir des actifs dossier dans le stockage interne, le transfert de toutes les données de l'ancienne base de données (qui a été renommé plus tôt) dans la nouvelle base de données et, enfin, la suppression de l'ancienne base de données. Vous pouvez créer une base de données à l'origine en utilisant le SQLite Manager plug-in FireFox pour exécuter vos instructions SQL de création.

L'autre option consiste à créer une base de données interne à partir d'un fichier sql. Ce n'est pas aussi rapide, mais le retard serait probablement imperceptibles aux utilisateurs si la base de données a seulement quelques tables. Mises à niveau sont déclenchées en modifiant le numéro de version de base de données dans la résolution / valeurs / fichier strings.xml. Mises à niveau seraient alors réalisées par le traitement d'un fichier sql de mise à niveau. Les données contenues dans la base de données ne changeront pas, sauf si son contenant est éliminé, par exemple suppression d'une table.

L'exemple ci-dessous montre comment utiliser ces deux méthodes.

Voici un fichier create_database.sql exemple. Il doit être placé dans le dossier actif du projet pour la méthode interne ou copié dans le « Exécuter SQL » de SQLite Manager pour créer la base de données pour la méthode externe (REMARQUE:. Notez le commentaire au sujet de la table requise par 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"; 

Voici un fichier update_database.sql exemple. Il doit être placé dans le dossier actif du projet pour la méthode interne ou copié dans le « Exécuter SQL » de SQLite Manager pour créer la base de données pour la méthode externe (NOTE:. Notez que les trois types des commentaires SQL seront ignorés par l'analyseur SQL qui est inclus dans cet exemple.)

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

Voici une entrée à ajouter au fichier /res/values/strings.xml pour le numéro de version de base de données.

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

Voici une activité qui accède à la base de données et utilise ensuite. ( Remarque:. Vous pouvez exécuter le code de base de données dans un thread séparé si elle utilise beaucoup de ressources )

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

    }
}

Voici la classe d'assistance de base de données où la base de données est créée ou mise à jour si nécessaire. (REMARQUE:. Android nécessite que vous créez une classe qui étend SQLiteOpenHelper afin de travailler avec une base de données 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.
     */

}

Voici la classe FileHelper qui contient des méthodes pour copier des fichiers de flux d'octets et l'analyse des fichiers 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 bibliothèque rend cette tâche SQLiteAssetHelper vraiment simple.

Il est facile d'ajouter une dépendance gradle (mais un pot est également disponible pour Ant / Eclipse), et en même temps que la documentation qu'elle se trouve à l'adresse:
https://github.com/jgilfelt/android-sqlite-asset-helper

Remarque:. Ce projet n'est plus maintenu comme indiqué sur le lien ci-dessus Github

Comme expliqué dans la documentation:

  1. Ajoutez la dépendance au fichier de construction gradle de votre module:

    dependencies {
        compile 'com.readystatesoftware.sqliteasset:sqliteassethelper:+'
    }
    
  2. Copiez la base de données dans le répertoire actif, dans un sous-répertoire appelé assets/databases. Par exemple:
    assets/databases/my_database.db

    (En option, vous pouvez compresser la base de données dans un fichier zip tel que assets/databases/my_database.zip. Ce n'est pas nécessaire, puisque l'APK est comprimé dans son ensemble déjà.)

  3. Créer une classe, par exemple:

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

Je crois que la meilleure et la nouvelle façon jusqu'à aujourd'hui est d'utiliser la classe SQLiteAssetHelper.

Ce tutoriel vous guide parfaitement dans importation et utilisation de base de données externe dans Android

  

La bibliothèque Android vous permet de construire votre SQLite   base de données dans votre ordinateur de bureau, et d'importer et l'utiliser dans votre   application Android. Nous allons créer une application simple à démontrer   l'application de cette bibliothèque.

     

Étape 1 : Créer une base de données quotes.db en utilisant votre favori SQLite   l'application de base de données (DB Browser pour SQLite est une coupe portable   freeware de plate-forme, qui peut être utilisé pour créer et modifier SQLite   bases de données). Créer une table « quotes » avec une seule colonne « citation ».   Insérez quelques citations au hasard dans la table « cite ».

     

Étape 2 : La base de données peut être importé dans le projet soit directement   il est, ou un fichier compressé. Le fichier compressé est recommandé, si   votre base de données est trop grande taille. Vous pouvez créer un ZIP   compression ou une compression de GZ.

     

Le nom du fichier du fichier db comprimé doit être quotes.db.zip, si vous   utilisent la compression ZIP ou quotes.db.gz, si vous utilisez GZ   compression.

     

Étape 3 : Créer une nouvelle application avec un External Database Demo   Nom du package com.javahelps.com.javahelps.externaldatabasedemo.

     

Étape 4 : Ouvrez le build.gradle (Module: app) fichier et ajouter ce qui suit   dépendance.

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

Une fois que vous avez enregistré le fichier, cliquez sur le Synchronize build.gradle « Sync Now »   mettre à jour un lien entre le projet. Vous pouvez synchroniser le assets/databases, par   un clic droit sur le fichier et en sélectionnant l'option DatabaseOpenHelper DatabaseAccess ainsi.

     

Étape 5 . Faites un clic droit sur le dossier de l'application et créer un nouveau dossier actif

     

Étape 6 :. Créer une nouvelle 'bases de données' dossier dans le dossier actif

     

Étape 7 : Copiez et collez le fichier dans le ListView   dossier activity_main.xml.

     

Étape 8 : Créer une nouvelle classe onCreate

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.
     

Étape 9 : Créer une nouvelle classe et entrez le MainActivity code affiché   au dessous de. Plus de détails sur cette classe est disponible chez Advanced Android   tutoriel de base de données.

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,
     

mise à jour et supprimer toutes les lignes dans la base de données comme d'habitude. Pour plus de détails,   suivez ce lien avancée Database Android.

     

Toutes les bases de données des configurations liées sont terminées et maintenant nous devons   créer un pour afficher les <=> guillemets.

     

Étape 10 :. Ajouter un <=> dans votre <=>

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

Étape 11 : Trouver l'objet de la méthode dans <=> de <=> et nourrir les <=> citations qui sont lus   former la base de données.

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

Étape 12 :. Sauvegardez toutes les modifications et exécutez l'application

En plus de cet article, vous pouvez télécharger ici <=>

Ma solution n'utilise une bibliothèque tierce, ni vous oblige d'appeler des méthodes personnalisées sur la sous-classe pour initialiser SQLiteOpenHelper la base de données sur la création. Il prend également en charge des mises à jour de bases de données ainsi. Tout ce qui doit être fait est de sous-classe android_metadata.

Pré-requis:

  1. La base de données que vous souhaitez expédier avec l'application. Il devrait contenir une table 1x1 nommée avec un attribut locale ayant la valeur en_US en plus private les tables uniques à votre application.

Subclassing onCreate:

  1. général onUpgrade.
  2. Créer une méthode au sein de la onOpen sous-classe getReadableDatabase(). Cette méthode contient la logique pour copier le contenu de base de données à partir du fichier de base de données dans le dossier "actifs à la base de données créée dans le cadre du dossier de candidature.
  3. Remplacer getWritableDatabase(), onCreate() et méthodes de <=> <=>.

Assez dit. Ici va la sous-classe <=>:

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

Enfin, pour obtenir une connexion de base de données, il suffit d'appeler ou <=> sur la <=> sous-classe et <=> se chargera de la création d'un db, copiez le contenu de db à partir du fichier spécifié dans le dossier « actifs », si la base de données n'existe pas.

En bref, vous pouvez utiliser la sous-classe pour accéder à la <=> db expédié dans les actifs dossier comme vous le feriez pour utiliser une base de données qui est initialisé à l'aide de requêtes SQL dans la méthode <=>.

Expédition l'application avec un fichier de base de données, dans Android Studio 3.0

Transport de l'application avec un fichier de base de données est une bonne idée pour moi. L'avantage est que vous n'avez pas besoin de faire une initialisation complexe, qui coûte parfois beaucoup de temps, si votre ensemble de données est énorme.

Étape 1: Préparer le fichier de base de données

Demandez à votre fichier de base de données prêt. Il peut être un fichier .db ou un fichier .sqlite. Si vous utilisez un fichier .sqlite, tout ce que vous devez faire est de changer le nom d'extension de fichier. Les étapes sont les mêmes.

Dans cet exemple, j'ai préparé un fichier appelé testDB.db. Il dispose d'une table et quelques exemples de données dans comme ça entrer la description d'image ici

Étape 2: Importez le fichier dans votre projet

Créer le dossier actif si vous ne l'avez pas eu. Ensuite, copiez et collez le fichier de base de données dans ce dossier

 ici

Étape 3: Copiez le fichier dans le dossier de données de l'application

Vous devez copier le fichier de base de données dans le dossier de données de l'application afin de faire une autre interaction avec elle. Ceci est une action d'une fois (d'initialisation) pour copier le fichier de base de données. Si vous appelez ce code plusieurs fois, le fichier de base de données dans le dossier de données sera remplacé par celui dans le dossier actif. Ce processus Ecraser est utile lorsque vous souhaitez mettre à jour la base de données à l'avenir lors de la mise à jour de l'application.

Notez que lors de la mise à jour de l'application, ce fichier de base de données ne sera pas modifiée dans le dossier de données de l'application. Seule désinstallation supprimer.

Le fichier de base de données doit être copié dans le dossier /databases. Ouvrez l'Explorateur de fichiers de périphériques. Entrez l'emplacement data/data/<YourAppName>/. Ceci est le dossier de données par défaut de l'application mentionnée ci-dessus. Et par défaut, le fichier de base de données sera dans un autre dossier bases de données appelé sous ce répertoire

 ici

Maintenant, le processus de copie de fichier est à peu près comme le Java ce que fait. Utilisez le code suivant pour faire le copier coller. Voici le code d'initiation. Il peut également être utilisé pour mettre à jour (en réécrivant) le fichier de base de données à l'avenir.

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

Ensuite, actualisez le dossier pour vérifier le processus de copie

 ici

Étape 4: Créer la base aide ouverte

Créer une sous-classe pour SQLiteOpenHelper, avec connexion, fermer, chemin, etc. Je l'ai appelé 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) {
    }
}

Étape 5: Créer une classe de haut niveau pour interagir avec la base de données

Ce sera la classe en lecture et écriture de votre fichier de base de données. En outre il y a une requête de l'échantillon pour imprimer la valeur dans la base de données.

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

Étape 6: Test en cours d'exécution

Testez le code en exécutant des lignes de code suivantes.

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

Appuyez sur le bouton Exécuter et remonter le moral!

 ici

En Novembre 2017 Google a publié le Bibliothèque Persistance Chambre

De la documentation:

  

La bibliothèque de persistance de la chambre fournit une couche d'abstraction sur SQLite   pour permettre l'accès de base de données couramment tout en exploitant toute la puissance de   SQLite.

     

La bibliothèque vous permet de créer un cache de données de votre application sur un périphérique   qui exécute votre application. Ce cache, qui sert unique de votre application   source de la vérité, permet aux utilisateurs de visualiser une copie cohérente de la clé   l'information dans votre application, que les utilisateurs ont un   connexion Internet.

La base de données de chambre a un rappel lorsque la base de données est créée ou ouverte. Vous pouvez utiliser la fonction de rappel créer pour remplir votre base de données.

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

.

D'après ce que je vous ai vu devriez embarquerai une base de données qui a déjà la configuration des tables et des données. Toutefois, si vous voulez (et en fonction du type d'application que vous avez) vous pouvez autoriser « la mise à niveau option de base de données ». Alors ce que vous faites est de télécharger la dernière version SQLite, obtenir la dernière Insérer / Créer des déclarations d'un fichier texte hébergé en ligne, exécutez les instructions et faire un transfert de données de l'ancien db vers le nouveau.

Enfin je l'ai fait !! Je l'ai utilisé ce lien aide à l'aide de votre propre SQLite base de données dans les applications Android , mais a dû changer un peu.

  1. Si vous avez beaucoup de paquets, vous devez mettre le nom du package maître ici:

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

  2. a changé la méthode qui copie la base de données à partir du dossier local vers un dossier émulateur! Il y avait un problème quand ce dossier n'existait pas. Alors tout d'abord, il faut vérifier le chemin et si elle n'y est pas, il devrait créer le dossier.

  3. Dans le code précédent, la méthode n'a jamais été appelé copyDatabase lorsque la base de données n'existait pas et la méthode fait exception checkDataBase. alors j'ai changé le code un peu.

  4. Si votre base de données ne dispose pas d'une extension de fichier, ne pas utiliser le nom de fichier avec un.

il fonctionne bien pour moi, je l'espère whould être utile pour u too

    package farhangsarasIntroduction;


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

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

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

import android.util.Log;


    public class DataBaseHelper extends SQLiteOpenHelper{

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

    private static String DB_NAME = "farhangsaraDb";

    private SQLiteDatabase myDataBase;

    private final Context myContext;

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

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

    }   

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

        boolean dbExist;
        try {

             dbExist = checkDataBase();


        } catch (SQLiteException e) {

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

        }

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

            try {

                copyDataBase();


            } catch (IOException e) {

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

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


    }

    }

    /**
      * Check if the database already exist to avoid re-copying the file each time you open the application.
      * @return true if it exists, false if it doesn't
      */
    private boolean checkDataBase(){

    SQLiteDatabase checkDB = null;

    try{
        String myPath = DB_PATH +"/"+ DB_NAME;

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

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

    }

    if(checkDB != null){

    checkDB.close();

    }

    return checkDB != null ? true : false;
    }

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



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

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

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

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

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



    }



    @Override
    public synchronized void close() {

        if(myDataBase != null)
        myDataBase.close();

        super.close();

    }

    @Override
    public void onCreate(SQLiteDatabase db) {

    }



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

    }

     you to create adapters for your views.

}

À l'heure actuelle il n'y a aucun moyen de créer au préalable une base de données SQLite pour expédier avec votre apk. Le mieux que vous pouvez faire est de sauvegarder le SQL approprié en tant que ressource et les exécuter à partir de votre application. Oui, cela conduit à la duplication des données (même information existe en tant que resrouce et comme une base de données), mais il n'y a pas d'autre moyen en ce moment. Le seul facteur atténuant est le fichier apk est compressé. Mon expérience est 908KB comprime à moins de 268KB.

Le fil ci-dessous a la meilleure discussion / solution que j'ai trouvé avec le code bon exemple.

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

J'emmagasinés mon CREATE en tant que ressource de chaîne à lire avec Context.getString () et a couru avec SQLiteDatabse.execSQL ().

Je mis en mémoire les données pour mes inserts dans res / raw / inserts.sql (j'ai créé le fichier sql, 7000+ lignes). En utilisant la technique à partir du lien ci-dessus je suis entré dans une boucle, lisez la ligne de fichiers en ligne et concactenated les données sur « INSERT INTO VALEUR TBL » et a fait une autre SQLiteDatabase.execSQL (). Aucun sens pour sauver 7000 s « INSERT INTO VALEUR tbl » quand ils peuvent juste être concactenated sur.

Il faut une vingtaine de secondes sur l'émulateur, je ne sais pas combien de temps cela prendrait un vrai téléphone, mais il arrive qu'une seule fois, lorsque l'utilisateur démarre d'abord l'application.

expédition la base de données à l'intérieur du apk, puis la copie à doublera la /data/data/... taille de la base de données (1 apk, 1 data/data/...), et augmentera la taille de apk (bien sûr). Donc, votre base de données ne devrait pas être trop grand.

Android fournit déjà une approche consciente version de gestion de base de données. Cette approche a été tiré parti dans le cadre BARACUS pour les applications Android.

Il vous permet de gérer le long de la base de données le cycle de vie de version d'une application, beeing capable de mettre à jour la base de données sqlite de toute version antérieure à l'actuel.

En outre, il vous permet d'exécuter chaud -backups et de récupération à chaud du SQLite.

Je ne suis pas sûr à 100%, mais une récupération à chaud pour un dispositif spécifique peut vous permettre d'expédier une base de données préparée dans votre application. Mais je ne suis pas sûr de la base de données format binaire qui peut être spécifique à certains appareils, les fournisseurs ou les générations de périphériques.

Étant donné que la substance est Licence Apache 2, vous pouvez réutiliser une partie du code, qui se trouve sur github

EDIT:

Si vous voulez seulement expédier des données, vous pourriez envisager instanciation et persistant POJO aux applications d'abord commencer. BARACUS a un support intégré pour cela (intégré dans la mémoire de valeur de clé pour infos de configuration, par exemple « APP_FIRST_RUN » plus un crochet d'amorçage après le contexte afin d'exécuter des opérations de post-lancement du contexte). Cela vous permet d'avoir des données couplées serré livrées avec votre application; dans la plupart des cas adapté à mes cas d'utilisation.

Si les données requises ne sont pas trop grandes (limites que je ne savez pas comment, dépendra beaucoup de choses), vous pouvez également télécharger les données (en XML, JSON, peu importe) à partir d'un site web / webapp. Après avoir reçu, exécuter les instructions SQL en utilisant les données reçues en créant vos tables et insérer les données.

Si votre application mobile contient beaucoup de données, il pourrait être plus facile par la suite de mettre à jour les données dans les applications installées avec des données plus précises ou des changements.

J'ai écrit un bibliothèque pour simplifier ce processus.

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

Il va créer une base de données fichier assets/databases/myDb.db. De plus, vous obtiendrez toutes les fonctionnalités:

  • Base de données de charge à partir du fichier
  • Accès Synchronisé à la base de données
  • Utilisation sqlite-android par requery, distribution spécifique Android des dernières versions de SQLite.

github .

J'utilise ORMLite et ci-dessous le code a fonctionné pour moi

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

    }
}

S'il vous plaît noter, Le code extrait le fichier de base de données à partir d'un fichier zip dans les actifs

Je l'ai modifié la classe et les réponses à la question et a écrit une classe qui permet de mettre à jour la base de données 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;
    }
}

Utilisation d'une classe.

Dans la classe d'activité, déclarer des variables.

private DatabaseHelper mDBHelper;
private SQLiteDatabase mDb;

Dans le procédé onCreate, écrire le code suivant.

mDBHelper = new DatabaseHelper(this);

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

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

Si vous ajoutez un fichier de base de données vers le dossier res / raw utilisent alors la modification suivante de la 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

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top