Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Android School 06

Android School 06

Adam Jodłowski

April 22, 2013
Tweet

More Decks by Adam Jodłowski

Other Decks in Programming

Transcript

  1. 2 Service • usługi pracują w tle, mają możliwości takie

    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)
  2. 3 Przykład usługi lokalnej • deklarujemy usługę w manifeście <service

    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; } }
  3. 4 Tworzene usługi zdalnej, AIDL • stworzenie zdalnej usługi wymaga

    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()
  4. 5 IntentService • specjalna wersja usługi, kolejkująca intencje z zadaniami

    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(); } } }
  5. 7 Support Package/Library • archiwum .jar z bibliotekami zapewniającymi częściową

    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
  6. 8 Fragmenty • lekkie aktywności posiadające własny cykl życia, ściśle

    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.
  7. 9 Główny układ widoków • niech aktywność zawiera dwa pionowe

    fragmenty rozłożone poziomo <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="horizontal" > <FrameLayout android:id="@+id/fragment1" android:layout_weight="0.25" android:layout_width="0dp" android:layout_height="fill_parent" /> <LinearLayout android:id="@+id/fragment2" android:layout_weight="0.75" android:layout_width="0dp" android:layout_height="fill_parent" /> </LinearLayout> • layout głównego okna umieszczamy w /res/layout-land/main.xml
  8. 10 Klasa fragmentu • rozszerzamy klasę Fragment i oprócz standardowych

    metod aktywności, obowiązkowo implementujemy metodę onCreateView() public class Fragment1 extends Fragment { TextView tv = null; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle b) { View view = inflater.inflate(R.layout.fragment1, container, false); tv = (TextView) view.findViewById(R.id.textView_fragment1); tv.setText("to jest 1 fragment"); ((Button) view.findViewById(R.id.button_fragment1)).setOnClickListener(new OnClickListener() {...}); return view; } }
  9. 11 FragmentManager, komunikacja fragmentów • FragmentManager* zarządza fragmentami i dba

    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
  10. 12 Adaptatywny interfejs • tworzymy layout poziomy z dwoma fragmentami

    • 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
  11. 14 Canvas • dostęp do płótna otrzymujemy implementując własny obiekt

    widoku i umieszczając go w layoucie public class CustomView extends View { public CustomView(Context context, AttributeSet attrs) { super(context, attrs); } @Override protected void onDraw(Canvas canvas) { int w = this.getWidth(); int h = this.getHeight(); canvas.drawColor(Color.WHITE); Paint paint = new Paint(); // new Paint(Paint.ANTI_ALIAS_FLAG); paint.setColor(Color.BLACK); paint.setStyle(Paint.Style.STROKE); canvas.drawRect(w/2 - w/4, h/2 - h/8, w/2 + w/4, h/2 + h/8, paint); paint = new Paint(); paint.setColor(Color.RED); paint.setStyle(Paint.Style.FILL); canvas.drawRect(w/2 - w/4, h/2, w/2 + w/4, h/2 + h/8, paint); } } <as.graphics.CustomView android:id="@+id/custom_view" android:layout_width="fill_parent" android:layout_height="fill_parent"> </as.graphics.CustomView>
  12. 15 Praca z płótnem • nakładanie elementów graficznych Bitmap bitmap

    = BitmapFactory.decodeResource(getResources(), R.drawable.pic); canvas.drawBitmap(bitmap, 10, 10, null); • inne przydatne metody paint.setFlags(Paint.UNDERLINE_TEXT_FLAG); paint.setTextSize(16); canvas.drawText("Tekst", 20, 20, paint); Bitmap.createScaledBitmap(pic, 30, 40, false); • przekształcenia względem płótna canvas.save(); canvas.rotate(45, 85, 85); canvas.drawBitmap(bitmap, 100, 100, null); canvas.restore(); • pozostałe dostępne przekształcenia to translate, scale, skew, concat, clipRect, clipPath
  13. 16 Transformacje macierzowe • omówione transformacje możemy przeprowadzać wprost za

    pomocą macierzy Matrix mirrorMatrix = new Matrix(); mirrorMatrix.preScale(-1, 1); Bitmap mirrorBmp = Bitmap.createBitmap(pic, 0, 0, pic.getWidth(), pic.getHeight(), mirrorMatrix, false); Matrix rotateMatrix = new Matrix(); rotateMatrix.preRotate(90); • pomagajmy zwolnić niepotrzebną pamięć po bitmapach bitmap.recycle();
  14. 17 Gradienty • gradient to nic innego jak styl pędzla

    Paint gradientPaint = new Paint(Paint.ANTI_ALIAS_FLAG); LinearGradient grad = new LinearGradient(0, 0, 25, 25, Color.RED, Color.BLACK, Shader.TileMode.MIRROR); RadialGradient grad = new RadialGradient(250, 175, 50, Color.GREEN, Color.BLACK, Shader.TileMode.MIRROR); SweepGradient grad = new SweepGradient(canvas.getWidth() - 175, canvas.getHeight() - 175, new int[] { Color.RED, Color.YELLOW, Color.GREEN, Color.BLUE, Color.MAGENTA }, null); gradientPaint.setShader(grad);
  15. 18 Kształty • kształty możemy tworzyć deklaratywnie w XML lub

    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
  16. 20 Niestandardowe czcionki • przykład zastosowania niestandardowej czcionki z zasobów

    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*
  17. 21 State list • listy stanów pozwalają na podmianę grafik

    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>
  18. 22 Style i tematy/motywy • definiujemy je w dowolnym pliku

    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" ... /> . . .