Android Tutorial Android home screen widgets tutorial - part I

Status
Not open for further replies.
Edit: widgets are handled with receivers now. See the attached example.

This tutorial will explain how to implement your own home screen widgets (also named App Widgets).

It is important to understand that the widgets are created and managed in another process, different than the process that your application is running in. The home screen application is hosting your widgets.
This means that it is not possible to directly access the widgets views. Instead we are using a special object named RemoteViews which gives us indirect access to the widget views.

Widgets do not support all views types. The following views are supported:
- Button (default drawable)
- Label (ColorDrawable or GradientDrawable)
- Panel (ColorDrawable or GradientDrawable)
- ImageView
- ProgressBar (both modes)

All views support the Click event and no other event.

The widget layout and configuration must be defined with XML files. During compilation Basic4android reads the layout file created with the designer and generates the required XML files.

Each widget is tied to a Service module. Through this module the widget is created and updated.

Creating a widget - step by step guide

- Add a Service module. Note that the service module handling the widget is a standard service.
- Design the widget layout with the designer. First add a Panel and then add the other views to this Panel.
The widget layout will be made from this panel.
- Add code similar to the following code the service module:
B4X:
Sub Process_Globals
    Dim rv As RemoteViews
End Sub

Sub Service_Create
    rv = ConfigureHomeWidget("LayoutFile", "rv", 0, "Widget Name")
End Sub

Sub Service_Start (StartingIntent As Intent)
     RV.HandleWidgetEvents(StartingIntent)
    Sleep(0)
    Service.StopAutomaticForeground
End Sub

Sub rv_RequestUpdate
    rv.UpdateWidget
End Sub

Sub rv_Disabled
    StopService("")
End Sub

Sub Service_Destroy

End Sub
- Compile and run your application. Go to the home screen, long press on the screen and you will see your widget listed on the widgets list.

ConfigureHomeWidget is a special keyword. At runtime it creates the RemoteViews object from the layout and set the events. At compile time the compiler generates the required files based on the arguments of this keyword.
The four parameters are: layout file, event name, update interval and the widget name.
Event name sets the subs that will handle the RequestUpdate and Disabled events.
The widget can be configured to update itself automatically. The interval, measured in minutes, defines how often will the widget request to update itself. Set to 0 to disable automatic updates. Updating the widget too often will have a bad impact on the battery. The minimum value is 30 minutes.
Widget name - the name that will appear in the widgets list.

As these arguments are read by the compiler, only strings or numbers are accepted.

Events:
B4X:
Sub Service_Start (StartingIntent As Intent)
    If rv.HandleWidgetEvents(StartingIntent) Then Return
End Sub
The above code checks the Intent message that caused this service to start and is responsible for raising the events related to the widget. It returns true if an event was raised.
The widget raises two events. RequestUpdate is raised when the widget needs to update itself. It will fire after adding the widget to the screen, after the device has booted, based on the scheduled updating interval (if set) or after the application was updated.
The Disabled event is raised when the last instance of our widget is removed from the screen.

As mentioned above all views support the Click event. All that needs to be done in order to handle the click event of a button named Button1 is to add a sub named Button1_Click (the sub name should actually match the EventName property which is by default the same as the name).

[/code]Modifying the widget:
It is not possible to directly access the widget views. Instead we need to use one of the RemoteView.Set methods.
If we want to change the text of a label named Label1 then we need to write the following code:
B4X:
rv.SetText("Label1", "This is the new text.")
'do more changes if needed
rv.UpdateWidget
After writing all the changes we call rv.UpdateWidget to send the updates to the widget.

A simple example is attached.
The example adds a simple widget. The widget doesn't do anything useful.
SS-2011.07.11-12.55.04.png

Note that it is recommended to test widgets in Release mode (the widget will fail in debug mode when the process is started by the OS).
 

Attachments

  • HomeWidgets.zip
    24.6 KB · Views: 569
Last edited:

enrique1

Member
Licensed User
Longtime User
I discussed this with Erel in another thread. B4A sets the Widget minWidth and minHeight values the same as your base panel. The problem here is that the cell size in portrait and landscape is different and you have to set the minimum of both variants for minWidth and minHeight. B4A currently does not support this very good.

You should calculate the values for minWidth and minHeight yourself with the formula (cellcount * 74) - 2 and then put these values manually in Objects/res/xml/<widget>_info.xml. Then make this file read only and be happy.

It is better to just set the panel size to this value instead.

Thank you very very much corwin42 and Erel! I had this problem! :icon_clap::icon_clap:
 

agraham

Expert
Licensed User
Longtime User
I'm confused about sizing and positioning widgets. On my Xoom a 1x1 widget can be a maximum of 95 x 95 pixels, on my Blade the same widget displays as 2x2. I need to reduce the widget size to 79 x 79 to get a 1x1 widget on the Blade but then the same widget on the Xoom doesn't look quite right as it is visually displaced up and to the left relative to the positioning of the other app icons. If I make it the "regulation" 72 x 72 pixels it looks even worse! I don't seem to be able to make a widget that looks the same on both devices as apparently I can't move or resize the Panel and it's views at runtime. :( Am I missing something obvious?
 

NJDude

Expert
Licensed User
Longtime User
I'm confused about sizing and positioning widgets. On my Xoom a 1x1 widget can be a maximum of 95 x 95 pixels, on my Blade the same widget displays as 2x2. I need to reduce the widget size to 79 x 79 to get a 1x1 widget on the Blade but then the same widget on the Xoom doesn't look quite right as it is visually displaced up and to the left relative to the positioning of the other app icons. If I make it the "regulation" 72 x 72 pixels it looks even worse! I don't seem to be able to make a widget that looks the same on both devices as apparently I can't move or resize the Panel and it's views at runtime. :( Am I missing something obvious?

I've been playing around with sizes too and I believe, at least from where I stand, the "sweet" number is 78x78, I will need to try this on different size screens but so far, on my phone and a tablet going by those numbers the widget looks centered.

I applied this formula, (cell-count x 80) - 2

on previous posts I've seen 74 instead of 80 for the same formula, but it looks better using 80.
 

corwin42

Expert
Licensed User
Longtime User
I'm confused about sizing and positioning widgets. On my Xoom a 1x1 widget can be a maximum of 95 x 95 pixels, on my Blade the same widget displays as 2x2.
[...]
I don't seem to be able to make a widget that looks the same on both devices as apparently I can't move or resize the Panel and it's views at runtime. :( Am I missing something obvious?

Thats the problem we all here have. The same widgets look different on all device resolutions. This is not a B4A issue but an Android issue. It gets even worse when you want to support portrait and landscape mode.

I've been playing around with sizes too and I believe, at least from where I stand, the "sweet" number is 78x78, I will need to try this on different size screens but so far, on my phone and a tablet going by those numbers the widget looks centered.

I applied this formula, (cell-count x 80) - 2

on previous posts I've seen 74 instead of 80 for the same formula, but it looks better using 80.

I think it will not look centered anymore when you change to landscape mode on your phone. The formula with 74 is from the official android development documentation.
 

Cableguy

Expert
Licensed User
Longtime User
This seems to beoverlooked, but in some home replacement apps like ADW, it is possible to define the number of columns for displaying apps icons...I have found that this setting afected the apearance of one of my current home screens widget... leaving a gapp in between the cells...

I'll try to post some images if I can replicate the issue
 
Last edited:

Cableguy

Expert
Licensed User
Longtime User
I cannot replicate it, seems to have been fixed in more ecent versions of ADW... Still, if we set a widget to its "original" size, to get a normal appearance one has to edit the widgwt on screen and resize it... or it will be down sized
 

corwin42

Expert
Licensed User
Longtime User
Here is a screen grab of one of my widgets on an HTC Desire.

What I did was lay down a transparent panel of 314 x 78, then put a visible panel on top which is 300 x 78 with all the controls on that visible panel. I then adjusted the second panel to center it

Neil

Ok your tip is really a step in the right direction but it is still static because you have to adjust the inner panel hard to the outer panel. So if your widget runs on another resolution or in landscape mode it is again not correctly centered. I have tried many things but wasn't successful to center a widget automatically in its cell.

I think we badly need layout variants for widgets as I suggested in the "Wishes" forum so we can create a variant for each resolution and for portrait and landscape mode.
 

corwin42

Expert
Licensed User
Longtime User
Note that the widget should scale properly on devices with different scales.

Yes, but devices with different screen resolutions have different cell sizes for the widgets. So it is impossible to get the widget centered properly on all resolutions.
 

anaylor01

Well-Known Member
Licensed User
Longtime User
I have a screen where a user can add icons to the widget. But they don't show up unless they delete the widget and re add it. Is there anyway around this without them having to wait half an hour?
 

corwin42

Expert
Licensed User
Longtime User
Widget sizes make me crazy...

I have done some more tests now and I have some nice things found out:

In this document they say that in portrait the widget cell size is 80x100 and in landscape it is 104x74. For portrait this seems to be correct on all resolutions. The problem is that on a 240x320 device the widget cells overlap! In landscape the document seems to be wrong for the standard android launcher (in the emulator) because here the cell size seems to be 80x74. On my device with Go-Launcher it seems to be correct with 106x74.

I have written a small test program in B4A to test widget sizes. I had to modify the xmls a bit to get the effect I want. Some screenshots are attached to show you my results:

1. Widget with cyan background: This is a standard widget how it can be created with B4A. This widget is always positioned in the upper left corner and positioning is very limited. The size of this widget is 294x74 (4x1) as suggested by the formula in the development documentation.

2. Widget with red background: This widget has a base panel with "fill_parrent" width and height. This means this widget will cover the complete cell size.

3. Widget with green background: This widget has a base panel with a fixed size of 320x100 dp so it should always cover full 4x1 cells in portrait mode. For landscape this widget is too high.

4. Widget with orange background: This widget is like the third widget but it should fit full 4x1 cells in landscape mode

5. Widget with yellow background: This is a test what can be done manually modifying the xml files. I added two linear layouts (one horizontal and one vertical) around the base panel to center the base panel in the middle of the cell. The base panel has a size of 300x70 dp and is nicely centered in all resolutions and orientations.

If it were christmas I had following wishes: :)
1. Additional parameters to ConfigureHomeWidget to specify the widget dimension (width, height so you can specify them as 4, 1 for a 4x1 widget). These parameter should be used to calculate the minWidth and minHeight for the widget_info.xml.

2. The compiler should add the trick of the 5th widget with the two linearlayouts that our widgets are always centered in the cells.

3. The compiler should support layout variants so that we can design widget layouts for all device resolutions. Then you can design different widgets layouts for portrait and landscape orientation. And even more important you can design different widget sizes for different resolutions (make your widget smaller on 240x320 devices so that they don't overlap)

I think with this changes widget support would be nearly perfect.

You can see in the screenshots that a 300x70dp widget looks nice on a 240x320 screen in portrait and landscape but leaves much space on a 480x800 screen in portrait mode.

I have added my project folder. I hope the xml files are still read only after unzipping.
 

Attachments

  • device240x320l.jpg
    device240x320l.jpg
    22.1 KB · Views: 644
  • device240x320l_centered.jpg
    device240x320l_centered.jpg
    20.7 KB · Views: 529
  • device240x320p.jpg
    device240x320p.jpg
    23.9 KB · Views: 506
  • device240x320p_centered.jpg
    device240x320p_centered.jpg
    22.9 KB · Views: 470
  • device320x480l.jpg
    device320x480l.jpg
    38.9 KB · Views: 496
  • device320x480l_centered.jpg
    device320x480l_centered.jpg
    37.7 KB · Views: 457
  • device320x480p.jpg
    device320x480p.jpg
    38.3 KB · Views: 469
  • device320x480p_centered.jpg
    device320x480p_centered.jpg
    39.2 KB · Views: 473
  • device480x800l_centered.jpg
    device480x800l_centered.jpg
    23.1 KB · Views: 456
  • device480x800p_centered.jpg
    device480x800p_centered.jpg
    23.2 KB · Views: 488
  • WidgetTest.zip
    13.9 KB · Views: 652

jota

Active Member
Licensed User
Longtime User
The example [HomeWidgets] to run it works perfectly, but if I add the library [Phone v1.42], I get the following error:


Installing file.
PackageAdded: package:anywheresoftware.b4a.samples.homewidgets
** Activity (main) Create, isFirst = true **
** Activity (main) Resume **
** Activity (main) Pause, UserClosed = true **
** Service (widgetservice) Create **
** Service (widgetservice) Start **
widgetservicehandleStart (java line: 61)
java.lang.Exception: Sub service_start signature does not match expected signature.
at anywheresoftware.b4a.BA.raiseEvent2(BA.java:107)
at anywheresoftware.b4a.BA.raiseEvent(BA.java:89)
at anywheresoftware.b4a.samples.homewidgets.widgetservice.handleStart(widgetservice.java:61)
at anywheresoftware.b4a.samples.homewidgets.widgetservice.onStartCommand(widgetservice.java:46)
at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:3246)
at android.app.ActivityThread.access$3600(ActivityThread.java:135)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2205)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:143)
at android.app.ActivityThread.main(ActivityThread.java:4914)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:521)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:858)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
at dalvik.system.NativeStart.main(Native Method)

This behavior only happens to me with the library [phone] the rest are good,
I tested this on a tablet BQ and a HTC firewire. thanks

----------------------------------------------------------------------------------

El ejemplo [HomeWidgets] al ejecutarlo funciona perfectamente, pero si le añado la libreria [Phone v1.42], me da el siguiente error:

....
....
....

este comportamiento solo me sucede con la libreria [phone] el resto van bien, esto lo he probado en una tablet bq y en un telefono HTC firewire. Gracias
 
Last edited:

jota

Active Member
Licensed User
Longtime User
Thanks, that was the problem. Is there any library most affected in the change or was only the phone library?.

-----------------------------------------------------------------------------------

Gracias, ese era el problema. Hay alguna libreria mas afectada en el cambio o solo era la libreria phone?.
 

alfcen

Well-Known Member
Licensed User
Longtime User
Widgets made easy.

Hi Erel,
Just a quick note to thank you very much, indeed, for implementing a painless means of creating attractive widgets.
It is as easy as 1-2-3! I tied a widget with interactive functions to one of my astronomy applications in virtually no time.

widget.png
 
Last edited:
Status
Not open for further replies.
Top