Fellow Developers!
I have a sync adapter in my app and a corresponding sync service. I have declared everything, including the sync service, according to Google example code. The greater picture looks something like this:
<service
android:name="com.myapp.SyncService"
android:exported="true"
android:process=":sync">
<intent-filter>
<action
android:name="android.content.SyncAdapter"/>
</intent-filter>
<meta-data
android:name="android.content.SyncAdapter"
android:resource="#xml/syncadapter" />
</service>
While it makes sense to set the android:exported attribute to true on the service (enabling the Android system to reach it), I'm a bit puzzled on how to tie it down in terms of access rights. I don't want anyone else but my app and the Android system to have access to the service.
Maybe a bit naively I have created my own permission for this:
<permission
android:name="com.myapp.permission.SYNC_ADAPTER"
android:protectionLevel="signatureOrSystem" />
But reading up a bit on the protectionLevel makes me wonder even more. Google says:
Please avoid using this option [...] "signatureOrSystem" permission is used for certain special situations where multiple vendors have applications built into a system image and need to share specific features explicitly because they are being built together.
The described scenario is far from my use case. The question then remains:
How do I secure my sync service so that the Android system, but no third party apps, can access it?
Any clarification would be greatly appreciated!
beworker is quite right. I have used signature permission and the system is able to sync without any trouble.
It doesn't look like there is a SyncAdapter permission. I'm guessing that we can safely ignore the error. See the bug filed here: https://code.google.com/p/android/issues/detail?id=37280
I have the same problem. Looking at this example source code here as a guide https://android.googlesource.com/platform/packages/apps/Exchange/+/ics-mr0/AndroidManifest.xml it seems to be that the sync adapters have plainly exported="true" without any permissions.
The 'signature' protection level should be sufficient for your use case, which grants access to the system package. 'signatureOrSystem' also grants access to apps built into the system image.
Source code: see grantSignaturePermission() method
https://android.googlesource.com/platform/frameworks/base/+/a029ea1/services/java/com/android/server/pm/PackageManagerService.java
You can safely set exported=false for both services
one service registering to the SyncAdapter
one service registering to the AccountAuthenticator intents
The system can still call the SyncAdapter Service via intents.
The reason why this works is mentioned in the official exported guide
If false, the activity can be launched ... [by] privileged system components.
I.e. you don't need to struggle with exported=true.
tested on Android 10 (Emulator with targetVersion: 30)
tested on Android 13 (with targetVersion: 31)
Old answer
The following is (for me) irrelevant as the above works.
I interpreted the replies in this thread this way:
Requesting this permission (see example) in an exported service (see below) should only allow apps signed with your signature - and the system - to call this service.
If you use exported=false then the system cannot call your service, i.e. Synchronization won't start if your app is closed(?)
<permission
android:name="com.myapp.USE_SYNC_AND_AUTHENTICATOR"
android:protectionLevel="signature" />
<application>
<!-- Export sync and auth to allow the Android System to call them. -->
<!-- Protect it using a signature permission. -->
<service
android:name="com.myapp.SyncService"
android:exported="true"
android:process=":sync"
android:permission="com.myapp.USE_SYNC_AND_AUTHENTICATOR">
<intent-filter>
<action android:name="android.content.SyncAdapter" />
</intent-filter>
<meta-data
android:name="android.content.SyncAdapter"
android:resource="#xml/sync_adapter" />
</service>
<service>..authenticator..</service>
</application>
Related
I am making an AccessibilityService to get package name of app where click events are registered. In my manifest do I need to ask for permission for
<uses-permission android:name="android.permission.BIND_ACCESSIBILITY_SERVICE" />
or inside the service tag, like this :
<service
android:name=".ListenToEvents"
android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">
<intent-filter>
<action android:name="android.accessibilityservice.AccessibilityService" />
</intent-filter>
<meta-data
android:name="android.accessibilityservice"
android:resource="#xml/accessibility_service_config" />
</service>
I am guessing I don't need both but if I ask for permission outside the services tag in uses permission the ide tells me this permission will make my app a system app. when the permission is inside the service tag, however, it doesn't raise any such warning.
I do enable the settings for the app after installing. The callback on events is not being called.
first of all I would like to know if my app is a system app which needs to be installed in the system partition of the android phone. any further help will be greatly appreciated. I have already looked at two projects on GitHub but they are too big to sort out the pertinent code. so please help with the code necessary to do the basic task, of lets say listening to a tap event.
thanks
When you are building your own Accessibility Service, when you execute the app, the service will become present in Settings->Accessibility under 'Services' section. You can then turn on your service and run it on any app you want. Regarding developing an accessibility service, refer to the following,
https://codelabs.developers.google.com/codelabs/developing-android-a11y-service/#2
https://developer.android.com/guide/topics/ui/accessibility/service
For listening to clicks, I suggest going through 'Configuring the scroll button' section of Codelabs and using ACTION_CLICK instead of ACTION_SCROLL_FORWARD
To clarify about BIND_ACCESSIBILITY_SERVICE. You expose that permission in the service to guarantee that only the system can bind to your service. Only the system may use that permission.
https://developer.android.com/reference/android/app/job/JobService.html
I am implementing an Android JobService, but I am confused whether it needs the "android:exported=true" attribute in the manifest or not.
There's little information on this in the Google documentation.
Some resources on the web, such as the answer here says it needs it.
how to call service in background, when application is close, that time continues work service and call api ?
No, it does not.
This sample app is one of several that I have that demonstrate the use of JobScheduler. There is no android:exported="true" or any <intent-filter> elements on the <service> elements:
<service
android:name=".DemoJobService"
android:permission="android.permission.BIND_JOB_SERVICE" />
You do need that android:permission attribute, though.
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
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.
I'm working with Mark Murphy's excellent Commonsware books - but it's a lot to digest. I built the 'FakePlayer' app (pretends to be an mp3 player). It contains a service. As a learning experience I tried to write a trivial app (has only a button) whose click handler does:
Intent i = new Intent();
i.setAction("com.example.cwfakeplayer.MyPlayerService");
Context context = getApplicationContext();
context.startService(i);
It worked fine - the service start ok. I noticed Eclipse complaining about no permission on the service, so I updated the service's manifest by adding 2 lines, android:permissions and android:exported:
<service
android:name="MyPlayerService"
android:permission="com.example.fakeplayer.permission.MY_PLAYER_PERMISSION"
android:exported="true"
<intent-filter>
<action android:name="com.example.fakeplayer.MyPlayerService"></action>
</intent-filter>
</service>
I reloaded the player app onto the device (I'm using a Galaxy S2) using 'debug' under eclipse. It seemed to work; the starter app caused a permission exception, which I expected.
I then added to the starter app's manifest (to give it the permission):
<manifest
...
<uses-sdk ....
....
<uses-permission android:name="com.example.fakeplayer.permission.MY_PLAYER_PERMISSION" />
I reloaded the starter app onto the device (using debug under Eclipse). Still get the permission error in the starter app.
I removed both apps from the device and reinstalled (using debug...), service app first, then starter. Still get perm error.
I am working my way through the 'how to use a remote service' section of Mr. Murphy's Advanced Android book, so I realized this is not the best way perhaps to work across apps.
I did a 'adb shell dumpsys package', located the starter app, and found it had 'permissionsFixed=false' and no 'grantedPermissions' section. I take this to mean the manifest change in the starter app did not manage to get the perm added to the app. But I have no idea why. As a learning experience, it's generated only confusion so far....
Any clues greatly appreciated! Thanks!
I updated the service's manifest by adding 2 lines, android:permissions and android:exported
Technically, android:exported="true" is superfluous, as having the <intent-filter> automatically makes the <service> be exported.
I removed both apps from the device and reinstalled (using debug...), service app first, then starter. Still get perm error.
You do not show where you ever declare the custom permission with the <permission> element. In practice, if you control both apps, put the same <permission> element in both manifests, so the order of installation of your two apps no longer matters.
Try replace this in your manifest
<service android:name="com.example.fakeplayer.MyPlayerService"></service>
instead of
<service
android:name="MyPlayerService"
android:permission="com.example.fakeplayer.permission.MY_PLAYER_PERMISSION"
android:exported="true"
<intent-filter>
<action android:name="com.example.fakeplayer.MyPlayerService"></action>
</intent-filter>
</service>
If this doesn't work, kindly post out your error.