Mark M. | has entered the room |
Mark M. | turned on guest access |
Jan 23 | 7:40 PM |
Tyler | has entered the room |
Tyler |
Hi Mark.
|
Mark M. |
hello, Tyler!
|
Mark M. |
sorry if there was a slight delay there
|
Jan 23 | 7:45 PM |
Mark M. |
how can I help you today?
|
Tyler |
no problem. I have a question about bound services. I want provide a simple service other apps can access..
|
Tyler |
I was thinking to use a Messenger to keep it simple and single threaded..
|
Tyler |
I noticed that from the client, the bindService() call fails if my "service app" has never been run, or the device has been rebooted.
|
Mark M. |
OK, so... what is the question?
|
Mark M. |
with regards to the never-been-run scenario, all apps are installed in the so-called "stopped state"
|
Mark M. |
nothing works on them until something uses an explicit Intent to interact with a component in the app
|
Tyler |
I was wondering if that is a limitation of services, or I am missing something in my manifest .. or do i need to explicitly get the "ON_BOOT" broadcast
|
Mark M. |
none of the above
|
Tyler |
even thought the client is explictly calling to my service?
|
Mark M. |
ideally, just using an explicit Intent should suffice for the never-been-run scenario
|
Mark M. |
where by "explicit Intent", I mean one that has the ComponentName in it
|
Tyler |
maybe I am constructing the intent incorrectly then?
|
Mark M. |
possibly, if you are just using an action string
|
Mark M. |
that won't work on Android 5.0+ in general
|
Jan 23 | 7:50 PM |
Mark M. |
and I would expect it to fail for the never-been-run scenario
|
Mark M. |
my chapter on remote services and the binding pattern goes through how to create an explicit Intent for binding
|
Mark M. |
I'm not sure what a reboot would do to affect matters, though
|
Mark M. |
when you call bindService(), are you passing in the BIND_AUTO_CREATE flag?
|
Tyler |
View paste
|
Mark M. |
OK, that looks fine for both of my concerns
|
Tyler |
View paste
|
Tyler |
doesn't seem to work on my device.. if i force stop the "service" app, (or reboot)
|
Mark M. |
I have never tried binding to a service from an app that has been force-stopped (or freshly installed)
|
Mark M. |
no, sorry, I have that backwards
|
Mark M. |
I have never tried binding from an app to a service in an app that has been force-stopped (or freshly installed)
|
Mark M. |
my guess is that an explicit Intent is sufficient to move the app out of the stopped state
|
Mark M. |
perhaps that's not the case
|
Mark M. |
if you launch an activity from the app (after having force-stopped it), then bind, does it work?
|
Tyler |
is this the right manifest for the service app:
|
Tyler |
View paste
|
Tyler |
yeah, if i launch the app it works.
|
Jan 23 | 7:55 PM |
Mark M. |
from a security standpoint, what you have is scary, but that's a separate issue
|
Mark M. |
and whether you need the android:process attribute depends on the situation
|
Mark M. |
otherwise, that should be fine
|
Mark M. |
try this sometime: force-stop the app, launch the activity, terminate the process (e.g., via the LogCat pane in Android Studio), then try binding
|
Tyler |
thinking off making a 'blank' activity that should be launched
|
Mark M. |
if the scenario I outlined works, then the problem is that binding, even with an explicit Intent, is insufficient to move the app out of the stopped state
|
Mark M. |
and you'll need the user to start the activity
|
Mark M. |
it should be more than blank, though -- you need to display a license agreement, support options, etc.
|
Mark M. |
since you have to have that stuff anyway, you may as well leverage it for this get-out-of-the-stopped-state activity
|
Mark M. |
if the scenario that I outlined does *not* work, then for some reason your binding is only working when the process is running, and that shouldn't be required
|
Tyler |
hrm.. you can terminate a process from logcat?
|
Mark M. |
hang on, they moved or got rid of it...
|
Jan 23 | 8:00 PM |
Mark M. |
oh, yeah, sorry -- it's the red stop button in the main toolbar, a few to the right of the run button
|
Mark M. |
it used to be in LogCat
|
Tyler |
ah. ok.
|
Tyler |
yeah, it won't run, like when i force stop it.
|
Mark M. |
OK, I can't explain that
|
Mark M. |
but, I do not use inter-app communication via services much
|
Mark M. |
so I haven't tried this scenario
|
Tyler |
ok.
|
Tyler |
so you said the manifest is scary from a security standpoint.. because the service is "exported=true"?
|
Mark M. |
I am fairly stunned at the behavior, though
|
Mark M. |
any app can start or bind to that service
|
Mark M. |
that is kinda wide open from a security standpoint
|
Mark M. |
what apps are the client apps? are they yours, or from other developers?
|
Tyler |
right, but the idea is for a service for other apps to call
|
Tyler |
3rd parties
|
Jan 23 | 8:05 PM |
Mark M. |
you will need to take great care with your exposed API, to ensure that your requests are legitimate and that you are not exposing any unnecessary or unfortunate data
|
Tyler |
I was trying to find any open source apps (or other companies/apps) that provide a service like this..
|
Tyler |
about the only thing i found was https://github.com/open-keychain/openpgp-api
|
Tyler |
to get some ideas on 'best practices'
|
Mark M. |
using a client-side library that manages the communication with the service can help somewhat
|
Mark M. |
but running a service sans any sort of required permission is a bit like running a Web service: anything can connect to it
|
Mark M. |
in the case of a Web service, you only have one instance of the Web service, but the whole planet is the source of connections
|
Mark M. |
in the case of an Android service, only the apps on a device can connect, but there are N copies of the service on those N devices
|
Tyler |
well, the service would ultimately talk to a server which would have an "apikey" for verifying valid calls
|
Tyler |
but needs to be able to do "on-device" when the device is offline
|
Jan 23 | 8:10 PM |
Tyler |
and will have some type of limit on number of 'offline' calls
|
Mark M. |
that doesn't really change my concerns with respect to security -- just make sure that you and your development team think about not only good clients, but bad ones as well
|
Tyler |
yeah, that is what I am worried out a bit too, but trying to figure out how to provide the functionality
|
Tyler |
worried about
|
Tyler |
what other type of permission/security could I add?
|
Mark M. |
if the user should get a vote as to whether a client app should be able to work with this service (and the Web service backend), you could use a custom permission
|
Jan 23 | 8:15 PM |
Mark M. |
either to defend the entire service (android:permission in the manifest) or specific calls (checkCallingPermission() in the binder)
|
Jan 23 | 8:15 PM |
Tyler |
so then the client would have to prompt the user for the permission? , would that need a permission dialog like with location/etc in
|
Tyler |
newer versions of android?
|
Mark M. |
if it is a permission with a protectionLevel of dangerous, then AFAIK it should be required
|
Tyler |
I haven't used custom permissions or remember using any apps with them.
|
Mark M. |
it dawns on me that I haven't tried that scenario since runtime permissions were introduced
|
Mark M. |
oh, no, I have
|
Mark M. |
see "Custom Dangerous Permissions, and Android 6.0" in the "Advanced Permissions" chapter for a sample app
|
Mark M. |
but, yes, it is an uncommon approach
|
Jan 23 | 8:20 PM |
Tyler |
hrm.. ok. so pre 6, i assume there would be no permission dialog to the user?
|
Mark M. |
well, pre-5.0, custom permissions are a problem in their own right
|
Mark M. |
what is your minSdkVersion?
|
Tyler |
18
|
Mark M. |
there's a bug prior to Android 5.0 where custom permissions can be bypassed
|
Tyler |
oh yea, i remember reading something about that on your blog
|
Mark M. |
I have some helper code to detect the scenario: https://github.com/commonsguy/cwac-security/#us...
|
Tyler |
thanks.
|
Jan 23 | 8:25 PM |
Tyler |
so as a service, can I see what app is bound to "me"?
|
Mark M. |
in onBind(), yes
|
Tyler |
or is it just for detecting if some other app is also intercepting my permissions?
|
Tyler |
hrm.. ok
|
Mark M. |
if you are referring to the helper code, it is just reporting that somebody else has declared the same custom permission as you
|
Tyler |
yeah.
|
Mark M. |
a Binder has getCallingPid() and getCallingUid() methods to see who called you
|
Mark M. |
that may not work well in your Messenger-centric scenario, as you are not implementing the Binder
|
Tyler |
I had also toyed around with the idea of a ContentResolver to implement instead of a service, would that be more secure?
|
Mark M. |
if you mean ContentProvider, it is more constrained than a service, which has some security benefits
|
Mark M. |
but it's really more a question of what the nature is of the communications from the client to the service (and vice versa, if applicable)
|
Tyler |
yeah, ContentResolver..
|
Mark M. |
if you are publishing something that looks like a database or looks like a stream, a ContentProvider is a likely candidate
|
Jan 23 | 8:30 PM |
Mark M. |
if you are publishing something that looks like a custom API, a bound service is a likely candidate
|
Tyler |
can the content provider run stuff in the background?
|
Mark M. |
well, neither a service nor a ContentProvider runs stuff in the background -- the process does
|
Mark M. |
the service and the ContentProvider are merely IPC APIs
|
Tyler |
right, when binding it runs as the clients's process
|
Tyler |
i didn't realize contentProvider did too, but that makes sense.
|
Mark M. |
but, for example, in the streaming scenario, the provider will fork a thread to emit data on the stream (if the stream isn't just from a simple file)
|
Tyler |
for purposes of not being killed off as a background process
|
Mark M. |
but, that's a wrap for today's chat
|
Mark M. |
the transcript will be posted to https://commonsware.com/office-hours/ shortly
|
Mark M. |
the next chat is tomorrow at 4pm US Eastern
|
Tyler |
yes. sorry for keeping you over.
|
Mark M. |
no problem
|
Tyler |
thank you very much for your help today!
|
Mark M. |
you're welcome!
|
Mark M. |
and, have a pleasant day!
|
Tyler |
you too!
|
Tyler | has left the room |
Mark M. | turned off guest access |