views:

2252

answers:

6

Hi,

I'm trying to do something which really ought to be quite easy, but it's driving me crazy. I'm trying to launch an activity when a home screen widget is pressed, such as a configuration activity for the widget. I think I've followed word for word the tutorial on the Android Developers website, and even a few unofficial tutorials as well, but I must be missing something important as it doesn't work.

Here is the code:

public class VolumeChangerWidget extends AppWidgetProvider {

public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds){
 final int N = appWidgetIds.length;

 for (int i=0; i < N; i++) {
  int appWidgetId = appWidgetIds[i];

  Log.d("Steve", "Running for appWidgetId " + appWidgetId);
  Toast.makeText(context, "Hello from onUpdate", Toast.LENGTH_SHORT);
  Log.d("Steve", "After the toast line");

  Intent intent = new Intent(context, WidgetTest.class);

  PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);

  RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget);
  views.setOnClickPendingIntent(R.id.button, pendingIntent);

  appWidgetManager.updateAppWidget(appWidgetId, views);
 }
}

}

When adding the widget to the homescreen, Logcat shows the two debugging lines, though not the Toast. (Any ideas why not?) However, more vexing is that when I then click on the button with the PendingIntent associated with it, nothing happens at all. I know the "WidgetTest" activity can run because if I set up an Intent from within the main activity, it launches fine.

In case it matters, here is the Android Manifest file:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.steve"
android:versionCode="1"
android:versionName="1.0">
<application android:icon="@drawable/icon" android:label="@string/app_name">
    <activity android:name=".Volume_Change_Program"
              android:label="@string/app_name">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>

 <activity android:name=".WidgetTest"
     android:label="@string/hello">
  <intent_filter>
   <action android:name="android.intent.action.MAIN"/>
   <category android:name="android.intent.category.LAUNCHER"/>
  </intent_filter>
 </activity>

    <receiver android:name=".VolumeChangerWidget" >
     <intent-filter>
      <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
     </intent-filter>
     <meta-data  android:name="android.appwidget.provider"
        android:resource="@xml/volume_changer_info" />
    </receiver>

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

Is there a way to test where the fault is? I.e. is the fault that the button isn't linked properly to the PendingIntent, or that the PendingIntent or Intent isn't finding WidgetTest.class, etc?

Thanks very much for your help!

Steve

A: 

When adding the widget to the homescreen, Logcat shows the two debugging lines, though not the Toast. (Any ideas why not?)

Don't try launching Toasts from a BroadcastReceiver.

Is there a way to test where the fault is?

Look at LogCat, via adb logcat, DDMS, or the DDMS perspective in Eclipse. You may find warnings about not finding an activity to match the given Intent.

I do not see any obvious problem. You may want to take a peek at one of my book examples and see if that works for you, and if it gives you any idea of what may be afoot.

CommonsWare
LogCat says this when the button is added:DEBUG/Steve(772): Running for appWidgetId 33DEBUG/Steve(772): After the toast lineDEBUG/Launcher(622): dumping extras content=Bundle[{appWidgetId=33}]WARN/InputManagerService(571): Window already focused, ignoring focus gain of: com.android.internal.view.IInputMethodClient$Stub$Proxy@4388abe0but then nothing at all when the button is pressed.Thanks for the example program, I'll look through and see if I can find some inidication of where I've gone wrong.
Steve H
Hmmm...it almost feels like it is not registering your click. Are you sure R.id.button is in your widget layout?
CommonsWare
I think it is. I've got a <Button> view in the xml file with a "@+id/button" line, and in the setOnClickPendingIntent line, R.id.button is highlighted in blue when using Eclipse. Hovering the mouse over it brings up a popup box stating "com.steve.R.id.button = ... [0x...]". In other words, it seems to properly recognise it.
Steve H
A: 

The problem with the Toast not showing is easy, you don't call show(), a mistake I always do too... do

Toast.makeText(context, "Hello from onUpdate", Toast.LENGTH_SHORT).show();

instead of

Toast.makeText(context, "Hello from onUpdate", Toast.LENGTH_SHORT);
JohanS
Lol, thanks for that. That's the kind of simple fix I was hoping was needed :P
Steve H
That indeed was the solution to the issue with the Toast. Now if only I can figure out why the activity doesn't launch...
Steve H
+1  A: 

I was having the same issue. I discovered that the fix is to call an update through the appwidget manager. here is an example of how to do that in onEnabled. It appears it needs to be done in both onEnabled and onUpdated so that when device is powering on your click intent is also intialized - in onUpdated the params already provide the reference to the manager, luckily.

@Override 
    public void onEnabled(Context context) {  
          //Log.v("toggle_widget","Enabled is being called"); 

          AppWidgetManager mgr = AppWidgetManager.getInstance(context); 
          //retrieve a ref to the manager so we can pass a view update 

          Intent i = new Intent(); 
          i.setClassName("yourdoman.yourpackage", "yourdomain.yourpackage.yourclass"); 
          PendingIntent myPI = PendingIntent.getService(context, 0, i, 0); 
          //intent to start service 

        // Get the layout for the App Widget 
        RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.togglelayout); 

        //attach the click listener for the service start command intent 
        views.setOnClickPendingIntent(R.id.toggleButton, myPI); 

        //define the componenet for self 
        ComponentName comp = new ComponentName(context.getPackageName(), ToggleWidget.class.getName()); 

        //tell the manager to update all instances of the toggle widget with the click listener 
        mgr.updateAppWidget(comp, views); 
} 
Unfortunately no, I haven't worked out how to do this yet. It must be something obscure, as like you I read all the tutorials I could find, but never found something that worked. I just ended up shelving this project and started working on something else until I know how to use Android a bit better.
Steve H
Hey Steve. I think I've discovered the solution. I'm developing on 2.0.1. The key was moving this exact code into the onUpdated, and then calling one additional thing - a reference to AppWidgetManager comes in to the onUpdated via the params. ComponentName comp = new ComponentName(context.getPackageName(), ToggleWidget.class.getName()); appWidgetManager.updateAppWidget(comp, views); This version tells it to update all instances of the widget like this. Only problem now is making onEnabled call onUpdate once so it inits when user is adding widget to home.
+1 thanks. by adding the mgr.updateAppWidget i was able to finally get my widget to do the same.
nategood
Thanks for the suggestion! I'll give it a go once I finish this other project I'm working on. (Your code looks rather similar to one of the other things I tried, but I'm coding in v1.5 as that's the version on my phone. I hope this isn't an issue of v1.5 not working properly, as per some reports about various workarounds needed for AppWidgets in this version...)
Steve H
A: 

Hi Steve, Me new to android ,actually i have a application and now my concern is 1) How do i create a home screen widget(With just a icon and a text view under it) 2) And when the widget on the home screen is clicked how do i show up my application would be looking forward for your help Thank you

warrior
Umm, this section is for answering questions, not asking a new one of your own. I would recommend reading the official tutorials on developer.android.com and then googling around for other tutorials as well. That will give you an idea of how to do it. Once you've tried a few things, you can then ask a more specific question.
Steve H
A: 

Steve,

Have you found the problem? I use widget and it works fine for me without onEnabled trick. I'm interested why it doesn't for you.

My guess: in your original code please try

PendingIntent pendingIntent = PendingIntent.getActivity(context, 1, intent, 0);

instead of

PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);
Fedor
Hi, this question hasn't been active for ages! However, the change you suggested doesn't make a difference. I was able to solve the problem by starting the project over again from scratch. As far as I can tell the two projects are identical, but this one doesn't work. I don't understand why this one doesn't work, but it's not an issue since the other one does.
Steve H
A: 

Hi Steve; you must define your configuration activity in res/xml/volume_changer_info.xml. Add this tag and give a fully qualified path to the configuration activity.

android:configure = ""


e.g.

<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
    android:minWidth="200dip"
    android:minHeight="100dip"
    android:updatePeriodMillis="60000"
    android:initialLayout="@layout/widget_loading"
    android:configure = "org.raza.ConfigureWidgetActivity"/>
Raza
Hi, I think we're talking about different things when we referred to a "configuration activity". I meant something that could be launched at any time after adding the widget rather than something that would be launched as you added the widget. This issue was solved a while ago but thanks for trying to help!
Steve H