Собственная база данных на Android с возможностью обновления


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




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

Почему не работает обычный способ.

В примерах которые можно найти в интернете в большем обилии, при обращении к вашей БД, приходится вызывать её с помощью метода createDatabase(), которая копирует вашу заранее созданную базу в папку приложения. Но при вызове данного метода Android не обращается к методу onUpdate() , потому даже если вы измените версию базы, ничего не произойдёт, так как не произойдёт сравнение её версий. 
Метод onUpdate() вызывается только в случае обращения к базе данных с помощью методов getWritableDatabase() или getReadableDatabase(), в этом случае база создается и копируется если не существовала ранее и вызывается метод onUpdate(),если база уже существовала. Но если вы попробуете в методе onUpdate() удалить прошлую версию БД - приложение закроется с крешем, так как метод обновления будет вызван (а значит и база будет удалена) раньше чем будет создана новая, а потому получить доступ к несуществующей в этот момент базе не удастся.

Как обновить собственную базу данных.

Для того, чтобы удалить старую и обновить БД  придется вручную контролировать её версию и сделать это до вызова метода onUpdate(), чтобы избежать попытки её открытия до её фактического создания. Для этого будем использовать собственный метод обновления, а версии хранить и контролировать с помощью SharedPreferences.
Для использования собственной базы данных в Android создайте новый класс ExternalDbOpenHelper и поместите в него приведённый ниже код.




import android.content.Context;
import android.content.SharedPreferences;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.preference.PreferenceManager;

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

/**
 * Created by AwesomeDevelop on 24.12.2014.
 */
public class ExternalDbOpenHelper extends SQLiteOpenHelper
    {
        private static final String DATABASE_NAME = "db.sqlite3"; // Название файла с БД
        private static final int DATABASE_VERSION = 1;            //Версия БД
        private static final String SP_KEY_DB_VER = "db_ver";
        private final Context mContext;

        public ExternalDbOpenHelper(Context context, String DB_NAME) {
            super(context, DATABASE_NAME, null, DATABASE_VERSION);
            mContext = context;
            initialize();
        }

        /**
         * Инициализация БД. Создание новой если ранее не существовала.
         */
        private void initialize() {
            if (databaseExists()) {
                SharedPreferences prefs = PreferenceManager
                        .getDefaultSharedPreferences(mContext);
                int dbVersion = prefs.getInt(SP_KEY_DB_VER, 1);
                if (DATABASE_VERSION != dbVersion) {
                    File dbFile = mContext.getDatabasePath(DATABASE_NAME);
                    if (!dbFile.delete()) {
                       // Log.w(TAG, "Невозможно обновить БД");
                    }
                }
            }
            if (!databaseExists()) {
                createDatabase();
            }
        }

        /**
         * Проверка существования файла БД. Если существует - возвращает true.
         * @return
         */
        private boolean databaseExists() {
            File dbFile = mContext.getDatabasePath(DATABASE_NAME);
            return dbFile.exists();
        }

        /**
         * Создание БД, копирование файла из Assets.
         */
        private void createDatabase() {
            String parentPath = mContext.getDatabasePath(DATABASE_NAME).getParent();
            String path = mContext.getDatabasePath(DATABASE_NAME).getPath();

            File file = new File(parentPath);
            if (!file.exists()) {
                if (!file.mkdir()) {
                  //  Log.w(TAG, "Невозможно создать папку БД");
                    return;
                }
            }

            InputStream is = null;
            OutputStream os = null;
            try {
                is = mContext.getAssets().open(DATABASE_NAME);
                os = new FileOutputStream(path);

                byte[] buffer = new byte[1024];
                int length;
                while ((length = is.read(buffer)) > 0) {
                    os.write(buffer, 0, length);
                }
                os.flush();
                SharedPreferences prefs = PreferenceManager
                        .getDefaultSharedPreferences(mContext);
                SharedPreferences.Editor editor = prefs.edit();
                editor.putInt(SP_KEY_DB_VER, DATABASE_VERSION);
                editor.commit();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if (is != null) {
                    try {
                        is.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                if (os != null) {
                    try {
                        os.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }

        @Override
        public void onCreate(SQLiteDatabase db) {
        }

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





Для работы данного класса, вам необходимо только указать название файла с созданной вами базой данных и её версию. Как только версия БД будет увеличена - старая её версия будет удалена, а новый файл БД скопирован. Но не пробуйте понизить версию, как и при обычном использовании будет получена ошибка о невозможности выполнить DownGrade и приложение будет закрыто. 
Работа с БД осуществляется стандартными для Android способами, потому вы можете работать с ней, как с стандартной Sqlite базой.

Открытие БД.
 ExternalDbOpenHelper dbOpenHelper = new ExternalDbOpenHelper(this, DB_NAME);

 SQLiteDatabase database= dbOpenHelper.getWritableDatabase();

Получить данные можно, к примеру, вот так:
data = new ArrayList();

        Cursor dataCursor = database.query(
                TABLE_NAME,
                new String[] { DATA_NAME,DATA_IMAGE},
                null, null, null, null,
                DATA_NAME);
        dataCursor.moveToFirst();


        if(!dataCursor.isAfterLast()){
            do {
                String image =dataCursor.getString(1);
                String name = dataCursor.getString(0);
                data.add(new BrandData(name,image));

            } while (dataCursor.moveToNext());
        }
        dataCursor.close();

И так, для использование заранее созданной базы данных необходимо:
  1. Создать файл базы данных Sqlite с любым наполнением, о том как это сделать можно прочитать тут, а для создания использовать Navicat .
  2. Поместить созданный файл в папку Assets.
  3. Создать класс ExternalDbOpenHelper и поместить в него код, приведённый в статье.
  4. Использовать вашу БД стандартными способами, описанными в официальной документации



Share on Google Plus

Автор Unknown

Android разработчик и Google-фил. В рабочее время пишу код, в свободное - его читаю. Google+

Комментариев нет:

Отправить комментарий