Android Widget @ whymca 2011

  • 2,255 views
Uploaded on

Talk sugli Android Widget di whymca 2011

Talk sugli Android Widget di whymca 2011

  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
    Be the first to like this
No Downloads

Views

Total Views
2,255
On Slideshare
0
From Embeds
0
Number of Embeds
2

Actions

Shares
Downloads
58
Comments
0
Likes
0

Embeds 0

No embeds

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • 10 minuti\n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n

Transcript

  • 1. Android Widget Fabio Collini
  • 2. SpeakerFabio Collini @fabioColliniTech Leader @ OmniaGroup http://www.omniagroup.itAndroid Developer Apps Organizer e Folder OrganizerBlogger http://android.devapp.it http://www.cosenonjaviste.it
  • 3. AgendaIntroduzioneEsempio widget AndroidScrollable widgetNovità di Android 3.0/3.1
  • 4. WidgetCosa si intende per widget?
  • 5. Il punto di vista dello sviluppatorePackage android.widget Contiene le view utilizzabili nelle interfaccePackage android.appwidget Contiene le classi per gestire gli widget nella home
  • 6. Il punto di vista dell’utente
  • 7. Esempi di widget
  • 8. Pro e controConviene aggiungere uno widget?Si! interazione facilitata con l’app funzionalità sempre a portata di mano categoria widget sul marketNo! impossibile spostare l’app sulla sd card
  • 9. Esempio
  • 10. Widget minimaleXml di definizione providerLayoutClasse AppWidgetProvider
  • 11. res/xml/appwidget_provider.xml<?xml version="1.0" encoding="utf-8"?><appwidget-provider xmlns:android= "http://schemas.android.com/apk/res/android" android:minWidth="294dp" android:minHeight="72dp" android:updatePeriodMillis="86400000" android:initialLayout="@layout/appwidget_loading"/>
  • 12. Attributi disponibiliCalcolo della dimensione (numero di celle * 74) - 2updatePeriodMillis millisecondi fra due aggiornamentiinitialLayout layout iniziale widget può essere diverso dal layout definitivo
  • 13. Android manifest<receiver android:name=".PicturesAppWidgetProvider" android:label="1. Normal widget"> <meta-data android:name="android.appwidget.provider" android:resource="@xml/appwidget_provider" /> <intent-filter> <action android:name= "android.appwidget.action.APPWIDGET_UPDATE" /> </intent-filter></receiver>
  • 14. Layout<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android= "http://schemas.android.com/apk/res/android" android:id="@+id/widget_layout" style="@style/widget_layout"> <ImageView android:id="@+id/img1" style="@style/picture_thumbnail" /> <ImageView android:id="@+id/img2" style="@style/picture_thumbnail" /></LinearLayout>
  • 15. Layout limitatiLayout: FrameLayout, LinearLayout e RelativeLayoutView: AnalogClock Button Chronometer ImageButton ImageView ProgressBar TextView
  • 16. Stile layout<style name="widget_layout"> <item name="android:layout_width"> fill_parent</item> <item name="android:layout_height"> fill_parent</item> <item name="android:orientation">horizontal</item> <item name="android:gravity">center</item> <item name="android:layout_marginLeft">5dip</item> <item name="android:layout_marginRight">5dip</item> <item name="android:background"> @drawable/background</item></style>
  • 17. res/drawable/background.xml<?xml version="1.0" encoding="UTF-8"?><shape xmlns:android= "http://schemas.android.com/apk/res/android"> <stroke android:width="2dp" android:color="#990634fd" /> <padding android:left="2dp" android:top="2dp" android:right="2dp" android:bottom="2dp" /> <corners android:radius="4dp" /> <solid android:color="#99FFFFFF" /></shape>
  • 18. Android non è solo touchDevice con trackball Gli utenti blackberry sono abituati a usarlaDevice con tastiera Possono contenere i tasti frecciaGoogle TV non avrà un telecomando touch
  • 19. Stile immagini<style name="picture_thumbnail"> <item name="android:layout_width">120dip</item> <item name="android:layout_height">90dip</item> <item name="android:layout_margin">5dip</item> <item name="android:focusable">true</item> <item name="android:background"> @drawable/selection</item></style>
  • 20. StateListDrawable<?xml version="1.0" encoding="utf-8"?><selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_focused="true" android:drawable="@drawable/background" /> <item android:state_pressed="true" android:drawable="@drawable/background" /></selector>
  • 21. Widget selezionato
  • 22. AppWidgetProviderEstende BroadcastReceiverRiscrive onReceive, mette a disposizione: onUpdate onDeleted onEnabled onDisabledBug su Android 1.5 http://groups.google.com/group/android-developers/msg/ e405ca19df2170e2
  • 23. AppWidgetProviderpublic class PicturesAppWidgetProvider extends AppWidgetProvider { @Override public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { for (int i = 0; i < appWidgetIds.length; i++) { int appWidgetId = appWidgetIds[i]; updateAppWidget(context, appWidgetManager, appWidgetId); } } //...}
  • 24. updateAppWidgetpublic static void updateAppWidget(Context context, AppWidgetManager appWidgetManager, int appWidgetId) { RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.appwidget_provider); views.setImageViewResource(R.id.img1, R.drawable.img1); views.setImageViewResource(R.id.img2, R.drawable.img2); views.setOnClickPendingIntent(R.id.img1, AppWidgetUtils.createPendingIntent(context, 1)); views.setOnClickPendingIntent(R.id.img2, AppWidgetUtils.createPendingIntent(context, 2)); appWidgetManager.updateAppWidget(appWidgetId, views);}
  • 25. RemoteViewsE’ una lista di comandi da effettuare I comandi vengono eseguiti in un altro processoMetodi con 3 parametri id di una view contenuta nel layout setter da richiamare valore da impostareEsempi di metodi setInt(int viewId, String methodName, int value) setString(int viewId, String methodName, String value)
  • 26. PendingIntentIntent da passare a una app esternaCreati con un metodo statico getActivity(Context context, int requestCode, Intent intent, int flags) getBroadcast(Context context, int requestCode, Intent intent, int flags) getService(Context context, int requestCode, Intent intent, int flags)Attenzione alla cache! requestCode: private request code for the sender (currently not used).
  • 27. PendingIntentpublic static Intent createIntent(Context ctx, int pos) { Intent intent = new Intent(ctx, PictureViewer.class); intent.putExtra(PictureViewer.IMAGE, "img" + pos); return intent;}public static PendingIntent createPendingIntent( Context ctx, int pos) { Intent intent = createIntent(ctx, pos); return PendingIntent.getActivity(ctx, pos, intent, 0);}
  • 28. Demo
  • 29. Activity di configurazionePuò essere configurata nel file xmlUtile quando il widget è configurabileAlla fine aggiorna manualmente il widgetAggiungiamo una configurazione al nostro esempio: checkbox per nascondere lo sfondo del widget
  • 30. appwidget_provider_config.xml<?xml version="1.0" encoding="utf-8"?><appwidget-provider xmlns:android= "http://schemas.android.com/apk/res/android" android:minWidth="294dp" android:minHeight="72dp" android:updatePeriodMillis="86400000" android:initialLayout="@layout/appwidget_loading" android:configure="org.whymca.appwidget.config. PicturesAppWidgetConfigure"/>
  • 31. Configurazione nel manifest<activity android:name=".config.PicturesAppWidgetConfigure" android:theme="@android:style/Theme.Dialog" android:label="@string/Configure_widget"> <intent-filter> <action android:name= "android.appwidget.action.APPWIDGET_CONFIGURE" /> </intent-filter></activity>
  • 32. PicturesAppWidgetConfigurepublic void save(View v) { boolean checked = showBackgroundCheck.isChecked(); PrefsSaver.saveShowBackground(this, mAppWidgetId, checked); PicturesAppWidgetProviderConfig.updateAppWidget( this, AppWidgetManager.getInstance(this), mAppWidgetId, checked); Intent resultValue = new Intent(); resultValue.putExtra( AppWidgetManager.EXTRA_APPWIDGET_ID, mAppWidgetId); setResult(RESULT_OK, resultValue); finish();}
  • 33. Impostazione sfondoif (showBackground) { views.setInt(R.id.widget_layout, "setBackgroundResource", R.drawable.background);} else { views.setInt(R.id.widget_layout, "setBackgroundResource", 0);}
  • 34. Demo
  • 35. Attenzione su Android < 2.205‐02
22:35:41.544:
WARN/AppWidgetHostView(108):
android.widget.RemoteViews$AcDonExcepDon:
view:
android.widget.LinearLayout
cant
use
method
with
RemoteViews:
setBackgroundResource(int)
  • 36. Cambio di orientation
  • 37. Home in landscapeAlcune home non hanno orientation fissa A differenza delle Activity non è possibile decidere l’orientationI tablet sono in landscapeDevice con tastieraOccorre gestire i layout directory layout-landscape
  • 38. Immagini esterneE se prendiamo le immagini dalla scheda sd o dagli asset?Se le immagini sono troppo grandi:Errore di memoria nella RemoteViews! :(
  • 39. Uri per ContentProviderviews.setImageViewUri(R.id.img1, createUri("img1"));views.setImageViewUri(R.id.img2, createUri("img2"));views.setImageViewUri(R.id.img3, createUri("img3"));views.setImageViewUri(R.id.img4, createUri("img4"));private static Uri createUri(String imageName) { return Uri.parse( "content://org.whymca.appwidget.pictures/" + imageName);}
  • 40. ContentProvider<provider android:name=".ImageContentProvider" android:authorities="org.whymca.appwidget.pictures" />@Overridepublic ParcelFileDescriptor openFile(Uri uri, String mode) throwsFileNotFoundException { String imageName = uri.getPath().substring(1); File tmpFile = getTempFile(getContext(), imageName); if (!tmpFile.exists()) { copyAssetFile(getContext(), imageName, imageName + ".JPG"); } try { return ParcelFileDescriptor.open(tmpFile, ParcelFileDescriptor.MODE_READ_ONLY); } catch (FileNotFoundException e) { return null; }}
  • 41. Timeout aggiornamentoonUpdate viene eseguito nel thread principalepossibili timeout al riavvio del device ci sono molte app in esecuzionepratica da seguire: spostare la logica in un service esterno
  • 42. Servicepublic void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { Intent intent = new Intent(context, PicturesAppWidgetService.class); intent.putExtra("appWidgetIds", appWidgetIds); context.startService(intent);}
  • 43. updatePeriodMillisPoco flessibile tutti gli widget sono aggiornati insieme e con la stessa frequenzaConfigurazione fissa è cablato in un xmlMinimo 30 minuti anche se nel file xml viene specificato un valore minoreAttivato anche con il telefono in stand by consumo eccessivo della batteria
  • 44. AlarmManagercreare un nuovo alarm in onUpdateBroadcastReceiver definito nel manifestun alarm per ogni widget ogni widget viene aggiornato con frequenza diversa alarm non eseguito con telefono in stand bycancellare l’alarm in onDeleted
  • 45. Widget scrollableForum http://groups.google.com/group/android-appwidget-extensionsEsempio di utilizzo http://code.google.com/p/scrollablecontacts/
  • 46. Widget scrollableVantaggi permettono di usare liste e griglie resize miglioreDifetti funzionano solo con home replacement (ADW, LauncherPro, GoLauncher, Home++, ...) su LauncherPro devono essere abilitati manualmente lag dovuto a un bug (o feature!) di android http://code.google.com/p/android/issues/detail?id=4536
  • 47. Demo
  • 48. Widget HoneycombNuove view utilizzabili: ListView GridView StackView ViewFlipper AdapterViewFlipper
  • 49. Provider con controllo versione@Overridepublic void onUpdate(Context context, AppWidgetManagerappWidgetManager, int[] appWidgetIds) { if (Build.VERSION.SDK_INT >= 11) { for (int i = 0; i < appWidgetIds.length; i++) { HoneycombUtils.onUpdateTablet(context, appWidgetManager, appWidgetIds[i]); } } else { super.onUpdate(context, appWidgetManager, appWidgetIds); }}
  • 50. HoneycombUtilspublic static void onUpdateTablet(Context ctx, AppWidgetManager appWidgetManager, int id) { RemoteViews views = new RemoteViews(ctx.getPackageName(), R.layout.scrollable_layout); Intent adapterIntent = new Intent(ctx, PicturesService.class); adapterIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, id); adapterIntent.setData(Uri.parse(adapterIntent.toUri( Intent.URI_INTENT_SCHEME))); views.setRemoteAdapter(id, R.id.grid, adapterIntent); PendingIntent clickPending = PendingIntent.getActivity(ctx, 0, new Intent(ctx, PictureViewer.class), PendingIntent.FLAG_UPDATE_CURRENT); views.setPendingIntentTemplate(R.id.grid, clickPending); appWidgetManager.updateAppWidget(id, views);}
  • 51. scrollable_layout.xml<?xml version="1.0" encoding="utf-8"?><GridView xmlns:android= "http://schemas.android.com/apk/res/android" android:id="@+id/grid" android:layout_width="fill_parent" android:layout_height="fill_parent" android:numColumns="auto_fit" android:columnWidth="120dip" android:background="@drawable/background" />
  • 52. PictureServicepublic class PicturesService extends RemoteViewsService { @Override public RemoteViewsFactory onGetViewFactory( Intent intent) { return new PicturesViewsFactory( this.getApplicationContext(), intent); }}
  • 53. PicturesViewFactorypublic class PicturesViewsFactory implements RemoteViewsService.RemoteViewsFactory {@Overridepublic RemoteViews getViewAt(int position) { RemoteViews row = new RemoteViews(ctxt.getPackageName(), R.layout.scrollable_cell); row.setImageViewUri(R.id.appwidget_image, createUri("img" + (position + 1))); Intent intent = new Intent(); intent.putExtra(PictureViewer.IMAGE, "img" + (position + 1)); row.setOnClickFillInIntent(R.id.appwidget_image, intent); return row;}//...
  • 54. Demo
  • 55. Preview di uno widgetL’emulatore Honeycomb contiene l’applicazione widget previewConfigurazione preview<?xml version="1.0" encoding="utf-8"?><appwidget-provider xmlns:android= "http://schemas.android.com/apk/res/android" android:minWidth="368dp" android:minHeight="368dp" android:updatePeriodMillis="86400000" android:initialLayout="@layout/appwidget_loading" android:previewImage="@drawable/widget_preview" />
  • 56. Demo preview
  • 57. Il futuro“Nuova” feature su Android 3.1 resize degli widgetTablet / Google TV su schermi grandi hanno più spazio nella home molto simile a un sistema operativo desktop
  • 58. RisorseAndroid developer http://developer.android.com/guide/topics/appwidgets/ index.html http://developer.android.com/guide/practices/ui_guidelines/ widget_design.htmlScrollable widget http://groups.google.com/group/android-appwidget-extensionsHoneycomb http://developer.android.com/sdk/android-3.0-highlights.html
  • 59. Thanks for your attention!Questions?Slide Presto disponibili su http://www.slideshare.net/Sorgenti https://github.com/fabioCollini/whymca2011Fabio Collini @fabioCollini http://www.omniagroup.it http://android.devapp.it http://www.cosenonjaviste.it