Transcript of Android App Development - 13 Broadcast receivers and app widgets
- 1. Broadcast Receivers e AppWidget
- 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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