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

Android School 06

Sponsored · SiteGround - Reliable hosting with speed, security, and support you can count on.

Android School 06

Avatar for Adam Jodłowski

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