3.1 What views does appwidget support?
In the Android 2.2 SDK, we started the simulator for the first time and we can see that, unlike before, there was an extra green robot prompt message, google showed us how to achieve the animation effect through remoteview and simple image rotation in Android in desktop gadgets. The appwidgetprovider class is used for the basic category of appwidget, however, the life cycle management of widgets is not activity, but broadcastreceiver broadcast. I always wanted to know how to add complicated views such as listview and edittext TO THE appwidget. we know that all views to be added to the appwidget are done through remoteview. However, remoteview itself has very weak functions and supports very few operations. In addition, there are few widgets that support remoteview:
A remoteviews object (and, consequently, an app widget) can support the following layout classes:
Framelayout
Linearlayout
Relativelayout
And the following widget classes:
Analogclock
Button
Chronometer
Imagebutton
Imageview
Progressbar
Textview
Descendants of these classes are not supported.
You can see from here why adding edittext to the appwidget will display loaderror, because it does not support these complex widgets.
But we have another question. Why does Google search have edittext? In fact, this is an illusion, not that appwidget supports edittext. After careful consideration, you should find that analogclock is not a simple widget like button and textview. In fact, analogclock is also a custom remoteviews of Google.
On the Internet, we can see that appwidget has many special effects. It does support complex widgets, such as listview, gridview, and edittext. These are what we can see, but how does it do it? I also want to know that appwidget supports so powerful and even exceeds its ap functions, which is very eye-catching. But no matter how it is implemented, I think people must have made great efforts to do it. I guess it is possible that the appwidget provided by Google has been greatly changed. Let's take a look at the appwidget under the framework:
: Ls frameworks/base/CORE/Java/Android/appwidget/-lH
Total 60 k
-RW-r -- 1 pjq users 7.9 K appwidgethost. Java
-RW-r -- 1 pjq users 12 K appwidgethostview. Java
-RW-r -- 1 pjq users 14 K appwidgetmanager. Java
-RW-r -- 1 pjq users 691 appwidgetproviderinfo. aidl
-RW-r -- 1 pjq users 5.6 K appwidgetproviderinfo. Java
-Rwxr-XR-x 1 pjq users 6.3 K appwidgetprovider. Java
-RW-r -- 1 pjq users 1.5 K package.html
As you can see, there are very few appwidget files. Although I cannot describe anything, but according to the normal reasoning, there are usually few files with powerful functions. This idea is somewhat far-fetched, but for the moment, I think so.
3.2 How to customize remoteviews
You need to know that remoteview has very few functions, especially the ability to process events, which must be passed to broadcastreceiver through pendingintent for processing. So here we can only process some simple things: for example, button clicked. Others seem to have not been used yet. For complex views: for example! Listview (not supported here, for example ),! There are so many items in the listview that you need to set listener and pass values. These remoteviews cannot be processed as a simple activity. If you want to implement them, you need more complicated means, broadcast.
Because the calendar widget needs to implement complex operations and effects such as onclick events, display calendars, and animation effects, the operations supported by appwidget are far from sufficient. Therefore, you need to modify the code in the framework, currently, I have displayed complex widgets OF THE calendarview and viewflipper IN THE appwidget, and realized how to make these custom remoteviews interact with the appwidget. Now let me introduce in detail how to customize the complex widgets in the appwidget, such as calendarview (inherited from the View) and viewflipper (only modified on the original basis.
We know that appwidgets only support remoteview, and which widgets are remoteview. I will show you how to search for them:
frameworks/base/core/java/android/widget $ grep -i -n -A 1 @remoteview *.javaAbsoluteLayout.java:40:@RemoteViewAbsoluteLayout.java-41-public class AbsoluteLayout extends ViewGroup {--AnalogClock.java:39:@RemoteViewAnalogClock.java-40-public class AnalogClock extends View {--Button.java:58:@RemoteViewButton.java-59-public class Button extends TextView {--Chronometer.java:45:@RemoteViewChronometer.java-46-public class Chronometer extends TextView {--FrameLayout.java:47:@RemoteViewFrameLayout.java-48-public class FrameLayout extends ViewGroup {--ImageButton.java:66:@RemoteViewImageButton.java-67-public class ImageButton extends ImageView {--ImageView.java:55:@RemoteViewImageView.java-56-public class ImageView extends View {--LinearLayout.java:44:@RemoteViewLinearLayout.java-45-public class LinearLayout extends ViewGroup {--ProgressBar.java:122:@RemoteViewProgressBar.java-123-public class ProgressBar extends View {--RelativeLayout.java:66:@RemoteViewRelativeLayout.java-67-public class RelativeLayout extends ViewGroup {--TextView.java:186:@RemoteViewTextView.java-187-public class TextView extends View implements ViewTreeObserver.OnPreDrawListener {
That's all. "@ remoteview" is added before the class name. Is it the same as the ones listed above? Therefore, if you need to customize a (or a complicated view such as listview) as remoteviews, you must add the "@ remoteview" identifier before the class name.
For details about how to customize a widget, refer to the existing widgets of frameworks/base/CORE/Java/Android/widget.
In fact, if you need to customize a widget, for example, to support listview, You can implement it in an activity and then move it to the framework.
Note the following points:
1. If you have multiple files and want to package them, you 'd better follow the format below: Android. widget. calendarview
The calendarview is the place where you want to add widgets to store them. In this way, you can add the calendarview folder in the frameworks/base/CORE/Java/Android/widget directory, put the Java file in this directory.
If the new widget has only one Java file, you can use the existing widget as needed, directly put the Java file in the frameworks/base/CORE/Java/Android/widget directory.
2. Resource file storage:
Frameworks/base/CORE/RES/Res
All resource source files are stored in this directory.
3. Resource reference:
Reference: COM. Android. Internal. R. drawable.
- Remember to add the "@ remoteview" mark before the customer widget class name.
After completing these steps, you have added a custom widget to the framework. The next step is to compile the entire project. (here we will teach you a relatively lazy method. Compile frameworks directly and run the following command:
: Mmm frameworks/base/
: ADB push out/target/product/msm7627_ffa/system/framework/
Framework. Jar/system/framework /).
Finally, you can reference your custom widget in appwidget:
Com. widget. calendarview.
3.3 How does appwidget access remoteviews
At this point, you have used the custom widget and can add it to the appwidget. If you want to display calendar-like content on the custom remoteviews, you only need to implement it in the ondraw () method of the custom remoteviews. However, not all content is pre-configured in remoteviews, and many content is set by the user. For example, if "helloword" is displayed in appwdiget, we implement it in this way.
Remoteviews views = new remoteviews (context. getpackagename (), R. layout. appwidget_provider );
Views. settextviewtext (R. Id. appwidget_text, "helloword ");
Remoteviews provides a very limited number of external methods. For more information, see the API documentation:
Public Methods view apply (context, viewgroup parent)
Inflates the view hierarchy represented by this object and applies all of the actions.
Int describecontents ()
Describe the kinds of special objects contained in this parcelable's stored alled representation.
Int getlayoutid () string getpackage () Boolean onloadclass (class clazz)
Hook to allow clients of the layoutinflater to restrict the set of views that are allowed to be inflated.
Void reapply (context, view V)
Applies all of the actions to the provided view.
Void setbitmap (INT viewid, string methodname, bitmap value)
Call a method taking one bitmap on a view in the layout for this remoteviews.
Void setboolean (INT viewid, string methodname, Boolean value)
Call a method taking one Boolean on a view in the layout for this remoteviews.
Void setbyte (INT viewid, string methodname, byte value)
Call a method taking one byte on a view in the layout for this remoteviews.
Void setchar (INT viewid, string methodname, char value)
Call a method taking one char on a view in the layout for this remoteviews.
Void setcharsequence (INT viewid, string methodname, charsequence value)
Call a method taking one charsequence on a view in the layout for this remoteviews.
Void setchronometer (INT viewid, long base, string format, Boolean started)
Equivalent to calling chronometer. setbase, chronometer. setformat, and chronometer. Start () or chronometer. Stop ().
Void setdouble (INT viewid, string methodname, double value)
Call a method taking one double on a view in the layout for this remoteviews.
Void setfloat (INT viewid, string methodname, float value)
Call a method taking one float on a view in the layout for this remoteviews.
Void setimageviewbitmap (INT viewid, Bitmap bitmap)
It is equivalent to calling the imageview. setimagebitmap method, and setting an image from the bitmap object
Void setimageviewresource (INT viewid, int srcid)
It is equivalent to calling imageview. setimageresource to set an image from a resource.
Void setimageviewuri (INT viewid, Uri URI)
It is equivalent to calling imageview. setimageuri to set the image from URI
Void setint (INT viewid, string methodname, int value)
Call a method taking one int on a view in the layout for this remoteviews.
Void setlong (INT viewid, string methodname, long value)
Call a method taking one long on a view in the layout for this remoteviews.
Void setonclickpendingintent (INT viewid, pendingintent)
Equivalent to calling setonclicklistener (Android. View. View. onclicklistener) to launch the provided pendingintent.
Void setprogressbar (INT viewid, int Max, int progress, Boolean indeterminate)
It is equivalent to calling progressbar. setmax, progressbar. setprogress, and progressbar. If indeterminate is true, the maximum and minimum progress of the progress bar will be ignored.
Void setshort (INT viewid, string methodname, short value)
Call a method taking one short on a view in the layout for this remoteviews.
Void setstring (INT viewid, string methodname, string value)
Call a method taking one string on a view in the layout for this remoteviews.
Void settextcolor (INT viewid, int color)
It is equivalent to settextcolor (INT). It sets the text color.
Void settextviewtext (INT viewid, charsequence text)
Equivalent to textview. settext, set text content
Void seturi (INT viewid, string methodname, Uri value)
Call a method taking one URI on a view in the layout for this remoteviews.
Void setviewvisibility (INT viewid, int visibility)
It is equivalent to calling view. setvisibility to set the visibility of the ID control.
Void writetoparcel (parcel DEST, int flags)
Flatten this object in to a parcel.
No matter how many methods your custom remoteview has, it is a remoteviews after all. Therefore, you can only call the methods provided above by using remoteviews (whether custom or not) in appwidget. Now you must be confused. Isn't the appwidget able to call methods in custom remoteviews? Yes, of course. In addition, the results in remoteviews can be fed back to appwidget to realize interaction between appwidget and remoteviews. However, this method is complicated, so let me know it slowly.
There are several special methods in the above method
Void java. Lang. String, Android. Graphics. Bitmap) setbitmap (INT viewid, string methodname, bitmap value)
Void java. Lang. String, Boolean) setboolean (INT viewid, string methodname, Boolean value)
Void java. Lang. String, byte) setbyte (INT viewid, string methodname, byte value)
Void java. Lang. String, char) setchar (INT viewid, string methodname, char value)
Void java. Lang. String, java. Lang. charsequence) setcharsequence (INT viewid, string methodname, charsequence value)
Void java. Lang. String, double) setdouble (INT viewid, string methodname, double value)
Void java. Lang. String, float) setfloat (INT viewid, string methodname, float value)
Void java. Lang. String, Android. OS. Bundle) setbundle (INT viewid, string methodname, bundle value)
These methods are interfaces to custom remoteviews. They all contain three parameters. The first parameter viewid is the ID you want to call remoteviews defined in the layout file, and the second parameter methodname is the method name in the remoteviews you want to call, if you want to call a setname (string name) in remoteviews, you can set the second parameter to "setname". The third parameter is the parameter of the method you want to call, take the setname (string name) method as an example. If you must input a string parameter, void Java is called here. lang. string,
Java. Lang. charsequence) setcharsequence (INT viewid, string methodname, charsequence value), because only the third parameter of this method is of the string type. Here is an example:
/* Custom remoteview */@ remoteviewpublic class calendarview extends view {... /@ hide */@ android. view. remotableviewmethod public void settextsize (bundle) {mlinesize = bundle. getint ("linesize", 1); mdigitalsize = bundle. getint ("digitalsize", 2 );}...} /* how to call appwidget */... remoteviews views = new remoteviews (context. getpackagename (), R. layout. agenda_appwidget); bundle = new bundle ();...... views. java. lang. string, android. OS. bundle) setbundle (R. id. preview, "settextsize", bundle );
This completes a call. When the appwidget calls views. java. Lang. String, Android. OS. Bundle) setbundle (...), it is equivalent to calling
The settextsize method in the calendar. In this way, the appwidget accesses remoteviews.
Note: Before settextsize, you must add @...
3.4 appwidget receives information from remoteviews
Next, let's talk about your operations on custom remoteviews. How can I make the appwidget respond to feedback?
There seems to be no better way. Fortunately, Android provides a very effective medium for different processes to transmit data and events, that is, the broadcast mechanism. When you need to inform the appwidget of the custom remoteviews operation, you need to use the broadcast mechanism to send a broadcast and register the broadcast listening in the appwidget. Then the appwidget can respond. The broadcast mechanism is very clear to everyone, so we will not be able to make an axe here.
3.5 enable the appwidget to achieve page flip Animation
So how can we achieve viewflipper flip animation?
If you know all about the above, it's easy to flip the page. Similarly, the remoteview ID @ remoteview will be added before the viewflipper class, so that the appwidget supports viewflipper. Because the custom calendarview above is supported, viewflipper and calendarview can be added to the appwidget layout file (widgets not supported by appwidget cannot be added to the appwidget layout file, otherwise, an error occurs ). So how to achieve the page flip animation effect is actually not much different from the general viewflipper, first look at the layout file:
<ViewFlipper android:id="@+id/flipper" android:layout_width="fill_parent" android:layout_height="fill_parent" android:gravity="center" android:persistentDrawingCache="animation" android:flipInterval="1000" <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"><CalendarView android:id="@+id/preview" android:layout_width="match_parent" android:layout_height="match_parent"/></LinearLayout><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:orientation="vertical" android:layout_width="match_parent"android:layout_height="match_parent"><CalendarView android:id="@+id/nextview" android:layout_width="match_parent" android:layout_height="match_parent"/></LinearLayout></ViewFlipper>
There are two calendarviews in viewflipper. How to achieve page turning? If you only need to flip the page in one direction, you can write it in the configuration file. However, if you need to flip the page up or down, you need to add two shownext entries in viewflipper, showprevious method (because the appwidget cannot use remoteview to draw an object to viewflipper), and put the animation file in the framework, for example:
/@hide*/ @android.view.RemotableViewMethod public void showPreviousAppWidget(String str) { setInAnimation(AnimationUtils.loadAnimation(this.getContext(), com.android.internal.R.anim.slide_in_right)); setOutAnimation(AnimationUtils.loadAnimation(this.getContext(), com.android.internal.R.anim.slide_out_left)); setDisplayedChild(mWhichChild - 1); } /@hide*/ @android.view.RemotableViewMethod public void showNextAppWidget(String str) { setInAnimation(AnimationUtils.loadAnimation(this.getContext(), com.android.internal.R.anim.slide_in_left)); setOutAnimation(AnimationUtils.loadAnimation(this.getContext(), com.android.internal.R.anim.slide_out_right)); setDisplayedChild(mWhichChild + 1); }
Similarly, the two methods will be called in the appwidget. Therefore, add @ Android. View. remotableviewmethod to the appwidget. The STR parameter is only used for matching.
Void java. Lang. String, java. Lang. charsequence) The third parameter of setcharsequence (INT viewid, string methodname, charsequence value. Call java. Lang. String in appwidget,
Java. Lang. charsequence) when the setcharsequence method is used, the third parameter is passed in "".
Then, how does one implement ontouch events in appwidget? In fact, it is also simple to add gesturedetector to the custom remoteview to identify gestures and send the corresponding broadcast to the appwidget so that the appwidget can be processed accordingly.
3.6 conclusion
Then I will talk about Some Problems and Suggestions for using appwidget.
1. Check the appwidget source code to know that appwidget inherits broadcastreceiver, And the onupdate, ondeleted, onenabled, and ondisabled methods of appwidget are all differentiated from onreceive. How can appwidget receive broadcasts? Rewrite onreceive, but at last you must call appwidgetmanager. updateappwidget (appwidgetids, views.
2. the life cycle of broadcastreceiver is short. When a message is received, it will be destroyed soon. It is best to start a service after receiving the message to make a lot of calculations, and pass the data to the service, let the service help us calculate. Of course, another key here is to upload int [] appwidgetids to the service through a Share Class. After the service executes the play task, it calls appwidgetmanager. updateappwidget (appwidgetids, views) to refresh the appwidget.
3. The appwidget is refreshed on a regular or regular basis. Therefore, it is necessary to put static variables in a share class. You can also use the Share Class to pass the appwidgetids value, so that you can easily refresh the appwidget in the service.