Android JobIntentService ADB Error: Requires permission android.permission.BIND_JOB_SERVICE - android

I'm trying to setup a JobIntentService and test it using adb.
When I use this command:
adb shell am startservice -a "com.example.package.action.DO_THING"
It produces the error:
Error: Requires permission android.permission.BIND_JOB_SERVICE
My AndroidManifest.xml has the following entry:
<service
android:name=".services.intents.IntentHandlerService"
android:permission="android.permission.BIND_JOB_SERVICE"
android:exported="true">
<intent-filter>
<action android:name="com.example.package.action.DO_THING"/>
</intent-filter>
</service>

JobIntentService, like JobService, is only usable from within an app. You cannot have another app talk to those services, nor is there any sort of direct PendingIntent option.
(in theory, you might be able to talk to a JobIntentService from other apps on Android 4.4 and older, as I'm not certain how android:permission="android.permission.BIND_JOB_SERVICE" will be handled when that permission is undefined, but I wouldn't count on it)
For IPC, you will need to use something else. So, for example, if you want a PendingIntent to be processed by a JobIntentService, create a broadcast PendingIntent with an explicit Intent pointing to a manifest-registered receiver, and have it post the job to the JobIntentService.

Related

Disabling BroadcastReceiver for Oreo?

I have a receiver registered in my app's manifest file with action BOOT_COMPLETED.
There is a third-party library in my app and when it receives BOOT_COMPLETED action, it starts a service. Since there is background execution limits in Android Oreo, it crashes.
Now, I want to disable this receiver for only Android O devices. Is there a way to do this? Maybe just like #TargetApi but in Android Manifest?
I forgot to write that I cannot change library class, it's an external jar file.
Since Library's code is not in your control, any approach won't work. You should ask the library provider to comply with latest OS.
You can try following work around:
Register BOOT_COMPLETED in your app with high priority as follows:
<action android:name="android.intent.action.BOOT_COMPLETED" android:priority="999"/>
Start a Foreground Service immediately
This might allow your library to start background service.
Alternatively, If you have access to the BootReceiver class of the library, you can disable it as follows:
PackageManager pm = getPackageManager();
ComponentName compName =
new ComponentName(getApplicationContext(),
<library_broadcastreceiver>.class);
pm.setComponentEnabledSetting(
compName,
PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
PackageManager.DONT_KILL_APP);
It's too late for answer, but maybe it will help someone.
I found different solution, like in accepted answer you can register receiver in your manifest, but instead of priority you can specify tools:node="remove" and this attribute will be removed from the resulting manifest. Also I think it's possible to create separate manifest for Android O.
<receiver android:name="com.package.app.SomeReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" tools:node="remove"/>
</intent-filter>
</receiver>

How to make my service only run in one instance in multiple user android system?

Our android system supports multiple user feature. I'd like to start my server from other apps, like app1, app2 with command startService(intent).
Per google's document at https://source.android.com/devices/tech/admin/multiuser-apps.html.
I need to set android:singleUser="true" to make sure my service only running in one instance in multiple user android system. but when I startservice in other app, I got below exception:
Not allowed to start service Intent { act=com.xx.xxx.action.Start pkg=com.xx.xxx (has extras) } without permission not exported from uid 1000
it seemed android:exported="true" was disabled by android:singleUser="true". if I didn't add android:singleUser="true", it worked fine, but there are more than one instance of my service running in background.
My question is how can I make my service only running in one single instance with startService(intent) from other apps?
My Manifest.xml is configured as below:
<application
android:name=".App"
android:label="#string/app_name"
android:directBootAware="true"
android:multiprocess="false"
android:persistent="true">
<service
android:name=".MyService"
android:singleUser="true"
android:exported="true"
android:permission="com.xx.permission.xx">
<intent-filter>
<action android:name="com.xx.xx.action.xx" />
</intent-filter>
</service>
</Application>
Thanks so much.
Yes, Need to declare app as system app. also use bindServiceAsUser() with System UserHandler.
As the documentation you linked says: "only system apps can currently use this feature". If it's feasible for your product, make your app a system app.
You need the INTERACT_ACROSS_USERS_FULL permission at allow binding to a single instance service from a non primary user. It is a signature only permission so your app needs to be signed with the platform keys.
make android:exported and android:singleUser to true
add permission INTERACT_ACROSS_USERS
make sure you app is privileged. so you should make your app system signature

AnalyticsReceiver - what is that for? And why it causes 'Receiver does not require permission' warning?

In my Android application in manifest file i have following receiver and service declaration:
<receiver
android:name="com.google.android.gms.analytics.AnalyticsReceiver"
android:enabled="true">
<intent-filter>
<action android:name="com.google.android.gms.analytics.ANALYTICS_DISPATCH" />
</intent-filter>
</receiver>
<service
android:name="com.google.android.gms.analytics.AnalyticsService"
android:enabled="true"
android:exported="false" />
To be honest it's quite old app and I don't remember why I've put that there. It was probably taken from Google Analytics docs. But now I can't find any up-to-date information about it.
What is more Android Studio shows me warning with that receiver:
Receiver does not require permission
Exported receivers (receivers
which either set exported=true or contain an intent-filter and do not
specify exported=false) should define a permission that an entity must
have in order to launch the receiver or bind to it. Without this, any
application can use this receiver.
Do I really need that receiver and service in my code? What is this responsible for? Is it still actual?
If you are using the latest version of Google Analytics, no, you do not need to manually specify the service and receiver in your manifest file.
Here is the Google Analytics getting start guide for Android. Note that if you are upgrading from a significantly older version, you may have additional work to perform elsewhere to upgrade. You should read through the entire guide to ensure that your app is still configured properly.

Can I start NotificationListenerService in code explicitly rather than it be started for me by the OS?

I have class derived from NotificationListenerService and it is getting created and started for me automatically when the app starts.
However I would like to lazily start the service later from an activity and not have it start automatically when the app starts. Is it possible to do this?
The manifest is:
<service android:name=".MyNotificationListener"
android:label="#string/app_name"
android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE">
<intent-filter>
<action android:name="android.service.notification.NotificationListenerService" />
</intent-filter>
</service>
NOTE that before NotificationListenerService can be used the user has to grant the app notification access via the setting. However if the intent filter is removed from the manifest then the app does not appear in the settings and thus the user is unable to grant permission, so without permission the service can't be started. Seems like the OS needs that intent filter to be there before it will display the app in the settings.
UPDATE:
The documentation for BIND_NOTIFICATION_LISTENER_SERVICE says:
Must be required by an NotificationListenerService, to ensure that
only the system can bind to it.
So I guess that means only the OS can start NotificationListenerService and nobody else can.
Yes. Create an Intent for the service then call startService.

How to start service using external intent?

I'd like to know if it's possible to start service using intents sent from another app? I've a Broadcast Receiver for android.intent.action.BOOT_COMPLETEDand it works even though at the time when the intent is received BrodcastReceiver class for it is not instancionated. I did something similar for external intents from tasker but it doesn't work.
<receiver android:name="BootReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
I'd like to know if it's possible to start service using intents sent from another app?
Sure.
I've a Broadcast Receiver for android.intent.action.BOOT_COMPLETEDand it works even though at the time when the intent is received BrodcastReceiver class for it is not instancionated.
That is because manifest-registered BroadcastReceiver objects are not instantiated ahead of time. They are only created when a matching broadcast is sent.
I did something similar for external intents from tasker but it doesn't work.
"it doesn't work" is insufficient information for anyone to help you.
But, if you have a <service> with an <intent-filter>, other apps can create an Intent matching your <intent-filter> and use that to start (or bind to) your service. There are two exceptions:
If you add android:exported="false" to the <service>, third party apps cannot invoke it at all, though you would be better served simply getting rid of the <intent-filter> in that case
If you use android:permission on the <service> element, the other app needs to hold your stated permission in order to start or bind to your service

Categories

Resources