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: 823
Last edited:

Quillok

Member
Licensed User
Longtime User
I have done some more tests now and I have some nice things found out:

[...]

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.

[...]

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

Hi,
I'm trying to use you suggestion with the 5th widget, but my widget will not center. I did everything as you in your file, the settings in the designer are the same, the size and the settings in the xml also. But my widget is everytime at the left border.
Then i tried copying your code and .bal file and .xml file, but nothing changes, the widget is never be centered. When I compile your program and add the widget it is perfectly centered, which makes me crazy.
Have you done something more that I can't see from your code? For example I'm don't really sure what you mean with this sentence:
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.
Did you mean the panel with alpha = 0? Or have you done something else I'm not seeing?
 

corwin42

Expert
Licensed User
Longtime User
My centering hack is not necessary anymore since Erel added it directly to the ConfigureHomeWidget call. Add a "True" for the last parameter and your widget will be centered automatically.
 

joneden

Active Member
Licensed User
Longtime User
Widget heights in JB and maybe ICS

Morning Erel,

I'm having a quick stab at Widgets and they seem simple (with one exception) so far.

I'm finding a problem with the size. If I set the height to 80 then it almost matches the height of an existing 4x1 widget (the existing one must be something like 85 - it's the JB stock weather panel) BUT Android seems to think that mine needs to take up 2 rows. If I change the panel size down to 62 then the widget is way smaller than the weather one but this time it does install on one row.

This is running on a JB device if that makes a difference.

Are there some padding or margin settings that apply?

Best Regards,

Jon
 

joneden

Active Member
Licensed User
Longtime User
OK I've played with the size and increased it to what I wanted and for some odd reason now it sees it as the correct size. I did add (4 x 1) to the name but doubt that Android uses that as a guide :)

Another question re widgets is that some seem to have the app icon and others have a picture of the widget - AccuWeather for example. How do you go about adding a picture of the widget to the Widget chooser screen?

Regards,

Jon
 

joneden

Active Member
Licensed User
Longtime User
Hi Erel,

You linked to my own post :) This was a different problem though. For some reason the system thought that a very small widget was bigger than it is. All sorted now, although it's still intermittently not ahowing the widget in the list of available widgets. I'll post a message if it seems to be a bug and not my code.

Regards,

Jon
 

ggpanta

Member
Licensed User
Longtime User
Possible to create the GUI as normal without the designer?

Is it possible to create the GUI as I do with a normal app?
Loading the a GUI from the designer is not optimal for me, can I just draw the GUI in Service_Create?

Regards
 

Jost aus Soest

Active Member
Licensed User
Longtime User
It's possible to create the GUI via code. You find many examples in this forum...

The base idea is something like this:
B4X:
Private Sub Globals
  'Declare vars for all your views:
  Private svMenu As ScrollView
  Private pnlDetail As Panel
  '...
End Sub

Private Sub Activity_Create(FirstTime As Boolean)

  svMenu.Initialize(2000)
  svMenu.Color = Colors.LightGray
  '... more settings for ScrollView...
  Activity.AddView(svMenu, 0, 0, 30%x, 100%y)

  pnlDetail.Initialize("pnlDetail")
  pnlDetail.Color = Colors.DarkGray
  '... more settings for Panel...
  Activity.AddView(pnlDetail, 50%x, 0, 50%x, 100%y)

  '...

End Sub
 

Jost aus Soest

Active Member
Licensed User
Longtime User
Wish List

I still have open wishes/problems:
- multi instances of one widget
- resolve bug(?): I cannot define 1x1 Widgets with android:targetSdkVersion="14" (Even with Panel.Width/Height = 30!)
(or is this a known Galaxy Note problem)?
- defining widget size by cell dimensions (e. g. 3x1), independent from orientation
- creating (or at least moving and sizing) views on widget by code

I know, I'm only dreaming... ;)
 
Last edited:

walterf25

Expert
Licensed User
Longtime User
Widget Size confusion

Hello all, first of all i want to apologize if i ask questions that have already been answered, i have been looking at many posts regarding widget sizes, but i just can't seem to understand the whole deal.
I just started making a widget app, but i need to learn how to go about making a widget that will automatically resize to fit different screen resolutions, for example i made a widget on my Motorola Photonm the widget consists of two panels the first panel size is 540x225, the second panel is inside panel1 and it's size is 510x195 this works very good on my phone, but if i tried to install this on a 480x800 screen resolution device, it won't add to the home screen it tells me there's no more room on this home screen even though the screen is completely empty. I have read about the formula used (cells * 74) - 2 but it just doesn't seem to work for me, i read somewhere else that the formula is actually (cells * 74) - 30, so i'm a little confused as to what's what, if there's anyone here that can point me in the right direction that will be awesome!

Thanks,
Walter
 

walterf25

Expert
Licensed User
Longtime User
Fonts on Widgets

Hello Erel, thanks for your help, i have a question, how difficult would it be to add a function to change different fonts for labels on widgets, i see that we can change textsize, textcolor but there's no function to use different fonts since the views can not be accessed directly if we declared them in the Sub Globlas in the WidgetSerivce service. I would love to have this option and give users the ability to choose different fonts.

Cheers,
Walter
 

Basis64

New Member
HELP! am I doing something wrong here? :S I cant imagine, i exactly followed the steps..
still when i compile and try to run the widget it say :

"AndroidManifest.xml:40: error: Error: No resource found that matches the given name (at 'resource' with value '@xml/widgy_info')."

what does that even mean? :s kinda stuck here...
 

carchek

Member
Licensed User
Longtime User
hi!
I am making a widget, that will be able to display a webpage, is that even possible?
I was thinking of using webview, but i do no know if this is the right way... I would like to connect my application which shows website in webview and display that webview in widget. I that possible?
 
Last edited:
Status
Not open for further replies.
Top