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.
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.
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 !
In my application, I have a Fragment which is attached to the main activity. This Fragment displays data with the help of an adapter. In the adapter, I have inflated a layout which has a clickable text "Watch From Home". The adapter displays data from the server. I want to show the same data on the home screen and when I click on the "Watch From Home" text, a home screen widget should be created without any user interaction.
I made a receiver MyWidgetProvider.What should the method onClickText() for "Watch From Home" have so that it takes me to the widget? I must admit, I am new to android. Thanks
Android Manifest file
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.pack.android.receiver"
android:versionCode="1"
android:versionName="1.0" >
<application
android:icon="#drawable/icon"
android:label="#string/app_name" >
<receiver android:name="MyWidgetProvider" >
<intent-filter >
<action
android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="#xml/widget_info" />
</receiver>
</application>
<uses-sdk android:minSdkVersion="8" />
</manifest>
MyWidgetProvider.Java file
public class MyWidgetProvider extends AppWidgetProvider {
private TextView team1Name;
private TextView team2Name;
private TextView team1Score;
private TextView team2Score;
public static boolean widgetView=false;
private static final String LOG = "com.playup.android.receiver";
public MyWidgetProvider(TextView team1Name, TextView team2Name, TextView team1Score, TextView team2Score){
this.team1Name=team1Name;
this.team2Name=team2Name;
this.team1Score=team1Score;
this.team2Score=team2Score;
initializeViews();
}
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,int[] appWidgetIds) {
Log.w(LOG, "onUpdate method called");
// Get all ids
ComponentName thisWidget = new ComponentName(context,MyWidgetProvider.class);
int[] allWidgetIds = appWidgetManager.getAppWidgetIds(thisWidget);
// Build the intent to call the service
Intent intent = new Intent(context.getApplicationContext(), UpdateWidgetService.class);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, allWidgetIds);
// Update the widgets via the service
context.startService(intent);
}
public void initializeViews(){
// team1Name= (TextView)content_layout.findViewById(R.id.team1Name);
}
}
UpdateWidgetService
public class UpdateWidgetService extends Service {
private static final String LOG = "com.playup.android.receiver";
#Override
public void onStart(Intent intent, int startId) {
Log.i(LOG, "Called");
// Create some random data
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(this
.getApplicationContext());
int[] allWidgetIds = intent
.getIntArrayExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS);
ComponentName thisWidget = new ComponentName(getApplicationContext(),
MyWidgetProvider.class);
int[] allWidgetIds2 = appWidgetManager.getAppWidgetIds(thisWidget);
Log.w(LOG, "From Intent" + String.valueOf(allWidgetIds.length));
Log.w(LOG, "Direct" + String.valueOf(allWidgetIds2.length));
for (int widgetId : allWidgetIds) {
// Create some random data
int number = (new Random().nextInt(100));
RemoteViews remoteViews = new RemoteViews(this
.getApplicationContext().getPackageName(),0x7f030061); //Since R could not be resolve, I used the generated ids
Log.w("Widget", String.valueOf(number));
// Set the text
remoteViews.setTextViewText(0x7f0a022a,"Random: " + String.valueOf(number));
// Register an onClickListener
Intent clickIntent = new Intent(this.getApplicationContext(),MyWidgetProvider.class);
clickIntent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
clickIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS,
allWidgetIds);
PendingIntent pendingIntent = PendingIntent.getBroadcast(getApplicationContext(), 0, clickIntent,PendingIntent.FLAG_UPDATE_CURRENT);
remoteViews.setOnClickPendingIntent(0x7f0a022a, pendingIntent);
appWidgetManager.updateAppWidget(widgetId, remoteViews);
}
stopSelf();
super.onStart(intent, startId);
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
Simply saying, You can't create a home widget without any user interaction.
Update:
Your receiver tag should start like this:
<receiver
android:name=".MyWidgetProvider"
android:label="My widget label" >
<!-- The rest as is -->
</receiver>
Home Screen Widget can only add to Home Screen directly by user.Only user can add widget as guest to Home Screen or other applications.
Edit:
To see your widget in widgets list:
It is necessary that register your AppWidgetProvider in manifest.
Your App has to have Launcher/Main Activity,and App must be directly run by user,before it be visible in widgets list.This is necessary ,because no broadcastreceiver(and so no AppWidgetProvider),no service,... of your App could not register before your App run directly by user.If you look at your manifest,you will see that your App has no Launcher/Main Activity(it has only a receiver),so it can not run by user and your AppWidgetProvider(that is a broadcastreceiver) will not register and thereupon you can not see your widget in widget list.
This had me scratching my head for a while.
I had the meta-data tag as child of the intent-filter tag, which is wrong. The meta-data is to be child of the receiver tag.
Incorrect version
<receiver
android:name=".AppWidgetReceiver"
android:label="AppWidgetReceiver" >
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
<meta-data
android:name="android.appwidget.provider"
android:resource="#xml/appwidget_info" />
</intent-filter>
</receiver>
Following is the correct version
<receiver android:name=".AppWidgetReceiver"
android:label="AppWidgetReceiver" >
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="#xml/appwidget_info" />
</receiver>
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?
I have a problem opening an activity from an appwidget. I have tried different Intent flags, PendingIntent and launch modes without any luck. I have read diffent examples here and many other places without finding the solution.
Right now when I click my button on my appwidget it opens a new activity instead of showing the instance which already exists in the app. I have posted my code below and hope you can help me.
Is there a way to find the existing activity and show it instead of creating a new one when clicking my bottom on the appwidget?
Manifest:
<application android:icon="#drawable/icon" android:label="#string/app_name" android:debuggable="true" android:name="widget.helper.ResourceHelper">
<activity android:name=".ScoreBoard"
android:label="#string/app_name"
>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!-- Broadcast Receiver that will process AppWidget updates -->
<receiver android:name="Widget" 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/widget_provider" />
</receiver>
</application>
The AppWidget:
public class Widget extends AppWidgetProvider {
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
RemoteViews remoteViews;
ComponentName thisWidget;
remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget);
thisWidget = new ComponentName(context, Widget.class);
appWidgetManager.updateAppWidget(thisWidget, remoteViews);
}
#Override
public void onReceive(Context context, Intent intent)
{
super.onReceive(context, intent);
if(intent.getAction().equals("OPEN_APP")) {
Intent i = new Intent(Intent.ACTION_MAIN);
i.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
i.setComponent(new ComponentName("widget","widget.ScoreBoard"));
ResourceHelper.getScoreBoard().startActivity(i);
}
}
}
set the activity launchMode to singleInstance in manifest.
Let us know if it is working.
Saneesh
Use either FLAG_ACTIVITY_REORDER_TO_FRONT or the combination of FLAG_ACTIVITY_CLEAR_TOP and FLAG_ACTIVITY_SINGLE_TOP. FLAG_ACTIVITY_CLEAR_TOP without FLAG_ACTIVITY_SINGLE_TOP would not work, AFAIK.