Office Hours — Today, January 23

Saturday, January 20

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!
sorry if there was a slight delay there
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..
I was thinking to use a Messenger to keep it simple and single threaded..
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?
with regards to the never-been-run scenario, all apps are installed in the so-called "stopped state"
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
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
that won't work on Android 5.0+ in general
7:50 PM
Mark M.
and I would expect it to fail for the never-been-run scenario
my chapter on remote services and the binding pattern goes through how to create an explicit Intent for binding
I'm not sure what a reboot would do to affect matters, though
when you call bindService(), are you passing in the BIND_AUTO_CREATE flag?
Tyler
View paste
yes .. something likeIntent intent = new Intent("com.example.tyler.MessengerService");
intent.setComponent(new ComponentName("com.example.tyler.quicksanddemoapp", "com.example.tyler.MessengerService"));
boolean result = bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
Mark M.
OK, that looks fine for both of my concerns
Tyler
View paste
Intent intent = new Intent("com.example.tyler.MessengerService");
intent.setComponent(new ComponentName("com.example.tyler.quicksanddemoapp", "com.example.tyler.MessengerService"));
boolean result = bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
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)
no, sorry, I have that backwards
I have never tried binding from an app to a service in an app that has been force-stopped (or freshly installed)
my guess is that an explicit Intent is sufficient to move the app out of the stopped state
perhaps that's not the case
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:
View paste
<service
    android:name=".MessengerService"
    android:enabled="true"
    android:exported="true"
    android:process=":remote">
    <intent-filter>
        <action android:name="com.example.tyler.MessengerService" />
    </intent-filter>
</service>
yeah, if i launch the app it works.
7:55 PM
Mark M.
from a security standpoint, what you have is scary, but that's a separate issue
and whether you need the android:process attribute depends on the situation
otherwise, that should be fine
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
and you'll need the user to start the activity
it should be more than blank, though -- you need to display a license agreement, support options, etc.
since you have to have that stuff anyway, you may as well leverage it for this get-out-of-the-stopped-state activity
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...
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
it used to be in LogCat
Tyler
ah. ok.
yeah, it won't run, like when i force stop it.
Mark M.
OK, I can't explain that
but, I do not use inter-app communication via services much
so I haven't tried this scenario
Tyler
ok.
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
any app can start or bind to that service
that is kinda wide open from a security standpoint
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
3rd parties
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..
about the only thing i found was https://github.com/open-keychain/openpgp-api
to get some ideas on 'best practices'
Mark M.
using a client-side library that manages the communication with the service can help somewhat
but running a service sans any sort of required permission is a bit like running a Web service: anything can connect to it
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
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
but needs to be able to do "on-device" when the device is offline
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
worried about
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
8:15 PM
Mark M.
either to defend the entire service (android:permission in the manifest) or specific calls (checkCallingPermission() in the binder)
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
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
oh, no, I have
see "Custom Dangerous Permissions, and Android 6.0" in the "Advanced Permissions" chapter for a sample app
but, yes, it is an uncommon approach
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
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.
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?
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
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
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
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
the service and the ContentProvider are merely IPC APIs
Tyler
right, when binding it runs as the clients's process
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
the transcript will be posted to https://commonsware.com/office-hours/ shortly
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!
and, have a pleasant day!
Tyler
you too!
Tyler
has left the room
Mark M.
turned off guest access

Saturday, January 20

 

Office Hours

People in this transcript

  • Mark Murphy
  • Tyler