- Pobierz pliki czcionek, których potrzebujesz
- Przekonwertuj czcionki do formatu .ttf (jeśli są w innym)
- Utwórz katalog czcionek w swoim projekcie (jeśli go nie ma)
- Wybierz menu konekstowe z katalogu res
- New -> Android Resource Directory
- Recource type: font
- Dodaj do katalogu font swoje czcionki
- Wprowadź swoje czcionki do projektu, np.
- Dodaj je do swojego stylu: <item name="android:fontFamily">@font/pt_sans</item> (API >=16)
- Dodaj je do swojego obiektu tekstowego w layout: android:fontFamily="@font/pt_sans"
- Dodaj je w kodzie swojej aplikacji do obiektu tekstowego
czwartek, 9 sierpnia 2018
Jak ustawić własne czcionki w aplikacji
wtorek, 7 sierpnia 2018
Exception - org.json.JSON.typeMismatch
Dlaczego wystąpił?
Myślałam, że parsowany string to JSONObject a to był JSONArray.
Plik .json (a właściwie String) zrobiłam sama, więc wystarczyło usunąć [ ] z początku i końca.
Myślałam, że parsowany string to JSONObject a to był JSONArray.
Plik .json (a właściwie String) zrobiłam sama, więc wystarczyło usunąć [ ] z początku i końca.
niedziela, 5 sierpnia 2018
Room - kilka słów o przechowywaniu danych
- Dodaj odpowiednie zależności do build.gradle(Module: app)
def room_version = "1.1.1"
implementation "android.arch.persistence.room:runtime:$room_version"
annotationProcessor "android.arch.persistence.room:compiler:$room_version"
testImplementation "android.arch.persistence.room:testing:$room_version" - Zsynchronizuj build.gradle
- kliknij prawym przyciskiem na build.gradle
- wybierz Synchronize build.gradle
- Dodaj klasę obiektu, który będzie reprezentował tabelę
- Daj jej annotację @Entity
- Dodaj kolumnę @PrimaryKey
- Dodaj pozostałe kolumny
- Dodaj gettery i settery elementów obiektu (na potrzeby Room)
@Entity
public class StoryObject {
@PrimaryKey
private int storyId;
@ColumnInfo(name = "main_text")
private String mainText; - Stwórz interfejs z metodami dostępu do bazy - DAO
- Daj jej annotację @Dao
- Dodaj metody dostępu (napisane w SQL)
@Dao
public interface StoryDao {
@Query("SELECT * FROM story")
List<StoryObject> getAll();
@Insert
void insertAll(StoryObject... objects);
@Delete
void delete(StoryObject object);
} - Stwórz klasę (abstract) bazy danych
- Dodaj jej annotację @Database i przypisz klasy, które ją reprezentują (entities)
- Dodaj metodę (abstract), która zwróci odpowiedni obiekt Dao
@Database(entities = {StoryObject.class}, version = 1)
public abstract class StoryDatabase extends RoomDatabase {
public abstract StoryDao getStoryDao();
} - W kodzie aplikacji wywołaj budowanie bazy danych
StoryDatabase db = Room.databaseBuilder(getApplicationContext(),
StoryDatabase.class, "story_database").build();
poniedziałek, 30 lipca 2018
Release – checklista
- Change log - powiązanie z zadaniami (historyjkami) - scope of work vs lista commitów
- Kiedy wypuszczono produkt
- Jaki jest tag w repozytorium
- Jakie były testy i gdzie są raporty
- Gdzie znajduje się backup
- Dokumentacja i konfiguracja - aktualne wersje
sobota, 28 lipca 2018
Android - testy wydania
Kilka dni temu wysłałam kolejną wersję aplikacji, jeszcze ciągle w wersji próbnej, testowej, w trakcie pracy. Ogólnie wydawałoby się - nic poważnego. Ale jednak wysłałam ją komuś - to jest poważne, powinnam być za to odpowiedzialna. Zrozumiałam, że nie zrobiłam jej wcześniej absolutnie podstawowych testów wydania. Nawet nie mam przygotowanych... Pora to zmienić.
Testy wydania aplikacji - android (ogólne)
- Aplikacja aktualizuje się z poprzedniej wersji do nowej (update)
- Aplikacja w aktualnej wersji może być zainstalowana na "czystym" urządzeniu (na takim, na którym nie jest zainstalowana) (instal)
- Aplikacja po wybraniu ikony włącza się i pokazuje ekran startowy (start)
- Aplikacja po wybraniu przycisku cofinij wyłącza się (end)
- Aplikacja wykonuje podstawową funkcję (work)
- Aplikacja aktualizuje się do poprzedniej wersji (downgrade)
Testy wydania aplikacji - android (dodatkowe)
- Aplikacja działa bez internetu (internet permission)
- brak wyjątków
- informacja o braku połączenia
- niezakłócone działanie
- Aplikacja działa przy obracaniu ekranu (orientation)
- dźwięk
- obraz
- funkcje
- ...
poniedziałek, 23 lipca 2018
Jak dodać odtwarzacz audio?
- Dodaj do pliku build.gradle -> dependencies
compile 'com.google.android.exoplayer:exoplayer:r2.2.0' - Dodaj do swojej aktywności
implements View.OnClickListener, ExoPlayer.EventListener - Dodaj do swojej aktywności obsługującej audio zmienne ExoPlayer
private SimpleExoPlayer mExoPlayer;
private SimpleExoPlayerView mPlayerView;
private static MediaSessionCompat mMediaSession;
private PlaybackStateCompat.Builder mStateBuilder;
private NotificationManager mNotificationManager; - Zainicjalizuj wstępnie zmienne
mPlayerView = (SimpleExoPlayerView) findViewById(R.id.playerView);
mPlayerView.setPlayer(mExoPlayer);
initializeMediaSession();
initializePlayer(Uri.parse(audioPath)); - Zaimplementuj inicjalizację MediaSession
mMediaSession = new MediaSessionCompat(this, this.getClass().getSimpleName());
mMediaSession.setFlags(
MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS |
MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS);
mMediaSession.setMediaButtonReceiver(null);
mStateBuilder = new PlaybackStateCompat.Builder()
.setActions(
PlaybackStateCompat.ACTION_PLAY |
PlaybackStateCompat.ACTION_PAUSE |
PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS |
PlaybackStateCompat.ACTION_PLAY_PAUSE);
mMediaSession.setPlaybackState(mStateBuilder.build());
mMediaSession.setCallback(new MySessionCallback());
mMediaSession.setActive(true); - Zaimplementuj podklasę MySessionCallback
@Override
public void onPlay() {
mExoPlayer.setPlayWhenReady(true);
}
@Override
public void onPause() {
mExoPlayer.setPlayWhenReady(false);
}
@Override
public void onSkipToPrevious() {
mExoPlayer.seekTo(0);
} - Zaimplementuj inicjalizację playera
if (mExoPlayer == null) {
// Create an instance of the ExoPlayer.
TrackSelector trackSelector = new DefaultTrackSelector();
LoadControl loadControl = new DefaultLoadControl();
mExoPlayer = ExoPlayerFactory.newSimpleInstance(this, trackSelector, loadControl);
mPlayerView.setPlayer(mExoPlayer);
// Set the ExoPlayer.EventListener to this activity.
mExoPlayer.addListener(this);
// Prepare the MediaSource.
String userAgent = Util.getUserAgent(this, "ClassicalMusicQuiz");
MediaSource mediaSource = new ExtractorMediaSource(mediaUri, new DefaultDataSourceFactory(
this, userAgent), new DefaultExtractorsFactory(), null, null);
mExoPlayer.prepare(mediaSource);
mExoPlayer.setPlayWhenReady(true);
} - Zaimplementuj funkcję zamykania playera
mNotificationManager.cancelAll();
mExoPlayer.stop();
mExoPlayer.release();
mExoPlayer = null; - Dodaj funkcję zamykania playera do odDestroy()
super.onDestroy();
releasePlayer();
mMediaSession.setActive(false); - Zaimplementuj funkcję onPlayerStateChanged()
if((playbackState == ExoPlayer.STATE_READY) && playWhenReady){
mStateBuilder.setState(PlaybackStateCompat.STATE_PLAYING,
mExoPlayer.getCurrentPosition(), 1f);
} else if((playbackState == ExoPlayer.STATE_READY)){
mStateBuilder.setState(PlaybackStateCompat.STATE_PAUSED,
mExoPlayer.getCurrentPosition(), 1f);
}
mMediaSession.setPlaybackState(mStateBuilder.build());
showNotification(mStateBuilder.build()); - Zaimplementuj MediaReceiver
public static class MediaReceiver extends BroadcastReceiver {
public MediaReceiver() {
}
@Override
public void onReceive(Context context, Intent intent) {
MediaButtonReceiver.handleIntent(mMediaSession, intent);
}
} - Dodaj do manifestu aktywność obsługującą odtwarzacz
<activity android:name=".QuizActivity"
android:launchMode="singleTop"/>
<receiver android:name=".QuizActivity$MediaReceiver">
<intent-filter>
<action android:name="android.intent.action.MEDIA_BUTTON" />
</intent-filter>
</receiver> - Przygotuj layout uwzględniający SimpleExoPlayerView
<com.google.android.exoplayer2.ui.SimpleExoPlayerView
android:id="@+id/playerView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="0dp"
android:layout_marginRight="0dp"
android:layout_marginBottom="0dp"
android:layout_marginLeft="0dp"/>
niedziela, 22 lipca 2018
Jak przechowywać dane - json
Jedną z możliwości przechowywania danych jest plik w formacie .json (JavaScript Object Notation).
Cechy w porównaniu z XML i JAML
Jak zastosować?
Stworzyć obiekt .java, który będzie odczytywał dane, np.:
private Sample(int sampleID, String composer, String title, String uri, String albumArtID) {
mSampleID = sampleID;
mComposer = composer;
mTitle = title;
mUri = uri;
mAlbumArtID = albumArtID;
}
Cechy w porównaniu z XML i JAML
- dostęp do danych w formacie JSON jest bardziej naturalny z poziomu języka JavaScript niż dostęp do tych samych danych w formacie XML
- nie jest już jednak tak naturalny dla Javy i wymaga stosowania specjalnych bibliotek
- w nowszych wersjach standardów dopuszczana jest wymiana danych za pomocą JSON-a (np. w REST)
- w praktyce zajmuje znacząco mniej miejsca niż analogiczny obiekt przesyłany za pomocą formatu XLM.
- JSON jest łatwiejszy do analizowania składni niż jego nadzbiór YAML
[ | ||||||||||||||
{ | ||||||||||||||
"name": "Toccata and Fugue in D minor", | ||||||||||||||
"id": 0, | ||||||||||||||
"uri": "asset:///toccata_fugue.mp3", | ||||||||||||||
"composer": "Johann Sebastian Bach", | ||||||||||||||
"albumArtID": "bach" | ||||||||||||||
}, | ||||||||||||||
{ | ||||||||||||||
"name": "Fur Elise", | ||||||||||||||
"id": 1, | ||||||||||||||
"uri": "asset:///fur_elise.mp3", | ||||||||||||||
"composer": "Ludwig van Beethoven", | ||||||||||||||
"albumArtID": "beethoven" | ||||||||||||||
} ] |
Jak zastosować?
Stworzyć obiekt .java, który będzie odczytywał dane, np.:
private Sample(int sampleID, String composer, String title, String uri, String albumArtID) {
mSampleID = sampleID;
mComposer = composer;
mTitle = title;
mUri = uri;
mAlbumArtID = albumArtID;
}
środa, 11 lipca 2018
java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.res.Resources android.content.Context.getResources()' on a null object reference
Co się stało?
Próbowałam inicjalizować zmienne String jeszcze przed zaczęciem funkcji, tam gdzie powinna być tylko deklaracja.
Rozwiązanie - na górze tylko geklaracje, inicjalizacja w kodzie funkcji.
Próbowałam inicjalizować zmienne String jeszcze przed zaczęciem funkcji, tam gdzie powinna być tylko deklaracja.
Rozwiązanie - na górze tylko geklaracje, inicjalizacja w kodzie funkcji.
wtorek, 10 lipca 2018
Jak dodać menu do aplikacji?
- Nadaj nazwy swoim opcjom - np. wprowadź je jako wartości w strings.xml
- Utwórz katalog zasobów dla menu:
- Kliknij prawy przyciskiem na katalog res
- Wybierz New Resource Directory
- Zmień Recource Type z value na menu
- Dodaj w katalogu plik menu.xml:
- Kliknij prawy przyciskiem na katalog menu
- Wybierz New -> Menu Resource File
- Wprowadź ustawienia opcji menu, np.:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item android:id="@+id/menu_day1"
android:orderInCategory="1"
app:showAsAction="never"
android:title="@string/menu_d1" />
</menu>
- Zaimplementuj w aktywności, która udostępnia menu funkcje onCreateOptionsMenu i onOptionsItemSelected, np.:
@Overridepublic boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.menu, menu); return true;} @Overridepublic boolean onOptionsItemSelected(MenuItem item) { return selectItem(item);} public boolean selectItem(MenuItem item) { switch (item.getItemId()) { case R.id.menu_day1: return true; case R.id.menu_day2: return true; case R.id.menu_day3: return true; case R.id.menu_day4: return true; case R.id.menu_day5: return true; default: return super.onOptionsItemSelected(item); } }
poniedziałek, 25 czerwca 2018
Co robi widget czyli kilka słów o onUpdate
Funkcja onUpdate:
public void onUpdate (Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds)
Tu definiujemy:
public void onUpdate (Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds)
- Context: obiekt typu Context, z którym aktualnie działa widget
- AppWidgetManager: obiekt typu AppWidgetManager, który umożliwi wywołanie funkcji aktualizacji - AppWidgetManager.updateAppWidget(ComponentName, RemoteViews)
- int: numery ID widgetów (jego instancji), które będą aktualizowane
Tu definiujemy:
- jak ma być skonfigurowany widget (jeśli nie ma specjalnej aktywności do konfiguracji)
- co ma zrobić widget gdy wystąpi jakieś działanie użytkownika
- jaką aktywność ma otworzyć widget (jeśli ma)
- jak mają działać elementy wigdetu, np. przyciski (jeśli je ma)
- updatePeriodMillis - update działa zgodnie z tym co zdefiniowano w pierwszej instancji widgetu (nawet jeśli druga instancja została skonfigurowana inaczej, to te ustawienia zostaną zignorowane
- AppWidgetProvider jest rozszerzeniem BroadcastReceiver co nie daje gwarancji, że gdy metoda widgetu zakończy wykonywanie, to proces będzie nadal działał
- w przypadku gdy wykonanie wszystkiego może potrwać dłużej zaleca się w metodzie onUpdate włączyć serwis
piątek, 22 czerwca 2018
Jak działa AppWidgetProvider czyli jakie widget otrzymuje sygnały i co się wtedy dzieje
AppWidgetProvider (zadeklarowany w Manifeście jako <receiver>) umożliwia odbieranie sygnałów przeznaczonych tylko dla widgetów z następujących metod:
- onUpdate()
- wywoływana automatycznie zgodnie z parametrem updatePeriodMillis
- wywoływana automatycznie przy dodawaniu widgetu, żeby np. domyślnie skofigurować widget, jeśli trzeba uruchomić serwis
- wywoływana z aktywności przy dodawaniu widgetu tylko wtedy, jeśli zostało tak zaprogramowane - programista musi zapewnić, że widget będzie w zupełności skonfigurowany, jeśli decyduje się sosać aktywność umożliwiającą konfigurację
- onAppWidgetOptionsChanged()
- wywoływana przy dodawaniu widgetu
- wywoływana przy zmianie rozmiaru widgetu
- umożliwia pokazanie lub schowanie elementów widgetu w zależności od jego rozmiaru
- wprowadzona w Android 4.1 (API 16)
- onDeleted(Context, int[])
- wywoływana gdy App Widget host zamyka widget - konkretną instancję, tylko jedną
- onEnabled(Context)
- wywoływana gdy dodawany jest pierwszy obiekt danego widgetu
- jeśli widget może mieć więcej niż jedną instancję, przy dodawaniu drugiej metoda nie jest wywoływana
- metoda odpowiednia do implementacji wszystkich funkcji, które mają się wykonać tylko raz, np. stworzenie bazy danych, szczególna konfiguracja
- onDisabled(Context)
- wywoływana gdy z App Widget host usuwana jest ostatnia instancja widgetu
- metoda odpowiednia do implementacji funkcji, które "posprzątają" po widgecie, np. usuną czasowe bazy danych
- onReceive(Context, Intent)
- wywoływana przy każdym odebraniu sygnału
- wywoływana przed każdą ze wspomnianych powyżej metod
- nie musi być implementowana - AppWidgetProvider ma domyślną implementację, która w odpowiedni sposób radzi sobie z odbieranymi sygnałami i wywołuje odpowiednie funkcje
Wygląd widgetu - zmiana rozmiaru
Widget nie musi mieć stałego, wybranego przez nas rozmiaru - może być konfigurowany przez użytkownika.
Nie musi też mieć stałych elementów - można je dopasować do wybranego rozmiaru.
Podczas zmiany rozmiaru widgetu wywoływana jest metoda onAppWidgetOptionsChanged(). To w jej treści możemy określić które elementy będą widoczne a które nie. Żeby zorientować się jaki jest aktualny (ustawiony przez użytkownika) rozmiar trzeba wywołać metodę getAppWidgetOptions(), która zwróci w odpowiedzi obiekt typu Bundle, który zawiera:
Nie musi też mieć stałych elementów - można je dopasować do wybranego rozmiaru.
Podczas zmiany rozmiaru widgetu wywoływana jest metoda onAppWidgetOptionsChanged(). To w jej treści możemy określić które elementy będą widoczne a które nie. Żeby zorientować się jaki jest aktualny (ustawiony przez użytkownika) rozmiar trzeba wywołać metodę getAppWidgetOptions(), która zwróci w odpowiedzi obiekt typu Bundle, który zawiera:
- OPTION_APPWIDGET_MIN_WIDTH - dolna granica szerokości w jednostkach dp
- OPTION_APPWIDGET_MAX_WIDTH - górna granica szerokości w jednostkach dp
- OPTION_APPWIDGET_MIN_HEIGHT - dolna granica długości w jednostkach dp
- OPTION_APPWIDGET_MAX_HEIGHT - górna granica długości w jednostkach dp
Wygląd widgetu - podstawowy projekt
Układ widgetu bazuje na klasie RemoteViews
Tworząc układ widgetu trzeba pamiętać o:
Tworząc układ widgetu trzeba pamiętać o:
- sprawdzeniu, czy wybrany układ (layout) i elementy są wspierane przez RemoteViews
- marginesach całego widgetu - widget nie powinien stykać się z krawędziami ekranu i z innymi aplikacjami (od wersji Android 4.0 (targetSdkVersion >= 14) te marginesy są ustawiane domyślnie, nie trzeba ich dodatkowo wprowadzać)
- marginesach elementów widgetu - powinny być od siebie trochę odsunięte, żeby dało się ich używać
czwartek, 21 czerwca 2018
Konfiguracja widgetu czyli metadane
Metadane określają podstawowe parametry widgetu:
- minWidth, minHeight - minimalna, domyślna przestrzeń zajmowana przez widget
- widgety zajmują na ekranie pewne zdefiniowane komórki (tak samo ustawiając ikonki aplikacji na ekranie też nie możemy ich mieć gdziekolwiek), jeśli podana wartość nie będzie odpowiadała wielkości pełnych komórek, zostanie zaokrąglona w górę, tak aby zająć pełną liczbę zdefiniowanych komórek
- minimalna wartość nie może być większa niż 4x4 komórki (żeby zachować przenoszalność widgetu na różne urządzenia)
- minResizeWidth, minResizeHeight - wielkość, poniżej której widget nie będzie nadawał się do użycia
- ustawienie tych parametrów oznacza, że użytkownik będzie mógł zmienić wielkość widgetu na mniejszy niż domyślny (ale nie mniejszy niż podany w tym parametrze)
- updatePeriodMillis - częstotliwość z jaką widget będzie wysyłał żądanie aktualizacji (onUpdate(), AppWidgetProvider )
- podana wartość jest tylko szacunkowa, system wykona aktualizację mniej więcej w tym czasie, jeśli będzie mógł
- trzeba ostrożnie dobrać ten parametr, żeby nie zużywać za dużo baterii
- sysem wybudzi urządzenie z uśpienia gdy nadejdzie czas aktualizacji ustawiony w tym parametrze
- żeby uniknąć budzenia urządzenia, można ustawić aktualizację opartą na alarmie "niebudzącym" urządzenia
- korzystając z AlarmManager ustaw alarm przez Intent otrzymywany przez AppWidgetProvider
- ustaw alarmowi typ ELAPSED_REALTIME lub RTC
- ustaw updatePeriodMillis = 0
- initialLayout - ścieżka do pliku określającego wygląd (layout) widgetu
- configure - aktywność, która zostanie uruchomiona po dodaniu widgetu w celu umożliwienia użytkownikowi skonfigurowania go
- previewImage - podgląd przykładowo skonfigurowanego widgetu dla użytkownika, dostępny dla niego gdy wybiera widgety
- jeśli nie ma ustwionego tego parametru, jako podgląd wyświetlana będzie ikona aplikacji
- autoAdvanceViewId - id widoku "rozszerzonego"
- dla widgetów, które mogą być rozbudowywane (advanceable)
- informuje host co powinno być rozbudowywane
- host będzie wykonywał akcję advance() gdy będzie to sensowne, czyli np. tylko gdy widget będzie widoczny
- resizeMode - określa zasady zmiany rozmiaru widgetu - horizontal, vertical, none
- widgetCategory - określa gdzie może być wyświetlany widget - home_screen, keyguard (tylko do Android 5.0), both
środa, 20 czerwca 2018
AndroidManifest - dodajemy widget
W manifeście informujemy aplikację o składowych częściach widgetu.
(deklarujemy obiekt, który będzie mógł odbierać informacje od aplikacji i/lub systemu) <receiver android:name="nazwa AppWidgetProvider" > (tu powyżej -"name"- mówimy aplikacji jak nazywa się klasa, która ma informacje jak będzie zachowywał się ten obiekt - widget) <intent-filter> (tu deklarujemy, na co widget będzie reagował, co będzie odbierał) <action android:name="android.appwidget.action.APPWIDGET_UPDATE" /> (jeśli widget ma być aktualizowany należy to koniecznie zadeklarować) </intent-filter> (tu mówimy gdzie są dane konfiguracyjne widgetu) <meta-data android:name="android.appwidget.provider" android:resource="@xml/example_appwidget_info" /> </receiver>więcej o atrybucie <receiver>
wtorek, 19 czerwca 2018
Z czego składa się widget?
- AppWidgetProviderInfo - plik XML zawierający metadane naszego widgetu
- metadane - dane o danych – ustrukturalizowane informacje stosowane do opisu zasobów informacji lub obiektów informacji, dostarczające szczegółowych danych, dotyczących atrybutów zasobów lub obiektów informacji, w celu ułatwienia ich znalezienia, identyfikacji, a także zarządzania tymi zasobami
- AppWidgetProvider (implementacja) - zdefiniownie tego jak widget będzie się zachowywał pod wpływem różnych działań
- View layout - plik XML opisujący wygląd widgetu
- App Widget configuration Activity (opcjonalnie) - sktywność, która otworzy się w momencie dodawania widgetu i umożliwi ustawienie konfiguracji
- zmiana w AndroidManifest.xml - deklaracja atrybutu <receiver> o takiej nazwie jaką ma dodany wcześniej AppWidgetProviderInfo
poniedziałek, 18 czerwca 2018
Co to jest widget?
To taka miniaturka aplikacji - np. większość telefonów ma na Home Screen ustawiony zegar.
Widget:
Widget:
- może być osadzony w innych aplikacjach (taka aplikacja to App Widget Host i jest nią np. home screen),
- cyklicznie się aktualizuje,
- jest wyświetlany dzięki App Widget Provider.
piątek, 18 maja 2018
Dlaczego moja aplikacja nie ma tej ładnej ikonki?
Znowu się na to złapałam.
Wygrywam apkę na wirtualkę a tam androidek zamiast mojej ikonki.
Sprawdzam manifest - OK.
Sprawdzam grafikę - OK.
Co się dzieje?
Jest nie w tym katalogu - znowy bezmyślnie dodałam ją do katalogu anydpi. A z tego katalogu poprawnie obsługiwane są grafiki wektorowe a nie rastowe...
Po przełożeniu mojego .png do innego katalogu wszystko zadziałało.
Wygrywam apkę na wirtualkę a tam androidek zamiast mojej ikonki.
Sprawdzam manifest - OK.
Sprawdzam grafikę - OK.
Co się dzieje?
Jest nie w tym katalogu - znowy bezmyślnie dodałam ją do katalogu anydpi. A z tego katalogu poprawnie obsługiwane są grafiki wektorowe a nie rastowe...
Po przełożeniu mojego .png do innego katalogu wszystko zadziałało.
czwartek, 17 maja 2018
Dlaczego "R" jest czerwone?
Coś jest nie tak z moimi zasobami.
Po raz kolejny mam nadzieję, że to kompilator ma jakiś problem - przecież dopiero go włączyłam, pewnie coś się źle załadowało. W dodatku znowu chce zrobić jakiś update. Pewnie to to.
NIE!
Zrobiłam "niewielką" modyfikację w zasobach, dodałam tylko jedną linijkę w stylach, kompilator jej nie podkreślił, uznałam, że wszystko jest OK. A jednak nie było.
Od dziś:
Po raz kolejny mam nadzieję, że to kompilator ma jakiś problem - przecież dopiero go włączyłam, pewnie coś się źle załadowało. W dodatku znowu chce zrobić jakiś update. Pewnie to to.
NIE!
Zrobiłam "niewielką" modyfikację w zasobach, dodałam tylko jedną linijkę w stylach, kompilator jej nie podkreślił, uznałam, że wszystko jest OK. A jednak nie było.
Od dziś:
Jeśli zasoby nie budują się poprawnie, upewnij się, że wprowadzone zmiany są poprawne.
piątek, 11 maja 2018
Czytać komentarze?
Komentarze dotyczące ocen aplikacji mogą być bardzo pomocne podczas tworzenia aplikacji.
Dzięki nim poznajemy różne oczekiwania klientów, możemy zobaczyć perspektywy, z jakich ludzie będą oceniać naszą aplikację.
Wiadomo, że nie uda nam się zadwolić każdego i że nie warto tego robić. Dzięki wiedzy na temat tego co może się podobać lub nie podobać użytkownikom:
Przejrzałam kilka aplikacji i ich komentarze - niestety bywało różnie. Część osób daje rzeczywiście wartościowy komentarz, ale często niestety spotykałam się z komentarzami bez sensu (w stylu "bla bla bla" lub "muj kot lubi ta aplikacje").
Bardzo wartościowe są opinie niezadowolonych użytkowników, zwłaszcza jeśli nie przeczytali czegoś dotyczącego działania aplikacji - bo dobra aplikacja nie potrzebuje instrukcji.
Chyba powinnam też zacząć komentować zainstalowane aplikacje.
Dzięki nim poznajemy różne oczekiwania klientów, możemy zobaczyć perspektywy, z jakich ludzie będą oceniać naszą aplikację.
Wiadomo, że nie uda nam się zadwolić każdego i że nie warto tego robić. Dzięki wiedzy na temat tego co może się podobać lub nie podobać użytkownikom:
- zaprojektujemy UX dla wybranej grupy odbiorców, dobierzemy odpowiednie narzędzia przekazu
- dopasujemy UI do tego co aktualnie najbardziej podoba się użytkownikom
- opiszemy projekt tak, żeby instalowały go tylko zainteresowane osoby (unikniemy odinstalowania i zniechęcenia naszymi produktami)
Przejrzałam kilka aplikacji i ich komentarze - niestety bywało różnie. Część osób daje rzeczywiście wartościowy komentarz, ale często niestety spotykałam się z komentarzami bez sensu (w stylu "bla bla bla" lub "muj kot lubi ta aplikacje").
Bardzo wartościowe są opinie niezadowolonych użytkowników, zwłaszcza jeśli nie przeczytali czegoś dotyczącego działania aplikacji - bo dobra aplikacja nie potrzebuje instrukcji.
Chyba powinnam też zacząć komentować zainstalowane aplikacje.
Drobiazgi SQL
Ten post będzie edytowany
Jak połączyć kilka warunków w wyszukiwaniu z bazy danych?
SELECT column1, column2, column3 FROM tableName WHERE condition1 AND condition2;
Ciąg dalszy nastąpi...
czwartek, 10 maja 2018
Moje charakterystyczne kolory
Kolory moich turkusowych aplikacji.
Wybrałam sobie kilka - nazwijmy je turkusowy i pudrowy róż (oba w wersji normalnej i ciemnej) oraz prawie biały i prawie czarny.
Będę je jeszcze testować ;)
Wybrałam sobie kilka - nazwijmy je turkusowy i pudrowy róż (oba w wersji normalnej i ciemnej) oraz prawie biały i prawie czarny.
<color name="colorPrimary">#39CCCC</color> <color name="colorPrimaryDark">#198787</color> <color name="colorAccent">#da878f</color> <color name="colorAccentDark">#962631</color> <color name="colorDark">#121616</color>
<color name="colorLight">#f7dadd</color>
Będę je jeszcze testować ;)
wtorek, 8 maja 2018
BabyPhone - zadania
Zadania:
założyć projekt - github, katalog- 8.05.2018, 1,5h (o masakra - następnym razem przy zakładaniu nowego projektu muszę baaardzo dokładnie się przyjrzeć wszystkim czynnościom, które wykonuję, bo coś jest bardzo nie tak...)wstępny manifest - aplikacja otwiera aktywność ustawień- 17.05.2018, 0,5h (wow, nie zaglądałam do projektu od 9 dni? zadanie nie zajęło 0,5, ale jak zwykle pojawiły się jakieś komplikacje...)- aplikacja umożliwia włączanie widgetu widocznego przy zalogowanym ekranie
- aplikacja umożliwia wyłączanie widgetu
- widget uruchamia aktywność pokazującą obrazek
- obrazek z widgetu zamyka się po X sekundach (początokowo X=3)
- widget uruchamia serię obrazków - Y obrazków po sobie (początoko Y = 5), seria zamyka się
- do obrazka dodany jest dźwięk
- aplikacja zamiast obrazka wyświetla tekst
- aplikacja ma przykładową bazę danych - tabelę: obraz/tekst, dźwięk, zestaw (jeśli obiekt jest w jakimś zestawie to może być prezentowany, jest zestaw old i new do tych, które nie są prezentowane), data pierwszej prezetacji, liczba dni gdy był prezentowany
Pamiętać o:
- wieczornych commitach
- komentarzach
- bierzącym blogowaniu
- testach automatycznych
Plan:
- aktualizacja tego posta o informacje kiedy coś zostało zrobione i ile trwało - trudno mi planować bez jakichkolwiek danych.
- weryfikacja - 2 tygodnie: 8 - 21.05.2018
poniedziałek, 30 kwietnia 2018
BabyPhone - zaczynamy
Powód:
Mój ukochany 2,5 letni syn uwielbia bawić się moim telefonem. Zawsze to lubił. Jego młodszy, pół roczny brat chętnie idzie w jego ślady.
Chcę przygotować aplikację, która zadba, żeby nie zrobili niczego problematycznego na moim telefonie.
Cel:
Wstępny pomysł:
Aplikacja będzie się otwierała przy zablokowanym telefonie, dzięki temu:
Aplikacja musi być:
Element naukowy:
Jakiś czas temu słyszałam o metodzie uczenia dzieci czytania, matematyki i języków obcych od wieku niemowlęcego. Temat był kontrowersyjny, ostatecznie nie zdecydowałam się - wymaga od rodzica sporo pracy, czasu, poza tym ja nie chciałam moich dzieci niczego uczyć inaczej niż przez zabawę, doświaczanie, rozmowy i obserwację (mam jakieś takie przekonanie, że chcę im pokazać świat i nauczyć je cieszenia się tym światem, ciekawości świata itp.). Mniejsza o to - w każdym razie metoda jest i pomyślałam, że jest w sam raz na apkę.
Plan:
Mój ukochany 2,5 letni syn uwielbia bawić się moim telefonem. Zawsze to lubił. Jego młodszy, pół roczny brat chętnie idzie w jego ślady.
Chcę przygotować aplikację, która zadba, żeby nie zrobili niczego problematycznego na moim telefonie.
Cel:
- aplikacja dla dzieci
- ma zaciekawić dziecko a najlepiej czegoś je nauczyć
- ma zadbać o bezpieczeństwo telefonu
Wstępny pomysł:
Aplikacja będzie się otwierała przy zablokowanym telefonie, dzięki temu:
- dziecko nie będzie się starało go odblokować
- dziecko nie będzie miało dostąpu do innych aplikacji
- dziecko nie będzie próbowało dzwonić na numery alarmowe
Aplikacja musi być:
- kolorowa
- z interakcją
- dźwiękowa
- może jakiś ruch?
- dobrze by było jakiś element nauki
- możliwość dopasowywania przez rodzica
- zmienna - żeby się nie nudziła
Element naukowy:
Jakiś czas temu słyszałam o metodzie uczenia dzieci czytania, matematyki i języków obcych od wieku niemowlęcego. Temat był kontrowersyjny, ostatecznie nie zdecydowałam się - wymaga od rodzica sporo pracy, czasu, poza tym ja nie chciałam moich dzieci niczego uczyć inaczej niż przez zabawę, doświaczanie, rozmowy i obserwację (mam jakieś takie przekonanie, że chcę im pokazać świat i nauczyć je cieszenia się tym światem, ciekawości świata itp.). Mniejsza o to - w każdym razie metoda jest i pomyślałam, że jest w sam raz na apkę.
Plan:
- zacznę od ogólnej apki - BabyPhone
- dodam lekcję matematyki - BabyPhone Mat
- dodam lekcję czytania - BabyPhone Read
- dodam lekcję języka - BabyPhone Lang
Subskrybuj:
Posty (Atom)