I have appWidgetProvider that updates views of each widget located on homescreen and each widget has a button which triggers updating the view but apparently no matter which button I press on whichever widget only and always the one of them is being updated
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
super.onUpdate(context, appWidgetManager, appWidgetIds);
for (int widgetId: appWidgetIds){
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.appwidget);
Intent update = new Intent(context, QuotesAppWidgetProvider.class);
Bundle bundle = new Bundle();
bundle.putIntArray(AppWidgetManager.EXTRA_APPWIDGET_IDS, new int[]{widgetId});
update.putExtras(bundle);
update.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, update, 0);
views.setOnClickPendingIntent(R.id.widget_refresh, pendingIntent);
appWidgetManager.updateAppWidget(widgetId, views);
}
}
Let's say I have widget with id=30 and widget with id=31 and I click the refresh button on widget30 and then widget30 is being updated which is desired but when I click on refresh button on widget31 then widget30 is being updated for I don't know what reason.
It took me a bit but I finally figured it out. All of the widgets had pendingintents with the same request code and since it was broadcast it overwritten all of them with one. This was the line that helped me:
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, widgetId, update, PendingIntent.FLAG_UPDATE_CURRENT);
Use this code and check.
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
super.onUpdate(context, appWidgetManager, appWidgetIds);
for (int widgetId: appWidgetIds){
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.appwidget);
Intent update = new Intent(context, getClass());
update.setAction("actUpdateWidgets");
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, update, 0);
views.setOnClickPendingIntent(R.id.widget_refresh, pendingIntent);
appWidgetManager.updateAppWidget(widgetId, views);
}
}
#Override
public void onReceive(Context context, Intent intent)
{
super.onReceive(context, intent);
if (intent.getAction().equalsIgnoreCase("actUpdateWidgets"))
{
Intent i = new Intent(context, QuotesAppWidgetProvider.class);
i.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
int ids[] = AppWidgetManager.getInstance(context).getAppWidgetIds(new ComponentName(context, QuotesAppWidgetProvider.class));
i.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, ids);
context.sendBroadcast(i);
}
}
Related
I'm trying to have my widget use an onClick action to prompt a refresh. I found some demo code that works, but it opens a URI in browser. I'm having trouble replacing the URI action with something simpler, like displaying a toast. I've marked the line that I'm trying to change, but I don't know how to make Android set a different action other than Action.VIEW.
public class NewAppWidget extends AppWidgetProvider {
static void updateAppWidget(Context context, AppWidgetManager appWidgetManager, int appWidgetId) {
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.new_app_widget);
//I AM TRYING TO CHANGE THIS INTENT
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://google.com/"));
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);
views.setOnClickPendingIntent(R.id.refresh, pendingIntent);
appWidgetManager.updateAppWidget(appWidgetId, views);
}
#Override //Nothing changed here
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
for (int appWidgetId : appWidgetIds) {
updateAppWidget(context, appWidgetManager, appWidgetId);
}
}
}
The specific lines are
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://google.com/"));
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);
I got this to work completely unexpectedly. I followed this post but left my intent declarations where they were. The resulting lines were:
Intent intent = new Intent(context, NewAppWidget.class);
intent.setAction(refresh);
intent.putExtra("appWidgetId", appWidgetId);
views.setOnClickPendingIntent(R.id.refresh, PendingIntent.getBroadcast(context,0,intent, PendingIntent.FLAG_UPDATE_CURRENT));
appWidgetManager.updateAppWidget(appWidgetId, views);
followed by onReceive:
#Override
public void onReceive(Context context, Intent intent) {
if(refresh.equals(intent.getAction())) {
Toast.makeText(context, "Clicked", Toast.LENGTH_LONG).show();
}
}
Edit for clarity: intent.getAction() needs to be a registered action within the receiver's intent filter.
I have no idea why this is happening. I'm making widgets which show the best currency rate for the currencies that the user chooses. I've noticed after a reboot, they sometimes turn into a clock and a calendar widget. Here's my code. I assume it could be something with my Intents or OnReceive() but I'm not sure what.
public class LightRowWidget extends RowWidget {
List<CurrencyObject> currencyObjects = new ArrayList<>();
public LightRowWidget() {
super(R.layout.widget_row_layout, R.color.white, Constants.FULL_OPACITY, R.color.black);
}
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
super.onUpdate(context, appWidgetManager, appWidgetIds);
if (appWidgetIds != null && appWidgetIds.length > 0) {
for (int appWidgetId : appWidgetIds) {
// Create currencyObjects. They're used to assign the correct value
// to the correct texView
CurrencyObject currObj1 = new CurrencyObject(
R.id.currency1, R.id.currency1_buy, R.id.currency1_sell);
currencyObjects.add(currObj1);
CurrencyObject currObj2 = new CurrencyObject(R.id.currency2, R.id.currency2_buy, R.id.currency2_sell);
currencyObjects.add(currObj2);
// Register an onClickListener to Update the current widget on a click
Intent clickIntent = new Intent(context, LightRowWidget.class);
clickIntent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
clickIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, appWidgetIds);
onUpdate(context, appWidgetManager, appWidgetId, currencyObjects, clickIntent);
}
//start an intent that will schedule the alarm for the next update
Intent startIntent = new Intent(context, LightRowWidget.class);
scheduleNextUpdate(context, startIntent, appWidgetIds);
}
and Here is my RowWidget class with the relevant code.
public abstract class RowWidget extends AppWidgetProvider implements WidgetInterface{
public RowWidget(int layout, int background_color, int background_opacity, int text_color){
super();
this.layout = layout;
this.background_color=background_color;
this.background_opacity=background_opacity;
this.text_color=text_color;
}
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int appWidgetId, List<CurrencyObject> currencyObjects, Intent clickIntent) {
theAppWidgetManager = appWidgetManager;
//Get the current name of class
String currentClass = this.getClass().getName();
switch(currentClass){
case("foobar"):
configure_class=Constants.FOUR_ROW_CONFIGURE;
break;
case("foo"):
configure_class=Constants.ROW_APP_WIDGET_LIGHT_CONFIGURE;
break;
case("bar"):
configure_class=Constants.ROW_APP_WIDGET_DARK_CONFIGURE;
break;
case("barfoo"):
configure_class=Constants.TWO_ROW_CONFIGURE;
break;
}
// There may be multiple widgets active, so update all of them
// Get the preferred Currencies
Set<String> preferredCurrencies = AppWidgetConfigure.loadCurrencyPref(context,appWidgetId, configure_class);
// Inflate the layout
RemoteViews view = new RemoteViews(context.getPackageName(), layout);
// if the preferred Currencies have been declared already
if(preferredCurrencies!= null){
// Set the currencies for each object
for(String currency: preferredCurrencies){
if(currencyCount<currencyObjects.size()){
currencyObjects.get(currencyCount).setCurrencyType(currency);
currencyCount+=1;
}
}
}
else{
for(CurrencyObject curObj:currencyObjects){
curObj.setCurrencyType("RUB");
}
}
// Open up the Currency fragment on the click of the widget
Intent configIntent = new Intent(context, MainActivity.class);
configIntent.putExtra("LaunchCurrency", true);
configIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent configPendingIntent = PendingIntent.getActivity(context, 0, configIntent, 0);
view.setOnClickPendingIntent(R.id.row_widget_layout, configPendingIntent);
// Update the widget whenever refresh button clicked
PendingIntent pendingIntent = PendingIntent.getBroadcast(context,
0, clickIntent, PendingIntent.FLAG_UPDATE_CURRENT);
view.setOnClickPendingIntent(R.id.refresh, pendingIntent);
makeRequest(context, theDate, view, currencyObjects, appWidgetId);
currencyCount = 0;
}
//Handle receiving the intent
#Override
public void onReceive(Context context, Intent intent){
if (intent.getAction().equals(ACTION_APPWIDGET_UPDATE)) {
AppWidgetManager manager = AppWidgetManager.getInstance(context);
// Get id's
int[] allWidgetIds = intent
.getIntArrayExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS);
onUpdate(context, manager, allWidgetIds);
}
else{
super.onReceive(context, intent);
}
}
EDIT: Widgets transform to a lot of different widgets that are already on my screen.
I want to create a simple widget with an icon to launch my app.
I have the widget and its layout working properly, but I can't find the way to make it launcher the app when clicking it.
This is the widget class:
public class LauncherWidget extends AppWidgetProvider {
private static final String ACTION_CLICK = "ACTION_CLICK";
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager) {
Intent intent = new Intent(context, SplashActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
// Attach the intent to the widget's button.
final PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);
remoteViews.setOnClickPendingIntent(R.id.widget, pendingIntent);
}
}
I have never created a widget so I have no idea what to do here.
I have checked round here for more info but all I can find are widgets that update its content when clicking, but I tried to use their code but it isn't working.
Thanks in advance.
This is what worked for me...
The onUpdate method code should be:
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
for (int i = 0; i < appWidgetIds.length; i++) {
int appWidgetId = appWidgetIds[i];
try {
Intent intent = new Intent("android.intent.action.MAIN");
intent.addCategory("android.intent.category.LAUNCHER");
intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
intent.setComponent(new ComponentName(context.getPackageName(),
"Activity.class"));
PendingIntent pendingIntent = PendingIntent.getActivity(
context, 0, intent, 0);
RemoteViews views = new RemoteViews(context.getPackageName(),
R.layout.widget_layout);
views.setOnClickPendingIntent(R.id.widget, pendingIntent);
appWidgetManager.updateAppWidget(appWidgetId, views);
} catch (ActivityNotFoundException e) {
Toast.makeText(context.getApplicationContext(),
"There was a problem loading the application: ",
Toast.LENGTH_SHORT).show();
}
}
}
Use this snippet in onUpdate() method of your widget AppWidgetProvider class:
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.widgetlayout);
Intent configIntent = new Intent(context, Activity.class);
PendingIntent configPendingIntent = PendingIntent.getActivity(context, 0, configIntent, 0);
remoteViews.setOnClickPendingIntent(R.id.widget, configPendingIntent);
appWidgetManager.updateAppWidget(appWidgetIds, remoteViews);
}
I have seen several questions regarding how to update widgets but nothing is helping me with my issue.
I created a widget that has a textview that I want to dynamically update upon widget creation.
I have a configuration activity that is called when adding the widget on the screen. I store the value in the sharedpreferences and retreive it onUpdate. The problem is that the widget doesn't get updated. Any idea how it can be done? I do not want to update the textview after a click on the widget, just get the correct text to be displayed on creation.
public class AndroidWidget extends AppWidgetProvider {
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds) {
ComponentName thisWidget = new ComponentName(context,
AndroidWidget.class);
int[] allWidgetInstancesIds = appWidgetManager
.getAppWidgetIds(thisWidget);
for (int widgetId : allWidgetInstancesIds) {
RemoteViews remoteViews = new RemoteViews(context.getPackageName(),
R.layout.widget_layout);
// Create an intent that when received will launch the PopUpActivity
Intent intent = new Intent(context, AndroidWidget.class);
intent.setAction(SHOW_POPUP_DIALOG_ACTION);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, widgetId);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context,
widgetId, intent, 0);
// Set up the onClickListener of the widget
remoteViews.setOnClickPendingIntent(R.id.myText, pendingIntent);
SharedPreferences prefs = context.getSharedPreferences(
String.valueOf(widgetId), Context.MODE_PRIVATE);
remoteViews.setTextViewText(R.id.myText,
prefs.getString("storedtext", null));
appWidgetManager.updateAppWidget(widgetId, remoteViews);
}
super.onUpdate(context, appWidgetManager, appWidgetIds);
}
This actually updates the textview but only after clicking or creating another widget.
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
//set widget id
ComponentName thisWidget = new ComponentName(context, WidgetProvider.class);
int[] allWidgetIds = appWidgetManager.getAppWidgetIds(thisWidget);
for (int i = 0; i < appWidgetIds.length; i++) {
Intent intentService = new Intent(context, WidgetService.class);
intentService.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetIds[i]);
intentService.setData(Uri.parse(intentService.toUri(Intent.URI_INTENT_SCHEME)));
RemoteViews widget = new RemoteViews(context.getPackageName(), R.layout.widget);
Intent clickIntent = new Intent(context, MainActivity.class);
PendingIntent clickPI = PendingIntent.getActivity(context, 0, clickIntent, PendingIntent.FLAG_UPDATE_CURRENT);
widget.setTextViewText(R.id.currency, " Dollar");
appWidgetManager.updateAppWidget(appWidgetIds[i], widget);
}
super.onUpdate(context, appWidgetManager, appWidgetIds);
}
This code works for me. You may try this.
For below code...
below code is for the android widget
the same code is on this link Clickhere
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
for (int widgetId : appWidgetIds)
{
updateAppWidget(context, appWidgetManager, widgetId);
}
}
protected static void updateAppWidget(Context context, AppWidgetManager appWidgetManager, int appWidgetId)
{
//Inflate layout.
RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.time_weight_layout);
//Update UI.
remoteViews.setTextViewText(R.id.tvTime, Utility.settemp());
remoteViews.setTextViewText(R.id.tvTitle, Utility.gettitle()); //When user click on the label, update ALL the instances of the widget.
Intent labelIntent = get_ACTION_APPWIDGET_UPDATE_Intent(context);
labelIntent.setData(Uri.withAppendedPath(Uri.parse("abc" + "://widget/id/"), String.valueOf(appWidgetId)));
PendingIntent labelPendingIntent = PendingIntent.getBroadcast(context, appWidgetId, labelIntent, PendingIntent.FLAG_UPDATE_CURRENT);
remoteViews.setOnClickPendingIntent(R.id.tvTime, labelPendingIntent);
Log.d("updateAppWidget", "Updated ID: " + appWidgetId);
//Call the Manager to ensure the changes take effect.
appWidgetManager.updateAppWidget(appWidgetId, remoteViews);
}
protected static Intent get_ACTION_APPWIDGET_UPDATE_Intent(Context context)
{
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
ComponentName thisAppWidget = new ComponentName(context.getPackageName(), TimeWidgetProvider.class.getName());
int[] appWidgetIds = appWidgetManager.getAppWidgetIds(thisAppWidget);
Intent intent = new Intent(context, MainActivity.class);
intent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, appWidgetIds);
return intent;
}
here Main activity is configure activity I want to start MainActivity on click of widget
Here's a youtube link for the same.
It's only 6 min tut.