| Feb 26 |  7:20 PM | 
| Mark M. | has entered the room | 
| Mark M. | turned on guest access | 
| Feb 26 |  7:25 PM | 
| Guido | has entered the room | 
| Mark M. | hello, Guido | 
| Mark M. | how can I help you today? | 
| Guido | Hi Mark | 
| Susheel | has entered the room | 
| Susheel | Hi Mark | 
| Guido | I've got a question about fragments going through configuration change.... I prepared it earlier today so I'm going to paste it here | 
| Mark M. | hello, Susheel! | 
| Susheel | Hi Guido | 
| Guido | Hi Susheel | 
| Susheel | I'll go after Guido | 
| Guido | View paste
  | 
| Mark M. | "setRetainInstance seems not to keep the selected items/action mode when in CHOICE_MODE_MULTIPLE_MODAL" -- your views get rebuilt; setRetainInstance() has nothing to do with this on its own | 
| Guido | oh I see, I didn't get this, so the class is retained but the view gets rebuilt? | 
| Mark M. | correct | 
| Mark M. | onCreateView() gets called again | 
| Mark M. | as you need fresh widgets to go with the fresh activity | 
| Guido | yes, that's right | 
| Feb 26 |  7:30 PM | 
| Mark M. | all setRetainInstance() does for you is say that non-widget data members could be held onto across the configuration change | 
| Mark M. | for widget state like this, option #2 (onSaveInstanceState()) is the best answer, as that not only survives configuration change, but handles the recent-tasks list and such as well | 
| Mark M. | for your model data, for something of this complexity, I'd lean towards #3 or a singleton data manager | 
| Mark M. | the latter would be if the same model data is needed by multiple components (multiple activities, or activities plus services, etc.0 | 
| Mark M. | er, etc.) | 
| Svetlin S. | has entered the room | 
| Guido | OK and would I need to persist also the adapters or the cursors only? | 
| Svetlin S. | Hello everyone. | 
| Mark M. | hello, Svetlin -- I will be with you after Susheel! | 
| Svetlin S. | Thanks. | 
| Mark M. | Guido: I use "persist" specifically to refer to file-based storage | 
| Mark M. | in which case, your data is already persisted | 
| Guido | yep sorry... that's right | 
| Mark M. | if you mean "retained", in terms of the model fragment, then I'd retain the cursors (the model data) | 
| Guido | yep, that's what I meant :-) | 
| Guido | thanks! | 
| Mark M. | Susheel: your turn! do you have a question? | 
| Susheel | View paste
  | 
| Feb 26 |  7:35 PM | 
| Mark M. | um, well | 
| Mark M. | that's probably something for you to take up with a manufacturer or something | 
| Mark M. | first, flash drives like that aren't part of the Android SDK, at least pre-4.4 | 
| Susheel | right | 
| Susheel | but the same thing happens to my externally mounted sdcard | 
| Mark M. | which, again, is not part of the Android SDK | 
| Susheel | oh really | 
| Susheel | ok | 
| Mark M. | removable media, pre-4.4, was outside the scope of the Android SDK | 
| Susheel | gotcha | 
| Mark M. | the sole exception is a device that uses removable media for external storage | 
| Mark M. | and there haven't been many of those since Android 3.0 | 
| Mark M. | so, by and large, the rules of the game for removable media are up to the manufacturer | 
| Susheel | Perfect, thanks :) | 
| Susheel | I have another question but I will wait for my turn. | 
| Mark M. | sorry I didn't have a better answer for you | 
| Susheel | That's cool, thanks | 
| Mark M. | Svetlin: your turn! do you have a question? | 
| Svetlin S. | Yes. | 
| Svetlin S. | I'm working on a handset which will run only one application. | 
| Svetlin S. | The handset connects to external devices using services. | 
| Svetlin S. | I implemented a Watchdog service started on boot to "oversee" them. | 
| Svetlin S. | Using AlarmManager. | 
| Svetlin S. | Now I need to consistently check the status of those service (list, (re)start) etc. | 
| Svetlin S. | Inside the Watchdog, periodically. | 
| Feb 26 |  7:40 PM | 
| Svetlin S. | I've come up with the idea of having a Pojo, ServiceManager which will provide the needed callbacks (registration of services, invoking operations on them etc.) to the Watchdog. | 
| Svetlin S. | So far OK? | 
| Mark M. | I'm baffled as to why all of this isn't being done in custom firmware, but, beyond that, I'm with you | 
| Svetlin S. | Let me copy in Pastebin. | 
| Svetlin S. | BTW the plan is eventually the app to run on a normal phone/tablet handset. | 
| Svetlin S. | |
| Mark M. | wait | 
| Mark M. | "the app"? | 
| Mark M. | singular? | 
| Mark M. | all of these services are in one app? | 
| Svetlin S. | The device will run just this app. | 
| Mark M. | then I'm really lost | 
| Svetlin S. | Yes, some are local, some remote (in another process). E.g. Bluetooth, RemoteSync etc. | 
| Mark M. | ok | 
| Feb 26 |  7:45 PM | 
| Svetlin S. | It is a normal approach for a medical device running a custom Android version. | 
| Feb 26 |  7:45 PM | 
| Svetlin S. | Using ActivityManager in the ServiceManager does not seem to work out well, because the Watchdog has to run and take action even if the device is asleep. | 
| Mark M. | I don't see how ActivityManager helps or harms in this are | 
| Mark M. | er, in this area | 
| Mark M. | if you want to check on the status of services periodically, and you want to do so even if the device is asleep, you'll use a _WAKEUP alarm | 
| Svetlin S. | I can't get my services using it, including inside a ServiceTestCase. | 
| Mark M. | I haven't used ActivityManager much, and I have never used getRunningServices(), so I have no idea what the expected behavior should be | 
| Mark M. | other than I'd be stunned if waking the device out of sleep mode somehow affected that behavior | 
| Mark M. | if you have these so tightly coupled, you might consider using the binding pattern | 
| Mark M. | your "watchdog" simply binds to each of the services and does some AIDL equivalent of a "ping" or status check or whatever | 
| Svetlin S. | There is the problem of the context, so that ActivityManager works called from an Activity, not so much from IntentService. | 
| Svetlin S. | I hear you. | 
| Svetlin S. | That's why I decided to put a static inside the controlled Service so that it reports its state. | 
| Mark M. | in your case, you'd leave off BIND_AUTO_CREATE, so you would know if the service was not already created, so you could use startService() to get it running more durably | 
| Feb 26 |  7:50 PM | 
| Mark M. | but that is not useful across process boundaries | 
| Svetlin S. | Let me pastebin what I tried. | 
| Mark M. | actually, let me take questions from the others | 
| Mark M. | and I'll be back with you in a bit | 
| Mark M. | as this has gone on a little long | 
| Svetlin S. | Sure! | 
| Mark M. | Guido: your turn! do you have another question? | 
| Guido | yes please | 
| Guido | View paste
 (5 more lines)   | 
| Guido | I realise it can be due to multiple factors but I wonder if you have an idea where to start from... | 
| Guido | or just knowledge of some "popular" mistakes... | 
| Mark M. | I don't think the back stack is designed to handle situations where you replace what was supposed to removed on a BACK press | 
| Mark M. | in fact, that feels like a UX or code smell | 
| Mark M. | oh, well, wait | 
| Mark M. | never mind | 
| Mark M. | I have a better picture for what you're doing | 
| Mark M. | but I don't think the framework-supplied back stack will work well here | 
| Guido | ok | 
| Mark M. | it's designed for simpler scenarios, like EU4You | 
| Mark M. | there, we only have two fragments, and either both are showing, or just the master | 
| Mark M. | an example of your scenario would be master/detail, with N possible detail fragments | 
| Mark M. | such as a shopping cart, with different fragments for different types of products (books versus movies versus boxes of laundry detergent) | 
| Feb 26 |  7:55 PM | 
| Mark M. | and there I would expect to have to handle the BACK stuff myself in onBackPressed(), though simply "knowing" whether the detail is showing and how to remove it | 
| Guido | ok, that clarifies my problem then | 
| Mark M. | in terms of the action mode stuff, are you referring to your own action mode, or a system-supplied one (e.g., EditText)? | 
| Guido | in one fragment type is system supplied in a ListView and in the other one is custom becasue I have a RecyclerView | 
| Mark M. | ListView doesn't have an action mode | 
| Mark M. | EditText does, and WebView kinda does | 
| Mark M. | but very few other widgets have one built in | 
| Mark M. | (actually, TextView does if you make it selectable) | 
| Mark M. | for your own action mode, I can see where onBackPressed() would need to know about it and finish() the action mode | 
| Guido | oh I see what you mean | 
| Mark M. | so it'd be: if action mode, then finish() it; else if detail showing, remove() it; else super.onBackPressed() | 
| Mark M. | where the latter will do your finish() for the activity for you, along with anything else that normal BACK processing might need | 
| Mark M. | doing finish() yourself is *probably* OK, but I just chain to super.onBackPressed(), so I know I'm not forgetting anything :-) | 
| Guido | yep, sounds great | 
| Mark M. | now, I may be off on your detail fragment handling, as I don't have a complete picture of what you're doing | 
| Feb 26 |  8:00 PM | 
| Mark M. | but let me take questions from the others, and I'll be back with you in a bit | 
| Mark M. | Susheel: your turn! do you have another question? | 
| Susheel | Going back to my previous question, when I replug the flash drive I'm able to view the contents of the flashdrive using a filemanager app. Does that mean that I should also be able to write a file to it?  Or is that not sufficent info and should I still contact the manufacturer about it? | 
| Guido | alright great | 
| Mark M. | "Does that mean that I should also be able to write a file to it?" -- off the cuff, I would expect so | 
| Mark M. | particularly if this file manager is a third-party one | 
| Mark M. | not a pre-installed one | 
| Mark M. | a third-party file manager should have no more capabilities than does your app | 
| Mark M. | (modulo the device being rooted and that file manager leveraging that where your app does not) | 
| Susheel | Ok. So do you think for some reason when I unplug the device the file path is being broken or something like that? Is that possible? | 
| Susheel | because when I restart it works well | 
| Susheel | until I unplug | 
| Mark M. | aw, heck, on this Ubuntu notebook that I'm using, I sometimes have to reboot as the system freezes when I unmount the external hard drive I use for backups | 
| Mark M. | *anything* can go haywire when dealing with removable storage as far as I am concerned :-) | 
| Mark M. | then again, my last name is Murphy, and so I'm used to problems like this... | 
| Susheel | Oh I see that makes sense...haha | 
| Mark M. | so, while an Android device should be stable and well-behaved when unmounting and re-mounting removable media, that can have bugs just like anything else | 
| Susheel | ok | 
| Mark M. | and probably more than its fair share, given that device manufacturers can kinda do what they want | 
| Susheel | Right | 
| Mark M. | and some device manufacturers can get awfully creative when given that amount of flexibility | 
| Susheel | No kidding | 
| Mark M. | so, if you're not seeing stable results, that's definitely something you'll have to take up with the manufacturer | 
| Susheel | Got it. Thank you Mark!  | 
| Feb 26 |  8:05 PM | 
| Mark M. | (or reseller or whoever handles that support for the hardware in question) | 
| Mark M. | Svetlin: your turn! | 
| Svetlin S. | Thanks, let me continue from where I stopped. | 
| Svetlin S. | I went over the binding pattern, and it looks it will do the job. | 
| Svetlin S. | My problem is, other people with less experience are writing some of the services. | 
| Mark M. | sounds like they need a good book :-D | 
| Svetlin S. | That's why I'm trying to get away with the least possible changes to their code. | 
| Svetlin S. | Please take a look at the static in http://pastebin.com/AFHT47Ab | 
| Svetlin S. | In AuthenticatorService. | 
| Svetlin S. | The idea is to have "state" variables describing the state a service is in. | 
| Svetlin S. | I know you are against "constantly" running services, but in this case it is a matter of life/wellbeing that if a service stops, it is restarted ASAP. | 
| Mark M. | for dedicated hardware, that's fine | 
| Mark M. | it gets to be a bigger problem on off-the-shelf stuff used by ordinary people for other things | 
| Mark M. | but, again, this is only an issue for remote processes | 
| Svetlin S. | How so? | 
| Mark M. | anything inside the same process as the watchdog won't stop unless you stop it or Android terminates that whole process | 
| Feb 26 |  8:10 PM | 
| Svetlin S. | I thought that's the case only if the service runs in "foreground"? | 
| Mark M. | no | 
| Mark M. | now, there's the case where the user goes into Settings and manually stops an individual service, but I am assuming that's not a worry for dedicated hardware | 
| Svetlin S. | Hm. Anyway, opinion on the static? | 
| Mark M. | you mean the singleton-ish instance of AuthenticatorService? | 
| Svetlin S. | Yes.  | 
| Mark M. | IMHO it is not doing anything for you | 
| Susheel | has left the room | 
| Svetlin S. | I'm aware stopService is async, so onDestroy will not get called immediately, anything else? | 
| Mark M. | but, if you want it, you're not leaking anything | 
| Svetlin S. | Also, the service may mis-behave and get stopped because the hardware it is attached to mis-behaves. | 
| Mark M. | but there your singleton won't help you | 
| Mark M. | say for example you crash with an unhandled exception | 
| Mark M. | assuming that it doesn't take down the whole process, Android might get rid of the individual service | 
| Mark M. | but it's not going to call onDestroy() | 
| Mark M. | because it assumes that your crashed service has lost its proverbial marbles | 
| Mark M. | and it's just going to let go of it | 
| Mark M. | and so your singleton will still point to it | 
| Svetlin S. | Correct. OK then, the way to go is to have an interface basically implementing the binding pattern for all services? | 
| Feb 26 |  8:15 PM | 
| Svetlin S. | Then the ServiceManager will undertake this actions on behalf of the Watchdog? | 
| Mark M. | well, the first thing is to have robust exception handling in all your code in the service :-) | 
| Mark M. | the nice thing about the binding pattern approach is that your watchdog/ServiceManager neither knows nor cares what is or is not in your process | 
| Mark M. | it just knows that it tries to bind and uses that to get state information | 
| Mark M. | and if the attempt to bind fails, then the service collapsed for some reason, and so we need to startService() it again | 
| Mark M. | that behavior is identical whether the service in question is in your process or in a :remote process | 
| Mark M. | you could even create a ManagedService base class that handles all of the common stuff for the binding, and have the other developers inherit from it instead of Service | 
| Svetlin S. | Yes. Thanks, very useful indeed. I also have a question about Service unit testing. | 
| Mark M. | let me swing back to Guido first | 
| Mark M. | Guido: your turn! do you have another question? | 
| Svetlin S. | I think I'll do exactly that. Any sample code to share ;-) | 
| Svetlin S. | Oops, sorry. | 
| Mark M. | (Svetlin: not really, as I don't do a lot with binding -- yours is one of the few use cases where I find binding to be valuable) | 
| Guido | no Mark, unless you have anything else to add, I think I'm good with your suggestions | 
| Mark M. | OK | 
| Mark M. | Svetlin: back to you | 
| Svetlin S. | Are there any problems with this sort of testing? | 
| Feb 26 |  8:20 PM | 
| Guido | Thanks Mark, have a good night | 
| Svetlin S. | View paste
 (20 more lines)   | 
| Mark M. | Guido: see you later! | 
| Guido | has left the room | 
| Mark M. | Svetlin: well, startService() is asynchronous | 
| Mark M. | actually, perhaps not in ServiceTestCase | 
| Svetlin S. | Really?! I'm very confused then, I thought it calls either onCreate or onStartCommand which are on the UI thread? | 
| Mark M. | yes, but unit testing code is not on the UI thread | 
| Mark M. | that's why you have to do the whole wait-for-idle-sync stuff in UI testing | 
| Mark M. | personally, I haven't used ServiceTestCase | 
| Svetlin S. | ServiceTestCase provides both a mock application and a mock context, correct? | 
| Mark M. | if I understand the docs correctly, yes | 
| Mark M. | I usually test what's inside the service separately, using something like AndroidTestCase if I need a Context for that | 
| Svetlin S. | So from the point of view of ServiceTestCase isn't it that the behavior is the same "as if" it is running on a mock UI thread? | 
| Mark M. | beats me | 
| Mark M. | I can tell you that the activity TestCase classes don't work that way | 
| Svetlin S. | The instrumented or the plain ones? | 
| Mark M. | certainly ActivityInstrumentationTestCase2 has its test methods running on another thread | 
| Mark M. | and, from what I can tell, the equivalents you run using AndroidJUnitRunner for JUnit4 support do the same | 
| Feb 26 |  8:25 PM | 
| Mark M. | my testing life is dominated by standard JUnit and AndroidTestCase, with sporadic uses of ActivityInstrumentationTestCase | 
| Mark M. | (er, ActivityInstrumentationTestCase2) | 
| Mark M. | I don't mess with the other Android test case base classses | 
| Mark M. | that's not to say they're bad | 
| Svetlin S. | I'm using JUnit3 for now. I wish there was somewhere a complete example of how to use ServiceTestCase? | 
| Mark M. | I just don't use them | 
| Mark M. | there's probably some floating around the CTS somewhere | 
| Svetlin S. | CTS is what (sorry)? | 
| Mark M. | Compatibility Test Suite | 
| Svetlin S. | OK, I'll take a look. | 
| Mark M. | it is what device manufacturers have to pass in order to qualify for the Google proprietary apps | 
| Mark M. | a search on "extends ServiceTestCase" on Google turns up surprisingly few hits, though some may be useful to you | 
| Svetlin S. | Got it. Thank you so much for your time, Mark, appreciated. | 
| Mark M. | based on the hit count, it would appear I'm not the only one who skips ServiceTestCase... | 
| Svetlin S. | Yeah, seems like it. | 
| Svetlin S. | Thanks again. We actually met at the Google I/O a couple of years ago, BTW. | 
| Svetlin S. | Thanks for the Warescription, appreciated. | 
| Mark M. | you are very welcome | 
| Mark M. | though I've skipped the past three I/O's | 
| Mark M. | time flies when you're having fun and/or writing Android code :-) | 
| Feb 26 |  8:30 PM | 
| Svetlin S. | Me too, that was back in 2011, I think, when it was worth going... | 
| Svetlin S. | Have a good one, bye. | 
| Mark M. | that's a wrap for today's chat | 
| Mark M. | the transcript will be posted to http://commonsware.com/office-hours/ shortly | 
| Mark M. | the next chat is Tuesday at 4pm US Eastern | 
| Mark M. | have a pleasant day! | 
| Svetlin S. | has left the room | 
| Mark M. | turned off guest access | 
