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.
Related
I'm working on my first app that uses RecyclerView and while I am making great progress, I strongly suspect that my design needs some changes.
I've asked in several places over recent weeks for complete examples of a RecyclerView that read, update, insert and delete and have come up empty so I'm guessing my way along based on various passing remarks. First, let me explain concisely how I have designed this app. I imagine this will make my mistakes self-evident.
My RecyclerView is based around sales in the small company where I work. Each sale consists of a client code, an order number, an order date, a number of tickets sold, and a seller name. My design uses a listener to react to a FAB (FloatingActionBar) and, if pressed, goes to an Add activity that prompts the user for the information needed to create a new sale. No information is passed to this activity because none is needed. The Add activity validates the data and, when the user presses an Add button, that new data is passed back to my main activity. The main activity inserts a row into a remote MySQL table via a PHP script invoked from an AsyncTask in my app. Upon returning from the database, if the insert worked (it could fail if it was a duplicate record), I add the information to my ArrayList and notifyItemInserted in the onPostExecute() method. That all seems to work okay although I always get two copies of the new sale in the RecyclerView. The next time the screen refreshes though - when I do another Add, Update or Remove - the duplicate sale disappears.
Each item in my RecyclerView contains all of the information for one sale, plus two clickable images, one intended for Editing (it's a blue pencil), and one intended for Remove (it's a red garbage can). If the user wants to edit that sale, he clicks on the blue pencil; if he wants to delete it, he clicks on the red garbage can. I use listeners to determine which image got clicked.
When someone clicks on the Edit graphic, I launch an Edit activity, passing the information from the existing sale to that activity. The activity displays the information and the user can modify any of the five fields. All changes are validated and, if all the validations are successful, the changed information is passed back to the Main activity which updates the existing row in the database in the doInBackground() method of an AsyncTask. If the update is successful, I try to change the information in my ArrayList and notifyItemChanged in onPostExecute(). That always fails.
When someone clicks on the Remove graphic, I launch a Remove activity, passing the information from the existing sale to that activity. The activity displays the information and the user can only press Remove to confirm that the sale should be removed or press Cancel to abort the removal. If Remove was pressed, the information from the sale is passed back to MainActivity which removes the existing row in the database in the doInBackground() method of an AsyncTask. If the database delete is successful, I try to delete the item from the ArrayList and then notifyItemRemoved in onPostExecute(). That always fails.
As you can see, the Edit and Remove both fail every time. The reason is that there is an indexOutOfBoundsException with respect to the position used in attempting to modify or remove the item from the ArrayList.
Now that I've set out an understanding of the situation, I can ask my specific questions:
Is it reasonable/appropriate to use Activities to do the work I've described for Add, Edit and Remove processes in the first place or would I be better making them fragments?
Is it appropriate to be doing the database activity and the adjustment of the ArrayList in the main activity or should I be letting the Add, Edit, and Remove activities (or fragments if that's better) do the work?
I think my fundamental problem is that my code can't "see" everything it needs to see at the point where it is doing its work. I think I need to redesign things a bit to make the app work better.
RecyclerView seems to be pretty fundamental so I want to make sure I write everything correctly. In fact, given the absence of good examples that show a RecyclerView that has all the functionality I'm describing, I'd like to write a tutorial or make a video series showing my finished app with all the critical parts explained so that others can learn from it.
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... :)
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) .
I have an app that is a chat, while you navigate in the App, you can receive a message, if you receive it the icon "message" changes to a new one (that new icon tells the user that he has a new message).
while you are navigating in the app I created different Activities that have the same footer (include other layout)
So what I want is, how I can change the state of the message to new message in all the activities when I receive the message?
I thought about creating an interface with one method that checks if the activity has been created and if is, just change the imageView, but I think there is a better way.
Any Idea?
You might consider creating a interface that have methods based on different kind of updates.
For example onNewMessage(Message) and similar. Then you have let the implementors register themselves with the service that determines when these events occur. So when a message is received the service will go through the list of registered implementors and post the update.
The implementor would in this case update it's imageview.
Don't forget to also unregister when reasonable and so forth.
I have a general scenario, but couldn't make out how to handle it.
I have a ListView with each item having different clickable views. Of which 1 is add as friend button beside the user name in the item.
So, in the ListViewAdapter's getView() i implemented onClick for this button this way.
onClick(){
//make the button invisible, for UX
//change the value of is_friend = 1, in the Adapter ArrayList, which will be helpful when listView is scrolled and getView is called again, to make it visible or invisible.
//Send the info to the server as an AsyncTask
}
This works fine.
Problem:
instead of clicking the add as friend button, I can click the user name go to his profile and click the add as friend button in that Activity.
Now when i comeback to the ListView, the add as friend button is still visible, because the adapter ArrayList has old data taken from server and i am not even changing them.
I thought of StartActivityForResult when user name is clicked. But i might not comeback to the ListView as soon as i click add as friend, there are lot of other actions on a user's profile.
A familiar case easily handled by many apps. Any idea on how this is done?
Thank You
EDIT:
Though the answers given below work. They are not the best way to do.
So, a better way might be to make a call to a static method of the listViewAdapter to update that value only in its ArrayList??
The comment of gsingh2011 is valid. However, I am guessing that your remark will be something like "I populate the ArrayList by querying the server and I don't want to do that to often".
More generally speaking, the comment of gsingh can be translated to this: you should base your adapter and 'ViewProfileActivity' on the same data. You can do this by sharing the ArrayList between the two (as a static, or a public member or whatever you want). When you then change something from your 'ViewProfileActivity', your ListView will automatically update once you switch back to it (because getView() will be called on its adapter again, which will generate a view based on the new data).
The text above is an answer to your question, but let me just add some other remarks:
you say you are sending info to a server in an asynctask. You should change this to using an (Intent)Service for that. You don't have any guarantees that your data will be fully sent when your Activity is put in the background. If you delegate this server synchronization to a Service, it will make sure your process is kept around long enough for your send to finish.
once you have that service, that would be a nice place to put your "shared data" as discussed above. You could also use a small database for that and let the service only handle the synchronization between your local database and the remote server. Then you have something that is beginning to look like a REST implementation, where your device is caching remote data locally, but in the end is only visualizing the state of the remote server. You can look up an excellent google i/o presentation on dealing with REST servers. This presentation is also nice if you are not interested in the REST part, because (maybe more importantly) it shows you what things you have to take into account when you want to have guarantee of successful persistence of data.