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.
Related
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
Can anyone suggest me how to hide and unhide an app icon? After hiding the icon I would like to launch the app if user called on specific number like 1234. How would I do that?
Well, as noted above, the first part of the question is a duplicate of Android: How to Remove/Uninstall application shortcuts from Home Screen? among others.
As for the second part, you need to use a BroadcastReceiver and that has been answered by Using Broadcast receiver to detect the outgoing calls among others.
Note however, that you need to deploy an intent filter in your manifest, as a BroadcastReceiver is called for all intents.
<receiver android:name=".OutgoingCallReceiver" >
<intent-filter>
<action android:name="android.intent.action.NEW_OUTGOING_CALL" />
</intent-filter>
</receiver>
And add a permission as well:
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
Finally, in Android 6.0 and above, this is a dangerous permission. You'll need to explicitly ask for it before you can use it. So it's a good idea not to remove the app from the home page before you get it.
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>
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.
I have implemented an app that is basically a custom app store for updating and launching a family of related apps. It also needs to update itself, which works, but the app is killed without warning during the install process. I want to automatically restart the app in this case so that the user can continue to use it immediately after an update.
So I made a separate application including only a single Broadcast Receiver that listens for package events for the first app's package name and starts a new activity. That receiver is never called:
<application android:icon="#drawable/ic_launcher"
android:label="#string/app_name">
<receiver android:name=".AppUpdateReceiver">
<intent-filter>
<action android:name="android.intent.action.PACKAGE_REPLACED"/>
<action android:name="android.intent.action.PACKAGE_ADDED"/>
<action android:name="android.intent.action.PACKAGE_INSTALL"/>
<data android:scheme="package" />
</intent-filter>
</receiver>
In searching for similar implementations I have seen directly contradictory information on whether an application with only a receiver will ever execute, and whether a receiver will be called if its app is not already running. I've even come across example code of an application containing only a receiver, with a manifest very similar to my own. So what do I need in this application to ensure that the receiver is called whenever another package is installed?
If there is a better solution, I'd be happy to hear it.
Depending on the version of Android, you might need to start an application component in order for the BroadcastReceiver to be registered. By this I mean there will need to be a launcher Activity which must be started manually by the user.
From Honeycomb (I think) onwards it isn't possible to have application components 'active' unless the app has been manually started in some way. The reasoning behind this is the potential for insecure code executing without the end-users' knowledge.
I suspect this is what you're experiencing. To test it, add a simple "Hello World" Activity to the app that has the BroadcastReceiver in it. Launch the Activity and then check to see if the BroadcastReceiver then gets called after your other package is updated.