I am making a simple app widget that displays a toast message when a button in the widget is touched. The issue I am having is that the toast never appears when the button is clicked. In fact, the onReceive event is never fired when the button is touched. I suspect the issue has to do with my manifest, but it looks ok to me.
Here is the relevant portions of my manifest:
<receiver android:name=".GPSWidget" android:label="GPS Receiver">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
<action android:name="luke.app.steal.GPSWidget.ACTION_WIDGET_RECEIVER"/>
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="#xml/widget_provider" />
</receiver>
Here is the code to "wire up" the button to an event listener, as well as the onReceive event it is in a class called GPSReceiver.
public static String ACTION_WIDGET_RECEIVER = "ActionReceiverWidget";
#Override
public void onReceive(Context context, Intent intent) {
if(intent.getAction().equals(ACTION_WIDGET_RECEIVER)) {
Toast.makeText(context, "Button hit", Toast.LENGTH_SHORT).show();
}
super.onReceive(context, intent);
}
#Override
public void onUpdate( Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds )
{
RemoteViews remoteViews;
remoteViews = new RemoteViews( context.getPackageName(), R.layout.gpswidget );
remoteViews.setTextViewText( R.id.widgetTexts, "Click Me!");
Intent inte = new Intent(context, lukeService.class);
inte.setAction(ACTION_WIDGET_RECEIVER);
PendingIntent configPendingIntent = PendingIntent.getBroadcast(context, 0, inte, 0);
remoteViews.setOnClickPendingIntent(R.id.widgetTexts, configPendingIntent);
appWidgetManager.updateAppWidget(appWidgetIds, remoteViews );
}
widgetTexts is the button that should be launching the toast, but like I said nothing happens when the button is hit. I thought that my path in the manifest was wrong, luke.app.steal, but that same path works just fine for all my other activities.
Anyone got any ideas? or need more info?
Related
Update: Solved it, solution below
I'm trying to write a widget that starts a service, which then will do some stuff not implemented yet. So far my service is only that:
public class SmartWifiService extends Service {
private static final String WIDGET_CLICK = "de.regenhardt.smartwifiwidget.WIDGET_CLICK";
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
Log.e("DEBUG", "Service started");
Toast.makeText(getApplicationContext(), "Widget clicked", Toast.LENGTH_SHORT).show();
stopSelf();
return START_NOT_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
}
So everything it does is send a Toast and stop itself after that.
Unfortunately, it doesn't come to that. My Provider looks like that:
public class SmartWifiWidgetProvider extends AppWidgetProvider {
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
Log.e("DEBUG", "onUpdate called");
super.onUpdate(context, appWidgetManager, appWidgetIds);
Intent clickIntent = new Intent(context, SmartWifiWidgetProvider.class);
clickIntent.setAction("de.regenhardt.smartwifiwidget.WIDGET_CLICK");
PendingIntent pendingIntent = PendingIntent.getBroadcast(context.getApplicationContext(),
0, clickIntent, 0);
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget_layout);
views.setOnClickPendingIntent(R.id.layout, pendingIntent);
//for (int ID:appWidgetIds) {
// views.setOnClickPendingIntent(ID, pendingIntent);
appWidgetManager.updateAppWidget(appWidgetIds, views);
//}
#Override
public void onReceive(Context context, Intent intent) {
Log.e("DEBUG", "received");
super.onReceive(context, intent);
if(intent.getAction().equals("de.regenhardt.smartwifiwidget.WIDGET_CLICK")){
Log.e("DEBUG", "Click action fits");
Intent i = new Intent(context.getApplicationContext(), SmartWifiService.class);
context.startService(i);
}
}
}
I went through several answered questions here, changed stuff, added stuff, and so far nothing really worked, and I still have no idea why.
When I click the Widget there is no animation, but I'm pretty sure my widget itself is clickable:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/layout"
android:clickable="true">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/wifi"
android:clickable="true"
android:id="+id/widgetImage"/>
</LinearLayout>
Also tried it with ImageButton, no change in effect.
I hope you guys can help me, I have been sitting in this little thing for days and my head is spinning (not literally).
Greetings,
Marlon
Edit: Here's my Manifest:
<application android:allowBackup="true"
android:label="#string/app_name"
android:icon="#drawable/wifi"
android:theme="#style/AppTheme">
<receiver android:name=".SmartWifiWidgetProvider">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE"/>
<action android:name="de.regenhardt.smartwifiwidget.WIDGET_CLICK"/>
</intent-filter>
<meta-data android:name="android.appwidget.provider"
android:resource="#xml/smart_wifi_widget_info"/>
</receiver>
<service android:name="de.regenhardt.smartwifiwidget.SmartWifiService"/>
</application>
Edit 2: Update; updated to current state of my code, adapted to Y.S.' answer.
LogCat after adding the widget, clicking it still doesn't do anything:
04-08 20:12:30.985 14867-14867/de.regenhardt.smartwifiwidget E/DEBUG﹕ received
04-08 20:12:30.998 14867-14867/de.regenhardt.smartwifiwidget E/DEBUG﹕ received
04-08 20:12:30.998 14867-14867/de.regenhardt.smartwifiwidget E/DEBUG﹕ onUpdate called
04-08 20:12:31.155 14867-14867/de.regenhardt.smartwifiwidget E/DEBUG﹕ received
Solution:
The blowing line was views.setOnClickPendingIntent(R.id.widgetImage, pendingIntent);, I had R.id.layout instead of widgetImage there. It seems a widget doesnt hand the click through to views below if it doesnt get handled.
The Problem:
To start a Service in this way, you need to use PendingIntent.getBroadcast(), not PendingIntent.getService(). And the WIDGET_CLICK action needs to be specified in the app manifest under the receiver tag, not the service tag.
STEP 1:
Replace
Intent clickIntent = new Intent("de.regenhardt.smartwifiwidget.WIDGET_CLICK");
with
Intent clickIntent = new Intent(context, SmartWifiWidgetProvider.class);
clickIntent.setAction("de.regenhardt.smartwifiwidget.WIDGET_CLICK");
STEP 2:
Replace
PendingIntent pendingIntent = PendingIntent.getService(context.getApplicationContext(),
0, clickIntent, PendingIntent.FLAG_UPDATE_CURRENT);
with
PendingIntent pendingIntent = PendingIntent.getBroadcast(context.getApplicationContext(),
0, clickIntent, 0);
STEP 3:
In the manifest, add the action to the receiver tag and remove it from the service tag:
<application android:allowBackup="true"
android:label="#string/app_name"
android:icon="#drawable/wifi"
android:theme="#style/AppTheme">
<receiver android:name=".SmartWifiWidgetProvider">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE"/>
<action android:name="de.regenhardt.smartwifiwidget.WIDGET_CLICK"/>
</intent-filter>
<meta-data android:name="android.appwidget.provider"
android:resource="#xml/smart_wifi_widget_info"/>
</receiver>
<service android:name="de.regenhardt.smartwifiwidget.SmartWifiService"></service>
</application>
STEP 4:
Set the PendingIntent on the RemoteViews in your widget:
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget_layout);
views.setOnClickPendingIntent(R.id.widgetImage, pendingIntent);
STEP 5:
Override the onReceive() method of the SmartWifiWidgetProvider class:
#Override
public void onReceive(Context context, Intent intent) {
super.onReceive(context, intent);
if (intent.getAction().equals("de.regenhardt.smartwifiwidget.WIDGET_CLICK")) {
Intent i = new Intent(context.getApplicationContext(), SmartWifiService.class)
startService(i);
}
}
Try this. This should start the Service correctly.
You should add your service into manifest:
<service android:name="SmartWifiService"></service>
You didn't say how you are calling service, so I could say that need to call startService(Intent) from some Activity - it would not start without that.
I tried to create clickable widget on android. I was looking for solution on this site and I found it, but finally this widget is working only on the emulator - not on real phone. This is my code:
AppWidgetProvider:
public static String WIDGET_BUTTON = "apps.test.widget.WIDGET_BUTTON";
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds) {
super.onUpdate(context, appWidgetManager, appWidgetIds);
RemoteViews views = new RemoteViews(context.getPackageName(),
R.layout.main);
Intent clickIntent = new Intent(WIDGET_BUTTON);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0,
clickIntent, PendingIntent.FLAG_UPDATE_CURRENT);
views.setOnClickPendingIntent(R.id.imageView1, pendingIntent);
appWidgetManager.updateAppWidget(appWidgetIds, views);
}
#Override
public void onReceive(Context context, Intent intent) {
super.onReceive(context, intent);
if (WIDGET_BUTTON.equals(intent.getAction())) {
Toast.makeText(context, "asdfsdgdasfg", Toast.LENGTH_SHORT).show();
}
}
Manifest:
<application
android:allowBackup="true"
android:icon="#drawable/image"
android:label="#string/app_name" >
<receiver
android:name=".Widget"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
<action android:name="apps.test.widget.WIDGET_BUTTON"/>
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="#xml/test_widget_provider" />
</receiver>
</application>
Toast is showing up on the emulator but not on phone.
Ok, nevermind.
I had to reset the phone to factory settings. I don't know what was wrong.
This is a common issue,had it a few times with my phone , if the app is installed on sdcard instead of internal storage ,the widget does not appear on the list,
you can simply go to Settings->apps->find the app and then select the option to move it to internal storage from your android itself.
[http://www.technipages.com/fix-android-app-widgets-not-appearing-on-widget-list][1]
There is another way to declare in the manifest as android:externalstorage(syntax isnt correct) which works as well (I cant find the link though to the answer and I have not tried it)
hi friends enter link description here
this link to create list view widget for my app, but here i want to add a button below the list view ,which on click will open my app,
using the below code to acheive this,because it worked for me on other app, but not with this example, how to do that .
class widgetprovider
public class WidgetProvider extends AppWidgetProvider {
// String to be sent on Broadcast as soon as Data is Fetched
// should be included on WidgetProvider manifest intent action
// to be recognized by this WidgetProvider to receive broadcast
public static final String DATA_FETCHED = "com.wordpress.laaptu.DATA_FETCHED";
/*
* this method is called every 30 mins as specified on widgetinfo.xml this
* method is also called on every phone reboot from this method nothing is
* updated right now but instead RetmoteFetchService class is called this
* service will fetch data,and send broadcast to WidgetProvider this
* broadcast will be received by WidgetProvider onReceive which in turn
* updates the widget
*/
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds) {
// which layout to show on widget
RemoteViews remoteViews = new RemoteViews(context.getPackageName(),
R.layout.widget_layout);
Intent informationIntent = new Intent(context,info.class);
PendingIntent infoPendingIntent = PendingIntent.getActivity(context,0, informationIntent, 0);
remoteViews.setOnClickPendingIntent(R.id.btnSeeMore,infoPendingIntent);
final int N = appWidgetIds.length;
for (int i = 0; i < N; i++) {
Intent serviceIntent = new Intent(context, RemoteFetchService.class);
serviceIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,
appWidgetIds[i]);
context.startService(serviceIntent);
}
super.onUpdate(context, appWidgetManager, appWidgetIds);
}
manifest added a activity
<activity android:name=".info" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.INFO" />
</intent-filter>
</activity>
when on click it should open my app,how to do that please help, thank you
finaly i solved what i want to get,
just wrote a button click code onReceive & it worked
#Override
public void onReceive(Context context, Intent intent) {
super.onReceive(context, intent);
if (intent.getAction().equals(DATA_FETCHED)) {
Log.i("inside action", "DATA_FETCHED");
int appWidgetId = intent.getIntExtra(
AppWidgetManager.EXTRA_APPWIDGET_ID,
AppWidgetManager.INVALID_APPWIDGET_ID);
AppWidgetManager appWidgetManager = AppWidgetManager
.getInstance(context);
RemoteViews remoteViews = updateWidgetListView(context, appWidgetId);
Intent informationIntent = new Intent(context,MainActivity.class);
PendingIntent infoPendingIntent = PendingIntent.getActivity(context,0, informationIntent, 0);
remoteViews.setOnClickPendingIntent(R.id.txtSeeMore,infoPendingIntent);
appWidgetManager.updateAppWidget(appWidgetId, remoteViews);
}
}
You need to define how the PendingIntent you are setting will be handled, by overriding the onReceive method inside your provider :
#Override
public void onReceive(Context context, Intent intent) {
super.onReceive(context, intent);
if (intent.getAction().equals(ACTION_NAME)) {
// Open your activity here.
}
}
If every item in your ListView needs a different extra to help the onReceive create the proper Intent, you can use a FillInIntent for each item of the ListView, in getViewAt :
// Set the onClickFillInIntent
final Intent fillInIntent = new Intent();
final Bundle extras = new Bundle();
extras.putInt(YourWidgetProvider.ACTION_EXTRA_ITEM, event.getId()); // retrieve this in onReceive with intent.getIntExtra(ACTION_EXTRA_ITEM, -1)
fillInIntent.putExtras(extras);
rv.setOnClickFillInIntent(R.id.listview_main_layout, fillInIntent);
return rv;
Also, don't forget to add your Provider and your RemoteViewsService to your Manifest :
<receiver
android:name="com.example.YourWidgetProvider"
android:label="#string/widget_name">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="#xml/provider_definition_in_xml" />
</receiver>
<service android:name="com.example.YourRemoteViewsService"
android:permission="android.permission.BIND_REMOTEVIEWS"
android:exported="false" />
EDIT :
To handle clicks on buttons in the main widget (not in the collection view), it's even easier :
rv.setOnClickPendingIntent(R.id.button_id, PendingIntent.getBroadcast(context, 0,
new Intent(context, YourWidgetProvider.class)
.setAction(ACTION_NAME),
PendingIntent.FLAG_UPDATE_CURRENT));
The ACTION_NAME needs to be different from the name you use for the clicks on the collection view, of course, since it needs to produce a different Intent.
I hope this helps !
I've created a simple widget have only a button and textView. When I add my widget first time to the homescreen a FC message coming and widget will added. And button click toast message won't work. Only i need to have a toast message when clicking the widget button. I've gone through lots of tutorials but couldn't figure out whats the problem. Any genius who'd like to help..really appriciate the help..Thanks..
widgetProvider.java
public class widgetProvider extends AppWidgetProvider{
#Override
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];
Intent intent = new Intent(context, widgetProvider.class);
intent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widgetlayout);
views.setOnClickPendingIntent(R.id.button1, pendingIntent);
appWidgetManager.updateAppWidget(appWidgetId, views);
}
}
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(AppWidgetManager.ACTION_APPWIDGET_UPDATE)) {
Toast.makeText(context, "Button Clicked", Toast.LENGTH_SHORT).show();
}
}
}
AndroidManifest.xml
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<receiver android:name=".widgetProvider" 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/widgetprovider" />
</receiver>
</application>
your onUpdate is never called since you overriden the onReceive method.
I have a widget whose layout has an imageView. The view needs to be changed based on some activity. So, whenever that happens, I am calling a sendBroadcast() with the action set to UPDATE_WIDGET. However, the onReceive() in the widget code is not getting called. Below is my code.
public class TaskWidget extends AppWidgetProvider {
...
#Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "widget update", 2000).show();
RemoteViews views = new RemoteViews(context.getPackageName(),
R.layout.searchwidget);
if (intent.getAction().equals(UPDATE_WIDGET)) {
views.setImageViewResource(R.id.newImage, R.drawable.Pic1);
}
super.onReceive(context, intent);
}
}
In the manifest,
<receiver
android:name="com.rahul.testwidget.TaskWidget"
android:label="Task Widget" >
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
<action android:name="com.rahul.UPDATE_WIDGET" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="#xml/widget" />
</receiver>
you have to update your widget layout
use this code just befor super.onReceive(context, intent);
ComponentName widget = new ComponentName(context, SimpleWidget.class);
AppWidgetManager.getInstance(context).updateAppWidget(widget, views);
I think your action name must be com.rahul.UPDATE_WIDGET instead of UPDATE_WIDGET.
If you are sending the broadcast from a listener on your widget you need to create a PendingIntent for a Broadcast.
PendingIntent sentPI = PendingIntent.getBroadcast(activity, 0, intent,PendingIntent.FLAG_CANCEL_CURRENT);
Also, you don't seem to be able to attach 2 pending intents to a button in the widget.