I'm setting up campaign tracking using custom analytics (not google analytics) and setting up a receiver for that. My receiver seems to be working, but when I install I get an android lint warning:
ExportedReceiver: Receiver does not require permission
It looks like any old android app could call my application with the com.android.vending.INSTALL_REFERRER intent which I do not want. It should only be the Google Play Store (or any other android system application that would install my app from the play store) sending that intent to my application.
So I've tried to figure out how to set up a permission that limits the valid applications to the play store, but I can't figure out the correct way to set up the permission according to the documentation:
https://developer.android.com/guide/topics/manifest/permission-element.html
Could someone help me setup a permission that limits the applications my application will accept this intent from to the play store? Here's my current receiver config:
<receiver
android:name=".referrals.MyCampaignTrackingReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="com.android.vending.INSTALL_REFERRER"/>
</intent-filter>
</receiver>
I tried setting a permission for the receiver at the normal level but that prevented the app from receiving the intent from the playstore.
You need to set android:permission attribute on your receiver. So that it will look something like this:
<receiver
android:name=".referrals.MyCampaignTrackingReceiver"
android:enabled="true"
android:exported="true"
android:permission="android.permission.CLEAR_APP_CACHE">
<intent-filter>
<action android:name="com.android.vending.INSTALL_REFERRER"/>
</intent-filter>
</receiver>
Usage of "android.permission.CLEAR_APP_CACHE" here is arbitrary, you can use any permission that Play Store has AND is not possible for third-party apps to have (because CLEAR_APP_CACHEs protection level is system|signature only system apps or apps signed with the same certificate as the application that declared this permission; in this case the platform). For example, looking through Play Store's manifest suggests, "com.android.vending.permission.C2D_MESSAGE" could be another good candidate.
Hope this helps.
INSTALL_REFERRER broadcast permission is not a great concern. Assuming you know you need to handle this broadcast only once, right after install, and you take measures to handle it only once, an attacker will have to know when your app has been installed and somehow send this broadcast before the playstore app, which seems unlikely.
3rd party apps can not broadcast this intent. It is blocked. And permission to send is only granted to system apps.
Related
Getting an error on uploading an app to the Google Play store
You uploaded an APK or Android App Bundle which has an activity, activity alias, service or broadcast receiver with intent filter, but without the 'android:exported' property set. This file can't be installed on Android 12 or higher. See: developer.android.com/about/versions/12/behavior-changes-12#exported
All activities, activity alias, services, or broadcast receivers that have intent-filter are marked with android:exported.
The app installs to device and emulator running Android 12 without errors. Also, Android Studio doesn't report any error on merged AndroidManifest file.
Any ideas what could be wrong when there are no errors on the development environment but Google Play store still complains? How this can be resolved?
I think mentioned link in your question answers itself.
In simple words, if your app is responding to system or by other apps and if that is intended then you need set android:exported=true else false. I mean if your app activity gets opened by any other app or your app listens to other apps broadcasts or your app starts any service by other apps then this case is involved.
Doing this will resolve your issue on play store while publishing app. This assessment is done as part of behaviour changes when targeting android 12
https://developer.android.com/about/versions/12/behavior-changes-12#exported
Update : Add below tag in all your activities, services, broadcasts etc.
android:exported="false/true" based on above explanation.
E.g.
<service android:name="com.example.app.backgroundService"
android:exported="false">
<intent-filter>
<action android:name="com.example.app.START_BACKGROUND" />
</intent-filter>
</service>
Dexguard can be the cause of this issue. Add rule -keepresourcexmlattributenames manifest/** to your Dexguard/Proguard file.
The original answer found https://stackoverflow.com/a/70703375/1474153
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 am trying to receive SMS from my android app. I have following receiver specified in my manifest.
<receiver android:exported="true" android:name="com.lahiruchandima.myapp.SMSReceiver">
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
SMSReceiver successfully receives SMS if my app is installed and opened once (app does not need to be running at the moment the SMS is received to the device). But, if i do not open my app at least once after a fresh install, it doesn't receive any SMS.
Does anybody know a way to make it possible to receive SMS without opening the app at least once?
Does anybody know a way to make it possible to receive SMS without opening the app at least once?
It can't be done, on newer Android versions at least. Ever since Android 3.1, apps are installed in a stopped state, and require that the user open it at least once before components like your BroadcastReceiver can function. This is for security reasons, to prevent, or at least hamper, malicious program behavior.
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.