Android JobIntentService permission error - android

I have created a JobIntentSerivce and in the manifest file for the MyService class I didn't specify the BIND_JOB_SERVICE permission. So while I enqueue work for this service it is throwing run time error "MyService does not require android.permission.BIND_JOB_SERVICE permission". If I give the permission to MyService in android manifest it will fix the issue. But my doubt is why the error showing "does not require permission", is it a typo or any logical reason behind it?

JobIntentService must be protected by BIND_JOB_SERVICE permission, but while adding permission in the manifest, setting android:exported to true will resolve this somewhat confusing error e.g
<service android:name="com.example.jobscheduler.MyService"
android:permission="android.permission.BIND_JOB_SERVICE"
android:exported="true"/>

Looking at the source the comments on the method: enforceValidJobRequest(int uid, JobInfo job) in JobSchedulerStub does go some way to explain what it is checking :
JobSchedulerService.JobSchedulerStub :
// Enforce that only the app itself (or shared uid participant) can schedule a
// job that runs one of the app's services, as well as verifying that the
// named service properly requires the BIND_JOB_SERVICE permission
private void enforceValidJobRequest(int uid, JobInfo job) { .. }
Inside this method it definitely checks that the Service in JobInfo (jobinfo.getService()) has the permission BIND_JOB_SERVICE - if not throws the error, to me a somewhat misleading message. It Also checks that only the system or app uid can enqueue work, this is obviously for security reasons.

Related

Job Scheduler cant find job/service?

My app needs to do something periodically so I'm trying the Job Scheduler introduced in Android API 21. At this moment I'm just gettingto know it and try the basics. Unfortunately I get an error:
Java.lang.illegalArgumentException: No such service ComponentInfo{The whole path here to the service class name TestJobService}
I understand this has been solved for some by adding permission to Manifest, but not me. What else can cause this?
This is my code part where I guess it goes wrong:
Toast.makeText(getApplicationContext(), "Exec reaches here...",Toast.LENGTH_SHORT).show();
JobInfo.Builder builder = new JobInfo.Builder(1, new ComponentName(getPackageName(),TestJobService.class.getName()));
//runs job service after every 10 seconds
builder.setPeriodic(10000);
jobScheduler.schedule(builder.build());
I have this in my Manifest:
<service
android:name=".TestJobService"
android:permission="android.permission.BIND_JOB_SERVICE"
android:exported="true" >
</service>
One thing that confuses me is that I cant manually give job-permission to the app manually in the device settings (I do that to get permission to storage). If the app needs permission for schedualing jobs, shouldn't I have to give permission in the settings?
I really hope someone has the solution for this.
Thanks.
Make sure you put your service element inside application element and nowhere else. When I did it worked fine.
add <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> to the user permissions in the manifest. it did it for me.

App permissions for services

When an application calls a service through an intent, will the permissions that the app has, hold for the service as well? Do I need to explicitly check if permissions are granted and request permissions separately in the service again? I'm using the Permiso library to handle runtime permissions for me/
You should always Check the permissions before you used it.
if the permission given, Just go forward.
Otherwise, Stop the service (or) Intimate the requirement of permission to the App User.

Unable to start service in Android 6.0

I'm trying to run a service by using following code:
Intent i = new Intent(getApplicationContext(),MyService.class);
startService(i);
This code works fine on versions older than Android 6.0 Marshmallow. But here on Android 6.0, the service never gets created. startService() is returning null. I'm calling it from an Activity in the same package. My manifest is like:
<service
android:name="com.example.app2.MyService"
android:label="#string/app_name">
</service>
Also my application is not crashing, it's just the service is not starting (not created).
Once I was having the same problem. It was a very small and stupid mistake. I had given <service> tag outside <application> tag in manifest.xml. After moving it inside <application> tag service started successfully. Check for any typos in service name also. Hope it helps!
If you are accessing any device hardware features(Camera, Storage, Location etc) in the Service. You need to ask runtime permission in the Marshmallow devices. Otherwise, it will make a crash if your compile SDK version >=23. Please paste your Crash log or Service code for further clarification.
Please check the link to implement the feature:
https://developer.android.com/training/permissions/index.html
https://developer.android.com/training/permissions/requesting.html

How to request permissions from a Service in Android Marshmallow

In Android Marshmallow, permissions should be requested at runtime when they are needed, instead of all at once when an app is installed. However, I can only seem to request permissions from an Activity, which is a problem since my app contains only Services. (Why is that, you might ask? The app has an Android Wear watch face bundled inside, and all the phone does is look up photos nearby to send to the watch - no Activity needed. But it does require location permissions.)
So, is there any way to request permissions from a Service? Or somehow force the permissions to be granted at install time as in the past?
requestPermission() can only be called from an Activity and not a Service (unlike checkPermission() that only requires PackageManager). So you need to do some extra work to get around that; you do need to provide an Activity in your app and, for example, your Service can check for permissions it needs and if they have not been granted yet, it can create a notification and that can inform user with a descriptive short message as to why there is a notification and what needs to happen when they click on the notification, etc.
I agree, this is very troublesome for services, I think you should report an issue on Android Developer Preview page for this.
At the moment, I think the best solution is to check for permission on service, and show notification if the permission is missing. Even better, create an DialogActivity to request for permission when users press on the notification.
Have a look at PermissionEverywhere library. It allows you to request permission from any context.
It creates a notification clicking on which it opens up an activity asking for permission.
Sample code from library's github page:-
#Override
protected Boolean doInBackground(Void... params) {
PermissionResponse response = PermissionEverywhere.getPermission(getApplicationContext(),
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
REQ_CODE,
"Notification title",
"This app needs a write permission",
R.mipmap.ic_launcher)
.call();
//waits..
boolean isGranted = response.isGranted();
if(isGranted){ //changed from isGrante to isGranted
// Do stuff
}
}
There is a very simple library that allows doing exactly this. You can check for permissions from anywhere (even from a service), based on whether the app is in foreground or background, it either shows normal dialog or generates a notification asking for permissions. The code is really easy to understand and it's really easy to use too.
Do give it a try: Android Permissions
You can use ResultReceiver to create a receiver of the users answer, then pass it as callback to the Activity, through notification's PendingIntent.
Reference

Permissions for a WearableListenerService

I've implemented a WearableListenerService in both my main app and the companion Wear app. In the manifests, the service needs to be declared as android:exported="true" (or not declared at all and left to default to true) since it's started by Google Play Services. An exported service with no permissions can be called by any app on the system, but I can't find the correct permission to add to the service declaration to secure it. I've looked through the permissions on both the phone and the Wear device with pm list permissions but I don't see anything that looks like what I need.
Is there a permission that I can/should add to secure my services?
If not, is it a good idea to manually secure the service by checking the package name of the caller?
The best way to see how to implement a WearableListenerService on Android Wear is to look at one of the existing samples provided by the SDK. If you look at the DataLayer sample included at $SDK/samples/android-20/wearable/DataLayer it has a full implementation of what you are wanting to do.
If you look in the AndroidManifest.xml for the wearable side, you can see it has the following:
<meta-data
android:name="com.google.android.gms.version"
android:value="#integer/google_play_services_version" />
<service
android:name=".DataLayerListenerService" >
<intent-filter>
<action android:name="com.google.android.gms.wearable.BIND_LISTENER" />
</intent-filter>
</service>
For your security concerns ... When we declare a service in manifest and add a filter to it, it automatically becomes an exported service. So in general, other apps can bind to that service. In case of WearableListenerService, there is a security check that happens in the framework to make sure that the agent binding to that is Google Play Services so no one else can really bind to that service, unless the app developer exposes other intent filters in which case the intention is for others to access it.
So if you implement your code in the same way as the Wear SDK samples, your app should be secure and you do not need to worry about any extra permissions, etc.
Is there a permission that I can/should add to secure my services?
If not, is it a good idea to manually secure the service by checking the package name of the caller?
You don't need to worry about securing your WearableListenerService implementation with permissions or caller package checks. As #Wayne pointed in his answer: there is a security check that happens in the framework. This check is done in the WearableListenerService base class. You can find further security analysis of the Wearable SDK in the following article:
https://labs.mwrinfosecurity.com/blog/android-wear-security-analysis. Here is the quote from it:
The method pr() first checks if com.google.android.gms is Google
signed and then calls cU() to check if the calling process UID is for
the package com.google.android.gms (the Google Play Service package).
If the class is further decompiled, it can be seen that this security
check happens in each method exposed in WearableListenerService.
Unfortunately currently Lint checker produces false positive warning for the wearable listener service declaration whenever it doesn't contain BIND_LISTENER filter (which inclusion produces other warning since it's now deprecated and should be avoided):
Exported services should define a permission that an entity must have in order to launch the service or bind to it. Without this, any application can use this service.
This is certainly a bug in the security detector code (it just wasn't updated when BIND_LISTENER intent became deprecated). I've opened an issue regarding this on the Android bug tracker. Meanwhile to get rid of the warning one needs to add tools:ignore="ExportedService" to its wearable listener service declaration.

Categories

Resources