onUpdate() intilized variable are null in onReceive of widget class - android

I initialize one variable in an onUpdate() method and after that I call onReceive() function which runs fine but cannot access varible set in onUpdate() method. Why is that? Those varible is string variableand are declared public. Am I missing something?
public class WidgetTest extends AppWidgetProvider {
public static String ACTION_WIDGET_RECEIVER = "ActionReceiverWidget";
public String state;
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds)
{
Log.e("UPDATE", "Start");
RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.main);
state="State_update"
System.out.println(state);// My variable is initilised
Intent active = new Intent(context, WidgetTest.class);
active.setAction(ACTION_WIDGET_RECEIVER);
PendingIntent actionPendingIntent = PendingIntent.getBroadcast(context, 0, active, 0);
remoteViews.setOnClickPendingIntent(R.id.buttonclick, actionPendingIntent);
super.onUpdate(context, appWidgetManager, appWidgetIds);
appWidgetManager.updateAppWidget(appWidgetIds, remoteViews);
Log.e("UPDATE", "End");
}
#Override
public void onReceive(Context context, Intent intent)
{
super.onReceive(context, intent);
Log.e("RECEIVE", "Start 2");
if (intent.getAction().equals(ACTION_WIDGET_RECEIVER))
{
Log.e("Test", "My State is "state);//it gives me null point exception;
}
Log.e("RECEIVE", "End");
}
state varible in onReceive gives null point exception

for a AppWidgetReceiver , first onReceive() will be called and then based on the Action received, it will call onUpdate(...) method. so here you are initializing state in onUpdate() which will be called after onReceive(), thus state is null in onReceive().

Related

In Appwidget RemoteViews' setOnClickPendingIntent is not getting called after user force stops application

Here i have made one widget and added its click listener where i'm starting one service.It works perfectly.But once user force stops application from appinfo my widget's click is not responding.I m not getting why this is happening.Help on this will be appreciated.Thank you
My app widget class code:
MyWidget.java:
public class MyWidget extends AppWidgetProvider {
static Context cont;
static SharedPreferences preferences;
static void updateAppWidget(Context context, AppWidgetManager appWidgetManager,
int appWidgetId) {
cont = context;
Intent intent2 = new Intent();
intent2.setAction("....");
PendingIntent pendingIntent = PendingIntent.
getBroadcast(context, 0,
intent2, PendingIntent.FLAG_UPDATE_CURRENT);
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.my_widget);
views.setOnClickPendingIntent(R.id.appwidget_text, pendingIntent);
appWidgetManager.updateAppWidget(appWidgetId, views);
}
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
// There may be multiple widgets active, so update all of them
for (int appWidgetId : appWidgetIds) {
updateAppWidget(context, appWidgetManager, appWidgetId);
}
}
#Override
public void onReceive(Context context, Intent intent) {
super.onReceive(context, intent);
context.startService(new Intent(context, MyService.class));
}
#Override
public void onEnabled(Context context) {
.................. }
#Override
public void onDisabled(Context context) {
.................}
Always use an explicit Intent whenever possible. Your code would not work on Android 8.0 and higher, where implicit broadcasts are banned. And an explicit Intent can move your app out of the stopped state.

How to use Eventbus in a widget?

I'm trying to figure out how I can use the Greenbot Eventbus library in my AppWidgetProvider. I've tried the following, which doesn't work:
public class SimpleWidgetProvider extends AppWidgetProvider {
RemoteViews remoteViews;
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
final int count = appWidgetIds.length;
for (int i = 0; i < count; i++) {
int widgetId = appWidgetIds[i];
remoteViews = new RemoteViews(context.getPackageName(), R.layout.simple_widget);
//set image
remoteViews.setImageViewResource(R.id.piggy_bank, R.drawable.piggy_bank);
Intent intent = new Intent(context, SimpleWidgetProvider.class);
intent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, appWidgetIds);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context,
0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
//set refresh button
remoteViews.setOnClickPendingIntent(R.id.refresh_btn, pendingIntent);
appWidgetManager.updateAppWidget(widgetId, remoteViews);
}
}
#Override
public void onEnabled(Context context) {
super.onEnabled(context);
EventBus.getDefault().register(this);
}
//set total price
#Subscribe
public void onPriceEvent(TotalPriceEvent event) {
double price = event.totalPrice;
remoteViews.setTextViewText(R.id.total_amount, String.valueOf(price));
}
#Override
public void onDisabled(Context context) {
EventBus.getDefault().unregister(this);
super.onDisabled(context);
}
}
Please, let me know if I need to attach more code.
An AppWidgetProvider is just a BroadcastReceiver with a specialized onReceive() method that delegates broadcasts to other methods based on the action. Instances of a manifest-registered BroadcastReceiver aren't meant to live very long. They run just long enough to handle a broadcast and then die, so subscribing one to an event bus isn't going to work as expected, and is kinda pointless, given the overlapping patterns. If you want to notify your SimpleWidgetProvider of something, just send a broadcast to it.
For an example, we define our own action for the SimpleWidgetProvider class, and check for it in the onReceive() method. If it's ours, we'll handle it as needed, and otherwise call the super method to allow AppWidgetProvider to properly delegate it.
public class SimpleWidgetProvider extends AppWidgetProvider {
public static final String MY_SPECIAL_ACTION = "com.mycompany.myapp.SPECIAL_ACTION";
#Override
public void onReceive(Context context, Intent intent) {
if(MY_SPECIAL_ACTION.equals(intent.getAction())) {
// Do your thing
}
else {
// Not our action, so let AppWidgetProvider handle it
super.onReceive(context, intent);
}
}
...
}
We can send a broadcast to it with the usual mechanism.
Intent widgetNotify = new Intent(context, SimpleWidgetProvider.class);
widgetNotify.setAction(SimpleWidgetProvider.MY_SPECIAL_ACTION);
widgetNotify.putExtra(...);
...
context.sendBroadcast(widgetNotify);
I would also mention that the super calls in onEnabled() and onDisabled() are unnecessary, as those methods are empty in AppWidgetProvider.

Automatically update widget in the home screen when i make modification in my application

How can we updating the View of a Home Screen Widget on the onReceive method of AppWidgetProvider?.I am trying to update the listview of my Home screen widget but it seems that I cant access the listview of my AppWidgetProvider on onReceive method.My problem is when i changes in my application and come back to the home screen that the widget has no modification.Here is a sample code of my onReceive
public class WidgetTaskSchedular extends AppWidgetProvider {
private final String TAG = "CalendarViewSample:"
+ this.getClass().getName();
static int ID;
int[] sameid=new int[1];
#Override
public void onReceive(Context context, Intent intent) {
super.onReceive(context, intent);
if(intent.getAction().equals("update_widget"))
{
Log.i(TAG,"AppWidgetIds:"+ID);
for(int i=0;i<1;i++)
{
sameid[i]=ID;
Log.i(TAG,"SameId:"+sameid[i]);
onUpdate(context, AppWidgetManager.getInstance(context),sameid);
}
}
}
public static String EXTRA_WORD=
"com.capsone.testing.calendar.WORD";
#SuppressWarnings("deprecation")
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds) {
super.onUpdate(context, appWidgetManager, appWidgetIds);
for (int i=0; i<appWidgetIds.length; i++) {
ID=appWidgetIds[i];
Log.i(TAG,"LengthofWidget:"+appWidgetIds.length);
Log.i(TAG,"TestAppWidget:"+appWidgetIds[i]);
Intent intentWidgetService=new Intent(context, WidgetService.class);
intentWidgetService.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetIds[i]);
intentWidgetService.setData(Uri.parse(intentWidgetService.toUri(Intent.URI_INTENT_SCHEME)));
RemoteViews remoteView=new RemoteViews(context.getPackageName(),
R.layout.widgetlayout);
remoteView.setRemoteAdapter(appWidgetIds[i], R.id.listWidget,
intentWidgetService);
Intent clickIntent=new Intent(context, ActionBarActivity.class);
PendingIntent clickPendingIntent=PendingIntent
.getActivity(context, 0,
clickIntent,
PendingIntent.FLAG_UPDATE_CURRENT);
remoteView.setPendingIntentTemplate(R.id.listWidget, clickPendingIntent);
ComponentName component=new ComponentName(context,WidgetTaskSchedular.class);
appWidgetManager.updateAppWidget(component, remoteView);
}
}
}
MainActivity class:
In this main class i change some modification and broadcast this to widget class using on pause method:
#Override
public void onPause() {
super.onPause();
Intent updateWidget = new Intent(getActivity(), WidgetTaskSchedular.class);
updateWidget.setAction("update_widget");
PendingIntent pending = PendingIntent.getBroadcast(getActivity(), 0, updateWidget, PendingIntent.FLAG_CANCEL_CURRENT);
try {
pending.send();
} catch (CanceledException e) {
e.printStackTrace();
}
}

TextView not getting updated in android app widgets

I am using asynctask to do my feature function and getting the values there. But my text view is not getting updated, though my log statements giving me the result.
I am not using custom intent here, just the basic one.
Here are my code snippets:
public class ListViewWidget extends AppWidgetProvider{
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds) {
super.onUpdate(context, appWidgetManager, appWidgetIds);
updateViews = new RemoteViews(context.getPackageName(), R.layout.list_layout);
thisWidget = new ComponentName(context, ListViewWidget.class);
FetchTask fetchTask=new FetchTask();
AppWidgetManager.getInstance(context.getApplicationContext());
fetchTask.execute();
}
//FetchTask
public static class FetchTask extends AsyncTask<URL,Integer,String> implements ServerRequestEnvironment{
protected String doInBackground(URL... arg0) {
//logic part and stuff not entered
//This is the end part that returns me the result, which is not getting printed to text view.
String name="";
int i = new Random().nextInt(27);
storeObject=store.getStores().getItems().get(i).getStore();
name= storeObject.getName();
resultStuff(name);
Log.i("StoreTag","storeval:"+name); //returns name of the 0th item
return name;
}//end of doInBackground() method
protected void onPostExecute(String name) {
// TODO Auto-generated method stub
Intent intent=new Intent("android.appwidget.action.APPWIDGET_UPDATE");
PendingIntent pendingIntent=PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
updateViews.setTextViewText(R.id.text_view,resultStuff(name));
updateViews.setOnClickPendingIntent(R.id.next, pendingIntent);
AppWidgetManager manager = AppWidgetManager.getInstance(context.getApplicationContext());
manager.updateAppWidget(thisWidget, updateViews);
}//end of PostExecute
}//End of async task class
}//end of ListViewWidget class
What I am missing here? Please please guide..
UPDATE: Is this fine? Async task to be called both in onReceive and onUpdate??
#Override
public void onReceive(Context context,Intent intent){
if(intent.getAction().equals("android.appwidget.action.APPWIDGET_UPDATE")){
fetchTask.execute();
}
}
Update 2:
public static String name="New text"
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds) {
super.onUpdate(context, appWidgetManager, appWidgetIds);
updateViews = new RemoteViews(context.getPackageName(), R.layout.list_layout);
//-----------NEW LINE ADDED-------------
updateViews.setTextViewText(R.id.text_view,name);
thisWidget = new ComponentName(context, ListViewWidget.class);
//Now in onPostExecute()
//AppWidgetManager manager = AppWidgetManager.getInstance(context.getApplicationContext());
//manager.updateAppWidget(thisWidget, updateViews);
fetchTask.execute();
}
protected void onPostExecute(String name) {
// TODO Auto-generated method stub
Intent intent=new Intent("android.appwidget.action.APPWIDGET_UPDATE");
PendingIntent pendingIntent=PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
updateViews.setTextViewText(R.id.text_view,name);
updateViews.setOnClickPendingIntent(R.id.next, pendingIntent);
AppWidgetManager manager = AppWidgetManager.getInstance(context.getApplicationContext());
manager.updateAppWidget(thisWidget, updateViews);
}
#Dororo Didn't get you. Please explain. I have created public var in my class:
public static Context context;
public static RemoteViews updateViews;
public static ComponentName thisWidget;
FetchTask fetchTask=new FetchTask();
Have you tried using this:
TextView textView = (TextView) findViewById(R.id.textView);
textView.setText(toThis);
Are you sure you're not overwriting the updated value when you create new ComponentName(context, ListViewWidget.class);? onUpdate will be called when you call manager.updateAppWidget(thisWidget, updateViews); You shouldn't need to use static, you just need an initialisation boolean which is set to true after you've created the objects for the first time.
Solved my exception and error. Was setting context to be null. I assigned context with the application context.

How do I trigger something from a widget button?

No matter what I do I cannot trigger anything by clicking on a button on a widget. Here is some code I wrote, can anyone tell me why onReceive isn't called when the widget button is clicked?
Furthermore, I want to run a function on button click... based on the code below do I have the right idea?
public class WidgetProvider extends AppWidgetProvider {
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
Intent intent = new Intent(context, WidgetProvider.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget);
views.setOnClickPendingIntent(R.id.toggleButton, pendingIntent);
appWidgetManager.updateAppWidget(appWidgetIds[0], views);
}
#Override
public void onReceive(Context context, Intent intent) {
// why don't i get here with the button click?
Log.e("!", intent.getAction());
}
}
Try to call the super method of onReceive first.
#Override
public void onReceive(Context context, Intent intent) {
super.onReceive(context, intent);
// why don't i get here with the button click?
Log.e("!", intent.getAction());
}
Worked just fine for me!

Categories

Resources