Android AppWidgetProvider onReceive not called on button click - java

I have a widget running under android and I would like for it to update itself when the user clicks a button on the widget.
For some reason, the onReceive method is never called when a button is clicked after i install the widget.
I have a onUpdate method like this in my AppWidgetProvider class:
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds) {
super.onUpdate(context, appWidgetManager, appWidgetIds);
for (int i = 0; i < appWidgetIds.length; ++i) {
final RemoteViews rv =
new RemoteViews(context.getPackageName(), R.layout.appwidget_provider);
final Intent nextIntent =
new Intent(context, TestAppWidgetProvider.class);
nextIntent.setAction(TestAppWidgetProvider.NEXT_ACTION);
nextIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetIds[i]);
final PendingIntent refreshPendingIntent =
PendingIntent.getBroadcast(context, 0,
nextIntent, PendingIntent.FLAG_UPDATE_CURRENT);
rv.setOnClickPendingIntent(R.id.next, refreshPendingIntent);
appWidgetManager.updateAppWidget(appWidgetIds[i], rv);
}
}
And then in my on receive i have a method that looks like:
#Override
public void onReceive(Context ctx, Intent intent) {
super.onReceive(ctx, intent);
final String action = intent.getAction();
if (action.equals(PREV_ACTION)) {
Toast.makeText(ctx, "Previous clicked..", Toast.LENGTH_SHORT).show();
} else if (action.equals(NEXT_ACTION)) {
Toast.makeText(ctx, "Next was clicked..", Toast.LENGTH_SHORT)
.show();
}
else {
Toast.makeText(ctx, "Other action..", Toast.LENGTH_SHORT).show();
}
}
I have this in my manifest file too:
<receiver android:name="com.test.android.widget.TestAppWidgetProvider" >
<intent-filter >
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<intent-filter >
<action android:name="com.test.android.widget.PREV" />
</intent-filter>
<intent-filter >
<action android:name="com.test.android.widget.NEXT" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="#xml/appwidget_info" />
</receiver>
After I install the widget and click on the next button, the onReceive method is never called for some reason...

Fixed it, turned out to be trivial.
It was because onReceive wasn't even being called on widget creation, so the event listener wasn't setup.
Added some of the code that was in onReceive (setting the setOnClickPendingIntent etc) to a function which is called when the widget configure activity is ready to update the widget.

Related

Make your android widget default on android home screen

I have system level privileges and I want to be have my widget be a default item on the devices home screen.
What I have tried using the following in my manifest
<uses-permission android:name="android.permission.BIND_APPWIDGET"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
and this in the application tag in the manifest
<receiver
android:name=".StartOnBootReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
This is in the class called StartOnBootReceiver.java
public class StartOnBootReciever extends BroadcastReceiver {
private static final String TAG = "rwid_StartOnBootReceiver";
public StartOnBootReciever(){
}
#Override
public void onReceive(Context context, Intent intent){
Log.d(TAG, "Your app is alive");
final AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
final AppWidgetHost appWidgetHost = new AppWidgetHost(context,R.id.Acceleration_Widget);
int appWidgetId = appWidgetHost.allocateAppWidgetId();
ComponentName comp = new ComponentName(context.getPackageName(),WidgetActivity.class.getName());
Log.d(TAG,""+appWidgetManager.bindAppWidgetIdIfAllowed(appWidgetId,comp));
Intent intent1 = new Intent(context, WidgetActivity.class);
intent1.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent1);
}
}
I know that this code runs when the device boots up due to my logging but I cant seem to get the widget on my home screen.

Android broadcast not received from widget

I Have a widget that upon button press I send broadcast to service. But I am not receving any broadcast in my onReceive().
My intention is basically on widget button click, it tellls service to perform some action.
But I am unable to receive any broadcast from widget in service.
Here is my widget code -
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds) {
RemoteViews remoteViews;
ComponentName componentName;
remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget_layout);
componentName = new ComponentName(context, MyWidgetProvider.class);
remoteViews.setOnClickPendingIntent(R.id.play,getPendingSelfIntent(context, "PLAY",componentName));
appWidgetManager.updateAppWidget(componentName, remoteViews);
}
#Override
public void onReceive(Context context, Intent intent)
{
super.onReceive(context, intent);
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
RemoteViews remoteViews;
ComponentName componentName;
remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget_layout);
componentName = new ComponentName(context, MyService.class);
if (intent.getAction().equals("PLAY")) {
Log.d("hi","PLAY0");
remoteViews.setOnClickPendingIntent(R.id.engine_lock_unlock,getPendingSelfIntent(context,"PLAY",componentName));
serviceIntent = new Intent(context,MyService.class);
serviceIntent.setAction("PLEASE_PLAY");
Log.d("hi","PLAY1");
context.sendBroadcast(serviceIntent);
}
appWidgetManager.updateAppWidget(componentName, remoteViews);
}
protected PendingIntent getPendingSelfIntent(Context context, String action, ComponentName componentName) {
Intent intent = new Intent(context, MyWidgetProvider.class);
intent.setAction(action);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, componentName);
return PendingIntent.getBroadcast(context, 0, intent, 0);
}
In MyService,
public class ServiceWidgetReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Log.d("hi","PLAY2");
if (intent.getAction().equals("PLEASE_PLAY")) {
}
}
}
My MAnifest looks like this -
<receiver android:name=".widget.MyWidgetProvider" >
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data android:name="android.appwidget.provider"
android:resource="#xml/homescreen_widget_preview" />
</receiver>
<receiver android:name=".service.MyService$ServiceWidgetReceiver" />
I only get the logs -
PLAY0
PLAY1
Why I dont get my broadcast???
Seams that your receiver has no intent-filter provided. Try to add this in your mainfest file:
<receiver android:name=".service.MyService$ServiceWidgetReceiver">
<intent-filter>
<action android:name="PLEASE_PLAY" />
</intent-filter>
</receiver>
I assume that you have implement the action in intent-filter like Myon said, but the still no broadcast to the onReceive. you may try this:
protected PendingIntent getPendingSelfIntent(Context context, String action, ComponentName componentName) {
Intent intent = new Intent(context, MyWidgetProvider.class);
intent.setAction(action);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, componentName);
//this line replace the original
return PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
}
Actually, i have facing the similar problem yesterday that my widget work fine on my android 5.1 phone. However, I find it cannot perform click on android 7.0 sony phone. I still trying to find out whether is the sony phone os problem or android 7.0 or after problem because after the upgrade of the 7.0 or after, there is so many different issues appeared as they changed quite a lot in the API. Anyway, I used the PendingIntent.FLAG_UPDATE_CURRENT solved the problem I have on 7.0
I just think will directly register the receiver class to manifest like this be work. The service binded doesnt directly affect the receive, as the only thing affect the receiver is context. So, maybe just the receive class is enough.
<receiver android:name="packageName.ServiceWidgetReceiver">
<intent-filter>
<action android:name="PLEASE_PLAY" />
</intent-filter>
</receiver>
I found out the mistake I was doing. I had to registerreceiver and unregister it in Service itself rather in Manifest.
This worked for me.

Taping an android home-screen widget doesn't work the second time

I am new to Android(started yesterday :))
I am trying to make a simple home-screen widget with a TextView that changes it's value when you tap on it.
Things aren't going so well. It only works after I tap it 3 times and then it works once and never works again. Also the debugger always crashes after I "step over" for the first time.
Manifest:
<application
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name">
<receiver android:name=".GeeDeeBeeDee"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
<action android:name="android.appwidget.action.APPWIDGET_CLICK" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="#xml/gee_dee_bee_dee_info" />
</receiver>
</application>
Widget class:
public class GeeDeeBeeDee extends AppWidgetProvider {
private int DayType = 0;
public static String APPWIDGET_CLICK = "android.appwidget.action.APPWIDGET_CLICK";
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
// There may be multiple widgets active, so update all of them
final int N = appWidgetIds.length;
for (int i = 0; i < N; i++) {
updateAppWidget(context, appWidgetManager, appWidgetIds[i]);
and then:
static void updateAppWidget(Context context, AppWidgetManager appWidgetManager,int appWidgetId)
{
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.gee_dee_bee_dee);
Intent intent = new Intent(APPWIDGET_CLICK);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, appWidgetId, intent, 0);
views.setOnClickPendingIntent(R.id.appwidget_text, pendingIntent );
appWidgetManager.updateAppWidget(appWidgetId, views);
}
#Override
public void onReceive(Context context, Intent intent)
{
int widgetId = 0;
if (APPWIDGET_CLICK.equals(intent.getAction()))
{
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.gee_dee_bee_dee);
if(DayType == 0)
remoteViews.setTextViewText(R.id.appwidget_text, "0");
else if(DayType == 1)
remoteViews.setTextViewText(R.id.appwidget_text, "1");
else if(DayType == 2)
remoteViews.setTextViewText(R.id.appwidget_text, "2");
if(DayType > 2)
DayType = 0;
Bundle extras = intent.getExtras();
if(extras!=null)
{
widgetId = extras.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
}
if(widgetId > 0)
appWidgetManager.updateAppWidget(widgetId, remoteViews);
}
else
super.onReceive(context, intent);
}
Can anyone help, please? Thank you in advance.
I believe the problem is in your onUpdate() method. You may want to check this link: Android: How to update widget text on creation
I hope it will help you.

Android Widget - works first time only

I have a widget, that on click of a text view, launches a new activity which is an editText to allow the user to search. After you search, it opens the app at the desired results. If the user puts the app in the background, and does not press back, when the user goes to click on the widget again, instead of bring up the search editText view, it opens the app to where it left off.
Ideally I want to bring up the search box everytime, even if it overlays the app behind it. Any thoughts? Code is below:
SearchWidgetClass:
public class SearchWidget extends AppWidgetProvider {
private static final String SHOW_POPUP_DIALOG_ACTION = "launch.search.widget";
private static final String LAUNCH_WIDGET = "launch.homescreen.widget";
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
ComponentName thisWidget = new ComponentName(context, SearchWidget.class);
int[] allWidgetInstancesIds = AppWidgetManager.getInstance(context).getAppWidgetIds(thisWidget);
for (int widgetId : allWidgetInstancesIds) {
RemoteViews remoteViews = new RemoteViews(context.getPackageName(),
R.layout.search_widget_layout);
// Create an intent that when received will launch the search bar
Intent searchIntent = new Intent(context, SearchWidget.class);
searchIntent.setAction(SHOW_POPUP_DIALOG_ACTION);
// Create an intent that when received will open the app on the home screen
Intent WidgetIntent = new Intent(context, SearchWidget.class);
WidgetIntent.setAction(LAUNCH_WIDGET);
PendingIntent searchPendingIntent = PendingIntent.getBroadcast(context, widgetId, searchIntent, PendingIntent.FLAG_UPDATE_CURRENT);
PendingIntent openPendingIntent = PendingIntent.getBroadcast(context, widgetId, WidgetIntent, PendingIntent.FLAG_UPDATE_CURRENT);
// Set up the onClickListener of the widget
// Now, when the widget is pressed the pendingIntent will be sent
remoteViews.setOnClickPendingIntent(R.id.widget_search_textview, searchPendingIntent);
remoteViews.setOnClickPendingIntent(R.id.widget_open, openPendingIntent);
appWidgetManager.updateAppWidget(widgetId, remoteViews);
}//End of For Each loop
super.onUpdate(context, appWidgetManager, appWidgetIds);
}//End of onUpdate method
#Override
public void onReceive(final Context context, Intent intent) {
Intent actionIntent;
if (intent.getAction().equals(SHOW_POPUP_DIALOG_ACTION)) {
actionIntent = new Intent(context, SearchWidgetDialogActivity.class);
actionIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(actionIntent);
} else if (intent.getAction().equals(LAUNCH_WIDGET)){
actionIntent = new Intent(context, HomeActivity.class);
actionIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(actionIntent);
}
super.onReceive(context, intent);
}//End of onReceive method
}//End of SearchWidget Class
Search Dialog Activity:
public class SearchWidgetDialogActivity extends Activity {
private EditText searchWidgetEditText;
private String actionArg;
#Override
protected void onCreate(Bundle savedInstanceState) {
requestWindowFeature(Window.FEATURE_NO_TITLE);
super.onCreate(savedInstanceState);
setContentView(R.layout.search_widget_dialog_layout);
LayoutParams params = getWindow().getAttributes();
params.width = LayoutParams.MATCH_PARENT;
getWindow().setAttributes((android.view.WindowManager.LayoutParams) params);
getWindow().setBackgroundDrawableResource(android.R.color.transparent);
searchWidgetEditText = (EditText) findViewById(R.id.search_widget_edit_text);
searchWidgetEditText.setOnEditorActionListener(new OnEditorActionListener() {
#Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (((event != null && (event.getKeyCode() == KeyEvent.KEYCODE_ENTER)) || (actionId == EditorInfo.IME_ACTION_DONE)) &&
(!StringUtils.isEmpty(searchWidgetEditText.getText().toString()))) {
handleWidgetAction(SearchWidgetDialogActivity.this);
}
return false;
}
});
}//End of onCreate method
public void handleWidgetAction(Context aContext) {
actionArg = searchWidgetEditText.getText().toString();
QLog.d("Launching search activity for " + actionArg + " from the widget");
Intent serachProductsIntent = new Intent(aContext, BrowseProductsSearchActivity.class);
serachProductsIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
serachProductsIntent.setAction(Intent.ACTION_SEARCH);
serachProductsIntent.putExtra(SearchManager.QUERY, actionArg);
serachProductsIntent.putExtra(SearchManager.USER_QUERY, actionArg);
aContext.startActivity(serachProductsIntent);
}//End of handleWidgetSearch method
}// End of SearchWidgetDialogActivity class
Manifest Activities:
<activity
android:name="android.activities.SearchWidgetDialogActivity"
android:label="#string/app_label"
android:theme="#android:style/Theme.Dialog"
android:noHistory="true"
android:windowSoftInputMode="adjustResize">
</activity>
<receiver
android:name="android.widget.SearchWidget" >
<intent-filter>
<action android:name="launch.search.widget"/>
<action android:name="launch.homescreen.widget"/>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="#xml/search_widget_provider" />
</receiver>

Get from Android BroadcastReceiver to a UI

I have a receiver that works well, but I can't seem to show a proper UI, although the toast appears correctly. As far as I can tell, this is caused by Android requiring the class to extend Activity, however, the class already extends BroadcastReceiver, so I can't do this.
So, I tried to do an Intent, but this failed too. There are no errors, but the screen doesn't show. Source code is below.
Broadcast (Method in AndyRoidAlarm)
public void setAlarm(){
Intent intent = new Intent(AndyRoidAlarm.this, Reciever.class);
PendingIntent sender = PendingIntent.getBroadcast(AndyRoidAlarm.this,
0, intent, 0);
// We want the alarm to go off 30 seconds from now.
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.add(Calendar.SECOND, 10);
// Schedule the alarm!
AlarmManager am = (AlarmManager)getSystemService(ALARM_SERVICE);
am.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), sender);
// Tell the user about what we did.
if (mToast != null) {
mToast.cancel();
}
mToast = Toast.makeText(AndyRoidAlarm.this, "Alarm Scheduled for 30secs", Toast.LENGTH_LONG);
mToast.show();
}
Reciever
public class Reciever extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent)
{
Toast.makeText(context, "Alarm Received", Toast.LENGTH_LONG).show();
Intent i = new Intent();
i.setClass(context, AlarmRing.class);
}
}
Reciever V2
#Override
public void onReceive(Context context, Intent intent)
{
Toast.makeText(context, "Alarm Received", Toast.LENGTH_LONG).show();
Intent foo = new Intent(context, AlarmRing.class);
//foo.putExtra("id", "id");//example, if you wish to pass custom variables
context.startActivity(foo);
}
AlarmRing
public class AlarmRing extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.alarm);
MediaPlayer mp = MediaPlayer.create(getBaseContext(), R.raw.sweetchild);
mp.start();
}
Manifest
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.comaad.andyroidalarm"
android:versionCode="1"
android:versionName="1.0">
<application android:icon="#drawable/icon" android:label="#string/app_name">
<activity android:name=".AndyRoidAlarm"
android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name="com.comaad.andyroidalarm.Reciever" android:enabled="true">
<intent-filter>
<action android:name="com.comaad.andyroidalarm.Reciever"></action>
</intent-filter>
</receiver>
<activity android:name=".AlarmRing"></activity>
</application>
</manifest>
}
In a BroadcastReceiver onReceive() method, if you need a Context (e.g., to create an Intent), use the Context that is passed to you as a parameter of onReceive(). You even have this code in your onReceive() -- you're just not doing anything with the resulting Intent (e.g., calling startActivity()).
Intent foo = new Intent(this, AlarmRing.class);
foo.putExtra("id", id);//example, if you wish to pass custom variables
this.startActivity(foo);
Edit
Check out this example to use BroadcastReciever within an Activity. http://almondmendoza.com/2009/01/04/getting-battery-information-on-android/

Categories

Resources