Controlling number of AppWidget instance - android

I want to create a widget for my android app that display some real time details about locations e.g. weather. but i want to allow max 3 instances of the widget at any point of time, each with a different location. I am not sure how to go about it and can't find any information.
my questions are:
Is there a limit on number of appWidget instances that could be created?
How to go about limiting the number of widget instances user can create at any point?

there are multiple ways to count the app widgets that i can think of:
send an intent to all of your app widgets to see that they still exist, and count them, and only in the end you would know how many there are. however, i'm not sure how you would know when to stop counting.
not sure if it works but maybe you could use:
   
final ComponentName cn=new ComponentName(context,YourAppWidgetProviderClass.class);
int[] appWidgetsIds=appWidgetManager.getAppWidgetIds(cn);
and check the size of the result.
update the counter based on receving the ACTION_APPWIDGET_DELETED (or ACTION_APPWIDGET_DISABLED) and ACTION_APPWIDGET_BIND (or ACTION_APPWIDGET_ENABLED) actions in the intents on the onReceive() method of your AppWidgetProvider class.
anyway, if there are too many (4 or more in your case) , just show an alternative layout for the new widget.
you would also need to handle the case of removing app widgets (those that weren't disabled) so that you would enable new ones (and decrease the counter), or you could let the user click on disabled ones to trigger the check again.
about limiting the creation itself, i don't think it's possible, but as i wrote, it's possible to count them and disable new ones.
do note that the user might have the app widget available on more than one app . it doesn't even have to be a launcher that will show your app widget. also not sure how it would work in case there are multiple users (available on android 4.2 and above) .

Related

Android Widgets: Differentiating between initial update and auto-update?

I'm currently developing a widget that requires the user to be logged in. When the user initially adds the widget and they're not logged in, I take them to the login activity so that they can log in. However, I don't want to do that when the widget auto-updates (it would be very annoying to have an app randomly launch when you're just browsing your home screen).
The updating code is currently in onUpdate(), but I haven't been able to figure out how to differentiate between the update that occurs when the widget is initially added and the update that occurs periodically. Is there a way to do this?
To summarize, I'm trying to make the following:
- Initial update when user adds the widget: Open login activity
- Subsequent periodic updates: Don't open login activity
Note: I'd like to avoid onEnabled(), since that is only called when the FIRST widget is added. I'd like my code to run every time a new widget is added.
If you are looking for just one instance of your widget, then you could go with shared preference boolean to solve this issue.
onEnabled - Clear boolean
onUpdate - if boolean not set -> Means first time (Do your work and set the boolean)
If boolean is set -> Means its the normal widget update.
Work around option if you need to deal with multiple widget instances :
If you need to achieve the above requirement, you need to handle auto update in intervals by your own.
That means, all the the call towards onUpdate should come from your own created Intents. That is :
Use Alarm manager to trigger the onUpdate functionality of Widget. Add bundle value to intent stating its an update call.
All widget interaction intents should contain the bundle value to say its an update call.
In onUpdate method, check for the same bundle value mentioned above and if its there, its a normal update else BINGO... :)

App Inventor: A way to track 2 scores across multiple screens

I am looking for a way to send two scores (called Coins and Gems) for a treasure game across several screens. It is for a class.
I have tried Tiny DB but it does not wipe after each game is played and I have not found a fool proof way to make it clear itself if someone closes the game.
I have tried using a close screen with start value but it only does one value and I need to have both send to the next screen.
I have also tried creating a list with the gems and coins value as the start value but then I can not continue to add the scores on the next screen and it gives me errors.
I would include screenshots and code but at this point its very jumbled together. I have also tried to make sure that each screen closes and sends the value but this has also been not successful any help would be appreciated. I can post whatever is helpful!
What it sounds like you need is an umbrella type class.
Make a separate class, with any name, for example, myApp.
Then make Coin and Gem values in the myApp Class. Use these values to maintain across multiple activities. When you are done on a certain screen, add the values accumulated on that screen to your myApp totals, then once you get to the new "activity or fragment" screen. You initialize that screen with the values from myApp Class.
If you want the totals to be cleared upon each start up, make a boolean value variable in the myApp class as well. Something like "firstGameBool", if initial value is true, then set all variables back to their initial states, set to false after first run to keep your program from erasing values after restarting play, not entire app.

How to tell if a new activity appeared?

I'm doing some black box testing (using UiAutomator 2.0 btw, extending InstrumentationTestCase) and I need to know:
1 - when a new activity is created
2 - to know if it's the first time the activity is created
I need this because there are some tests that I want to apply when a new activity appears but I want this detection to be automatic, not manual.
Prior to Android L there was the UiDevice.getCurrentActivityName() method. However, now it is deprecated (moreover, they don't even ensure it works for previous versions). This also happened with the options to getting the activity though the PackageManager.
As such, I would like to know:
Is it possible to programatically detect a new activity? If so, is is possible to know if it's the first time the activity occurs.
If it's not possible, how should I define an activity according to its UI? How many widgets should change for me to conclude it's a different activity?
Thanks.
EDIT: Just to be clear, I don't want to test what happens when the activity is created, I want to be able to identify if it's the first time this activity occurs in a run.
Here is what I currently implemented for this problem, base on a assumption that the same Activity won't change it's UI View hierarchy dynamically. This is OK to me, seems I only want to distinguish between UI changes, not necessary for Activities.
1.Build a signature to identify between screens
signature1:FrameLayout;ListView;LinearLayout;RelativeLayout;...
signature2:FrameLayout;FrameLayout;FrameLayout;LinearLayout;...
2.Then, use a List to keep screens you already known.
3.For performance, you can use a fixed length for screen signatue.
The idea is refer to this paper
And if adb is ok to you, you can use this command,
adb shell dumpsys activity
This refer to another post here

App Widget Update Headaches: Failed Binder Transaction, RemoteViews, setImageURI, and orientation changes

I am having an issue with updating AppWidgets and a confluence of limitations/bugs in android is preventing me finding a workaround.
My app widget is themeable so I need to be able to update the imageviews on it at runtime (as well as the textviews and intents). There are up to 9 imageviews that I am updating but the size of the graphics I'm using are fairly modest (max 11kb pngs). The total size of data I am pushing through the RemoteViews object should be under 100kb, well within the limit of 1mb. I think that actual drawable resources on screen end up being larger in size than the original pngs, but 10% of the limit seems reasonable enough to account for that. However, with certain phones and launchers, I am getting "FAILED BINDER TRANSACTION" errors.
There are two solutions that I have found for this:
1) Use setImageViewUri (which calls setImageURI) instead of setImageViewResource with the RemoteViews object, this gets rid of sending drawables through the RemoteViews object and loads the image from URI instead. Solves the memory error (see https://groups.google.com/forum/#!topic/android-developers/KKEyW6XdDvg/discussion )
2) Divide the updates to the app widget into multiple RemoteViews calls. So I update 3 of the images, call updateAppWidget, create a new RemoteViews object, update the next 3 images, call updateAppWidget, etc.
The problem with the 1st approach is that it only works for medium density devices. All other devices scale the images incorrectly due to a bug in the android codebase (see bug report: http://code.google.com/p/android/issues/detail?id=22590 )
The problem with the 2nd approach is that when the screen orientation changes, android destroys and recreates widget views using the last RemoteViews call which it stores in some secret place. This meams the appwidget doesn't get fully redrawn because I split my RemoteView calls up and the widget ends up unusable. There appears to be no reliable way to figure out when android is destroying and recreating the appwidgets - onConfigurationChanged in the service doesn't always fire and no Activity level call is ever made (ie. onUpdate, onReceive) that I can find. In order for the widgets to be able to be redrawn fully and correctly on orientation change, I can only use one RemoteViews (updateAppWidget) call so this solution won't work.
Does anyone have any idea how to work around this? I'm wondering if it'd be possible to implement my own RemoteViews that called a non-buggy setImageURI function (in a custom ImageView class) so that the scaling happened correctly. It seems like a lot of work just update a few widgets and I am not sure android will let me extend RemoteViews/ImageView that way.
Is there anyway to intercept android when the screen orientation changes and force it to redraw the whole widget?
Would love to hear any other suggestions or workaround ideas! Thanks.
I've encountered the same problems when developing collections' AppWidgets. Many times the following would happened:
On rotation, the ListView entirely dissapeared;
The button listeners (actually called PendingIntents) stopped responding;
Changes in images via setImageViewResource didn't get updated;
.. and so on. I came to the same conclusion as you did: android destroys and recreates widget views using the last RemoteViews call which it stores in some secret place. After acknowledging that, it was a question of fine-timing the calls to AppWidgetManager.getInstance(context).updateAppWidget() because I wanted to disable the clickListeners (or PendingIntents) after telling the ListView to refresh itself (it was a network operation of calling web-services and retrieving a non-trivial amount of data) and wanted to enabled the listeners after the ListView finished loading while maintaining the RemoteViews fully loaded in order to handle a rotation.
I was this close to giving up and using as an alternative..
Is there anyway to intercept android when the screen orientation changes and force it to redraw the whole widget?
.. a service that does intercept Android rotation changes, unlike an AppWidget. If you're running out of options, I'd suggest you'd try it out:
public class MyWidget extends AppWidgetProvider {
#Override
public void onConfigurationChanged(Configuration newConfig)
{
// insert code here
}
}
Find out more about the service here in StackOverflow.

How can one get the appwidget's own ID?

I am trying to debug a problem where my widget becomes invalid and a new one fills in. This only happens once at the beginning of time and then it remains the second widget forever. So, I want to put code in to narrow down the point in time when it happens. What I would like to do it something like this:
e.g., (not real code) Log.d(TAG, "myWidgetId=" + this.getMyWidgetId());
Then I would get a list of all the enabled IDs and see if I am in the list. I cannot find a method, member, attribute, etc. that would give me my id?
It cannot be done. The AppWidgetProvider's ID is implicitly handled and can change, therefore, the best one can do is to ask the AppWidgetManager to generate a list of the widgets for a particular component, invoke them, then respond to the service request using the provided ID.

Categories

Resources