Nov 21 | 7:25 PM |
Mark M. | has entered the room |
Mark M. | turned on guest access |
Steve S. | has entered the room |
Steve S. |
Hi Mark!
|
Mark M. |
hi, Steve!
|
Mark M. |
how can I help you today?
|
Steve S. |
I have a follow-up question about the Bluetooth service we've discussed previously:
|
Steve S. |
. The service is a started service that needs to be available to several activities in the app, so my idea is to start it in an Application subclass. The service needs some data that is persisted to run Bluetooth, so I was going to include that in the intent used to start the service. My question is what the return value from onStartCommand() should be - I think I should use START_NOT_STICKY but am not sure.
|
Mark M. |
IIRC, this is a kiosk app, right?
|
Steve S. |
yes
|
Mark M. |
and you want this Bluetooth service to basically be running all the time?
|
Steve S. |
yes
|
Nov 21 | 7:30 PM |
Mark M. |
then between that, and the "include that in the intent" bit, you should use START_REDELIVER_INTENT
|
Mark M. |
most likely, your process won't ever get terminated, outside of a crash (in which case, you have bigger problems)
|
Mark M. |
but, if during some maintenance cycle, when the app is in the background, Android terminates your process, it should restart it soonish to get your service running again
|
Mark M. |
and, it will hand you the Intent that you used to start the service earlier, so you have your data
|
Mark M. |
though, IMHO, the service should read its own data, rather than have an Application be responsible for reading it from persistent storage
|
Steve S. |
as things stand, there's an issue with redelivering intents (so i might need to do what you said regarding having the service get its own data).
|
Steve S. |
Here's onStartCommand:
|
Steve S. |
View paste
|
Steve S. |
An intent is used for both start and write, and they carry different data
|
Mark M. |
hmmm...
|
Mark M. |
OK, then with this flow, START_REDELIVER_INTENT is not the right answer
|
Steve S. |
so maybe i'll need to change things around
|
Nov 21 | 7:35 PM |
Mark M. |
I'm just not sure what value there is in having the Application push initialization data into the service
|
Mark M. |
ideally, components are self-sufficient to the extent possible
|
Mark M. |
and, in your service, you're in ideal shape to do that I/O on a background thread
|
Steve S. |
right. i've considered both approaches. the main reason for not having the service get the data is that it makes the Bluetooth code less general. but there may be countervailing considerations then
|
Steve S. |
backing up a bit, i'm not very clear on the circumstances surrounding shutting down and restarting the service
|
Mark M. |
um, could you be more specific?
|
Steve S. |
sure
|
Steve S. |
i was thinking that the service would get shut down only if the rest of the app (e.g. the activity last running) would also get shut down. is that correct?
|
Mark M. |
there are four scenarios:
|
Nov 21 | 7:40 PM |
Mark M. |
(at least for your environment, where the user doesn't have access to Settings)
|
Mark M. |
1. you call stopService()
|
Mark M. |
2. you call stopSelf()
|
Mark M. |
3. your service crashes with an unhandled exception
|
Mark M. |
4. your process is terminated while it is in the background
|
Mark M. |
assuming that you don't do the first two, and that you don't have any bugs, the only consideration is the last one
|
Mark M. |
and even that's fairly unlikely in your scenario, as your app won't be in the background much, I imagine
|
Steve S. |
ok
|
Mark M. |
if your service is in the same process as your activities (the default behavior), then all of that goes away when the process does
|
Steve S. |
right
|
Mark M. |
if you have your service in a separate process (via android:process), then that process could be terminated separately
|
Steve S. |
no, everything is in one process
|
Steve S. |
great - very helpful
|
Mark M. |
cool
|
Nov 21 | 7:45 PM |
Steve S. |
so the next thing i'm unclear about is how things get restarted after the process is terminated
|
Steve S. |
i take it it's not the same as starting the app for the first time?
|
Mark M. |
that depends on what "things" are
|
Mark M. |
your service will get restarted automagically if you use START_STICKY or START_REDELIVER_INTENT
|
Mark M. |
it will not if you use START_NOT_STICKY; it will be your job to start that service from elsewhere in your code as appropriate
|
Mark M. |
your UI is gone until some future startActivity() call
|
Mark M. |
(in theory, it could come back due to BACK navigation or the RECENTS list, but I'm assuming those aren't relevant in your kiosk scenario)
|
Steve S. |
so in those scenarios, Application#onCreate wouldn't be called?
|
Mark M. |
that will be called when your process is started for whatever reason (e.g., your service is being restarted due to START_STICKY or START_REDELIVER_INTENT)
|
Nov 21 | 7:50 PM |
Steve S. |
so if i start the service in MyApplication#onCreate, and if the process is terminated, the service would still get restarted (it might just take longer)?
|
Nov 21 | 7:55 PM |
Steve S. |
i mean if use use START_NOT_STICKY
|
Mark M. |
well, that depends on what would cause your process to exist
|
Steve S. |
ok
|
Mark M. |
if you are using START_NOT_STICKY, Android will not start your process as part of restarting your service automatically
|
Mark M. |
so now you need some external agent to start an activity, start a service, or send a broadcast to your app
|
Steve S. |
so that could be the user navigating back to the app?
|
Mark M. |
in principle, yes -- not sure how relevant that is to your kiosk scenario, though
|
Steve S. |
ok
|
Nov 21 | 8:00 PM |
Steve S. |
ok. i think i have a better understanding of the situation
|
Steve S. |
users will be able to access Android options (with a password).
|
Steve S. |
it would be ok if Bluetooth stopped running then, as long as it starts again once the user goes back to the activity
|
Mark M. |
there is the theoretical possibility that they could Force Stop your app from Settings
|
Steve S. |
ok
|
Mark M. |
and, depending on the version of Android you're running, they might have the ability to stop the service from the Settings UI
|
Steve S. |
we're now using 4.4
|
Mark M. |
yeah, that probably still has the manual service control stuff in Settings
|
Mark M. |
by "user", I assume you mean somebody responsible for administering these devices
|
Steve S. |
yes
|
Mark M. |
in that case, if they Force Stop your app or stop your service from Settings, it's their own damn fault
|
Mark M. |
:-)
|
Mark M. |
your app will resume normal behavior as soon as they go back to your UI, though
|
Nov 21 | 8:05 PM |
Steve S. |
so they could do that by starting the app normally?
|
Mark M. |
yes
|
Steve S. |
ok
|
Steve S. |
so reviewing:
|
Steve S. |
i could leave onStartCommand the way i have it now (not that I should) as long as i'm ok with the possibility of pathological cases where the administrator calls Force Stop or the stops the service from Settings?
|
Mark M. |
pretty much
|
Steve S. |
great.
|
Steve S. |
thank you so much for working through all these details with me!
|
Mark M. |
if the admin leaves your UI via the password, brings up Settings, then goes to lunch, your process might be terminated while Settings is in the foreground
|
Steve S. |
ok
|
Mark M. |
but, as soon as the admin navigates back to your app, Android will create a fresh process for you
|
Nov 21 | 8:10 PM |
Steve S. |
cool
|
Steve S. |
i'm wondering if i could show you some more of the service code and get your feedback
|
Mark M. |
um, sure, but do bear in mind that these chat transcripts get archived
|
Mark M. |
be judicious about posting significant quantities of non-open source code
|
Steve S. |
sure - thanks
|
Steve S. |
here's the start() method that gets called in onStartCommand():
|
Steve S. |
(i've tried to take account of feedback i've gotten from you in prior chat sessions)
|
Steve S. |
View paste
|
Steve S. |
so i'm now getting the adapter on the main thread, and stopSelf() is called here but nowhere else
|
Steve S. |
and here's the run method of ConnectThread:
|
Nov 21 | 8:15 PM |
Steve S. |
View paste
(2 more lines)
|
Mark M. |
I'm not a big fan of infinite loops with sleep() delays
|
Steve S. |
so (taking your advice) i don't recreate ConnectThread for each connection attempt, but use a sleep loop
|
Steve S. |
ok. what would be better?
|
Mark M. |
perhaps nothing -- I don't know enough of your app
|
Mark M. |
and, assuming that these kiosks are always connected to power, it's not a big deal
|
Steve S. |
right, the device is always plugged in
|
Steve S. |
anything else?
|
Mark M. |
and this loop exits once you connect, so that's not too bad
|
Mark M. |
I was thinking at first that this would be going the entire time your app was running
|
Steve S. |
no
|
Mark M. |
however, the loop keeps going so long as mmAdapter.isEnabled() is false and mIsStopped is false
|
Mark M. |
not sure how much of an issue that is
|
Mark M. |
do you want to be calling postError() every 200ms in this situation?
|
Nov 21 | 8:20 PM |
Steve S. |
right, maybe that could be less frequent
|
Mark M. |
either extend your sleep time, or only call postError() every Nth pass through the loop, or something
|
Steve S. |
ok
|
Steve S. |
i'm not wedded to that sleep time
|
Mark M. |
that's good, because marrying a sleep time is probably illegal in your jurisdiction
|
Mark M. |
:-)
|
Steve S. |
good point
|
Mark M. |
come for the developer support, stay for the bizarre legal advice!
|
Mark M. |
(note: nothing in these chats constitutes legal advice)
|
Steve S. |
then i won't rule out marrying the sleep time
|
Steve S. |
no more questions today
|
Mark M. |
OK
|
Steve S. |
this has been extremely helpful
|
Mark M. |
glad to be useful!
|
Steve S. |
i really appreciate you're working through the details of shutting down and starting up the app with me
|
Mark M. |
it's a messy area
|
Mark M. |
in a sea of messy areas known as Android app development
|
Nov 21 | 8:25 PM |
Steve S. |
i've looked all over for that information and haven't found anything at that level of detail
|
Steve S. |
thank you, and have a good rest of the evening!
|
Mark M. |
you too!
|
Steve S. | has left the room |
Nov 21 | 8:30 PM |
Mark M. | turned off guest access |