jak aktywności, ale nie posiadają interfejsu użytkownika, działanie usług odbywa się w wątku UI • mogą być lokalne dla naszej aplikacji lub zdalne, udostępniając interfejs w formie RPC (za pomocą AIDL) • metoda kontekstu startService() działa analogicznie do startActivity() – identyfikuje usługę i dostarcza jej parametrów do wykonania startService(new Intent(context, BackgroundService.class)); • usługa odbierze intencję w metodzie onStartCommand(), która zwraca wartość kluczową dla jej cyklu życia (START_STICKY, START_REDELIVER_INTENT, START_NOT_STICKY) • możemy zatrzymać usługę jawnie przez analogiczne wywołanie stopSelf() w jej własnym kodzie lub z komponentu wywołującego stopService(new Intent(context, BackgroundService.class)); • klient może wysyłać pojedyńcze komunikaty do usługi lub podłączyć się do niej na stałe (bind)
android:name=".MyService"/> • implementujemy usługę public class BackgroundService extends Service { @Override public void onCreate() {...} @Override public void onDestroy() {...} @Override // reakcja na startService() public int onStartCommand(Intent intent, int flags, int startId) { super.onStartCommand(intent, flags, startId); // kod przetwarzania return START_STICKY; } @Override // reakcja na bindService() public IBinder onBind(Intent intent) { return null; } }
1. zdefiniowania interfejsu w pliku .aidl 2. uzyskania interfejsu Javy w wyniku kompilacji (zawiera stub) 3. implementacji w usłudze i zwrócenia interfejsu w onBind() 4. dodania konfiguracji usługi do manifestu • metody zwracają android.os.RemoteException, powinny być thread-safe • klient implementuje interfejs ServiceConnection z metodami zwrotnymi oraz podłącza się za pomocą bindService()
i wykonująca je w osobnym wątku* • możemy przekazać jej obiekt Messenger do komunikacji zwrotnej z handlerem aktywności Intent intent = new Intent(context, Downloader.class); intent.setData(Uri.parse("http://nyan.cat/favicon.ico")); intent.putExtra("MESSENGER", new Messenger(handler)); startService(intent); • public class Downloader extends IntentService { public Downloader() { super("Downloader"); } @Override protected void onHandleIntent(Intent intent) { String uri = intent.getData().toString(); ... Bundle extras = intent.getExtras(); Messenger messenger = (Messenger) extras.get("MESSENGER"); Message msg = new Message(); try { messenger.send(msg); } catch (RemoteException e) { e.printStackTrace(); } } }
kompatybilność starszych platform z nowymi wersjami API • należy dołączyć odpowiedni plik do projektu SDK/extras/android/support/v4/android-support- v4.jar • do najpopularniejszych komponentów udostępnianych przez bibliotekę należy Fragment, ViewPager, Loader, ShareCompat, NotificationCompat
związane z aktywnością, której są częścią • używane głównie do tworzenia elastycznych układów interfejsu, dostosowujących się do urządzeń z różnymi rozmiarami ekranów • pojawiły się w wersji 3.0 Androida (API 11), deklarowane w XML sprawiają pewne kłopoty (węzeł <fragment>) • ich różne wersje to m.in. Fragment, ListFragment, DialogFragment, PreferenceFragment, posiadają dotychczas poznane metody takie jak onCreate(), onPause(), onResume() itd.
o transakcje z ich udziałem (dodaje, usuwa, podmienia) oraz przechowuje stos wywołań – BackStack • aktywność może dynamicznie dodawać fragmenty do swojego layoutu FragmentManager fragMgr = getSupportFragmentManager(); FragmentTransaction trans = fragMgr.beginTransaction(); if (null == fragMgr.findFragmentByTag(FRAGMENT_1_TAG)) { trans.add(R.id.fragment1, new Fragment1(), FRAGMENT_1_TAG); } trans.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE); trans.addToBackStack(null); trans.commit(); • fragmenty otrzymują referencję do aktywności, której są częścią przez metodę getActivity() • mogą pozyskiwać referencje do innych fragmentów dzięki getFragmentManager().findFragmentByTag(FRAGMENT_TAG); • aktywność może zaimplementować interfejs komunikacji zwrotnej dostarczony przez fragment zamiast definiować metody pomocnicze
• obsługujemy je z aktywności w sposób tradycyjny • layout pionowy zawiera tylko pierwszy fragment • uruchamiając drugi fragment sprawdzamy, czy mamy gdzie go umieścić – jeśli nie, odpalamy osobną aktywność prezentującą tę część interfejsu • logika fragmentów jest już zaimplementowana, wystarczy stworzyć dodatkowe aktywności i dostosować orientacje layoutów • PROFIT
programowo ShapeDrawable sd = new ShapeDrawable(new RoundRectShape(new float[] { 5, 5, 5, 5, 5, 5, 5, 5 }, null, null)); sd.setIntrinsicHeight(80); sd.setIntrinsicWidth(80); sd.getPaint().setColor(Color.LTGRAY); • podobnie możemy rysować owale i ścieżki, kształty możemy wyświetlać wprost na komponencie ImageView imageView.setImageDrawable(myShapeDrawable); • definicja elementu <shape> w formie XML w celu użycia ich np. jako tła komponentów interfejsu użytkownika, pozwala na określanie właściwości corners, gradient, padding, size, solid, stroke
TextView tv = (TextView) findViewById(R.id.text); Typeface tf = Typeface.createFromAsset(getAssets(), "fonts/learningcurve_ot.otf"); tv.setTypeface(tf); • niestety nie ma łatwego sposobu na ustawienie czcionki w deklaracji XML*
w zależności od stanu widoku, mają postać drawable w pliku XML <selector xmlns:android="http://schemas.android.com/apk/re s/android"> <item android:drawable="@drawable/info" /> <item android:state_selected="true" android:drawable="@drawable/info" /> <item android:state_focused="true" android:drawable="@drawable/info_active" /> <item android:state_pressed="true" android:drawable="@drawable/info_active" /> </selector>
o postaci XML w /res/values <?xml version="1.0" encoding="utf-8"?> <resources> <style name="CodeFont" parent="@android:style/TextAppearance.Medium"> <item name="android:layout_width">fill_parent</item> <item name="android:layout_height">wrap_content</item> <item name="android:textColor">#00FF00</item> <item name="android:typeface">monospace</item> </style> </resources> • stosujemy je do elementów wizualnych <EditText style="@style/CodeFont" android:text="Hello Android!" /> • podobnie aplikujemy motywy graficzne dla całych aplikacji lub aktywności <activity android:theme="@android:style/Theme.NoTitleBar.Fullscreen" ... /> . . .