I am a newbie in Android development and I am faced with a problem which I can't figure out. I am following this link. It is a simple widget which has a listView which shows harcoded feed.
I wanted to make the widget interactive. So I came up with a solution as follows: I created a Intent, associated with it a Action and Broadcasted it with PendingIntent. Now I tried to catch that Intent in the onReceive() function of the WidgetProvider.java class.
I thought this approach is great except the fact that onUpdate function is called every 30 minutes. I am not sure even if it works after 30 minutes, haven't tried it. So I can't figure out how do I achieve this.
Basically I wanted to make it into widget, on which if clicked, it launches another activity. And can you also tell when is the onReceive function of the AppWidgetProvider called.
Related
When using the intended(IntentMatcher) from the Android Espresso API, is it possible to do this twice in the same Activity?
So for example I click a button which starts an Activity for result. I check that this Activity has fired using intended(IntentMatcher). That works.
However, when I get the result, I want to fire off an Intent for a different Activity. In this case just a local Activity in the same app package with no result.
When I do this manually in the app it works fine, but Espresso can't seem to detect the second Intent in my test. What I am I missing or is this not possible? Alternatively, how should I be doing it? Maybe my design is bad.
When I do the check I'm trying this:
intended(toPackage(<packageName>));
intended(hasComponent(hasClassName(<className>)));
The first line matches but not the second one. And even if the second line is not completely correct it never seems to show anything in the error log about the second Activity I'm actually starting.
Another thing adding to the confusion is that two intents are definitely being fired as it shows that in the log. They both seem to be the same one but with slightly different details - one is a package, one is a component. Does it log the result from the first Intent as an Intent in itself? Sounds unlikely but where is this other intent coming from? I know it's not the second Activity I'm launching as it still fires even when that Activity isn't called (when the first Intent result is a fail).
I've also considered that maybe it's not getting detected because it's not waiting long enough for the second intent to fire. If that were the case, what would I do about that? I don't see much talk about handling time sensitive things in Espresso. Like checking if a progress bar is shown but then hidden again while not pressing anything. How do you do that? Maybe it's the same answer.
Any help appreciated!
Ok I found the problem. My IdlingResource wasn't working.
After fixing that it works like a charm :)
I've followed the tutorial on widget at http://developer.android.com/guide/topics/appwidgets/index.html, and I also know how to create an AlarmManager to update the widget. What I'm wondering is how to effectively turn off the default onUpdate(). According to the guide lines (at that link), when I use AlarmManager I should set updatePeriodMillis to zero. But onUpdate() keeps being called (because 0 always lapses). If I set it to, say, 30 mins, it updates at that period. So practically it keeps using the value in updatePeriodMillis , which nullifies the effect of using AlarmManager. Am I missing anything?
Update: actually there's another code that triggers the update on another event, so never mind.
Cheers.
I am writing a launcher activity to host appwidgets. Basically here is what I am doing.
My container view for all appwidgets is some customized ViewGroup.
When adding widgets, I do call config activity first for the widget being added.
I am calling AppWidgetHost.startListening() in main activity.onStart() and stopListening() in onStop()
When adding widget, here is what I do
application.getAppWidgetManager().bindAppWidgetIdIfAllowed(appWidgetId, componentName);
AppWidgetHostView hostView = application.getAppWidgetHost().createView(context, appWidgetId, appWidgetInfo);
hostView.setAppWidget(widgetId, appWidgetInfo);
myViewGroup.addView(hostView);
I am not seeing RemoteException in logs and calling AppWidgetHost.startListening() aggressively doesn't help.
In addition, not all widgets fail to update, the stock clock widget, for example, works fine. This happens especially on Minimalistic Text Widget and some others. Once the widget has been added, it is able to update for 1~2 minutes before stop working. The other related observation is that when I tap the Minimalistic widget, modify the layout and save. The new layout won't be applied to the existing widget. That makes me feel there is something buggy in my code, but I cannot figure out where.
Thanks for help in advance!
Sorry I cannot paste detail code here because they are scattered around. But I can provide any detail information if you need. Thanks again!
Never mind. I figured out eventually. The reason is that I was using application context instead of activity context when creating AppWidgetManager and AppWidgetHost.
I am developing an appwidget that uses the RemoteViews to display a ListView. For simplicity's sake, I will give an analogy of the appwidget's functionality:
The user will select to add the appwidget to the home screen. Upon selecting the widget, a configuration activity is launched and the user selects from one recipe from a list of recipes.
Upon selecting the recipe from the configuration activity, the configuration activity broadcasts the AppWidgetManager.ACTION_APPWIDGET_UPDATE intent. This intent received and handled in the onReceive method of my AppWidgetProvider class. From here the RemoteView is instantiated and passed into the AppWidgetManager.updateAppWidget() method. This proceeds to fill in the ListView of ingredients.
This all works as expected, except when I attempt to manually update the ListView from the appwidget. I have set a PendingIntent to re-launch the configuration activity, which also works. Unfortunately, the call to AppWidgetManager.updateAppWidget() does not get called instantly as it did when being launched upon adding it to the home screen and the ListView does not get updated. The update does get called, however, after scrolling down the list a ways (until it gets passed the number of rows it has loaded in its cache, I reckon). This fires off my FlightBoardAppWidgetService and ViewsFactory as it should. It is almost as if the updateAppWidget is getting put into some lazily-loaded queue. I tried to look at the Android source code to see how AppWidgetManager.updateAppWidget() is coded, but it appears to be hidden.
tl;dr: AppWidgetManager.updateAppWidget() does not always get called instantly, what gives?
Is there any way to get the ListView to update when it is actually called? What am I doing wrong? Thanks!
Well, I ended up solving the problem finally. It is somewhat of a hack, but I ended up solving the problem by declaring a refresh broadcast and an update broadcast. Each time I want to update the widget I call updateAppWidget(), and then from the function that receives and handles this broadcast, I launch another broadcast that calls notifyChanged. This works all of the time!
whenever I recreate the home screen widget on my phone, the onReceive() method is not called.
the problem would be that it doesn't respond to Button press that I assign which its function resides in the onReceive method..
The issue does not reside on the emulator but when I tested it with my phone, it doesnt respond to it.
What would be the best solution for it?
Since you don't have any more detail stuff (maybe some source code on how you register the receiver and how you bind the pending intent). Probably your phone is a model with sliding keypad, or those home screen can change orientation. Because when screen orientation of home screen changed (or any hardware configuration), the home screen is inflated and recreated. So, for your buttons, the intent that originally bound to it is gone after the recreation. According to the documentation (sorry, can't find the link), the inflater will only get the latest update from remoteviews. So, the following would not work:
RemoteViews rv = ...;
// Assign the button to some pending intent
rv.setOnClickPendingIntent(View, pi);
AppWidgetManager.Update(...);
// And after sometime, you make changes to the rv
rv.setFloat();
// And update again
AppWidgetManager.Update(...);
It is still ok and the button will fire the Pending Intent as expected, but, if for any reason configuration changed and the home screen is invalidated (and recreated), the appwidgetmanager will only update according to the last update, which, did not specify anything about the clicking intent.
Solution to this is, everytime you update the remote view, you have to set all the pending intent as well. I am not sure how it would impacts the performance, but it is the only working method I can have. (but my widget is updating like 16 times/second and at least it works :)