My widget provider has intent with value named id, wchich is equal current day of year. But this intent does not change. If today it is focused on 8th March, tomorrow it will also be focused on this day. And on the next day also and so on. But I need to refresh this intent every day.
MyWidgetProvider.java:
public class MyWidgetProvider extends AppWidgetProvider {
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
super.onUpdate(context, appWidgetManager, appWidgetIds);
int layoutId = R.layout.widget;
Calendar c = Calendar.getInstance();
c.setTime(new Date());
int id = c.get(Calendar.DAY_OF_YEAR);
boolean leap = new GregorianCalendar().isLeapYear(c.get(Calendar.YEAR));
int targetId = id<60?id:id+(leap?0:1);
for (int i:appWidgetIds) {
Intent intent = new Intent(context, MainActivity.class);
intent.putExtra("from", "widget");
intent.putExtra("id", targetId);
intent.putExtra("widgetID", i);
RemoteViews remoteViews = new RemoteViews(context.getPackageName(), layoutId);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);
remoteViews.setOnClickPendingIntent(R.id.widget_relative_main, pendingIntent);
}
}
}
my_widget_provider.xml:
<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:initialLayout="#layout/widget"
android:minHeight="31dp"
android:minWidth="72dp"
android:resizeMode="horizontal|vertical"
android:updatePeriodMillis="300000" >
</appwidget-provider>
What is a problem?
SOLUTION:
There was required PendingIntent flag "FLAG_UPDATE_CURRENT":
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
And everything works well!
Related
I have simple app with widget. Widget works good for some time. After open and close another app (e.g. some game for the most cases) my widget stops responding to clicks. Do you know how to fix widget freezing please?
I folowed some similar situation, but with no success: Android widget not responding to touches, Android widget buttons stop working, Android Widget stops working randomly, atc.
My actual Widget.class:
public class Widget extends AppWidgetProvider{
private DBManager dbManager;
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
final int N = appWidgetIds.length;
String URI_SCHEME = "A";
// Perform this loop procedure for each App Widget that belongs to this provider
for (int i=0; i<N; i++) {
int appWidgetId = appWidgetIds[i];
// Create an Intent to launch ExampleActivity
Intent intent = new Intent(context, MainOverview.class);
Intent intent2 = new Intent(context, AddFragment.class);
intent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
intent2.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent2.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, appWidgetId);
intent2.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, appWidgetId);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
PendingIntent pendingIntent2 = PendingIntent.getActivity(context, 0, intent2, PendingIntent.FLAG_UPDATE_CURRENT);
// Get the layout for the App Widget and attach an on-click listener
// to the button
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget);
views.setOnClickPendingIntent(R.id.widget_all, pendingIntent);
views.setOnClickPendingIntent(R.id.widget_add, pendingIntent2);
Uri data = Uri.withAppendedPath(
Uri.parse(URI_SCHEME + "://widget/id/")
,String.valueOf(appWidgetId));
intent.setData(data);
intent2.setData(data);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM", Locale.ENGLISH);
final Calendar calendar = new GregorianCalendar();
String text_date = sdf.format(calendar.getTime());
CharSequence sumd = (CharSequence) text_date;
views.setTextViewText(R.id.widget_date, sumd);
dbManager = new DBManager(context);
dbManager.open();
int totalPayed = dbManager.getTotalPayed(text_date);
CharSequence sumw = Integer.toString(totalPayed);
views.setTextViewText(R.id.widget_summary, sumw);
dbManager.close();
// Tell the AppWidgetManager to perform an update on the current app widget
appWidgetManager.updateAppWidget(appWidgetId, views);
// Update the widgets via the service
context.startService(intent);
context.startService(intent2);
}
super.onUpdate(context, appWidgetManager, appWidgetIds);
}
#Override
public void onReceive(Context context, Intent intent)
{
super.onReceive(context, intent);
}
}
My actual widget_provider.xml:
<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:initialLayout="#layout/widget"
android:minHeight="40dp"
android:minWidth="110dp"
android:resizeMode="horizontal|vertical"
android:previewImage="#drawable/logo"
android:updatePeriodMillis="36000000" >
</appwidget-provider>
My actual part of AndroidManifest.xml:
<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>
I am working on an android app with a Widget.
Everything works fine except for one thing.
I debug and code my app on different computers so when I launch the app for the first time i need to reinstall it because of the different debug key. When I try readding my widget after the installation I get the 'problem loading widget' and I need to reboot my phone to get it to work again.
This does not always happen, there are also other strange things that might happen.
My widget name, in the add widget list screen, gets renamed to 'foo.packagename.WidgetName' instead of the Widget Title.
The Widget icon gets replaced by the default android launcher icon
When I try adding the widget and place it on the homescreen, the previewimage gets replaced by a random icon
Beta testers experience the same problems after an update, even with the same key (release version).
Is this an android issue, or is something wrong in my code?
My AppWidgetProvider (partially)
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds) {
final int N = appWidgetIds.length;
SimpleDateFormat fmt = new SimpleDateFormat("EEEE d MMMM");
String date = fmt.format(new Date());
for (int i = 0; i < N; i++) {
RemoteViews remoteViews = updateWidgetListView(context,
appWidgetIds[i], date);
appWidgetManager.updateAppWidget(appWidgetIds[i], remoteViews);
appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetIds[i], R.id.list);
}
super.onUpdate(context, appWidgetManager, appWidgetIds);
}
#Override
public void onDisabled(Context context) {
Intent intent = new Intent(context, AppService.class);
intent.setAction(AppService.ACTION_UPDATE_WIDGET);
PendingIntent sender = PendingIntent.getBroadcast(context, 0, intent, 0);
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
alarmManager.cancel(sender);
super.onDisabled(context);
}
private RemoteViews updateWidgetListView(Context context, int appWidgetId, String date) {
RemoteViews remoteViews = new RemoteViews(context.getPackageName(),
R.layout.widget);
Intent svcIntent = new Intent(context, ListWidgetService.class);
remoteViews.setRemoteAdapter(R.id.list, svcIntent);
remoteViews.setEmptyView(R.id.list, R.id.empty_view);
remoteViews.setTextViewText(R.id.widget_sub_title, date);
Intent intent = new Intent(context, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);
remoteViews.setOnClickPendingIntent(R.id.widget_root, pendingIntent);
return remoteViews;
}
widget_provider.xml
<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:minWidth="250dp"
android:minHeight="110dp"
android:previewImage="#drawable/ic_launcher"
android:initialLayout="#layout/widget"
android:resizeMode="horizontal|vertical"
android:updatePeriodMillis="0">
I have a homescreenwidget in Android with two buttons. Both buttons should call the same activity ( class ) just use a different intent plus intent extras, to know which button called the class.
For now only button1 is working and calling the activity. I also receive the keyvalue in the called Activity.
How can i make the second button work?
Here's my code:
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds) {
super.onUpdate(context, appWidgetManager, appWidgetIds);
for ( int i =0; i<appWidgetIds.length ; i++){
int appWidgetId = appWidgetIds[i];
Intent intent2 = new Intent(context, Main.class);
Intent intent1 = new Intent(context, Main.class);
// Intent put extras Button 1
String bread1 = "secure";
Bundle basket1 = new Bundle();
basket1.putString("key", bread1);
intent1.putExtras(basket1);
// Intent put extras Button 2
String bread2 = "insecure";
Bundle basket2 = new Bundle();
basket2.putString("key", bread2);
intent2.putExtras(basket2);
PendingIntent pending1 = PendingIntent.getActivity(context,0,intent1, 0);
PendingIntent pending2 = PendingIntent.getActivity(context, 0, intent2, 0);
RemoteViews views1 = new RemoteViews(context.getPackageName(),R.layout.maina);
RemoteViews views2 = new RemoteViews(context.getPackageName(),R.layout.maina);
views1.setOnClickPendingIntent(R.id.button1, pending1);
views2.setOnClickPendingIntent(R.id.button2, pending2);
appWidgetManager.updateAppWidget(appWidgetId, views1);
appWidgetManager.updateAppWidget(appWidgetId, views2);
here is the maina.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" android:weightSum="1" android:orientation="vertical">
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="TextView" android:id="#+id/tvWidget" android:textAppearance="?android:attr/textAppearanceLarge"></TextView>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" android:weightSum="1" android:orientation="horizontal">
<Button android:text="#string/button1" android:id="#+id/button1" android:layout_height="wrap_content" android:layout_width="wrap_content"></Button>
<Button android:text="#string/button2" android:id="#+id/button2" android:layout_height="wrap_content" android:layout_width="wrap_content"></Button>
</LinearLayout>
</LinearLayout>
#Arnold you have created 2 PendingIntent which are....
PendingIntent pending1 = PendingIntent.getActivity(context,0,intent1, 0);
PendingIntent pending2 = PendingIntent.getActivity(context, 0, intent2, 0);
Where PendingIntent.getActivity(Context context, int requestCode, Intent intent, int flags) has 4 parameters. You have to send different "requestCode" for different PendingIntents.
Your code should be....
PendingIntent pending1 = PendingIntent.getActivity(context,0,intent1, PendingIntent.FLAG_UPDATE_CURRENT);
PendingIntent pending2 = PendingIntent.getActivity(context, 1, intent2, PendingIntent.FLAG_UPDATE_CURRENT);
in the main class you need to create this...
String value;
#Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
Bundle b=intent.getExtras();
try{
value=b.getString("key");
}
catch (Exception e) {
// TODO: handle exception
}
super.onReceive(context, intent);
}
with the onUpdate code....
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds) {
// Get all ids
ComponentName thisWidget = new ComponentName(context,
main.class);
int[] allWidgetIds = appWidgetManager.getAppWidgetIds(thisWidget);
for (int widgetId : allWidgetIds) {
// Create some random data
RemoteViews remoteViews = new RemoteViews(context.getPackageName(),
R.layout.main);
// Register an onClickListener for 1st button
Intent intent = new Intent(context, main.class);
intent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS,allWidgetIds);
intent.putExtra("key", "1st Button");
PendingIntent pendingIntent = PendingIntent.getBroadcast(context,
0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
remoteViews.setOnClickPendingIntent(R.id.button1, pendingIntent);
// Register an onClickListener for 2nd button............
Intent intent2 = new Intent(context, main.class);
intent2.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
intent2.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS,allWidgetIds);
intent2.putExtra("key", "2nd Button");
PendingIntent pendingIntent2 = PendingIntent.getBroadcast(context,
1, intent2, PendingIntent.FLAG_UPDATE_CURRENT);
remoteViews.setOnClickPendingIntent(R.id.button2, pendingIntent2);
appWidgetManager.updateAppWidget(widgetId, remoteViews);
}
}
Then you can check whether value=1st Button or value=2nd Button to know which Button has been clicked.
It should work... IF it does not work please let me know what is the problem...
I had a similar problem with using 2 buttons on a widget. I set OnClickPendingIntents on both of them, distinguished by different setExtra() calls. But only the latter intent was called, even when clicking the first button.
I found 2 solutions:
- assign different actions to both PendingIntents
- on the second PendingEvent set the PendingEvent.FLAG_CANCEL_CURRENT flag
I am quite unfamiliar with PendingEvents and Widgets, so I can't see the pros and cons and will stick to the first solution.
Maybe that might help you with your problem, too.
Your widget will only have 1 remote view. Try changing the end of your code snippet to:
RemoteViews remoteView = new RemoteViews(context.getPackageName(),R.layout.maina);
remoteView.setOnClickPendingIntent(R.id.button1, pending1);
remoteView.setOnClickPendingIntent(R.id.button2, pending2);
appWidgetManager.updateAppWidget(appWidgetId, remoteView);
Failing that, it would be useful to see your layout in R.layout.maina.
In my case:
remoteViews.setOnClickPendingIntent(R.id.widget_head, touch_man(context));
remoteViews.setOnClickPendingIntent(R.id.widget_head2, touch_woman(context));
public static PendingIntent touch_man(Context context) {
Intent intent = new Intent();
intent.setAction("touch_man");
return PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
}
public static PendingIntent touch_woman(Context context) {
Intent intent = new Intent();
intent.setAction("touch_woman");
return PendingIntent.getBroadcast(context, 1, intent, PendingIntent.FLAG_UPDATE_CURRENT);
}
In AndroidManifest
<receiver
android:name="Receiver"
android:label="widgetBroadcastReceiver" >
<intent-filter>
<action android:name="touch_man" />
<action android:name="touch_woman"/>
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="#xml/demo_widget_provider" />
</receiver>
It's working.
i have a widget to my application that is refreshed every 10 sec. If i change the language of the phone, the widget stops working. I mean, the textviews do not load the texts until they are refreshed (so after 10sec). I added a functionality that the user can open the app by clicking on the widget (an ImageView). This problem still stays.
This whole problem appears also when I restart the phone. I have to wait 10 secs for the textviews to load the texts, but I cannot click on the widget. I may change this interval to 1 sec, what would solve this issue (making it almost invisible for the user). But like I said, I still cannot click on the widget.
Here is the full AppWidgetProvider class:
public class HelloWidget extends AppWidgetProvider {
public static String ACTION_WIDGET_CONFIGURE = "ConfigureWidget";
public static String ACTION_WIDGET_RECEIVER = "ActionReceiverWidget";
private static final int REQUEST_CODE_ONE = 10;
String elso;
public static String MY_WIDGET_UPDATE = "MY_OWN_WIDGET_UPDATE";
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
super.onUpdate(context, appWidgetManager, appWidgetIds);
final int N = appWidgetIds.length;
for (int i=0; i<N; i++) {
int appWidgetId = appWidgetIds[i];
updateAppWidget(context, appWidgetManager, appWidgetId);
Toast.makeText(context, "onUpdate(): " + String.valueOf(i) + " : " + String.valueOf(appWidgetId), Toast.LENGTH_SHORT).show();
}
Intent intent = new Intent(context, UpdateService.class);
context.startService(intent);
RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.main);
Intent configIntent = new Intent(context, MainActivity.class);
configIntent.setAction(ACTION_WIDGET_CONFIGURE);
PendingIntent configPendingIntent = PendingIntent.getActivity(context, REQUEST_CODE_ONE, configIntent, PendingIntent.FLAG_UPDATE_CURRENT);
remoteViews.setOnClickPendingIntent(R.id.ImageView01, configPendingIntent);
appWidgetManager.updateAppWidget(appWidgetIds, remoteViews);
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
Intent myIntent = new Intent(context, UpdateService.class);
PendingIntent pendingIntent = PendingIntent.getService(context, 0, myIntent, 0);
AlarmManager alarmManager = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
Calendar calendar2 = Calendar.getInstance();
calendar2.setTimeInMillis(System.currentTimeMillis());
calendar2.add(Calendar.SECOND, 1);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar2.getTimeInMillis(), 50*1000, pendingIntent);
}
#Override
public void onReceive(Context context, Intent intent) {
super.onReceive(context, intent);
if(MY_WIDGET_UPDATE.equals(intent.getAction())){
Bundle extras = intent.getExtras();
if(extras!=null) {
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
ComponentName thisAppWidget = new ComponentName(context.getPackageName(), HelloWidget.class.getName());
int[] appWidgetIds = appWidgetManager.getAppWidgetIds(thisAppWidget);
if (appWidgetIds.length > 0) {
new HelloWidget().onUpdate(context, appWidgetManager, appWidgetIds);
}
}
}
}
public static void updateAppWidget(Context context, AppWidgetManager appWidgetManager,
int appWidgetId){
}
}
From this code this is the part that serves for opening the MainActivity.class of the app when the user clicks on the widget:
RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.main);
Intent configIntent = new Intent(context, MainActivity.class);
configIntent.setAction(ACTION_WIDGET_CONFIGURE);
PendingIntent configPendingIntent = PendingIntent.getActivity(context, REQUEST_CODE_ONE, configIntent, 0);
remoteViews.setOnClickPendingIntent(R.id.ImageView01, configPendingIntent);
appWidgetManager.updateAppWidget(appWidgetIds, remoteViews);
This is the Manfiest part:
<receiver android:name=".HelloWidget" 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>
And this is the widget_provider.xml:
<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:minWidth="146dip"
android:minHeight="72dip"
android:updatePeriodMillis="86400000"
android:initialLayout="#layout/main"
/>
I have a widget to my application that is refreshed every 10 sec [...]
I may change this interval to 1 sec [...]
In short: That's very bad practice. You should (at maximum) only update every 30 minutes.
By refreshing your Widget every 10 seconds, you kill the battery so fast that nobody will use it. Instead, you could add an "refresh"-button which then manually refreshes the Widget.
Also, in the onUpdate-method, you don't need to call the super-method.
And the onReceive-method does not need to be overridden! The onUpdate-method is automatically called when you use an AppWidgetProvider (not if you use a normal BroadcastReceiver). See here.
Last but not least, you should check if your "call-Activity"-code gets reached and try to debug it with the Log-class. The LogCat-Output might also help solving this.
Can you add this flag
PendingIntent configPendingIntent = PendingIntent.getActivity(context, REQUEST_CODE_ONE, configIntent, PendingIntent.FLAG_UPDATE_CURRENT);
Also check Logcat for any exception it throws when you click on the widget.
My code:
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds) {
Intent active = new Intent(context, DialerWidget.class);
active.setAction(ACTION_WIDGET_RECEIVER);
active.putExtra("com.anirudha.android.appwidget.Number", currentNumber);
PendingIntent actionPendingIntent = PendingIntent.getBroadcast(context,
0, active, 0);
views.setOnClickPendingIntent(R.id.one,
actionPendingIntent);
views.setTextViewText(R.id.number, currentNumber);
appWidgetManager.updateAppWidget(appWidgetIds, views);
}
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(ACTION_WIDGET_RECEIVER)) {
currentNumber = intent.getStringExtra("Number");
currentNumber += "1";
Intent active = new Intent(context, DialerWidget.class);
active.setAction(ACTION_WIDGET_RECEIVER);
active.putExtra("com.anirudha.android.appwidget.Number", CurrentNumber);
active.putExtra("com.anirudha.android.appwidget.Key", "1");
PendingIntent actionPendingIntent = PendingIntent.getBroadcast(context,
0, active, 0);
views.setOnClickPendingIntent(R.id.one,
actionPendingIntent);
views.setTextViewText(R.id.number, currentNumber);
ComponentName cn = new ComponentName(context.getPackageName(),
DialerWidget.class.getName());
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
appWidgetManager.updateAppWidget(cn, views);
Toast.makeText(context, currentNumber, Toast.LENGTH_SHORT).show();
}
super.onReceive(context, intent);
}
So, basically i want to change the extras i should receive with the Intent. But whenever the button is pressed i receive the same value with the Intent. I'm new to android development. Any help would be appreciated. Thanks
If you want to update an existing pending intent, you have to use the FLAG_UPDATE_CURRENT flag when you create it.
PendingIntent actionPendingIntent =
PendingIntent.getBroadcast(context, 0, active, PendingIntent.FLAG_UPDATE_CURRENT);
What type is currentNumber? It's not shown but from the code I guess it's an int.
You are putting it into the extra as an int, but you are reading it out as a string. The string will always we empty because there is no string extra with that name so currentnumber will also be 0, then increased by 1, so always be 1.
Also you are writing it with "com.anirudha.android.appwidget.Number" but reading with "Number". This must be the same key for writing and reading.
Solution: use getIntExtra()