Android Study Notes: Home Screen Widgets (2): Widgets

Source: Internet
Author: User
Tags home screen

Android Study Notes: Home Screen Widgets (2): Widgets

Through the widget definition, we can see our TestWidget In the widget list. When we drag the widget to the home page, if the android: configure java class is defined in appwidet-provider, after a widget instance is created, the activity configuration is immediately triggered. This activity mainly completes two tasks: 1. Configure the initialization data; 2. Adapt the configuration data to the widget instance.

Use preference to store configuration data

Widget data can be stored in files, Share preference, or SQLite3. Widgets are configured with a small amount of data, which can be stored in preference conveniently. The BirthDayStoreData class is used for data storage and reading in preference. In Pro Android Study Notes (Sat 3): Preferences (7): "using preference to save status" in code control Preferences, we have already introduced how to implement it. Here, let's review it.

The stored content includes widgetID, name, birthday, and Preference, which are stored as key-value pairs. we store the information using name_widgetID as the key and birthday as the value.

Public class BirthDayStoreData {
Private final static String BIRTHDAY_WIDGET_PROVIDER_NAME = "cn. wei. flowingflying. testwidget. provider ";

// Save configuration data: Create a widget instance. When configuring through configure activity, save the configuration data.
Public static void storeData (Context context, int widgetId, String name, String value ){
String key = getKey (widgetId, name );
// The first parameter is the preferences file, which is created if it does not exist. For details, see/data/cn. wei. flowingflying. testwidget/shared_prefs/cn. wei. flowingflying. testwidget. provider. xml, which can be viewed in DDMS.
Editor editor = context. getSharedPreferences (BIRTHDAY_WIDGET_PROVIDER_NAME, Context. MODE_PRIVATE). edit ();
Editor. putString (key, value );
Editor. commit ();

}

//Delete configuration data: When deleting a widget instance, you must delete the data of the widget instance.
Public static void removeData (Context context, int widgetId ){
String key = getKeyById (context, widgetId );
If (key = null)
Return;
Editor editor = context. getSharedPreferences (BIRTHDAY_WIDGET_PROVIDER_NAME, Context. MODE_PRIVATE). edit ();
Editor. remove (key );
Editor. commit ();
}
// Clear all configuration data
Public static void removeAllData (Context context ){
Editor editor = context. getSharedPreferences (BIRTHDAY_WIDGET_PROVIDER_NAME, Context. MODE_PRIVATE). edit ();
Editor. clear ();
Editor. commit ();
}

// Display configuration data: Used for tracking in LogCat. Here, we also demonstrate how to display all the data through polling. In a similar way, we can find the corresponding name and birthday in the same way as widgetId. By using a similar method, we can query the key, name, birthday, and related code according to widgetId.
Public static void showData (Context context ){
SharedPreferences prefs = context. getSharedPreferences (BIRTHDAY_WIDGET_PROVIDER_NAME, Context. MODE_PRIVATE );
Map Pairs = prefs. getAll ();
Log. d ("DATA", "Total" + pairs. size () + "widgets :");
For (String key: pairs. keySet ()){
String value = (String) pairs. get (key );

Log. d ("DATA", key + "-" + value );
}
}

Public static String getNameById (Context context, int widgetId ){
... ...
}

Public static String getDateById (Context context, int widgetId ){
... ...
}

Private static String getKey (int widgetId, String name ){
Return name + "_" + widgetId;
}

Private static String getKeyById (Context context, int widgetId ){
... ...
}

}

Configure initialization data

The code for configuring configure activity is as follows:

Public class ConfigBirthDayWidgetActivity extends Activity {
Private static String tag = "ConfigActivity ";
Private int myWidgetId = AppWidgetManager. INVALID_APPWIDGET_ID;

@ Override// The operation for configuring an activity is the same as that for a normal activity. However, when AppWidgetManage is invoked, intent carries the widgetId information. We obtain the Widget ID in onCreate.
Protected void onCreate (Bundle savedInstanceState ){
... ...
Intent intent = getIntent ();
Bundle B = intent. getExtras ();
If (B! = Null ){
MyWidgetId = B. getInt (AppWidgetManager. EXTRA_APPWIDGET_ID, AppWidgetManager. INVALID_APPWIDGET_ID );
}

If (myWidgetId = AppWidgetManager. INVALID_APPWIDGET_ID ){
Toast. makeText (this, "Widget Error: no valid widget ID", Toast. LENGTH_LONG). show ();
Finish ();
}

}

......

// Method called after you click "Configure button"
Private void getAndStoreConfigInfo (){
... ... String name indicates the user's input name, and String date indicates the user's input valid date.
// [1] Keep data in preference and display all data
BirthDayStoreData. storeData (this, myWidgetId, name, date );
BirthDayStoreData. showData (this );
// [2] associate the configuration data with a specific widget instance. For details, refer to the following section.
BirthDayStoreData. updateAppWidget (this, myWidgetId, name, date );

// [3] Return the result to the AppWidget Manager to notify it that the aggregator has been completed. The function is as follows: startActivityForResult () returns a value and notifies AppWidgetManager that a widgetId has been configured. The created widget instance can be displayed on the homepage.
Intent resultIntent = new Intent ();
ResultIntent. putExtra (AppWidgetManager. EXTRA_APPWIDGET_ID, myWidgetId );
SetResult (RESULT_ OK, resultIntent );

// [4] disable activity
Finish ();
}
}

Configure data to adapt to the widget instance

The view of the Widget instance must be controlled through RemoteViews. The small example adopts the static method. The code snippet is as follows:

Public class BirthDayStoreData {
......

Public static void updateAppWidget (Context context, int widgetId, String name, String date ){
// [1] set the Remote view information
// 1.1). Obtain the remote view object.
RemoteViews views = new RemoteViews (context. getPackageName (), R. layout. birday_widget );
// 1.2). Set the setText () for the remote view.
Views. setTextViewText (R. id. bd_name, widgetId + ":" + name );
Views. setTextViewText (R. id. bd_date, date );
Views. setTextViewText
(R. id. bd_days, Long. toString (Utils. howFarInDays (Utils. getDate (date); // Utils is a class for processing dates.
// 1.3). Click to process a view through PendingIntent. In intent mode, you can open activity, service, Referer, and so on. In this example, a webpage is opened.
Intent intent = new Intent (Intent. ACTION_VIEW, Uri. parse ("http://www.taobao.com "));
PendingIntent pi = PendingIntent. getActivity (context, 0, intent, 0 );
Views. setOnClickPendingIntent (R. id. bd_buy, pi );


// [2] The application is implemented on the widgetId instance through AppWidgetManger.
AppWidgetManager appWidgetManager = AppWidgetManager. getInstance (context );
AppWidgetManager. updateAppWidget (widgetId, views );

}

Public static void updateAppWidget (Context context, int widgetId ){
... ...
}

}

According to the widget definition, the Java class of our App Widget Provider is BirthDayWidgetProvider, which is used to manage the lifecycle of widgets.

Public class BirthDayWidgetProvider extends AppWidgetProvider {
Private static String tag = "BirthDayWidgetProvider ";

@ Override/* OnUpdate () is called in three cases (). OnUpdate () is performed in the main thread. Therefore, if the processing takes more than 10 seconds, the processing should be completed in the service.
(1) call at the time interval. The interval is set in android: updatePeriodMillis defined by the widget;
(2) drag the user to the home page to generate a widget instance.
Whether Configure activity is set or not, in the test of Android4.4, when you drag an image to the home page, the widget instance is generated, onUpdate () is triggered, and then the activity is displayed (if any ). This is different from the document. The document assumes that if Configure acitivity is set, onUpdate () will not be called at the beginning, and the experiment shows that when the instance is generated (including when it is created and restarted ), onUpate () is called first (). In this example, because no data exists in the preference, you cannot set the data when creating an instance.
(3) When the machine restarts, the instance is displayed on the home page and onUpdate () is called again ()*/
Public void onUpdate (Context context, AppWidgetManager appWidgetManager, int [] appWidgetIds ){
Log. d (tag, "onUpdate () called. Available" + appWidgetIds. length + "widgets ");
For (int I = 0; I <appWidgetIds. length; I ++ ){
Log. d (tag, "update widget ID" + appWidgetIds [I]);
BirthDayStoreData. updateAppWidget (context, appWidgetIds [I]);
}
}

@ Override/* Some widgets are deleted from the home page and related data of the widget is deleted here */
Public void onDeleted (Context context, int [] appWidgetIds ){
Log. d (tag, "onDeleted () called ");
For (int I = 0; I <appWidgetIds. length; I ++ ){
Log. d (tag, "delete widget" + appWidgetIds [I] + "data ");
BirthDayStoreData. removeData (context, appWidgetIds [I]);
}
BirthDayStoreData. showData (context );
}

@ Override/* You do not need to override this method. The App Widget provider is essentially a receiver, which can track the messages received here, including AppWidgetManager. ACTION_APPWIDGET_DELETED/UPDATE/ENABLED/DISABLED, super. oncycler () triggers different callback functions based on the message type. If you use AlarmManager or custom broadcast, you can process it again. */
Public void onReceive (Context context, Intent intent ){

Log. I (tag, "onReceive ():" + intent );
Super. onReceive (context, intent );
}

@ Override/* Indicates that at least one widget instance is dragged to the homepage, that is, the callback function when the first widget appears. We need to allow the broadcast receiver to receive messages. The first widget appears. We can register other custom broadcasts of interest here */
Public void onEnabled (Context context ){

Log. d (tag, "onEnabled () called, context" + context. toString ());
// SetComponentEnabledSetting is equivalent to setting android: enabled to true | false for the squadron component in the AndriodMenifest. xml file. The listener is set here. If it is set to true, the listener is allowed, including starting and restarting the instance.
PackageManager pm = context. getPackageManager ();
/* An unknown error occurs when new ComponentName ("cn. wei. flowingflying. testwidget", ". BirthDayWidgetProvider") is used,
* You can use the full name for the class name, and new ComponentName ("cn. wei. flowingflying. testwidget ",
* "Cn. wei. flowingflying. testwidget. BirthDayWidgetProvider "),
* New ComponentName (context, getClass ())*/
Pm.SetComponentEnabledSetting(New ComponentName (context, getClass ()),
PackageManager. COMPONENT_ENABLED_STATE_ENABLED,
PackageManager. DONT_KILL_APP );
}

@ Override/* The Last widget has been deleted from the home page. Here, make sure that all configuration data is deleted. Broadcast listening is not required. Color-woven enabled = false. If a registered custom broadcast exists, here unregister */
Public void onDisabled (Context context ){
BirthDayStoreData. removeAllData (context );
PackageManager pm = context. getPackageManager ();
Pm. setComponentEnabledSetting (new ComponentName (context, getClass ()),
PackageManager. COMPONENT_ENABLED_STATE_DISABLED,
PackageManager. DONT_KILL_APP );
}

}

If no instance exists on the homepage, the trigger sequence of the new instance is onEnabled ()-> onUpdate ()-> Configure Activity. The first two sequences may change. It is estimated that the asynchronous processing of AppWidgetManager causes the order of broadcast messages. If an instance already exists, the trigger sequence of the new instance is onUpdate ()-> Configure activity. After configuration, wait for the defined interval to regularly trigger onUpdate ().

When the machine restarts onEnabled ()-> onUpdate (), the first two orders may be exchanged. After that, wait for the time interval defined by the widget to periodically trigger onUpdate ().

If we update or reinstall the apk, the instance will not be deleted and onUpdate () will be triggered ().

Supplement: Widget icon

Widgets are usually displayed in the Widget list. The Android simulator has an app widget Preview to help us get the widget's appearance icon, as shown below:

Use adb pull to obtain the preview image stored in the Download path of the SD card of the simulator as the list display icon.



Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.