środa, 28 kwietnia 2010

Android a baza danych cz. 2

Tworzenie pliku bazy danych

Można przygotować gotowy plik bazy danych i dystrybuować go razem z aplikacją. Dzięki temu przy pierwszym uruchomieniu nie będzie trzeba czekać wieków na wypełnienie tabel. 

Na początku należy stworzyć plik bazy danych. W tym przypadku korzystamy z sqlite3.exe znajdującego się w AndroidSDK\tools
W konsoli tworzymy bazę danych:

sqlite3.exe database.db

a następnie tworzymy tabele

sqlite>.read create.sql

i wypełniamy danymi

sqlite>.read data.sql

Oczywiście w pliku create.sql jest SQL tworzący tabele, a w data.sql inserty. Trzeba pamiętać o dodaniu tabeli android_metadata - o tym w poprzednim poście. Tak oto przygotowany plik database.db kopiujemy do res/raw naszej aplikacji. Teraz należy sprawić aby przy starcie aplikacji plik bazy został skopiowany do systemu plików androida.

Kopiowanie bazy
Baza danych naszej aplikacji znajduje się na androidzie w katalogu /data/data/nazwa.pakietu/databases/



private static final String DB_PATH ="/data/data/pl.pawelzieba.myapplication/databases/";
private static final int[] dbFiles = {R.raw.database};

void copyDataBase() {
    OutputStream out = null;
    try {
        Log.d(TAG, "Kopiowanie bazy danych ");
        this.getReadableDatabase();
        InputStream in = null;
        out = new FileOutputStream(DB_PATH + DATABASE_NAME);
        byte[] buffer;
        int total = 0;
        for (int i = 0; i < dbFiles.length; i++) {
            try {
                in = mCtx.getResources().openRawResource(dbFiles[i]);
                int size = in.available();
                total += size;
                buffer = new byte[size];
                in.read(buffer);
                out.write(buffer);
            } finally {
                if (in != null)
                    in.close();
            }
        }
        Log.d(TAG, "Kopiowanie zakonczone, calkowity rozmiar pliku bazy danych: " + total);
    } catch (NotFoundException e) {
        e.printStackTrace();
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try {
            if (out != null)
                out.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}


Oczywiście trzeba zadbać o wywołanie tej metody przy pierwszym uruchomieniu aplikacji (poprzedni post). Jeżeli korzystamy z SQLiteOpenHelper to należy zwrócić uwagę na to, że metoda onUpdate(SQLiteDatabase db, int oldVersion, int newVersion) nie będzie działała przy tym rozwiązaniu i trzeba samemu zaimplementować obsługę wersji bazy danych.


Niestety zaprezentowane podejście dalej posiada pewną wadę. Dane wciąż są duplikowane - baza znajduje się w swoim docelowym położeniu i w resources. Jedynym rozwiązaniem wydaje się pobieranie bazy z internetu. 


W następnej części opiszę co zrobić gdy baza danych jest większa niż 1MB.

4 komentarze:

Unknown pisze...

Jak duże mogą być bazy na androidzie, chodzi mi o ilość rekordów. Czy 100 000 rekordów to byłby jakiś problem ?

dziobas pisze...

Problemem może być tylko wielkość aplikacji na telefonie. Użytkownicy w razie braku pamięci odinstalują najpierw "najcięższe" aplikacje. Słyszałem o aplikacji, która miała chyba 20MB i działała - to był jakiś słownik. Jeśli chodzi o 100 000 rekordów to problem może być z czasem wykonywania się zapytań, ale proste zapytania SQL powinny się wykonywać w mgnieniu oka. Kiedyś robiłem test na około 16 000 rekordów w liście i nawet filtrowanie działało szybko.

Anonimowy pisze...

Ja miałem spory problem otworzyć już gotową bazę, która zajmowała ponad 1MB ale udało mi się spakować a potem rozpakować zip-em według instrukcji znalezionej na:

http://axlinux-programming.blogspot.com/2010/10/wasna-baza-danych-sqlite-w-android.html

dziobas pisze...

Jeżeli uda się spakować do pliku mniejszego niż 1MB to ok, ale jak się nie da? Niestety trzeba ciąć.