Wheeel logo Całkiem niedawno zacząłem pisać aplikację na Androida. Wheeel, bo tak nazywa się aplikacja ma pomagać rowerzystom we Wrocławiu, który używają “roweru miejskiego” (rowerów wypożyczanych ze stojaków ustawianych przez firmę NextBike). Aplikacja głównie ma się zajmować liczeniem czasu wypożyczenia roweru oraz sugerowaniem stojaka, do którego można przypiąć rower.

Podczas pisania aplikacji oczywiście pojawiło się parę problemów (:

Inicjalizacja bazy danych

Aplikacja potrzebuje danych tylko do odczytu, po zainstalowaniu dane muszą być od razu dostępne. Jest wiele sposobów rozwiązania tego problemu, np. można razem z aplikacją dostarczać gotową bazę sqlite i kopiować ją przy tworzeniu nowej bazy na androidzie.

Ja jednak zdecydowałem się na rozwiązanie prostsze w implementacji, mianowicie szereg insertów SQL. Okazuje się jednak, że SQLiteDatabase.execSQL() nie wspiera wielu instrukcji sql w jednym wywołaniu, niby wszystko jest ładnie opisane w dokumentacji do metody execSQL ale musiałem poświęcić trochę czasu na dochodzenie do istoty problemu.

@Override
public void onCreate(SQLiteDatabase db) {
    db.execSQL(CREATE_DB_STMT);
    seedData(db);
}
private void seedData(SQLiteDatabase db) {
    try {
        db.beginTransaction();
        for(int i = 0; i < INSERTS.length; i++) {
            db.execSQL(INSERTS[i]);
        }
        db.setTransactionSuccessful();
    } finally {
        db.endTransaction();
    }
}

Drawable jako własny marker dla OverlayItem

Android ma genialne wsparcie dla aplikacji wykorzystujacych Google Maps. Stworzono nawet osobny widok MapView, dzięki któremu osadzenie mapy we własnej aplikacji nie nastręcza większych trudności. Jednak oznaczanie własnych punktów na mapie jest już nieznacznie trudniejsze, chociaż też do zrobienia (:

Problem pojawił się gdy dla istniejącego na mapie punktu chcemy zmienić ikonkę, która jest przy nim prezentowana. OverlayItem ma nawet specjalną metodę, która do tego służy: OverlayItem.setMarker(Drawable marker). Jednak po wywołaniu tej metody nie otrzymujemy zamierzonego efektu - punkt, dla którego zmienilismy marker znika z mapy (:.

Kolejny raz dokładne przeczytanie dokumentacji okazało się pomocne (:. W dokumentacji do klasy Drawable przczytać możemy, że wywołanie metody setBounds() jest wymagane. Poniższy fragment kodu rozwiązuje problem - punkt zostaje poprawnie oznaczony na mapie.

private void prepareMarkers(Drawable defaultM, Drawable nearestM) {
    nearestMarker = nearestM;
    defaultMarker = defaultM;
    nearestMarker.setBounds(0, 0, 
            nearestMarker.getIntrinsicWidth(), 
            nearestMarker.getIntrinsicHeight());
    defaultMarker.setBounds(0, 0, 
            defaultMarker.getIntrinsicWidth(), 
            defaultMarker.getIntrinsicHeight());
}

Kod całej aplikacji dostępny jest na githubie. Logo dla aplikacji zostało ściągnięte ze strony Useful Free Stuff.