czwartek, 4 marca 2021
czwartek, 20 sierpnia 2020
Android Basics - User Interface
Tego kursu wcześniej nie słuchałam i jak teraz usłyszałam, że to dla kogoś, kto nigdy nie napisał ani jednej linijki kodu, to zaczęłam wątpić...
Ale dobrze, pomyślałam, przekonaj się, że to umiesz, a przy okazji może usłyszysz jakąś informację, o której nie wiesz. I tak dowiedziałam się o:
- atrybucie android:textAppearance="?android:textAppearanceSmallInverse" , którego mogę użyć, gdy nie będę wiedzieć jaki rozmiar czcionki wybrać
- atrybucie layout_weight, który może wystąpić w LinearLayout przy layout_width="0dp", a jego wartość określa jaką częścią całości jest dany element (sumuje się wartości tego atrybutu u wszystkich dzieci rodzica i proporcjonalnie rozdysponowuje się miejsce)
- RelativeLayout - gdy robiłam kurs mniej podstawowy, ten layout był pominięty, zastąpiony ConstraintLayout, okazuje się, że są bardzo podobne a atrybutem typu android:layout_toLeftOf lub android:layout_below można ustawiać elementy obok siebie
- da się sensownie podzielić ekran bez wartości procentowych Guideline w ConstraintLayout
- to, co ma być wyświetlane na ekranie nie musi być od razu w całoścu widoczne - mogę użyć ScrollView i wewnątrz niego zaprojektować ciekawy układ elementów
środa, 19 sierpnia 2020
Jak dopasować style tekstu - wnioski z Material Design
Jak się okazuje, AndroidStudio ma zaimplementowane style wg Material Design, tylko nigdy nie dałam sobie czasu na to, żeby się w tym zorientować. To teraz już wiem :)
Planowałam te style przenieść do mojego projektu wpisując wszystkie dane, zgodnie z informacjami, a już nie muszę, bo tam wszystko jest. Tylko kroje czcionek zmieniłam.
I teraz wskazówki z tamtej strony (są tam też ciekawe, dobrze ilustrujące zagadnienia przykłady):
- Nagłówki
- to krótkie, ważne teksty,
- wyraźne, ciekawe kroje czcionek,
- mniejsze nagłówki będą lepiej wyglądać w spokojniejszym kroju czcionki.
- Podtytuły
- mniejsze od nagłówków,
- krókie teksty,
- wyraźne kroje czcionek.
- Treść
- długa forma,
- wyraźne kroje czcionek.
- Podpisy
- mogą być pod lub nad,
- dotyczą tekstu, tytułu lub obrazu,
- najmniejszy rozmiar czcionki,
- proste, wyraźne kroje czcionek.
- Przycisk
- często allCaps,
- często sans serif,
- powinien być wyraźny, widoczny, dawać jasno do zrozumienia co robi.
- Wyrównanie tekstu
- Najczęściej do lewej
- Cytaty wyśrodkowane, nie bardzo długie
O typografii z Material Design jest tutaj.
czwartek, 13 sierpnia 2020
Zmiana myślenia
Choć pozornie nie ma to nic wspólnego z programowaniem, od 4 tygodni realizuję program Droga Artysty. Bardzo polecam, to chyba najlepszy program rozwojowy, w jakim brałam udział. A możę pierwszy, za który wzięłam się na poważnie?
Tak czy inaczej - on oraz mój zespół Mastermind pomogli mi odkryć moją największą blokadę.
Ja NIE MOGĘ być programistą
Taka myśl, za każdym razem w mojej głowie. I nie chodzi o to, że nie będę dobrym programistą, czy idealnym, że nie w jakomś języku. Wcale. Nie mogę i już. Nie moja ścieżka, nie moje miejsce. NIE. Wstęp wzbroniony, możesz sobie siedzieć IT, zajmować się czymkolwiek, ale tego nie wolno dotknąć. Jak Drzewo Poznania Dobra i Zła. A ja się słuchałam, nie moje, to nie. Czy kusiło? Nie wiem. Lubiłam inne rzeczy, lubiłam to, co robiłam.
Aż do środy, 3 tygodnie temu, kiedy uświadomiłam sobie, skąd to się wzięło i dlaczego to jest takie złe.
A zatem się z tego uwalniam, wróciłam do kursu, zaplanowałam kolejne. Wymyśliłam jak wykorzystam wiedzę w praktyce.
Jest lepiej, serio. Jeśli Cię coś blokuje i nie masz z kim pogadać - napisz do mnie, zrozumiem Cię :)
Zapiszę sobie jeszcze co sobie przypomniałam powtarzając pierwszy moduł kursu (już to umiałam, tylko zapomniałam):
- Używaj najprostrzego layoutu w kolejności:
- Frame
- Linear
- Constrain
- Ustawianie tekstu w TextView:
- setText - wpisuje nową wartość
- append - dodaje wartość do tego co już było
czwartek, 28 lutego 2019
Dobre praktyki - Lekcja 1
- Testuj małe elementy - im mniej, tym lepiej, nawet jeśli to tylko zmiana koloru - upewnij się, że się zmienił tam gdzie powinien.
- Testuj małe elementy - nawet jeśli nie powodują widocznej zmiany wyglądu lub zachowania - sprawdzaj, czy nic nie popsuły.
- Czytaj materiały branżowe regularnie - warto się uczyć od innych.
- Porządnie planuj - najpierw zgrubnie, później coraz dokładniej, im mniejsze zadania tym łatwiej je wykonać nawet przy zmęczeniu.
- Usuwaj logi, których nie potrzebujesz.
- Upewnij się, że element, którego używasz !=null
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, 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
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;
}
piątek, 22 czerwca 2018
Jak działa AppWidgetProvider czyli jakie widget otrzymuje sygnały i co się wtedy dzieje
- 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
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
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
- 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
(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?
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, 11 maja 2018
Drobiazgi SQL
Jak połączyć kilka warunków w wyszukiwaniu z bazy danych?
SELECT column1, column2, column3 FROM tableName WHERE condition1 AND condition2;sobota, 7 kwietnia 2018
Czy zawsze da się wrócić do zadania?
Czyli za każdym razem, gdy jakaś aktywność ma dla atrybutu launchMode wartość singleTask lub singleInstance, aktywność ta powinna:
- mieć zadeklarowane w manifeście (w tagu <intent filter>), że jest to
- aktywność główna - <action android:name="android.intent.action.MAIN" />
- można się przez nią połączyć z zadaniem - <category android:name="android.intent.category.LAUNCHER" />
- mieć ustawioną dla atrybutu finishOnTaskLaunch wartość false.
Mieszanie w zadaniu
Żeby zmienić naturalny sposób obsługi zadania (task) można zadeklarować to w manifeście podając odpowiednie atrybuty do taga <activity>:
- taskAffinity
- launchMode
- allowTaskReparenting
- clearTaskOnLaunch
- alwaysRetainTaskState
- finishOnTaskLaunch
- FLAG_ACTIVITY_NEW_TASK
- FLAG_ACTIVITY_CLEAR_TOP
- FLAG_ACTIVITY_SINGLE_TOP
Ważne - android doskonale radzi sobie ze swoimi zadaniami, kiedy mu się w tym nie przeszkadza. Mieszając w zadaniach należy bardzo dokładnie przetestować wszystkie przypadki cofania z różnych aktywności - upewnić się, że stos będzie odpowiednio obsłużony i aplikacja nie przestanie działać.
Jak android czyści stos (i co na to można poradzić)?
Żeby tak się nie działo należy w tej pierwszej aktywności wywołującej kolejne ustawić dla atrybutu alwaysRetainTaskState wartość true.
Żeby android nie czekał, tylko od razu po przejściu aplikacji z głównego wątku (foreground) do tła (background) zamknął wszystkie aktywności poza pierwszą należy w tej pierwszej aktywności wywołującej kolejne ustawić dla atrybutu clearTaskOnLaunch wartość true.
Żeby system po przejściu aplikacji do tła zamknął konkretną aktywność należy ustawić dla atrybutu finishOnTaskLaunch wartość true.
piątek, 30 marca 2018
Co to takiego jest to Affinity?
Domyślnie jest taka sama dla wszystkich aktywności danej aplikacji i jej wartość określana jest przez nazwę paczki aplikacji. Dzięki temu wszystkie aktywności aplikacji są ze sobą powiązane i będą się otwierały w stosie (stack) tego samego zadania (task).
Koligację inną niż domyślna można ustawić zmieniając w manifeście wartość atrybutu taskAffinity dla wybranej aktywności. Wartość ta musi być inna niż nazwa paczki aplikacji (to jest domyślna wartość tego atrybutu).
Koligacja jest brana pod uwagę, gdy:
- aktywność jest wywoływana z flagą FLAG_ACTIVITY_NEW_TASK - system sprawdza wtedy czy jest jakieś inne zadanie, którego aktywności mają tę samą koligację co wywoływana aktywność - jeśli tak, to aktywność jest do niego przypisywana, jeśli nie to wywoływana aktywność otwiera nowe zadanie
- atrybut allowTaskReparenting dla danej aktywności ma wartość true - wtedy każde zadanie, z którym dana aktywność ma koligację, przechodząc do gółwnego wątku (foreground) przypisuje sobie na górę stosu i wyświetla tę aktywność

