Null Pointer When Passing Data from App to Widget via Intent

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP



Null Pointer When Passing Data from App to Widget via Intent



I have a list of Recipes that I retrieve using Retrofit. I then get the recipe name, and I want to update the Widget associated with my app to display the selected recipeName. The recipeName is reflected below in my adapter for my RecyclerView.


recipeName


recipeName


RecyclerView



When a user clicks on an item in the RecylcerView, I want to update the associated widget I have for the app.


RecylcerView



Below is the adapter for the RecyclerView where I have the .setOnClickListener() method and pass all of my data, via an Intent.


RecyclerView


.setOnClickListener()


Intent


@Override
public void onBindViewHolder(@NonNull MyAdapter.ViewHolder holder, final int position)
String id = mRecipeDataSet.get(position).getId();
//The recipe name I want to pass to my widget
final String recipeName = mRecipeDataSet.get(position).getName();
holder.mTextView.setText(id);
holder.itemView.setOnClickListener(new View.OnClickListener()
@Override
public void onClick(View view)
Intent intent = new Intent(con, BakingWidgetProvider.class);
intent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
int ids = AppWidgetManager.getInstance(con).getAppWidgetIds(new ComponentName(con, BakingWidgetProvider.class));
if(ids != null && ids.length > 0)
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, ids);
intent.putExtra(RECIPE_NAME, recipeName);
con.sendBroadcast(intent);

Intent i = new Intent(con, IndividualRecipeActivity.class);
Bundle bundle = new Bundle();
bundle.putParcelableArrayList("Recipe_List", (ArrayList<? extends Parcelable>) mRecipeDataSet);
i.putExtras(bundle);
i.putExtra("Position",position);
con.startActivity(i);

);




Below is my BakingWidgetProvider class that manages my widget. I want to update the widget interface each time a user clicks on a new item from the RecyclerView:


BakingWidgetProvider


RecyclerView



public class BakingWidgetProvider extends AppWidgetProvider


private static final String RECIPE_NAME = "RECIPE_NAME";
public static final String ACTION_TEXT_CHANGED = "kitchenpal.troychuinard.com.kitchenpal.TEXT_CHANGED";
private static String mRecipeName;

static void updateAppWidget(Context context, AppWidgetManager appWidgetManager,
int appWidgetId)

CharSequence widgetText = context.getString(R.string.appwidget_text);
// Construct the RemoteViews object
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.baking_widget_provider);
Log.v("WIDGET", mRecipeName);
views.setTextViewText(R.id.selected_recipe, mRecipeName);
Intent intent = new Intent(context, MainActivity.class);
PendingIntent pIntent = PendingIntent.getActivity(context, 0,
intent, 0);
//TODO: Why isn't my widget launching my MainActivity onClick?
//TODO: I am trying to add a ListView of ingredients to my Widget
but have no idea where to begin
views.setOnClickPendingIntent(R.id.chef, pIntent);



@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 onEnabled(Context context)
// Enter relevant functionality for when the first widget is created


@Override
public void onDisabled(Context context)
// Enter relevant functionality for when the last widget is disabled


//TODO: I cannot pass data from MyAdapter to the BakingWidgerProvider. I am simply trying to display the most recently
//TODO: selected recipe on the widget. I have scoured StackOverflow to no avail
@Override
public void onReceive(Context context, Intent intent)
if (intent.getAction().equals(ACTION_TEXT_CHANGED))
// handle intent here
mRecipeName = intent.getStringExtra(RECIPE_NAME);

super.onReceive(context, intent);

// if(intent.getAction().equals("UPDATE_ACTION"))
// mRecipeName = intent.getStringExtra(RECIPE_NAME);
// int appWidgetIds =


intent.getExtras().getIntArray(AppWidgetManager.EXTRA_APPWIDGET_IDS);
// if (appWidgetIds != null && appWidgetIds.length > 0)

// this.onUpdate(context,
AppWidgetManager.getInstance(context), appWidgetIds);
//
// else
// super.onReceive(context, intent);
//
//

}



UPDATE: I have included the code to include the override for .onReceive(), and I set the field in this override method. I am trying to then use it to update my interface in .onUpdateAppWidget(), however the widget is not updating the TextView based on the mRecipeName field, as mRecipeName field is coming in null.


.onReceive()


.onUpdateAppWidget()





You should use a broadcast as showed in the second answer of this question: stackoverflow.com/questions/11718426/…
– jonathanrz
Aug 3 at 19:18





Thanks I believe I have it set up successfully, I just don't understand how to save the information and where to retrieve then pass to the TextView in my widget (through my WidgetProvider class).
– tccpg288
Aug 5 at 21:09




2 Answers
2



You should override onReceive within you AppWidgetClass. This receives the intent that was broadcasted so you may retrieve the data from it


@Override
public void onReceive(Context context, Intent intent)
super.onReceive(context, intent);
//Insert code here



And proceed to add your code to receive/assign Data from the Intent.





Just updated, I am not able to populate the UI with the String passed from the adapter class. Seems odd but it appears it might be null in the WidgetProvider class
– tccpg288
Aug 6 at 1:39



As soon as you trigger your widget by sending broadcast to your widget (which is BroadcastReceiver on steroids), you setting a field mRecipeName from bundle, but before setting field mRecipeName, you update RemoteView (so mRecipeName is null in this moment). Make something like that:


mRecipeName


mRecipeName


@Override
public void onReceive(Context context, Intent intent)
mRecipeName = intent.getStringExtra(RECIPE_NAME);
super.onReceive(context, intent);



Actually, to make it more cleaner for production. Make something like:


Intent intent = new Intent(con, BakingWidgetProvider.class);
intent.setAction("UPDATE_ACTION");
int ids = AppWidgetManager.getInstance(con).getAppWidgetIds(new ComponentName(con, BakingWidgetProvider.class));
if(ids != null && ids.length > 0)
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, ids);
intent.putExtra(RECIPE_NAME, recipeName);
con.sendBroadcast(intent);



And your onReceive will be like:


@Override
public void onReceive(Context context, Intent intent)
if(intent.getAction().equals("UPDATE_ACTION")
mRecipeName = intent.getStringExtra(RECIPE_NAME);
int appWidgetIds = extras.getIntArray(AppWidgetManager.EXTRA_APPWIDGET_IDS);
if (appWidgetIds != null && appWidgetIds.length > 0)
this.onUpdate(context, AppWidgetManager.getInstance(context), appWidgetIds);

else
super.onReceive(context, intent);






Got it, so it is simy the order of my methods? The syntax itself is correct?
– tccpg288
Aug 6 at 22:19





@tccpg288 Just change order of methods, seems like that's the problem. Cuz super will trigger your onUpdate() and only after that you're trying to get receipe name from intent, but this receipe name is using in on update(). If it doesn't help you, just make a sample app, so community will try to figure out that's the problem.
– HeyAlex
Aug 6 at 22:24






I don't understand the point of the id's Array either
– tccpg288
Aug 7 at 0:41





Just tried, it is still coming in null. Full code is available here: github.com/troy21688/KitchenPal
– tccpg288
Aug 7 at 0:46





Dude, the problem that onUpdate() callback is triggered not only by you. What does it mean? Your onUpdate() callback will be triggered when user add new widget, or it's time to update widget that you configure in baking_widget_provider_info.xml, so you will not get nullpointer if you trigger widget by yourself (from adapter), but as soon as user add new widget, there is no extra data (receipe_name), so in onUpdate you will get nullpointer.
– HeyAlex
Aug 7 at 9:12






By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Popular posts from this blog

Firebase Auth - with Email and Password - Check user already registered

Dynamically update html content plain JS

Creating a leaderboard in HTML/JS