Widget Click Not Registering Right Away

Put your problem here if it does not fit any of the other categories.

Widget Click Not Registering Right Away

Postby AndroidAC » Sat Jan 02, 2010 12:00 pm

I have a strange issue. I have a widget that when clicked, performs two actions. First it calls a function that does something (the specifics are not relevant). Second, it updates some text on the widget. When it works, it works exactly as I want it to. However, very often when the widget is added to the home screen, the click event isn't registered, sometimes for hours, sometimes minutes but sometimes right away as it is supposed to do. I can't figure out why and I can't spend any more time on it as I'm losing my mind. I've pieced together this code from about 20 different tutorials in an attempt to learn widget development but I think the opposite ended up happening. Anyway, here are the relevant code blocks. Any help would be greatly appreciated.

Here's my WidgetSmallIconCopy.java file.

Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1.  
  2. package com.my.appname;
  3.  
  4.  
  5.  
  6. import android.app.AlarmManager;
  7.  
  8. import android.app.PendingIntent;
  9.  
  10. import android.app.Service;
  11.  
  12. import android.appwidget.AppWidgetManager;
  13.  
  14. import android.appwidget.AppWidgetProvider;
  15.  
  16. import android.content.ComponentName;
  17.  
  18. import android.content.Context;
  19.  
  20. import android.content.Intent;
  21.  
  22. import android.content.SharedPreferences;
  23.  
  24. import android.net.Uri;
  25.  
  26. import android.os.Environment;
  27.  
  28. import android.os.IBinder;
  29.  
  30. import android.os.StatFs;
  31.  
  32. import android.os.SystemClock;
  33.  
  34. import android.os.Vibrator;
  35.  
  36. import android.preference.PreferenceManager;
  37.  
  38. import android.util.Log;
  39.  
  40. import android.widget.RemoteViews;
  41.  
  42. import android.widget.Toast;
  43.  
  44. import com.my.appname.RunTheProgram;
  45.  
  46.  
  47.  
  48. public class WidgetSmallIconCopy extends AppWidgetProvider {
  49.  
  50.         private static final String WIDGET_CLICK = "com.my.appname.CLICK";
  51.  
  52.         private static final String URI_SCHEME = "widgetsmallicon";
  53.  
  54.         private static final String TAG = "WidgetSmallIcon_TAG";
  55.  
  56.         private String widgetupdate = "600";
  57.  
  58.  
  59.  
  60.         @Override
  61.  
  62.         public void onUpdate(Context context, AppWidgetManager mgr, int[] appWidgetIds) {
  63.  
  64.                 Log.i(TAG, "onUpdate: Outside Loop");
  65.  
  66.                 final int N = appWidgetIds.length;
  67.  
  68.                 for (int i=0; i<N; i++) {
  69.  
  70.                         Log.i(TAG, "onUpdate: Inside Loop");
  71.  
  72.                         int appWidgetId = appWidgetIds[i];
  73.  
  74.                         Intent intent = new Intent(context, UpdateWidgetText.class);
  75.  
  76.                         context.startService(intent);
  77.  
  78.  
  79.  
  80.                         RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widgetsmallicon);
  81.  
  82.                         Intent clickintent = new Intent(WIDGET_CLICK);
  83.  
  84.                         PendingIntent pendingIntentClick = PendingIntent.getBroadcast(context, 0, clickintent, 0);
  85.  
  86.                         views.setOnClickPendingIntent(R.id.widget, pendingIntentClick);
  87.  
  88.                         mgr.updateAppWidget(appWidgetId, views);
  89.  
  90.                 }
  91.  
  92.                 super.onUpdate(context, mgr, appWidgetIds);
  93.  
  94.         }
  95.  
  96.  
  97.  
  98.         @Override
  99.  
  100.         public void onReceive(Context context, Intent intent) {
  101.  
  102.                 final String action = intent.getAction();
  103.  
  104.                 Log.i(TAG, "onReceive: intent.getAction(): " + action);
  105.  
  106.                 if (action.equals(WIDGET_CLICK)) {
  107.  
  108.                         Log.i(TAG, "onReceive: WIDGET_CLICK");
  109.  
  110.                         // this is a class that runs when the widget is clicked.
  111.  
  112.                         // what it does isn't important.
  113.  
  114.                         RunTheProgram.functionName(context);
  115.  
  116.                         Toast.makeText(context, "Tell user stuff was done.", Toast.LENGTH_LONG).show();
  117.  
  118.  
  119.  
  120.                         // update the widget's text with updated information
  121.  
  122.                         context.startService(new Intent(context, UpdateWidgetText.class));
  123.  
  124.                 }
  125.  
  126.  
  127.  
  128.                 if (AppWidgetManager.ACTION_APPWIDGET_DELETED.equals(action)) {
  129.  
  130.                         Log.i(TAG, "onReceive: ACTION_APPWIDGET_DELETED");
  131.  
  132.                         final int appWidgetId = intent.getExtras().getInt(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
  133.  
  134.             if (appWidgetId != AppWidgetManager.INVALID_APPWIDGET_ID) {
  135.  
  136.                 this.onDeleted(context, new int[] { appWidgetId });
  137.  
  138.             }
  139.  
  140.                 } else if (AppWidgetManager.ACTION_APPWIDGET_UPDATE.equals(action)) {
  141.  
  142.                         Log.i(TAG, "onReceive: ACTION_APPWIDGET_UPDATE");
  143.  
  144.                         if (!URI_SCHEME.equals(intent.getScheme())) {
  145.  
  146.                                 Log.i(TAG, "onReceive: " + intent.getScheme());
  147.  
  148.                 // if the scheme doesn't match, that means it wasn't from the
  149.  
  150.                 // alarm either it's the first time in (even before the
  151.  
  152.                 // configuration is done) or after a reboot or update
  153.  
  154.                 final int[] appWidgetIds = intent.getExtras().getIntArray(AppWidgetManager.EXTRA_APPWIDGET_IDS);
  155.  
  156.                 SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
  157.  
  158.                 widgetupdate = prefs.getString("widgetupdate", "600");
  159.  
  160.                 for (int appWidgetId : appWidgetIds) {
  161.  
  162.                         int updateRateSeconds = Integer.parseInt(widgetupdate);
  163.  
  164.  
  165.  
  166.                     if (updateRateSeconds != -1) {
  167.  
  168.                         Log.i(TAG, "Starting recurring alarm for id " + appWidgetId);
  169.  
  170.                         Intent widgetUpdate = new Intent();
  171.  
  172.                         widgetUpdate.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
  173.  
  174.                         widgetUpdate.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, new int[] { appWidgetId });
  175.  
  176.  
  177.  
  178.                         // make this pending intent unique by adding a scheme to it
  179.  
  180.                         widgetUpdate.setData(Uri.withAppendedPath(Uri.parse(URI_SCHEME + "://widget/id/"), String.valueOf(appWidgetId)));
  181.  
  182.                         PendingIntent newPending = PendingIntent.getBroadcast(context, 0, widgetUpdate, PendingIntent.FLAG_UPDATE_CURRENT);
  183.  
  184.  
  185.  
  186.                         // schedule the updating
  187.  
  188.                         AlarmManager alarms = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
  189.  
  190.                         alarms.setRepeating(AlarmManager.ELAPSED_REALTIME, SystemClock.elapsedRealtime(), updateRateSeconds * 1000, newPending);
  191.  
  192.                     }
  193.  
  194.                 }
  195.  
  196.             }
  197.  
  198.             super.onReceive(context, intent);
  199.  
  200.         } else {
  201.  
  202.                         Log.i(TAG, "onReceive: Not ACTION_APPWIDGET _DELETED OR _UPDATE");
  203.  
  204. ,               super.onReceive(context, intent);
  205.  
  206.         }
  207.  
  208.         }
  209.  
  210.  
  211.  
  212.         @Override
  213.  
  214.         public void onDeleted(Context context, int[] appWidgetIds) {
  215.  
  216.                 Log.i(TAG, "onDeleted: Outside Loop");
  217.  
  218.                 for (int appWidgetId : appWidgetIds) {
  219.  
  220.                         Log.i(TAG, "onDeleted: Inside Loop");
  221.  
  222.                         // stop alarm
  223.  
  224.                         Intent widgetUpdate = new Intent();
  225.  
  226.                         widgetUpdate.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
  227.  
  228.                         widgetUpdate.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
  229.  
  230.                         widgetUpdate.setData(Uri.withAppendedPath(Uri.parse(URI_SCHEME + "://widget/id/"), String.valueOf(appWidgetId)));
  231.  
  232.                         PendingIntent newPending = PendingIntent.getBroadcast(context, 0, widgetUpdate, PendingIntent.FLAG_UPDATE_CURRENT);
  233.  
  234.  
  235.  
  236.                         AlarmManager alarms = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
  237.  
  238.                         alarms.cancel(newPending);
  239.  
  240.                 }
  241.  
  242.                 super.onDeleted(context, appWidgetIds);
  243.  
  244.         }
  245.  
  246.  
  247.  
  248.         public static class UpdateWidgetText extends Service {
  249.  
  250.                
  251.  
  252.                 @Override
  253.  
  254.                 public void onStart(Intent intent, int startId) {
  255.  
  256.                         Log.i(TAG, "UpdateWidgetText: onStart");
  257.  
  258.                         super.onStart(intent, startId);
  259.  
  260.  
  261.  
  262.                         RemoteViews updateViews = new RemoteViews(this.getPackageName(), R.layout.widgetsmallicon);
  263.  
  264.  
  265.  
  266.                         // this text is normally calculated using functions not shown here.
  267.  
  268.                         String SomeString = "Some text";
  269.  
  270.                         updateViews.setTextViewText(R.id.SomeTextView, SomeString);
  271.  
  272.  
  273.  
  274.                         ComponentName thisWidget = new ComponentName(this, WidgetSmallIconCopy.class);
  275.  
  276.                 AppWidgetManager manager = AppWidgetManager.getInstance(this);
  277.  
  278.                 manager.updateAppWidget(thisWidget, updateViews);
  279.  
  280.                 }
  281.  
  282.  
  283.  
  284.                 @Override
  285.  
  286.                 public IBinder onBind(Intent intent) {
  287.  
  288.                         // TODO Auto-generated method stub
  289.  
  290.                         return null;
  291.  
  292.                 }
  293.  
  294.  
  295.  
  296.         }
  297.  
  298. }
  299.  
  300.  
Parsed in 0.057 seconds, using GeSHi 1.0.8.4


Here's my widgetsmalliconcopy.xml file.

Syntax: [ Download ] [ Hide ]
Using xml Syntax Highlighting
  1.  
  2. <?xml version="1.0" encoding="utf-8"?>
  3.  
  4.  
  5.  
  6. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  7.  
  8.    android:id="@+id/widget"
  9.  
  10.    android:layout_width="fill_parent"
  11.  
  12.    android:layout_height="wrap_content"
  13.  
  14.         android:paddingTop="9dip"
  15.  
  16.    android:focusable="true">
  17.  
  18.  
  19.  
  20.     <ImageView
  21.  
  22.        android:id="@+id/someid"
  23.  
  24.        android:layout_width="wrap_content"
  25.  
  26.        android:layout_height="wrap_content"
  27.  
  28.        android:layout_centerHorizontal="true"
  29.  
  30.                 android:src="@drawable/icon"/>
  31.  
  32.  
  33.  
  34.     <LinearLayout
  35.  
  36.        android:id="@+id/selection_block"
  37.  
  38.        android:layout_width="wrap_content"
  39.  
  40.        android:layout_height="wrap_content"
  41.  
  42.        android:layout_below="@id/someid"
  43.  
  44.        android:layout_centerHorizontal="true"
  45.  
  46.        android:orientation="horizontal"
  47.  
  48.        android:duplicateParentState="true"
  49.  
  50.                 android:background="@drawable/bg_xml">
  51.  
  52.  
  53.  
  54.         <TextView
  55.  
  56.            android:id="@+id/SomeTextView"
  57.  
  58.            android:layout_width="wrap_content"
  59.  
  60.            android:layout_height="wrap_content"
  61.  
  62.            android:includeFontPadding="false"
  63.  
  64.            android:singleLine="true"
  65.  
  66.            android:ellipsize="none"
  67.  
  68.                         android:textSize="11dip"
  69.  
  70.                         android:textColor="#ffff"/>
  71.  
  72.  
  73.  
  74.         </LinearLayout>
  75.  
  76. </RelativeLayout>
  77.  
  78.  
Parsed in 0.004 seconds, using GeSHi 1.0.8.4


And here are the relevant parts of my AndroidManifest.xml

Syntax: [ Download ] [ Hide ]
Using xml Syntax Highlighting
  1.  
  2. <?xml version="1.0" encoding="utf-8"?>
  3.  
  4. <manifest xmlns:android="http://schemas.android.com/apk/res/android"
  5.  
  6.         package="com.my.appname" android:versionCode="56" android:versionName="2.6">
  7.  
  8.         <application android:icon="@drawable/icon"
  9.  
  10.                 android:label="@string/app_name"
  11.  
  12.                 android:description="@string/app_description">
  13.  
  14.  
  15.  
  16.                 <receiver android:name=".WidgetSmallIconCopy"
  17.  
  18.                         android:label="@string/widget_name_1x1_icon"
  19.  
  20.                         android:icon="@drawable/widget_list_icon">
  21.  
  22.                         <intent-filter>
  23.  
  24.                                 <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
  25.  
  26.                                 <action android:name="android.appwidget.action.APPWIDGET_DELETED" />
  27.  
  28.                                 <action android:name="com.my.appname.CLICK" />
  29.  
  30.                         </intent-filter>
  31.  
  32.                         <intent-filter>
  33.  
  34.                                 <data android:scheme="widgetsmallicon"/>
  35.  
  36.                         </intent-filter>
  37.  
  38.                         <meta-data android:name="android.appwidget.provider"
  39.  
  40.                                 android:resource="@xml/widget_small_icon_info" />
  41.  
  42.                 </receiver>
  43.  
  44.  
  45.  
  46.                 <service android:name=".WidgetSmallIconCopy$UpdateWidgetText"/>
  47.  
  48.         </application>
  49.  
  50.  
  51.  
  52.         <uses-sdk android:minSdkVersion="3"/>
  53.  
  54.         <uses-permission android:name="android.permission.VIBRATE" />
  55.  
  56. </manifest>
  57.  
  58.  
Parsed in 0.004 seconds, using GeSHi 1.0.8.4
AndroidAC
Freshman
Freshman
 
Posts: 3
Joined: Sat Jan 02, 2010 11:45 am

Top

Postby lostdroid » Fri Mar 26, 2010 9:58 am

I believe your problem is due to the way you are using your click Intent. Try the following in onUpdate:

RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widgetsmallicon);
Intent clickintent = new Intent(context, UpdateWidgetText.class);
clickintent.setAction(WIDGET_CLICK);
PendingIntent pendingIntentClick = PendingIntent.getBroadcast(context, 0, clickintent, 0);
views.setOnClickPendingIntent(R.id.widget, pendingIntentClick);

I'm just learning myself so not an expert but this seems to work for me. Like you I've been piecing together lots examples but have some issues of my own.
lostdroid
Freshman
Freshman
 
Posts: 3
Joined: Fri Mar 26, 2010 9:22 am
Location: UK

Postby AndroidAC » Fri Mar 26, 2010 8:36 pm

lostdroid wrote:I believe your problem is due to the way you are using your click Intent. Try the following in onUpdate:

RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widgetsmallicon);
Intent clickintent = new Intent(context, UpdateWidgetText.class);
clickintent.setAction(WIDGET_CLICK);
PendingIntent pendingIntentClick = PendingIntent.getBroadcast(context, 0, clickintent, 0);
views.setOnClickPendingIntent(R.id.widget, pendingIntentClick);

I'm just learning myself so not an expert but this seems to work for me. Like you I've been piecing together lots examples but have some issues of my own.


I'm going to try this out. My problem is that there are few widget examples out there and I've had to piece code together from those few examples. None of them fit what I needed exactly so I hacked it up. I'm a hardcore scripter and Java, particularly when using it for Android development, is not very forgiving (as JavaScript and HTML might be). The weird thing is that is works but has trouble starting up. My friends and family get to use the widgets (which are awesome) but I'd like to allow my users to get them as well.
AndroidAC
Freshman
Freshman
 
Posts: 3
Joined: Sat Jan 02, 2010 11:45 am

Postby AndroidAC » Fri Mar 26, 2010 9:31 pm

lostdroid wrote:I believe your problem is due to the way you are using your click Intent. Try the following in onUpdate:

RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widgetsmallicon);
Intent clickintent = new Intent(context, UpdateWidgetText.class);
clickintent.setAction(WIDGET_CLICK);
PendingIntent pendingIntentClick = PendingIntent.getBroadcast(context, 0, clickintent, 0);
views.setOnClickPendingIntent(R.id.widget, pendingIntentClick);

I'm just learning myself so not an expert but this seems to work for me. Like you I've been piecing together lots examples but have some issues of my own.


After reading your code further, I realized that I have tried this before. I tried it again just to be sure and it does not change anything. What I have discovered in beta testing is that if the task (the application itself) is running, the widget doesn't register properly. If I kill the task using a task manager the widget will register fine and work fine. This is an issue because the application will often need to be on an exclude list in task managers because there is a service that can be running to automatically do something every X number of minutes, hours or days. So the task cannot be killed in order to properly register the widget. My friends and family who use it deal with the issue but I cannot release it to the public that way.
AndroidAC
Freshman
Freshman
 
Posts: 3
Joined: Sat Jan 02, 2010 11:45 am

Top

Return to Other Coding-Problems

Who is online

Users browsing this forum: Majestic-12 [Bot] and 23 guests