Android App Development - 13 Broadcast receivers and app widgets

download Android App Development - 13 Broadcast receivers and app widgets

If you can't read please download the document

Transcript of Android App Development - 13 Broadcast receivers and app widgets

  1. 1. Broadcast Receivers e AppWidget
  2. 2. Broadcast Receivers e AppWidget A Broadcast Receiver is a critical component that is designed to receive and handle Intent. It must be declared in the Manifest file, but it is not necessary to declare its Intent Filter: if declared, the receiver is always active and can receive the request for action at any time. If you want an Activity or a Service Intent receive in their life cycle, there is a Receiver by the method Context.registerReceiver() and is removed with Context.unregisterReceiver() within two states of the life cycle by specifying additional IntentFilter an object for matching. A Receiver receives Intent invocation of the methods: Context.sendBroadcast() Context.sendOrderedBroadcast() Broadcast Receiver
  3. 3. Broadcast Receivers e AppWidget The two methods identify the possible Broadcast: Normal Broadcasts (Context.sendBroadcast()): they are completely asynchronous and all Receivers receive the Intent simultaneously OrderedBroadcasts (Context.sendOrderedBroadcast()): Intents are sent to a receiver one at a time. Each Receiver manages the Intent and has the task of propagating it to the other. The order is defined by the matching Intent Filter and under the same filter with the android:priority Intent Filter tag: Broadcast Receiver
  4. 4. Broadcast Receivers e AppWidget To prevent errors and abuses: The Intent Action must be unique to avoid any conflict with other Intent When you specify an Intent Filter on Manifest file any other application can send a broadcast that the application can receive. To avoid this you must specify in the Manifest android:exported="false" When you send a broadcast using method Context.sendBroadcast() any other application can receive it. When you register a Receiver with Context.registerReceiver() any other application can send a broadcast. To enable applications that can send and/or receive use permissions. android:permission="com.example.BROADCAST_PERMISSION" Broadcast Receiver - Security
  5. 5. Broadcast Receivers e AppWidget To take advantage of the permission logic you can use the methods that specify the permission: Context.sendBroadcast(Intent, String) Context.sendOrderedBroadcast(Intent, String) Context.registerReceiver(BroadcastReceiver, IntentFilter, String) In this way only the Receiver that specify the same permission can receive the broadcast. All the security implications discussed are not valid if you use the object LocalBroadcastManager because this never goes outside of its process. Broadcast Receiver - Security
  6. 6. Broadcast Receivers e AppWidget The only method of a BroadcastReceiver is BroadcastReceiver.onReceive(). After running the method, the object is no longer active and is destroyed until the next received Intent. This affects the operation of the receiver: if you start a secondary thread from the Receiver, at the end of the onReceive() execution it is destroyed. It is therefore not possible to perform long operations. The Receiver is designed as a message handler. If you want to run a workload, the Receiver may delegate it to a Service with Context.startService(). Broadcast Receiver - LifeCycle
  7. 7. Broadcast Receivers e AppWidget public class ExampleBroadcastReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { } } N.B.: you can specify an Intent Filter in the Manifest file for each Activity and/or Service. These manages the Intents using the BroadcastReceiver taht starts the Activity in onRecive() method with Context.startActivity() or the Service with Context.startService(). Broadcast Receiver - LifeCycle
  8. 8. Broadcast Receivers e AppWidget An appwidget is a View that can be integrated into other applications (mainly the HomeScreen) and receives regular updates. In order to create an AppWidget, you need to use: AppWidgetInfo: it describes the AppWidget metadata as layout, update frequency and Provider. AppWidgetProvider: the class that extends BroadcastReceiver with the implementation of the basic methods for AppWidget editing at runtime Layout: .xml file to define the GUI In addition to this, it is possible to create a ConfigurationActivity for AppWidget configuration by the user. AppWidget
  9. 9. Broadcast Receivers e AppWidget Because the AppWidgetProvider is a BroadcastReceiver, this must be declared in the Manifest file: The metadata specify the name of the xml file to create the AppWidgetInfo object. The IntentFilter with the AppWidget Update should always be declared to enable the automatic update system. AppWidget - Declaration
  10. 10. Broadcast Receivers e AppWidget To create an AppWidgetInfo object, you must create a xml file in the /res/xml with the following content: AppWidget - MetaData
  11. 11. Broadcast Receivers e AppWidget To create the layout of a AppWidget, it must be considered that not all the View can be used. The Views that can be used are: FrameLayout LinearLayout RelativeLayout GridLayout Button ImageView ProgressBar TextView You can not use other View or Custom View (lists are not supported before HoneyComb). AppWidget - Layout
  12. 12. Broadcast Receivers e AppWidget The Android Home Screen is divided into cells: a smartphone is typically 4x4 cells, while a tablet can be 8x7. To determine the right size of the widget follow the following rule: AppWidget - Dimensions To define AppWidget different sizes depending on the terminal you can specify a different size in the xml file following the classic Android configurations pattern.
  13. 13. Broadcast Receivers e AppWidget public class ExampleAppwidgetProvider extends AppWidgetProvider { @Override public void onEnabled(Context context) { super.onEnabled(context); } @Override public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { super.onUpdate(context, appWidgetManager, appWidgetIds); } @Override public void onDeleted(Context context, int[] appWidgetIds) { super.onDeleted(context, appWidgetIds); } @Override public void onDisabled(Context context) { super.onDisabled(context); } } AppWidget - Provider
  14. 14. Broadcast Receivers e AppWidget public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { final int N = appWidgetIds.length; // Perform this loop procedure for each App Widget that belongs to this // provider for (int i = 0; i < N; i++) { int appWidgetId = appWidgetIds[i]; // Create an Intent to launch ExampleActivity Intent intent = new Intent(context, ExampleActivity.class); PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, Intent.FLAG_ACTIVITY_NEW_TASK); // Get the layout for the App Widget and attach an on-click // listener to the button RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.appwidget_provider_layout); views.setOnClickPendingIntent(R.id.button, pendingIntent); // Tell the AppWidgetManager to perform an update on the current // app widget appWidgetManager.updateAppWidget(appWidgetId, views); } } AppWidget - Provider
  15. 15. Broadcast Receivers e AppWidget To create an AppWidget configuration Activity, it must be declared in the Manifest file with an IntentFilter that specifies its purpose: The Activity must be declared in the AppWidgetProviderInfo: AppWidget Configuration Activity
  16. 16. Broadcast Receivers e AppWidget The Configuration Activity must always return an associated AppWidgetId result that identifies the instance of the Widget added to the Home Screen: when the user has defined the parameters, the Activity.setResult() method is invoked: setResult(RESULT_OK, intent); Then the Activity sends an update to the AppWidget: mAppWidgetId = getIntent().getIntExtra( AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID); AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(this); RemoteViews views = new RemoteViews(getPackageName(), R.layout.example_appwidget); appWidgetManager.updateAppWidget(mAppWidgetId, views); Intent resultValue = new Intent(); resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mAppWidgetId); setResult(RESULT_OK, resultValue); finish(); AppWidget Configuration Activity
  17. 17. Broadcast Receivers e AppWidget From HoneyComb (Android 3.0), you can create AppWidget composed by: ListViews GridViews StackViews To enter the data you need an Adapter that manages the RemoteView instead of the traditional view: that is why there is a service called RemoteViewsService that must be declared in the Manifest file: AppWidget Collections
  18. 18. Broadcast Receivers e AppWidget public class ExampleWidgetService extends RemoteViewsService { @Override public RemoteViewsFactory onGetViewFactory(Intent intent){ return new ExampleRemoteViewsFactory(); } } class ExampleRemoteViewsFactory implements RemoteViewsFactory{ @Override public int getCount() { return 0; } @Override public long getItemId(int arg0) { return 0; } @Override public RemoteViews getLoadingView() { return null; } @Override public RemoteViews getViewAt(int arg0) { return null; } AppWidget Collections @Override public int getViewTypeCount() { return 0; } @Override public boolean hasStableIds() { return false; }
  19. 19. Broadcast Receivers e AppWidget public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { // update each of the app widgets with the remote adapter for (int i = 0; i < appWidgetIds.length; ++i) { // Set up the intent that starts the StackViewService, which will // provide the views for this collection. Intent intent = new Intent(context, ExampleWidgetService.class); intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetIds[i]); intent.setData(Uri.parse(intent.toUri(Intent.URI_INTENT_SCHEME))); RemoteViews rv = new RemoteViews(context.getPackageName(), R.layout.widget_layout); // Set up the RemoteViews object to use a RemoteViews adapter. // This adapter connects // to a RemoteViewsService through the specified intent. // This is how you populate the data. rv.setRemoteViewsAdapter(appWidgetIds[i], R.id.stack_view, intent); rv.setEmptyView(R.id.stack_view, R.id.empty_view); appWidgetManager.updateAppWidget(appWidgetIds[i], rv); } super.onUpdate(context, appWidgetManager, appWidgetIds); } AppWidget Collections
  20. 20. Broadcast Receivers e AppWidget To handle the click of a single element of the list, use the method RemoteViews.setOnFillInIntent(). Its content is managed as following. @Override public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { for (int i = 0; i < appWidgetIds.length; ++i) { Intent toastIntent = new Intent(context, ExampleWidgetProvider.class); toastIntent.setAction(ExampleWidgetProvider.TOAST_ACTION); toastIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetIds[i]); PendingIntent toastPendingIntent = PendingIntent.getBroadcast( context, 0, toastIntent, PendingIntent.FLAG_UPDATE_CURRENT); rv.setPendingIntentTemplate(R.id.stack_view, toastPendingIntent); appWidgetManager.updateAppWidget(appWidgetIds[i], rv); } super.onUpdate(context, appWidgetManager, appWidgetIds); } AppWidget Collections
  21. 21. Broadcast Receivers e AppWidget @Override public RemoteViews getViewAt(int position) { RemoteViews rv = new RemoteViews(mContext.getPackageName(), R.layout.widget_item); rv.setTextViewText(R.id.widget_item, mWidgetItems.get(position).text); Bundle extras = new Bundle(); extras.putInt(StackWidgetProvider.EXTRA_ITEM, position); Intent fillInIntent = new Intent(); fillInIntent.putExtras(extras); rv.setOnClickFillInIntent(R.id.widget_item, fillInIntent); return rv; } AppWidget Collections