SlideShare ist ein Scribd-Unternehmen logo
1 von 12
Downloaden Sie, um offline zu lesen
How to: Android 'Hello Widget'

Table of Contents
   Document history......................................................................................................1
   HelloWidget...............................................................................................................1
     Prerequisites.........................................................................................................1
     Let’s start from scratch..........................................................................................1
     The Java-way Time-Widget..................................................................................6
     The Service-way Time-Widget (not working with 1.6 any more)..........................8
   How to use Buttons on Widgets................................................................................9
     Prerequisites.........................................................................................................9
     The Layout............................................................................................................9
     AppWidget Provider............................................................................................10
     Manifest file.........................................................................................................10
     ButtonWidget Provider........................................................................................11


Document history
 Version        Date                     User                                           Description
   1.0       2009-07-11     Norbert Möhring                     Initial document.
                            moehring.n [at] googlemail.com
    1.1      2009-07-21     Norbert Möhring                     Small fixes in code (copy&paste erros ).
                            moehring.n [at] googlemail.com      Thanks to Andreas Kompanez (ak@endlessnumbered.com)
                                                                for the review.
                                                                Better layout.
                                                                Added document history and table of contents.
                                                                Put all links behind text → looks better 
    1.2      2009-07-23     Norbert Möhring                     Fixed some typos
                            moehring.n [at] googlemail.com
    1.3      2009-09-27     Norbert Möhring                     - Some comments to the new 1.6 Version
                            moehring.n [at] googlemail.com      - How to use Buttons on widgets



HelloWidget
Since there is only the one not that self explaining example of a widget I
decided to invest some nightly hours to cut that example into pieces and
then start from scratch with an easy to follow “Hello Widget” tutorial.

Prerequisites

You should already have the android SDK and android Eclipse IDE plug-in
installed and running. If not, go here to learn how to get started with the
android plug-in. Also you should have at least basic knowledge about Java
programming since this is not a Java tutorial.

Let’s start from scratch

In Eclipse, go to

File → new Project … → other … and select 'Android Project'

The project name will be “Hello Widget” and in this case the target platform will be ‘Android 1.5’.
Uncheck the probably already checked Box “Create Activity”. We won’t create an Activity here we just
want a simple widget.




How to: Android ‚Hello Widget’                                                                                 Page 1 of 12
New Project Wizard

After that, your Project structure will look like this:




The project wizard gave us some default stuff already, like the default android app-icon e.g.
We’ll start with the layout and design of our widget.
Open main.xml and modify it like this:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="fill_parent"
  android:orientation="vertical"
  android:background="@drawable/widget_bg_normal"
  android:layout_gravity="center"
  android:layout_height="wrap_content">

<TextView android:id="@+id/widget_textview"
  android:text="@string/widget_text"
  android:layout_height="wrap_content"
  android:layout_width="wrap_content"
  android:layout_gravity="center_horizontal|center"
  android:layout_marginTop="5dip"
  android:padding="10dip"
  android:textColor="@android:color/black"/>

</LinearLayout>




How to: Android ‚Hello Widget’                                                              Page 2 of 12
We have a simple linear layout with a TextView for your message to display. At this point, you will get
an Error saying
ERROR Error: No resource found that matches the given name (at 'background'
with value '@drawable/widget_bg_normal')

That’s because you don’t have the widget_bg_normal resource at this point. I borrowed the image
from the SimpleWiktionary widget. It’s a png NinePatch image which will be our background of the
widget.
Put the file widget_bg_normal.9.png (or your own background image) into the folder res/drawable.
You also don’t have the @string/widget_text resource. To fix that, go to res/values/string.xml and add this
line to it:

         <string name="widget_text">Hello Widget!</string>

string.xml will look like this:

         <?xml version="1.0" encoding="utf-8"?>
         <resources>
            <string name="widget_text">Hello Widget!</string>
            <string name="app_name">Hello Widget</string>
         </resources>

We just finished our design part.

Now we have to tell Android that we are going to have a widget.
Open AndroidManifest.xml and go to the source view.




The lines you have to add are bold:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
   package="de.thesmile.android.widget"
   android:versionCode="1"
   android:versionName="1.0">
  <application android:icon="@drawable/icon" android:label="@string/app_name">

    <!-- Broadcast Receiver that will process AppWidget updates -->
    <receiver android:name=".HelloWidget" android:label="@string/app_name">
       <intent-filter>
          <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
       </intent-filter>
       <meta-data android:name="android.appwidget.provider"
                            android:resource="@xml/hello_widget_provider" />
    </receiver>

  </application>
  <uses-sdk android:minSdkVersion="3" />
</manifest>




How to: Android ‚Hello Widget’                                                                  Page 3 of 12
We declare our Broadcast Receiver which will be “HelloWidget”.
Don’t forget the dot before HelloWidget, this will create the full qualified path name with the declared
package at the top of the file. The Label of our application was already set be the project wizard and is
located in our string.xml.

From the documentation:
The <intent-filter> element must include an <action> element with the android:name attrib ute. This attrib ute
specifies that the AppWidgetProvider accepts the ACTION_APPWIDGET_UPDATE b roadcast. This is the only
b roadcast that you must explicitly declare. The AppWidgetManager automatically sends all other App Widget
b roadcasts to the AppWidgetProvider as necessary.


The meta-tag tells android about your widget provider. In this case, the widget provider is located at
res/xml/hello_widget_provider.xml. The provider.xml is pretty much self explaining:

<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
   android:minWidth="146dip"
   android:minHeight="72dip"
   android:updatePeriodMillis="10000"
   android:initialLayout="@layout/main"
/>

Define the size of your widget (should match the guidelines for desktop widgets).
updatePerdiodMillis as it’s name already says, the time in milliseconds to update your widget. In our
case, this is unimportant and we don’t need it because we don’t do any update on our widget.

The initial layout points the the main.xml file. We already defined our layout and design.

The only thing that is missing to run our widget is the Class that extends the AppWidgetProvider
which we declared in AndroidManifest.xml at the receiver-tag.

Create a new Class under the package de.thesmile.android.widget, name it HelloWidget
and set AppWidgetProvider as super class.




How to: Android ‚Hello Widget’                                                                     Page 4 of 12
Your new class will look like this:

package de.thesmile.android.widget;

import android.appwidget.AppWidgetProvider;

public class HelloWidget extends AppWidgetProvider {

}

Since our Widget is doing nothing, you’re now ready to go. To start your application, right click on your
project → Run As → Android Application




This will start the Android Virtual Device (AVD) and install your widget on this device.




How to: Android ‚Hello Widget’                                                               Page 5 of 12
Now press and hold your left mouse button on the AVD Desktop screen until the menu pops up.
Select Widgets → Hello Widget …




                                    … and have a look at the result.




Ok, that was pretty easy and now you have a widget which can do …. nothing 

Let’s do something with our widget ... display the current time. I’ll show you two versions of the time
example, one that I would call the Java-way and the other one to introduce you to services in widgets
(Service-way).

The Java-way Time-Widget

This is how the Java-way Time-Widget will look like. It will update
every second and display the time.

By the way: It’s 11:50 pm right now, I don’t know where the AVD
gets it’s time from but it’s definitely not my system time.

Now, open your empty class HelloWidget.
We have to override the protected method onUpdate from
AppWidgetProvider. Also, because of the Java-way, we’ll create
an inner class MyTime which will be derived from TimerTask. Just
have a look at the following code:

public class HelloWidget extends AppWidgetProvider {

         @Override
         public void onUpdate(Context context, AppWidgetManager appWidgetManager,
                                                                    int[] appWidgetIds) {

                   Timer timer = new Timer();
                   timer.scheduleAtFixedRate(new MyTime(context, appWidgetManager), 1, 1000);



How to: Android ‚Hello Widget’                                                              Page 6 of 12
}

         private class MyTime extends TimerTask {

                   RemoteViews remoteViews;
                   AppWidgetManager appWidgetManager;
                   ComponentName thisWidget;
                   DateFormat format = SimpleDateFormat.getTimeInstance(SimpleDateFormat.MEDIUM,
                                         Locale.getDefault());

                   public MyTime(Context context, AppWidgetManager appWidgetManager) {
                          this.appWidgetManager = appWidgetManager;
                          remoteViews = new RemoteViews(context.getPackageName(), R.layout.main);
                          thisWidget = new ComponentName(context, HelloWidget.class);
                   }

                   @Override
                   public void run() {
                          remoteViews.setTextViewText(R.id.widget_textview,
                                                       "Time = " + format.format(new Date()));
                          appWidgetManager.updateAppWidget(thisWidget, remoteViews);
                   }
         }
}

The method onUpdate will be called at first. We create a timer that will run our MyTime-Thread every
second. The constructor of the MyTime-Class gets some information to update our widget on the
desktop.
Get our main view that we created (at that point you could also change your layout to another design).
         remoteViews = new RemoteViews(context.getPackageName(), R.layout.main);

In the run method, we set the time with our new Date and update the remote View.
That’s already it. Now you have a widget that is displaying the current time.
At that point I want to give you some further information about a bug that has not been fixed yet, either
in the AVD nor on any machine. The bug-fix didn’t make it into the CUPCAKE Version (1.5).

To delete a widget, you tab and hold, then drag it and drop it into the trash can at the bottom.
At that point the widget provider usually runs an onDelete and onDisable method. Currently this is not
happening since the wrong IDs are sent. To fix this problem and really delete your widget, add the
following code to the onReceive method:

         @Override
         public void onReceive(Context context, Intent intent) {

                   // v1.5 fix that doesn't call onDelete Action
                   final String action = intent.getAction();
                   if (AppWidgetManager.ACTION_APPWIDGET_DELETED.equals(action)) {
                          final int appWidgetId = intent.getExtras().getInt(
                                         AppWidgetManager.EXTRA_APPWIDGET_ID,
                                         AppWidgetManager.INVALID_APPWIDGET_ID);
                          if (appWidgetId != AppWidgetManager.INVALID_APPWIDGET_ID) {
                                  this.onDeleted(context, new int[] { appWidgetId });
                          }
                   } else {
                          super.onReceive(context, intent);
                   }
         }

onReceive is always called before onUpdate is called. This code snipped checks the called action
and decides weather to just run the receive method or the delete method.
Jeff Sharkey provided us with this useful code-snipped.

If you don’t do that, your widget won’t be displayed any more, but your widget provider will still run
onReceive and onUpdate in the given period (updatePerdiodMillis) which will eat up battery and
memory. It seems like this problem has been fixed in the 1.6 update so that you don't need this
additional code anymore.




How to: Android ‚Hello Widget’                                                                 Page 7 of 12
The Service-way Time-Widget (not working with 1.6 any more)

Usually your widget will do some more stuff than updating your time. To do so, you should create an
UpdateService.class. Here’s the Time-Widget with a service. This is just an example and I’m
pretty sure that the service-way of the time widget will eat up more battery than the Java-way.

To register and start the service, change your onUpdate method like this:

         @Override
         public void onUpdate(Context context, AppWidgetManager appWidgetManager,
                        int[] appWidgetIds) {

                   Intent intent = new Intent(context, UpdateService.class);
                   context.startService(intent);
         }

The UpdateService.class looks like this:

         public static class UpdateService extends Service {

         @Override
         public void onStart(Intent intent, int startId) {
                RemoteViews updateViews = new RemoteViews(this.getPackageName(),
                                                                    R.layout.main);
                Date date = new Date();
                DateFormat format = SimpleDateFormat.getTimeInstance(
                                      SimpleDateFormat.MEDIUM, Locale.getDefault());

                   // set the text of component TextView with id 'message'
                   updateViews.setTextViewText(R.id.widget_textview, "Current Time "
                                         + format.format(date));

                   // Push update for this widget to the home screen
                   ComponentName thisWidget = new ComponentName(this, HelloWidget.class);
                   AppWidgetManager manager = AppWidgetManager.getInstance(this);
                   manager.updateAppWidget(thisWidget, updateViews);
         }

If you want the time to be updated every second, your have to modify the hello_widget_provider.xml
file and set updatePerdiodMillis to 1000.
The android update 1.6 unfortunately does not support any update periode that is less then 30
minutes. The result is, that you can not run the “service-way” in 1.6 any more. Since updating every
second is not very useful concerning the battery life of your phone, the 30 minute minimum period
makes sense. Still, it is not very useful concerning development and testing because no developer
wants to wait for 30 minutes to test the update of his widget.
Anyway, for usability purposes one should always use an AlarmManager for widget updates, since you
can let the user configure the periode. I'll get to the AlarmManager in my next tutorial update.




How to: Android ‚Hello Widget’                                                            Page 8 of 12
How to use Buttons on Widgets
After a few requests about updating this tutorial to show how buttons
work on widgets, I finally made it and here is an example App for
buttons. This application will not be functional like the Time-Widget. It
will just show you how you can add several buttons and click events.

Prerequisites

For the prerequisites, you already know how to create a widget project
from scratch. Just do that, or download the source code for this
example widget. You can get it here.

The Layout

For the layout, we use the main.xml which will look like this:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
       android:layout_width="fill_parent"
       android:orientation="horizontal"
       android:background="@drawable/widget_bg_normal"
       android:layout_gravity="center"
       android:layout_height="wrap_content">
<Button android:text="B1" android:id="@+id/button_one"
       android:layout_gravity="center_horizontal|center"
       android:layout_height="fill_parent"
       android:layout_width="wrap_content"/>

<Button android:text="B2" android:id="@+id/button_two"
       android:layout_gravity="center_horizontal|center"
       android:layout_height="fill_parent"
       android:layout_width="wrap_content"/>
</LinearLayout>

We use the background from our first widget and add two buttons to it, that's all we need.
Since this example will also start an activity from a button, we have to create a layout for this activity.
This e.g. could be a configuration screen. The configure.xml file looks like this:

<TableLayout android:id="@+id/TableLayout01"
               android:layout_width="fill_parent"
               android:layout_height="fill_parent"
               xmlns:android="http://schemas.android.com/apk/res/android">
       <TextView android:layout_width="wrap_content"
               android:layout_height="wrap_content"
               android:id="@+id/TextOne"
               android:text="Text"
               android:textColor="@android:color/white"
               android:textSize="15dip"
               android:textStyle="bold"
               android:layout_marginTop="5dip"/>
       <EditText android:layout_width="wrap_content"
               android:layout_height="wrap_content"
               android:id="@+id/txtFieldId"
               android:clickable="true"
               android:inputType="number"
               android:layout_marginTop="5dip"
               android:layout_marginBottom="20dip"/>
</TableLayout>

We just added a label with the string “Text” and a textfield to the screen. Nothing will be functional
here.




How to: Android ‚Hello Widget’                                                                   Page 9 of 12
AppWidget Provider

The appwidget-provider xml named button_widget_provider.xml is very simple. We don't need any
update periode so it will look like this:

<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
    android:minWidth="146dip"
    android:minHeight="72dip"
    android:updatePeriodMillis="0"
    android:initialLayout="@layout/main"
/>


Manifest file

The manifest file will have some more information this time and should look like this:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="de.thesmile.android.widget.buttons"
      android:versionCode="1"
      android:versionName="1.0">
    <application android:icon="@drawable/icon" android:label="@string/app_name">

       <!-- Broadcast Receiver that will process AppWidget updates -->
        <receiver android:name=".ButtonWidget" android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
                <!-- Broadcast Receiver that will also process our self created action -->
               <action
android:name="de.thesmile.android.widget.buttons.ButtonWidget.ACTION_WIDGET_RECEIVER"/>
            </intent-filter>
            <meta-data android:name="android.appwidget.provider"
android:resource="@xml/button_widget_provider" />
        </receiver>

<!-- this activity will be called, when we fire our self created ACTION_WIDGET_CONFIGURE -->
               <activity android:name=".ClickOneActivity">
                      <intent-filter>
                      <action
android:name="de.thesmile.android.widget.buttons.ButtonWidget.ACTION_WIDGET_CONFIGURE"/>
                      </intent-filter>
               </activity>
    </application>
    <uses-sdk android:minSdkVersion="3" />
</manifest>

Ok, let's have a detailled look at it.
We already know about the first part. We register our ButtonWidget as a receiver which will react on
the intent with the filter APPWIDGET_UPDATE. We also know about the meta-data tag which declares some
widget properties. The new thing here is the ACTION_WIDGET_RECEIVER, which, as you can see, belongs
to our package. What we do is, we add a certain event to our ButtonWidget-Receiver. If this event
(android calls these events intent) is fired, our ButtonWidget will be called to react on it.
The second thing is the activity ClickOneActivity. We register the intent-filter ACTION_WIDGET_CONFIGURE
to this activity.
The code for the ClickOneActivity is pretty straight forward and you already know how that is working.
We only use the onCreate method here and display a Toastmessage:
public class ClickOneActivity extends Activity {
 @Override
 protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       // change to our configure view
       setContentView(R.layout.configure);

         // don't call 'this', use 'getApplicationContext()', the activity-object is
         // bigger than just the context because the activity also stores the UI elemtents
         Toast.makeText(getApplicationContext(), "We are in ClickOneActivity",
                Toast.LENGTH_SHORT).show();
 }
}




How to: Android ‚Hello Widget’                                                              Page 10 of 12
Now we can have a look at the AppWidgetProvider code to see how the intent-filters work.

ButtonWidget Provider

First of all, we configure our own events which we already used in our manifest file. You should always
make sure that your actions have unique names not only in the namespace of your own apps but in
the global namespace of the whole android framework. My idea is to just use your package name of
the application to insure that. (I didn't do that in this example)
public class ButtonWidget extends AppWidgetProvider {

         public static String ACTION_WIDGET_CONFIGURE = "ConfigureWidget";
         public static String ACTION_WIDGET_RECEIVER = "ActionReceiverWidget";

         [...]

Now, let's have a look at the most important method; onUpdate()

@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {

 RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.main);
 Intent configIntent = new Intent(context, ClickOneActivity.class);
 configIntent.setAction(ACTION_WIDGET_CONFIGURE);

 Intent active = new Intent(context, ButtonWidget.class);
 active.setAction(ACTION_WIDGET_RECEIVER);
 active.putExtra("msg", "Message for Button 1");

 PendingIntent actionPendingIntent = PendingIntent.getBroadcast(context, 0, active, 0);
 PendingIntent configPendingIntent = PendingIntent.getActivity(context, 0, configIntent, 0);

 remoteViews.setOnClickPendingIntent(R.id.button_one, actionPendingIntent);
 remoteViews.setOnClickPendingIntent(R.id.button_two, configPendingIntent);

 appWidgetManager.updateAppWidget(appWidgetIds, remoteViews);
}

First, we get the RemoteViews for our main layout; that's where we will be working on. Then we
configure a new Intent that will hold our configuration activity. This event will be given our action
ACTION_WIDGET_CONFIGURE.

The second Intent will be configured with our ButtonWidget and be given the action
ACTION_WIDGET_RECEIVER. We also give this action some extra data that we will use later to display
something on the screen. This is just to show you how you can add extra data to an intent and use it
later when this intent is captured by whatever application is catching it.

Now we use PendingIntents which will be given to the remoteViews as click-events.


From the documentation:
By giving a PendingIntent to another application, you are granting it the right to perform the operation you
have specified as if the other application was yourself (with the same permissions and identity).


As usual, we have to update our widget with the appWidgetManager to „commit“ the updates. Now
everything is registered to our widget and the button „B2“ will be working already since it will start our
Activity as soon as you click the button.
Button one will do nothing at the moment because we didn't tell our ButtonWidget to do anything when
it receives the action ACTION_WIDGET_RECEIVER.




How to: Android ‚Hello Widget’                                                                 Page 11 of 12
Let's have a look at the important method that can react on the ACTION_WIDGET_RECEIVER:

@Override
public void onReceive(Context context, Intent intent) {

// v1.5 fix that doesn't call onDelete Action
final String action = intent.getAction();
if (AppWidgetManager.ACTION_APPWIDGET_DELETED.equals(action)) {
       final int appWidgetId = intent.getExtras().getInt(
               AppWidgetManager.EXTRA_APPWIDGET_ID,
               AppWidgetManager.INVALID_APPWIDGET_ID);
       if (appWidgetId != AppWidgetManager.INVALID_APPWIDGET_ID) {
               this.onDeleted(context, new int[] { appWidgetId });
       }
} else {
  // check, if our Action was called
  if (intent.getAction().equals(ACTION_WIDGET_RECEIVER)) {
               String msg = "null";
               try {
                      msg = intent.getStringExtra("msg");
               } catch (NullPointerException e) {
                      Log.e("Error", "msg = null");
               }
               Toast.makeText(context, msg, Toast.LENGTH_SHORT).show();

         PendingIntent contentIntent = PendingIntent.getActivity(context, 0, intent, 0);
         NotificationManager notificationManager =
                (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE);
         Notification noty = new Notification(R.drawable.icon, "Button 1 clicked",
                System.currentTimeMillis());

         noty.setLatestEventInfo(context, "Notice", msg, contentIntent);
         notificationManager.notify(1, noty);

    }
    super.onReceive(context, intent);
 }
}
At the beginning I put the 1.5 onReceive-fix here, but this time we ask for our action in the else
statement before we call super.onReceive. If ACTION_WIDGET_RECEIVER is called, we get our extra data
from the intent (which was stored under the key „msg“) and display a Toast-Message with this string to
the user.

As a little gimmick I also show you how you use the NotificationManager of the android framework.
The message „Button 1 clicked“ will pop up on the notification bar (the bar where your clock is placed)
and will also show the widget icon.




Feedback appreciated

Author:            Norbert Möhring (moehring.n [at] googlemail.com)
Blog:              http://blog.thesmile.de



How to: Android ‚Hello Widget’                                                             Page 12 of 12

Weitere ähnliche Inhalte

Was ist angesagt?

Implementing auto complete using JQuery
Implementing auto complete using JQueryImplementing auto complete using JQuery
Implementing auto complete using JQueryBhushan Mulmule
 
Vaadin Components @ Angular U
Vaadin Components @ Angular UVaadin Components @ Angular U
Vaadin Components @ Angular UJoonas Lehtinen
 
Top 7 Angular Best Practices to Organize Your Angular App
Top 7 Angular Best Practices to Organize Your Angular AppTop 7 Angular Best Practices to Organize Your Angular App
Top 7 Angular Best Practices to Organize Your Angular AppKaty Slemon
 
GWT training session 2
GWT training session 2GWT training session 2
GWT training session 2SNEHAL MASNE
 
Desenvolva um game para android ou iPhone
Desenvolva um game para android ou iPhoneDesenvolva um game para android ou iPhone
Desenvolva um game para android ou iPhoneTiago Oliveira
 
Android N Highligts
Android N HighligtsAndroid N Highligts
Android N HighligtsSercan Yusuf
 
Adding a view
Adding a viewAdding a view
Adding a viewNhan Do
 
Web Components for Java Developers
Web Components for Java DevelopersWeb Components for Java Developers
Web Components for Java DevelopersJoonas Lehtinen
 
Google Plus SignIn : l'Authentification Google
Google Plus SignIn : l'Authentification GoogleGoogle Plus SignIn : l'Authentification Google
Google Plus SignIn : l'Authentification GoogleMathias Seguy
 
Get started with meteor | designveloper software agency meteor prime partner
Get started with meteor | designveloper software agency   meteor prime partnerGet started with meteor | designveloper software agency   meteor prime partner
Get started with meteor | designveloper software agency meteor prime partnerDesignveloper
 
Getting your app ready for android n
Getting your app ready for android nGetting your app ready for android n
Getting your app ready for android nSercan Yusuf
 
Vue fundamentasl with Testing and Vuex
Vue fundamentasl with Testing and VuexVue fundamentasl with Testing and Vuex
Vue fundamentasl with Testing and VuexChristoffer Noring
 
Google Play Services Rock
Google Play Services RockGoogle Play Services Rock
Google Play Services RockPeter Friese
 
JSLab. Алексей Волков. "React на практике"
JSLab. Алексей Волков. "React на практике"JSLab. Алексей Волков. "React на практике"
JSLab. Алексей Волков. "React на практике"GeeksLab Odessa
 
Meteor.js Workshop by Dopravo
Meteor.js Workshop by DopravoMeteor.js Workshop by Dopravo
Meteor.js Workshop by DopravoArabNet ME
 

Was ist angesagt? (20)

An introduction to Vue.js
An introduction to Vue.jsAn introduction to Vue.js
An introduction to Vue.js
 
Implementing auto complete using JQuery
Implementing auto complete using JQueryImplementing auto complete using JQuery
Implementing auto complete using JQuery
 
Vaadin Components
Vaadin ComponentsVaadin Components
Vaadin Components
 
Android development module
Android development moduleAndroid development module
Android development module
 
Vaadin Components @ Angular U
Vaadin Components @ Angular UVaadin Components @ Angular U
Vaadin Components @ Angular U
 
Top 7 Angular Best Practices to Organize Your Angular App
Top 7 Angular Best Practices to Organize Your Angular AppTop 7 Angular Best Practices to Organize Your Angular App
Top 7 Angular Best Practices to Organize Your Angular App
 
GWT training session 2
GWT training session 2GWT training session 2
GWT training session 2
 
Desenvolva um game para android ou iPhone
Desenvolva um game para android ou iPhoneDesenvolva um game para android ou iPhone
Desenvolva um game para android ou iPhone
 
Android N Highligts
Android N HighligtsAndroid N Highligts
Android N Highligts
 
Adding a view
Adding a viewAdding a view
Adding a view
 
Web Components for Java Developers
Web Components for Java DevelopersWeb Components for Java Developers
Web Components for Java Developers
 
Google Plus SignIn : l'Authentification Google
Google Plus SignIn : l'Authentification GoogleGoogle Plus SignIn : l'Authentification Google
Google Plus SignIn : l'Authentification Google
 
Get started with meteor | designveloper software agency meteor prime partner
Get started with meteor | designveloper software agency   meteor prime partnerGet started with meteor | designveloper software agency   meteor prime partner
Get started with meteor | designveloper software agency meteor prime partner
 
Getting your app ready for android n
Getting your app ready for android nGetting your app ready for android n
Getting your app ready for android n
 
Rank Whizz User Guide
Rank Whizz User GuideRank Whizz User Guide
Rank Whizz User Guide
 
Vue fundamentasl with Testing and Vuex
Vue fundamentasl with Testing and VuexVue fundamentasl with Testing and Vuex
Vue fundamentasl with Testing and Vuex
 
Meteor Day Talk
Meteor Day TalkMeteor Day Talk
Meteor Day Talk
 
Google Play Services Rock
Google Play Services RockGoogle Play Services Rock
Google Play Services Rock
 
JSLab. Алексей Волков. "React на практике"
JSLab. Алексей Волков. "React на практике"JSLab. Алексей Волков. "React на практике"
JSLab. Алексей Волков. "React на практике"
 
Meteor.js Workshop by Dopravo
Meteor.js Workshop by DopravoMeteor.js Workshop by Dopravo
Meteor.js Workshop by Dopravo
 

Andere mochten auch (19)

Pat7.3 253
Pat7.3 253Pat7.3 253
Pat7.3 253
 
03 e
03 e03 e
03 e
 
Computer 9
Computer 9Computer 9
Computer 9
 
China turist
China turistChina turist
China turist
 
06 e
06 e06 e
06 e
 
ใบงานท 2
ใบงานท   2ใบงานท   2
ใบงานท 2
 
sci
scisci
sci
 
Comp6
Comp6Comp6
Comp6
 
Кланы и бизнес
Кланы и бизнесКланы и бизнес
Кланы и бизнес
 
04 e
04 e04 e
04 e
 
ไทย
ไทยไทย
ไทย
 
Computer 9
Computer 9Computer 9
Computer 9
 
Computer 9
Computer 9Computer 9
Computer 9
 
Process Baikal Management
Process Baikal ManagementProcess Baikal Management
Process Baikal Management
 
Pat7.6 253
Pat7.6 253Pat7.6 253
Pat7.6 253
 
Computer 9 16
Computer 9 16Computer 9 16
Computer 9 16
 
Vocab
VocabVocab
Vocab
 
Comproject
ComprojectComproject
Comproject
 
คณิต 51
คณิต 51คณิต 51
คณิต 51
 

Ähnlich wie Android howto hellowidget

NetWeaver Developer Studio for New-Beas
NetWeaver Developer Studio for New-BeasNetWeaver Developer Studio for New-Beas
NetWeaver Developer Studio for New-BeasChander445
 
Android tutorial
Android tutorialAndroid tutorial
Android tutorialAbid Khan
 
Yeoman AngularJS and D3 - A solid stack for web apps
Yeoman AngularJS and D3 - A solid stack for web appsYeoman AngularJS and D3 - A solid stack for web apps
Yeoman AngularJS and D3 - A solid stack for web appsclimboid
 
Lecture #1 Creating your first android project
Lecture #1  Creating your first android projectLecture #1  Creating your first android project
Lecture #1 Creating your first android projectVitali Pekelis
 
Introduction to Android and Java.pptx
Introduction to Android and Java.pptxIntroduction to Android and Java.pptx
Introduction to Android and Java.pptxGandhiMathy6
 
Angular kickstart slideshare
Angular kickstart   slideshareAngular kickstart   slideshare
Angular kickstart slideshareSaleemMalik52
 
Creating the first app with android studio
Creating the first app with android studioCreating the first app with android studio
Creating the first app with android studioParinita03
 
Volley lab btc_bbit
Volley lab btc_bbitVolley lab btc_bbit
Volley lab btc_bbitCarWash1
 
The ultimate guide to optimize your react native app performance in 2022
The ultimate guide to optimize your react native app performance in 2022The ultimate guide to optimize your react native app performance in 2022
The ultimate guide to optimize your react native app performance in 2022Katy Slemon
 
React Native +Redux + ES6 (Updated)
React Native +Redux + ES6 (Updated)React Native +Redux + ES6 (Updated)
React Native +Redux + ES6 (Updated)Chiew Carol
 
Installing android sdk on net beans
Installing android sdk on net beansInstalling android sdk on net beans
Installing android sdk on net beansAravindharamanan S
 
Learn reactjs, how to code with example and general understanding thinkwik
Learn reactjs, how to code with example and general understanding   thinkwikLearn reactjs, how to code with example and general understanding   thinkwik
Learn reactjs, how to code with example and general understanding thinkwikHetaxi patel
 
Angular 7 Firebase5 CRUD Operations with Reactive Forms
Angular 7 Firebase5 CRUD Operations with Reactive FormsAngular 7 Firebase5 CRUD Operations with Reactive Forms
Angular 7 Firebase5 CRUD Operations with Reactive FormsDigamber Singh
 
How to optimize the performance of vue js large application structure
How to optimize the performance of vue js large application structure How to optimize the performance of vue js large application structure
How to optimize the performance of vue js large application structure Katy Slemon
 
Android Tutorial
Android TutorialAndroid Tutorial
Android TutorialFun2Do Labs
 
Google I/O 2016 replay - Android N Development
Google I/O 2016 replay - Android N DevelopmentGoogle I/O 2016 replay - Android N Development
Google I/O 2016 replay - Android N DevelopmentTowhidul Haque Roni
 

Ähnlich wie Android howto hellowidget (20)

Getting started with android studio
Getting started with android studioGetting started with android studio
Getting started with android studio
 
NetWeaver Developer Studio for New-Beas
NetWeaver Developer Studio for New-BeasNetWeaver Developer Studio for New-Beas
NetWeaver Developer Studio for New-Beas
 
Android tutorial
Android tutorialAndroid tutorial
Android tutorial
 
Ap quiz app
Ap quiz appAp quiz app
Ap quiz app
 
Yeoman AngularJS and D3 - A solid stack for web apps
Yeoman AngularJS and D3 - A solid stack for web appsYeoman AngularJS and D3 - A solid stack for web apps
Yeoman AngularJS and D3 - A solid stack for web apps
 
Lecture #1 Creating your first android project
Lecture #1  Creating your first android projectLecture #1  Creating your first android project
Lecture #1 Creating your first android project
 
Introduction to Android and Java.pptx
Introduction to Android and Java.pptxIntroduction to Android and Java.pptx
Introduction to Android and Java.pptx
 
Angular kickstart slideshare
Angular kickstart   slideshareAngular kickstart   slideshare
Angular kickstart slideshare
 
Vanjs backbone-powerpoint
Vanjs backbone-powerpointVanjs backbone-powerpoint
Vanjs backbone-powerpoint
 
Creating the first app with android studio
Creating the first app with android studioCreating the first app with android studio
Creating the first app with android studio
 
Volley lab btc_bbit
Volley lab btc_bbitVolley lab btc_bbit
Volley lab btc_bbit
 
The ultimate guide to optimize your react native app performance in 2022
The ultimate guide to optimize your react native app performance in 2022The ultimate guide to optimize your react native app performance in 2022
The ultimate guide to optimize your react native app performance in 2022
 
React Native +Redux + ES6 (Updated)
React Native +Redux + ES6 (Updated)React Native +Redux + ES6 (Updated)
React Native +Redux + ES6 (Updated)
 
Installing android sdk on net beans
Installing android sdk on net beansInstalling android sdk on net beans
Installing android sdk on net beans
 
Learn reactjs, how to code with example and general understanding thinkwik
Learn reactjs, how to code with example and general understanding   thinkwikLearn reactjs, how to code with example and general understanding   thinkwik
Learn reactjs, how to code with example and general understanding thinkwik
 
Angular 7 Firebase5 CRUD Operations with Reactive Forms
Angular 7 Firebase5 CRUD Operations with Reactive FormsAngular 7 Firebase5 CRUD Operations with Reactive Forms
Angular 7 Firebase5 CRUD Operations with Reactive Forms
 
How to optimize the performance of vue js large application structure
How to optimize the performance of vue js large application structure How to optimize the performance of vue js large application structure
How to optimize the performance of vue js large application structure
 
Android Tutorial
Android TutorialAndroid Tutorial
Android Tutorial
 
Google I/O 2016 replay - Android N Development
Google I/O 2016 replay - Android N DevelopmentGoogle I/O 2016 replay - Android N Development
Google I/O 2016 replay - Android N Development
 
Android wear notes
Android wear notesAndroid wear notes
Android wear notes
 

Kürzlich hochgeladen

Sanyam Choudhary Chemistry practical.pdf
Sanyam Choudhary Chemistry practical.pdfSanyam Choudhary Chemistry practical.pdf
Sanyam Choudhary Chemistry practical.pdfsanyamsingh5019
 
1029 - Danh muc Sach Giao Khoa 10 . pdf
1029 -  Danh muc Sach Giao Khoa 10 . pdf1029 -  Danh muc Sach Giao Khoa 10 . pdf
1029 - Danh muc Sach Giao Khoa 10 . pdfQucHHunhnh
 
microwave assisted reaction. General introduction
microwave assisted reaction. General introductionmicrowave assisted reaction. General introduction
microwave assisted reaction. General introductionMaksud Ahmed
 
Presentation by Andreas Schleicher Tackling the School Absenteeism Crisis 30 ...
Presentation by Andreas Schleicher Tackling the School Absenteeism Crisis 30 ...Presentation by Andreas Schleicher Tackling the School Absenteeism Crisis 30 ...
Presentation by Andreas Schleicher Tackling the School Absenteeism Crisis 30 ...EduSkills OECD
 
The basics of sentences session 2pptx copy.pptx
The basics of sentences session 2pptx copy.pptxThe basics of sentences session 2pptx copy.pptx
The basics of sentences session 2pptx copy.pptxheathfieldcps1
 
9548086042 for call girls in Indira Nagar with room service
9548086042  for call girls in Indira Nagar  with room service9548086042  for call girls in Indira Nagar  with room service
9548086042 for call girls in Indira Nagar with room servicediscovermytutordmt
 
Beyond the EU: DORA and NIS 2 Directive's Global Impact
Beyond the EU: DORA and NIS 2 Directive's Global ImpactBeyond the EU: DORA and NIS 2 Directive's Global Impact
Beyond the EU: DORA and NIS 2 Directive's Global ImpactPECB
 
Disha NEET Physics Guide for classes 11 and 12.pdf
Disha NEET Physics Guide for classes 11 and 12.pdfDisha NEET Physics Guide for classes 11 and 12.pdf
Disha NEET Physics Guide for classes 11 and 12.pdfchloefrazer622
 
A Critique of the Proposed National Education Policy Reform
A Critique of the Proposed National Education Policy ReformA Critique of the Proposed National Education Policy Reform
A Critique of the Proposed National Education Policy ReformChameera Dedduwage
 
JAPAN: ORGANISATION OF PMDA, PHARMACEUTICAL LAWS & REGULATIONS, TYPES OF REGI...
JAPAN: ORGANISATION OF PMDA, PHARMACEUTICAL LAWS & REGULATIONS, TYPES OF REGI...JAPAN: ORGANISATION OF PMDA, PHARMACEUTICAL LAWS & REGULATIONS, TYPES OF REGI...
JAPAN: ORGANISATION OF PMDA, PHARMACEUTICAL LAWS & REGULATIONS, TYPES OF REGI...anjaliyadav012327
 
APM Welcome, APM North West Network Conference, Synergies Across Sectors
APM Welcome, APM North West Network Conference, Synergies Across SectorsAPM Welcome, APM North West Network Conference, Synergies Across Sectors
APM Welcome, APM North West Network Conference, Synergies Across SectorsAssociation for Project Management
 
The byproduct of sericulture in different industries.pptx
The byproduct of sericulture in different industries.pptxThe byproduct of sericulture in different industries.pptx
The byproduct of sericulture in different industries.pptxShobhayan Kirtania
 
Z Score,T Score, Percential Rank and Box Plot Graph
Z Score,T Score, Percential Rank and Box Plot GraphZ Score,T Score, Percential Rank and Box Plot Graph
Z Score,T Score, Percential Rank and Box Plot GraphThiyagu K
 
Sports & Fitness Value Added Course FY..
Sports & Fitness Value Added Course FY..Sports & Fitness Value Added Course FY..
Sports & Fitness Value Added Course FY..Disha Kariya
 
Paris 2024 Olympic Geographies - an activity
Paris 2024 Olympic Geographies - an activityParis 2024 Olympic Geographies - an activity
Paris 2024 Olympic Geographies - an activityGeoBlogs
 
Separation of Lanthanides/ Lanthanides and Actinides
Separation of Lanthanides/ Lanthanides and ActinidesSeparation of Lanthanides/ Lanthanides and Actinides
Separation of Lanthanides/ Lanthanides and ActinidesFatimaKhan178732
 
1029-Danh muc Sach Giao Khoa khoi 6.pdf
1029-Danh muc Sach Giao Khoa khoi  6.pdf1029-Danh muc Sach Giao Khoa khoi  6.pdf
1029-Danh muc Sach Giao Khoa khoi 6.pdfQucHHunhnh
 

Kürzlich hochgeladen (20)

Sanyam Choudhary Chemistry practical.pdf
Sanyam Choudhary Chemistry practical.pdfSanyam Choudhary Chemistry practical.pdf
Sanyam Choudhary Chemistry practical.pdf
 
1029 - Danh muc Sach Giao Khoa 10 . pdf
1029 -  Danh muc Sach Giao Khoa 10 . pdf1029 -  Danh muc Sach Giao Khoa 10 . pdf
1029 - Danh muc Sach Giao Khoa 10 . pdf
 
microwave assisted reaction. General introduction
microwave assisted reaction. General introductionmicrowave assisted reaction. General introduction
microwave assisted reaction. General introduction
 
INDIA QUIZ 2024 RLAC DELHI UNIVERSITY.pptx
INDIA QUIZ 2024 RLAC DELHI UNIVERSITY.pptxINDIA QUIZ 2024 RLAC DELHI UNIVERSITY.pptx
INDIA QUIZ 2024 RLAC DELHI UNIVERSITY.pptx
 
Presentation by Andreas Schleicher Tackling the School Absenteeism Crisis 30 ...
Presentation by Andreas Schleicher Tackling the School Absenteeism Crisis 30 ...Presentation by Andreas Schleicher Tackling the School Absenteeism Crisis 30 ...
Presentation by Andreas Schleicher Tackling the School Absenteeism Crisis 30 ...
 
The basics of sentences session 2pptx copy.pptx
The basics of sentences session 2pptx copy.pptxThe basics of sentences session 2pptx copy.pptx
The basics of sentences session 2pptx copy.pptx
 
9548086042 for call girls in Indira Nagar with room service
9548086042  for call girls in Indira Nagar  with room service9548086042  for call girls in Indira Nagar  with room service
9548086042 for call girls in Indira Nagar with room service
 
Beyond the EU: DORA and NIS 2 Directive's Global Impact
Beyond the EU: DORA and NIS 2 Directive's Global ImpactBeyond the EU: DORA and NIS 2 Directive's Global Impact
Beyond the EU: DORA and NIS 2 Directive's Global Impact
 
Disha NEET Physics Guide for classes 11 and 12.pdf
Disha NEET Physics Guide for classes 11 and 12.pdfDisha NEET Physics Guide for classes 11 and 12.pdf
Disha NEET Physics Guide for classes 11 and 12.pdf
 
A Critique of the Proposed National Education Policy Reform
A Critique of the Proposed National Education Policy ReformA Critique of the Proposed National Education Policy Reform
A Critique of the Proposed National Education Policy Reform
 
JAPAN: ORGANISATION OF PMDA, PHARMACEUTICAL LAWS & REGULATIONS, TYPES OF REGI...
JAPAN: ORGANISATION OF PMDA, PHARMACEUTICAL LAWS & REGULATIONS, TYPES OF REGI...JAPAN: ORGANISATION OF PMDA, PHARMACEUTICAL LAWS & REGULATIONS, TYPES OF REGI...
JAPAN: ORGANISATION OF PMDA, PHARMACEUTICAL LAWS & REGULATIONS, TYPES OF REGI...
 
APM Welcome, APM North West Network Conference, Synergies Across Sectors
APM Welcome, APM North West Network Conference, Synergies Across SectorsAPM Welcome, APM North West Network Conference, Synergies Across Sectors
APM Welcome, APM North West Network Conference, Synergies Across Sectors
 
Mattingly "AI & Prompt Design: Structured Data, Assistants, & RAG"
Mattingly "AI & Prompt Design: Structured Data, Assistants, & RAG"Mattingly "AI & Prompt Design: Structured Data, Assistants, & RAG"
Mattingly "AI & Prompt Design: Structured Data, Assistants, & RAG"
 
The byproduct of sericulture in different industries.pptx
The byproduct of sericulture in different industries.pptxThe byproduct of sericulture in different industries.pptx
The byproduct of sericulture in different industries.pptx
 
Z Score,T Score, Percential Rank and Box Plot Graph
Z Score,T Score, Percential Rank and Box Plot GraphZ Score,T Score, Percential Rank and Box Plot Graph
Z Score,T Score, Percential Rank and Box Plot Graph
 
Sports & Fitness Value Added Course FY..
Sports & Fitness Value Added Course FY..Sports & Fitness Value Added Course FY..
Sports & Fitness Value Added Course FY..
 
Paris 2024 Olympic Geographies - an activity
Paris 2024 Olympic Geographies - an activityParis 2024 Olympic Geographies - an activity
Paris 2024 Olympic Geographies - an activity
 
Código Creativo y Arte de Software | Unidad 1
Código Creativo y Arte de Software | Unidad 1Código Creativo y Arte de Software | Unidad 1
Código Creativo y Arte de Software | Unidad 1
 
Separation of Lanthanides/ Lanthanides and Actinides
Separation of Lanthanides/ Lanthanides and ActinidesSeparation of Lanthanides/ Lanthanides and Actinides
Separation of Lanthanides/ Lanthanides and Actinides
 
1029-Danh muc Sach Giao Khoa khoi 6.pdf
1029-Danh muc Sach Giao Khoa khoi  6.pdf1029-Danh muc Sach Giao Khoa khoi  6.pdf
1029-Danh muc Sach Giao Khoa khoi 6.pdf
 

Android howto hellowidget

  • 1. How to: Android 'Hello Widget' Table of Contents Document history......................................................................................................1 HelloWidget...............................................................................................................1 Prerequisites.........................................................................................................1 Let’s start from scratch..........................................................................................1 The Java-way Time-Widget..................................................................................6 The Service-way Time-Widget (not working with 1.6 any more)..........................8 How to use Buttons on Widgets................................................................................9 Prerequisites.........................................................................................................9 The Layout............................................................................................................9 AppWidget Provider............................................................................................10 Manifest file.........................................................................................................10 ButtonWidget Provider........................................................................................11 Document history Version Date User Description 1.0 2009-07-11 Norbert Möhring Initial document. moehring.n [at] googlemail.com 1.1 2009-07-21 Norbert Möhring Small fixes in code (copy&paste erros ). moehring.n [at] googlemail.com Thanks to Andreas Kompanez (ak@endlessnumbered.com) for the review. Better layout. Added document history and table of contents. Put all links behind text → looks better  1.2 2009-07-23 Norbert Möhring Fixed some typos moehring.n [at] googlemail.com 1.3 2009-09-27 Norbert Möhring - Some comments to the new 1.6 Version moehring.n [at] googlemail.com - How to use Buttons on widgets HelloWidget Since there is only the one not that self explaining example of a widget I decided to invest some nightly hours to cut that example into pieces and then start from scratch with an easy to follow “Hello Widget” tutorial. Prerequisites You should already have the android SDK and android Eclipse IDE plug-in installed and running. If not, go here to learn how to get started with the android plug-in. Also you should have at least basic knowledge about Java programming since this is not a Java tutorial. Let’s start from scratch In Eclipse, go to File → new Project … → other … and select 'Android Project' The project name will be “Hello Widget” and in this case the target platform will be ‘Android 1.5’. Uncheck the probably already checked Box “Create Activity”. We won’t create an Activity here we just want a simple widget. How to: Android ‚Hello Widget’ Page 1 of 12
  • 2. New Project Wizard After that, your Project structure will look like this: The project wizard gave us some default stuff already, like the default android app-icon e.g. We’ll start with the layout and design of our widget. Open main.xml and modify it like this: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:orientation="vertical" android:background="@drawable/widget_bg_normal" android:layout_gravity="center" android:layout_height="wrap_content"> <TextView android:id="@+id/widget_textview" android:text="@string/widget_text" android:layout_height="wrap_content" android:layout_width="wrap_content" android:layout_gravity="center_horizontal|center" android:layout_marginTop="5dip" android:padding="10dip" android:textColor="@android:color/black"/> </LinearLayout> How to: Android ‚Hello Widget’ Page 2 of 12
  • 3. We have a simple linear layout with a TextView for your message to display. At this point, you will get an Error saying ERROR Error: No resource found that matches the given name (at 'background' with value '@drawable/widget_bg_normal') That’s because you don’t have the widget_bg_normal resource at this point. I borrowed the image from the SimpleWiktionary widget. It’s a png NinePatch image which will be our background of the widget. Put the file widget_bg_normal.9.png (or your own background image) into the folder res/drawable. You also don’t have the @string/widget_text resource. To fix that, go to res/values/string.xml and add this line to it: <string name="widget_text">Hello Widget!</string> string.xml will look like this: <?xml version="1.0" encoding="utf-8"?> <resources> <string name="widget_text">Hello Widget!</string> <string name="app_name">Hello Widget</string> </resources> We just finished our design part. Now we have to tell Android that we are going to have a widget. Open AndroidManifest.xml and go to the source view. The lines you have to add are bold: <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="de.thesmile.android.widget" android:versionCode="1" android:versionName="1.0"> <application android:icon="@drawable/icon" android:label="@string/app_name"> <!-- Broadcast Receiver that will process AppWidget updates --> <receiver android:name=".HelloWidget" android:label="@string/app_name"> <intent-filter> <action android:name="android.appwidget.action.APPWIDGET_UPDATE" /> </intent-filter> <meta-data android:name="android.appwidget.provider" android:resource="@xml/hello_widget_provider" /> </receiver> </application> <uses-sdk android:minSdkVersion="3" /> </manifest> How to: Android ‚Hello Widget’ Page 3 of 12
  • 4. We declare our Broadcast Receiver which will be “HelloWidget”. Don’t forget the dot before HelloWidget, this will create the full qualified path name with the declared package at the top of the file. The Label of our application was already set be the project wizard and is located in our string.xml. From the documentation: The <intent-filter> element must include an <action> element with the android:name attrib ute. This attrib ute specifies that the AppWidgetProvider accepts the ACTION_APPWIDGET_UPDATE b roadcast. This is the only b roadcast that you must explicitly declare. The AppWidgetManager automatically sends all other App Widget b roadcasts to the AppWidgetProvider as necessary. The meta-tag tells android about your widget provider. In this case, the widget provider is located at res/xml/hello_widget_provider.xml. The provider.xml is pretty much self explaining: <?xml version="1.0" encoding="utf-8"?> <appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android" android:minWidth="146dip" android:minHeight="72dip" android:updatePeriodMillis="10000" android:initialLayout="@layout/main" /> Define the size of your widget (should match the guidelines for desktop widgets). updatePerdiodMillis as it’s name already says, the time in milliseconds to update your widget. In our case, this is unimportant and we don’t need it because we don’t do any update on our widget. The initial layout points the the main.xml file. We already defined our layout and design. The only thing that is missing to run our widget is the Class that extends the AppWidgetProvider which we declared in AndroidManifest.xml at the receiver-tag. Create a new Class under the package de.thesmile.android.widget, name it HelloWidget and set AppWidgetProvider as super class. How to: Android ‚Hello Widget’ Page 4 of 12
  • 5. Your new class will look like this: package de.thesmile.android.widget; import android.appwidget.AppWidgetProvider; public class HelloWidget extends AppWidgetProvider { } Since our Widget is doing nothing, you’re now ready to go. To start your application, right click on your project → Run As → Android Application This will start the Android Virtual Device (AVD) and install your widget on this device. How to: Android ‚Hello Widget’ Page 5 of 12
  • 6. Now press and hold your left mouse button on the AVD Desktop screen until the menu pops up. Select Widgets → Hello Widget … … and have a look at the result. Ok, that was pretty easy and now you have a widget which can do …. nothing  Let’s do something with our widget ... display the current time. I’ll show you two versions of the time example, one that I would call the Java-way and the other one to introduce you to services in widgets (Service-way). The Java-way Time-Widget This is how the Java-way Time-Widget will look like. It will update every second and display the time. By the way: It’s 11:50 pm right now, I don’t know where the AVD gets it’s time from but it’s definitely not my system time. Now, open your empty class HelloWidget. We have to override the protected method onUpdate from AppWidgetProvider. Also, because of the Java-way, we’ll create an inner class MyTime which will be derived from TimerTask. Just have a look at the following code: public class HelloWidget extends AppWidgetProvider { @Override public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { Timer timer = new Timer(); timer.scheduleAtFixedRate(new MyTime(context, appWidgetManager), 1, 1000); How to: Android ‚Hello Widget’ Page 6 of 12
  • 7. } private class MyTime extends TimerTask { RemoteViews remoteViews; AppWidgetManager appWidgetManager; ComponentName thisWidget; DateFormat format = SimpleDateFormat.getTimeInstance(SimpleDateFormat.MEDIUM, Locale.getDefault()); public MyTime(Context context, AppWidgetManager appWidgetManager) { this.appWidgetManager = appWidgetManager; remoteViews = new RemoteViews(context.getPackageName(), R.layout.main); thisWidget = new ComponentName(context, HelloWidget.class); } @Override public void run() { remoteViews.setTextViewText(R.id.widget_textview, "Time = " + format.format(new Date())); appWidgetManager.updateAppWidget(thisWidget, remoteViews); } } } The method onUpdate will be called at first. We create a timer that will run our MyTime-Thread every second. The constructor of the MyTime-Class gets some information to update our widget on the desktop. Get our main view that we created (at that point you could also change your layout to another design). remoteViews = new RemoteViews(context.getPackageName(), R.layout.main); In the run method, we set the time with our new Date and update the remote View. That’s already it. Now you have a widget that is displaying the current time. At that point I want to give you some further information about a bug that has not been fixed yet, either in the AVD nor on any machine. The bug-fix didn’t make it into the CUPCAKE Version (1.5). To delete a widget, you tab and hold, then drag it and drop it into the trash can at the bottom. At that point the widget provider usually runs an onDelete and onDisable method. Currently this is not happening since the wrong IDs are sent. To fix this problem and really delete your widget, add the following code to the onReceive method: @Override public void onReceive(Context context, Intent intent) { // v1.5 fix that doesn't call onDelete Action final String action = intent.getAction(); if (AppWidgetManager.ACTION_APPWIDGET_DELETED.equals(action)) { final int appWidgetId = intent.getExtras().getInt( AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID); if (appWidgetId != AppWidgetManager.INVALID_APPWIDGET_ID) { this.onDeleted(context, new int[] { appWidgetId }); } } else { super.onReceive(context, intent); } } onReceive is always called before onUpdate is called. This code snipped checks the called action and decides weather to just run the receive method or the delete method. Jeff Sharkey provided us with this useful code-snipped. If you don’t do that, your widget won’t be displayed any more, but your widget provider will still run onReceive and onUpdate in the given period (updatePerdiodMillis) which will eat up battery and memory. It seems like this problem has been fixed in the 1.6 update so that you don't need this additional code anymore. How to: Android ‚Hello Widget’ Page 7 of 12
  • 8. The Service-way Time-Widget (not working with 1.6 any more) Usually your widget will do some more stuff than updating your time. To do so, you should create an UpdateService.class. Here’s the Time-Widget with a service. This is just an example and I’m pretty sure that the service-way of the time widget will eat up more battery than the Java-way. To register and start the service, change your onUpdate method like this: @Override public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { Intent intent = new Intent(context, UpdateService.class); context.startService(intent); } The UpdateService.class looks like this: public static class UpdateService extends Service { @Override public void onStart(Intent intent, int startId) { RemoteViews updateViews = new RemoteViews(this.getPackageName(), R.layout.main); Date date = new Date(); DateFormat format = SimpleDateFormat.getTimeInstance( SimpleDateFormat.MEDIUM, Locale.getDefault()); // set the text of component TextView with id 'message' updateViews.setTextViewText(R.id.widget_textview, "Current Time " + format.format(date)); // Push update for this widget to the home screen ComponentName thisWidget = new ComponentName(this, HelloWidget.class); AppWidgetManager manager = AppWidgetManager.getInstance(this); manager.updateAppWidget(thisWidget, updateViews); } If you want the time to be updated every second, your have to modify the hello_widget_provider.xml file and set updatePerdiodMillis to 1000. The android update 1.6 unfortunately does not support any update periode that is less then 30 minutes. The result is, that you can not run the “service-way” in 1.6 any more. Since updating every second is not very useful concerning the battery life of your phone, the 30 minute minimum period makes sense. Still, it is not very useful concerning development and testing because no developer wants to wait for 30 minutes to test the update of his widget. Anyway, for usability purposes one should always use an AlarmManager for widget updates, since you can let the user configure the periode. I'll get to the AlarmManager in my next tutorial update. How to: Android ‚Hello Widget’ Page 8 of 12
  • 9. How to use Buttons on Widgets After a few requests about updating this tutorial to show how buttons work on widgets, I finally made it and here is an example App for buttons. This application will not be functional like the Time-Widget. It will just show you how you can add several buttons and click events. Prerequisites For the prerequisites, you already know how to create a widget project from scratch. Just do that, or download the source code for this example widget. You can get it here. The Layout For the layout, we use the main.xml which will look like this: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:orientation="horizontal" android:background="@drawable/widget_bg_normal" android:layout_gravity="center" android:layout_height="wrap_content"> <Button android:text="B1" android:id="@+id/button_one" android:layout_gravity="center_horizontal|center" android:layout_height="fill_parent" android:layout_width="wrap_content"/> <Button android:text="B2" android:id="@+id/button_two" android:layout_gravity="center_horizontal|center" android:layout_height="fill_parent" android:layout_width="wrap_content"/> </LinearLayout> We use the background from our first widget and add two buttons to it, that's all we need. Since this example will also start an activity from a button, we have to create a layout for this activity. This e.g. could be a configuration screen. The configure.xml file looks like this: <TableLayout android:id="@+id/TableLayout01" android:layout_width="fill_parent" android:layout_height="fill_parent" xmlns:android="http://schemas.android.com/apk/res/android"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/TextOne" android:text="Text" android:textColor="@android:color/white" android:textSize="15dip" android:textStyle="bold" android:layout_marginTop="5dip"/> <EditText android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/txtFieldId" android:clickable="true" android:inputType="number" android:layout_marginTop="5dip" android:layout_marginBottom="20dip"/> </TableLayout> We just added a label with the string “Text” and a textfield to the screen. Nothing will be functional here. How to: Android ‚Hello Widget’ Page 9 of 12
  • 10. AppWidget Provider The appwidget-provider xml named button_widget_provider.xml is very simple. We don't need any update periode so it will look like this: <appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android" android:minWidth="146dip" android:minHeight="72dip" android:updatePeriodMillis="0" android:initialLayout="@layout/main" /> Manifest file The manifest file will have some more information this time and should look like this: <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="de.thesmile.android.widget.buttons" android:versionCode="1" android:versionName="1.0"> <application android:icon="@drawable/icon" android:label="@string/app_name"> <!-- Broadcast Receiver that will process AppWidget updates --> <receiver android:name=".ButtonWidget" android:label="@string/app_name"> <intent-filter> <action android:name="android.appwidget.action.APPWIDGET_UPDATE" /> <!-- Broadcast Receiver that will also process our self created action --> <action android:name="de.thesmile.android.widget.buttons.ButtonWidget.ACTION_WIDGET_RECEIVER"/> </intent-filter> <meta-data android:name="android.appwidget.provider" android:resource="@xml/button_widget_provider" /> </receiver> <!-- this activity will be called, when we fire our self created ACTION_WIDGET_CONFIGURE --> <activity android:name=".ClickOneActivity"> <intent-filter> <action android:name="de.thesmile.android.widget.buttons.ButtonWidget.ACTION_WIDGET_CONFIGURE"/> </intent-filter> </activity> </application> <uses-sdk android:minSdkVersion="3" /> </manifest> Ok, let's have a detailled look at it. We already know about the first part. We register our ButtonWidget as a receiver which will react on the intent with the filter APPWIDGET_UPDATE. We also know about the meta-data tag which declares some widget properties. The new thing here is the ACTION_WIDGET_RECEIVER, which, as you can see, belongs to our package. What we do is, we add a certain event to our ButtonWidget-Receiver. If this event (android calls these events intent) is fired, our ButtonWidget will be called to react on it. The second thing is the activity ClickOneActivity. We register the intent-filter ACTION_WIDGET_CONFIGURE to this activity. The code for the ClickOneActivity is pretty straight forward and you already know how that is working. We only use the onCreate method here and display a Toastmessage: public class ClickOneActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // change to our configure view setContentView(R.layout.configure); // don't call 'this', use 'getApplicationContext()', the activity-object is // bigger than just the context because the activity also stores the UI elemtents Toast.makeText(getApplicationContext(), "We are in ClickOneActivity", Toast.LENGTH_SHORT).show(); } } How to: Android ‚Hello Widget’ Page 10 of 12
  • 11. Now we can have a look at the AppWidgetProvider code to see how the intent-filters work. ButtonWidget Provider First of all, we configure our own events which we already used in our manifest file. You should always make sure that your actions have unique names not only in the namespace of your own apps but in the global namespace of the whole android framework. My idea is to just use your package name of the application to insure that. (I didn't do that in this example) public class ButtonWidget extends AppWidgetProvider { public static String ACTION_WIDGET_CONFIGURE = "ConfigureWidget"; public static String ACTION_WIDGET_RECEIVER = "ActionReceiverWidget"; [...] Now, let's have a look at the most important method; onUpdate() @Override public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.main); Intent configIntent = new Intent(context, ClickOneActivity.class); configIntent.setAction(ACTION_WIDGET_CONFIGURE); Intent active = new Intent(context, ButtonWidget.class); active.setAction(ACTION_WIDGET_RECEIVER); active.putExtra("msg", "Message for Button 1"); PendingIntent actionPendingIntent = PendingIntent.getBroadcast(context, 0, active, 0); PendingIntent configPendingIntent = PendingIntent.getActivity(context, 0, configIntent, 0); remoteViews.setOnClickPendingIntent(R.id.button_one, actionPendingIntent); remoteViews.setOnClickPendingIntent(R.id.button_two, configPendingIntent); appWidgetManager.updateAppWidget(appWidgetIds, remoteViews); } First, we get the RemoteViews for our main layout; that's where we will be working on. Then we configure a new Intent that will hold our configuration activity. This event will be given our action ACTION_WIDGET_CONFIGURE. The second Intent will be configured with our ButtonWidget and be given the action ACTION_WIDGET_RECEIVER. We also give this action some extra data that we will use later to display something on the screen. This is just to show you how you can add extra data to an intent and use it later when this intent is captured by whatever application is catching it. Now we use PendingIntents which will be given to the remoteViews as click-events. From the documentation: By giving a PendingIntent to another application, you are granting it the right to perform the operation you have specified as if the other application was yourself (with the same permissions and identity). As usual, we have to update our widget with the appWidgetManager to „commit“ the updates. Now everything is registered to our widget and the button „B2“ will be working already since it will start our Activity as soon as you click the button. Button one will do nothing at the moment because we didn't tell our ButtonWidget to do anything when it receives the action ACTION_WIDGET_RECEIVER. How to: Android ‚Hello Widget’ Page 11 of 12
  • 12. Let's have a look at the important method that can react on the ACTION_WIDGET_RECEIVER: @Override public void onReceive(Context context, Intent intent) { // v1.5 fix that doesn't call onDelete Action final String action = intent.getAction(); if (AppWidgetManager.ACTION_APPWIDGET_DELETED.equals(action)) { final int appWidgetId = intent.getExtras().getInt( AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID); if (appWidgetId != AppWidgetManager.INVALID_APPWIDGET_ID) { this.onDeleted(context, new int[] { appWidgetId }); } } else { // check, if our Action was called if (intent.getAction().equals(ACTION_WIDGET_RECEIVER)) { String msg = "null"; try { msg = intent.getStringExtra("msg"); } catch (NullPointerException e) { Log.e("Error", "msg = null"); } Toast.makeText(context, msg, Toast.LENGTH_SHORT).show(); PendingIntent contentIntent = PendingIntent.getActivity(context, 0, intent, 0); NotificationManager notificationManager = (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE); Notification noty = new Notification(R.drawable.icon, "Button 1 clicked", System.currentTimeMillis()); noty.setLatestEventInfo(context, "Notice", msg, contentIntent); notificationManager.notify(1, noty); } super.onReceive(context, intent); } } At the beginning I put the 1.5 onReceive-fix here, but this time we ask for our action in the else statement before we call super.onReceive. If ACTION_WIDGET_RECEIVER is called, we get our extra data from the intent (which was stored under the key „msg“) and display a Toast-Message with this string to the user. As a little gimmick I also show you how you use the NotificationManager of the android framework. The message „Button 1 clicked“ will pop up on the notification bar (the bar where your clock is placed) and will also show the widget icon. Feedback appreciated Author: Norbert Möhring (moehring.n [at] googlemail.com) Blog: http://blog.thesmile.de How to: Android ‚Hello Widget’ Page 12 of 12