Setting Android Wear permissions in App with Android Studio - android

All:
I got one of those Android Privacy Policy notifications for an Android watch face I wrote. I wrote it in Android Studio, and it has the following permissions:
android.permission.ACCESS_NETWORK_STATE
android.permission.GET_ACCOUNTS
android.permission.INTERNET
android.permission.READ_EXTERNAL_STORAGE
android.permission.USE_CREDENTIALS
android.permission.WAKE_LOCK
android.permission.WRITE_EXTERNAL_STORAGE
com.google.android.c2dm.permission.RECEIVE
I really don't need all of those. I really think I only need the WAKE_LOCK and I think one other one. It shouldn't use any sort of writing, accessing networks, or any of that other stuff.
But the odd thing is, I can't find anywhere in my app where these permissions are located. This is my Wear manifest:
<?xml version="1.0" encoding="utf-8"?>
<uses-feature android:name="android.hardware.type.watch" />
<!-- Required to act as a custom watch face. -->
<uses-permission android:name="com.google.android.permission.PROVIDE_BACKGROUND" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:theme="#android:style/Theme.DeviceDefault" >
<service
android:name=".MorseWatchFace"
android:label="#string/my_digital_name"
android:permission="android.permission.BIND_WALLPAPER" >
<meta-data
android:name="android.service.wallpaper"
android:resource="#xml/watch_face" />
<meta-data
android:name="com.google.android.wearable.watchface.preview"
android:resource="#drawable/preview_digital" />
<meta-data
android:name="com.google.android.wearable.watchface.preview_circular"
android:resource="#drawable/preview_digital_circular" />
<intent-filter>
<action android:name="android.service.wallpaper.WallpaperService" />
<category android:name="com.google.android.wearable.watchface.category.WATCH_FACE" />
</intent-filter>
</service>
<meta-data
android:name="com.google.android.gms.version"
android:value="#integer/google_play_services_version" />
</application>
And this is my Mobile manifest:
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="monte.morsewatch">
<application android:allowBackup="true" android:label="#string/app_name"
android:icon="#mipmap/ic_launcher" android:theme="#style/AppTheme">
</application>
I know I'm missing something. The email said I had until January 30th to fix it, but I am unsure what I need to change to fix it.
Any help greatly appreciated.

Based from this documentation, the user must now grant permissions to Wear apps separately from the handset versions of the apps. Previously, when a user installed a Wear app, it automatically inherited the set of permissions that the user had granted to the handset version of the app. To declare that your app needs a permission, you're right in putting a <uses-permission> element in your app manifest, as a child of the top-level <manifest> element.
This SO thread might also help on how to remove unwanted permissions in your app.
The extra permissions are probably being added by some part of Google
Play Services - and which probably doesn't need them for what you're
doing.
Solution #1 is to only use the pieces of Google Play Services that you
actually need. In your Wear module's build.gradle file, you might
have an entry that looks like this:
dependencies {
compile com.google.android.gms:play-service:8.4.0
}
However, that will bring in the entire Play Services library -
which requires a number of extra permissions. It might well be that
all you need is this:
compile com.google.android.gms:play-services-wearable:8.4.0
...or perhaps other specific modules. But the point is, don't include
more than you need.
If you've pared the dependencies back as far as you can, and you're
still getting extra permissions in your merged manifest, then you may
need Solution #2 - which I described in detail in a different answer:
https://stackoverflow.com/a/31017339/252080
Hope this helps!

Related

Google Play - Can't install. Try again, and if it still doesn't work, see common ways to fix the problem

A large number of users are complaining that they receive the following error when trying to install the latest update of my application (see image below). I have been unable to replicate this issue myself. Have logged issue with Google, but they don't seem to know what is causing this either (asking for developer bug reports, but I feel uncomfortable walking users through how to do this). I've seen a few other posts about this topic, but no solutions. Any ideas on what could be the cause?
Things I have considered:
uses-permission - I haven't added any this release
uses-feature - I haven't added any this release
Package name has not been modified in this release
Min/target/compile sdk version - no changes made this release (min 24/target 30/compil 30)
Two changes I did make, but I don't suspect being an issue are:
I did change the android:label field in the application's manifest for <application>
I have added an exception to cleartextpermitted
Example error below:
And manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:sharedUserId="XXX..shared"
package="XXX">
<uses-feature
android:name="android.hardware.camera"
android:required="true" />
<uses-feature
android:name="android.hardware.sensor.compass"
android:required="true" />
<!--<uses-feature
android:glEsVersion="0x00020000"
android:required="true" />-->
<uses-feature
android:glEsVersion="0x00030002"
android:required="true" />
<queries>
<!-- Explicit apps you know in advance about: -->
<package android:name="XXX"/>
<package android:name="XXX2"/>
<package android:name="XXX3"/>
</queries>
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="28"
tools:ignore="ScopedStorage" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"
android:maxSdkVersion="28" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="com.android.vending.BILLING" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application
android:name="XXX"
android:allowBackup="true"
android:fullBackupContent="true"
android:icon="#mipmap/ic_launcher"
android:label="XXX"
android:usesCleartextTraffic="false"
android:theme="#style/AppTheme"
android:networkSecurityConfig="#xml/network_security_config">
<provider
android:authorities="XXX"
android:name="XXX.SharedPreferencesContentProvider"
android:exported="true"
android:protectionLevel="signature">
</provider>
<activity
android:name=".MainActivity"
android:label="XXX"
android:screenOrientation="fullSensor"
android:theme="#style/SplashTheme"
>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
...
</application>
</manifest>
EDIT:
Suspect that the following line in my manifest may be the culprit:
android:sharedUserId="XXX..shared"
Releasing new version, will keep you updated.
Issue was with the following line in the manifest:
android:sharedUserId="XXX..shared"
I added this since the previous release to experiment with my suite of apps communicating with one another, but had forgotten to remove this before my release. This sharedUserId is typically used to group apps that are signed with the same cert/developer so that they can share info with one another. However, the flag has now been deprecated, and if you need your apps to communicate with one another, there are far better ways to do this without breaking your app. Read more about sharedUserID here (but DON'T implement it, whatever you do!):
https://developer.android.com/guide/topics/manifest/manifest-element
App updates will fail for users if the sharedUserId is added or doesn't match the current installed version. Google play will just hang or show a generic error that isn't useful to your users, ending up with confusion and a bunch of 1 star reviews.
Warning: removing the sharedUserId can be just as problematic as adding it. Any users that downloaded the app after you added it (or reinstalled your app during this time) will now get the same error when trying to update to a version where you removed it. The only way for them to fix is to uninstall/reinstall the app again. Lucky for me, I worked out this root cause within a few days, so I only have to manage a few days worth of new users who will experience this issue now, but if this had gone on any longer, you could be looking at a large number of users with the update issue.

How android permission system works internally after reading manifest

How Android tracks permissions granted to application after reading from manifest file? Are application permission tracked based on applicationId/package name/signing key/some other way?
If it stores permissions on some storage then how android will retrieve the permissions array/data to match. What will it use? Something like SHA, Apllication ID or Package name?
Note : Marshmallow 6.0 is the Target Environment
Please take a look at following links -
1) http://trendblog.net/android-app-permissions/
2) https://www.se.jku.at/wp-content/uploads/2012/09/2012.permission-tracking.pdf
If Signature is specified, access is granted if a requesting
application is signed with the same certificate as the application
that declared the permission. The level SignatureOrSystem grants
access to applications that are in the Android system image or that
are signed with the same certificates as those in the system image.
So here Signing Certificate is the key ingredient which helps android system identify permitted applications for a specific Permission.
It may be helpful for you!
The android os will read the Manifest file of the Application.
Applications use a lot of permissions like using internet, accessing your phone book, accessing SD card, etc. Android shows what permissions an application needs before each install of the applications. User knows what permissions the application is using just before the application installation.
And Android knows this by going through the Androidmenifest file named Androidmenifest.xml. This file is contained in root directory of every Android applications. All of the permissions are controlled in there.
Structure of Manifest file:
<uses-permission />
<permission />
<permission-tree />
<permission-group />
<instrumentation />
<uses-sdk />
<uses-configuration />
<uses-feature />
<supports-screens />
<compatible-screens />
<supports-gl-texture />
<application>
<activity>
<intent-filter>
<action />
<category />
<data />
</intent-filter>
<meta-data />
</activity>
<activity-alias>
<intent-filter> . . . </intent-filter>
<meta-data />
</activity-alias>
<service>
<intent-filter> . . . </intent-filter>
<meta-data/>
</service>
<receiver>
<intent-filter> . . . </intent-filter>
<meta-data />
</receiver>
<provider>
<grant-uri-permission />
<meta-data />
<path-permission />
</provider>
<uses-library />
</application>
Each permission is identified by a unique label and the label indicates tha action that is restricted. Some examples of permission defined by Android:
android.permission.INTERNET
android.permission.READ_OWNER_DATA
android.permission.SET_WALLPAPER
android.permission.DEVICE_POWER
If an application needs permissions like the ones mentioned above, it must declare that with a <used-permission> element in the menifest file as shown below.
<uses-permission android:name="android.permission.INTERNET" />
In every android application, there is a file called AndroidManifest.xml which defines app's permission using tag called uses-permission. For example
<uses-permission android:name="android.permission.INTERNET" />
which define permission for Internet usage.

Migrated to Android Studio - now my app requests additional permissions

I just migrated an app from Eclipse to Android Studio. I tried exporting a signed APK and uploaded it to Google Play just to check that everything was working.
That's when I noticed that my app now requests two additional permissions except the ones that I have declared in my manifest! The two permissions are android.permission.WAKE_LOCK and com.google.android.c2dm.permission.RECEIVE.
What's going on here? I haven't changed any code since the last time I uploaded the app, and the manifest doesn't declare these permissions. I'm guessing some Google component is responsible for this, but why did this happen because I migrated to Android Studio? Can I turn off these permissions?
I'm using Google Play Services and Google AdMob, but I've been doing that for a long time without these permissions...
manifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.app"
android:versionCode="70"
android:versionName="7.0" >
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="com.android.vending.CHECK_LICENSE" />
<uses-sdk
android:minSdkVersion="10"
android:targetSdkVersion="23" />
<application android:name="com.example.app.MyApplication"
android:icon="#mipmap/ic_launcher_icon"
android:label="#string/app_name"
android:allowBackup="true"
android:uiOptions="none">
<meta-data android:name="com.google.android.gms.version" android:value="#integer/google_play_services_version" />
<activity android:name="com.example.app.MainActivity"
android:label="#string/app_name"
android:theme="#style/Theme.MyTheme.App"
android:windowSoftInputMode="adjustPan" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name="com.example.app.OtherActivity"
android:label="#string/otherActivityTitle"
android:theme="#style/Theme.MyTheme.App"
android:parentActivityName="com.example.app.MainActivity" >
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="com.example.app.MainActivity" />
</activity>
<activity
android:name="com.example.app.PreferencesActivity"
android:label="#string/prefsTitle" >
</activity>
<activity android:name="com.google.android.gms.ads.AdActivity"
android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize"
android:theme="#android:style/Theme.Translucent" />
</application>
</manifest>
Here's a screenshot of the APK built using Android Studio:
I couldn't change the language to english, but it basically says it's now supporting 22 less devices, requires 2 new permissions and uses OpenGL 2.0+ instead of 1.0+.
Here's a screenshot of the same APK built using Eclipse:
After some more searching I found this thread on Stackoverflow: Android Studio adds unwanted permission after running application on real device.
One of the answers there (not the accepted one) solved my issues. It seems that the Android Studio import process added this dependency to my build.gradle:
compile 'com.google.android.gms:play-services:+'
After changing it to
compile 'com.google.android.gms:play-services-base:8.4.0' // Needed for API Availability test
compile 'com.google.android.gms:play-services-ads:8.4.0'
compile 'com.google.android.gms:play-services-analytics:8.4.0'
the APK no longer requests the unwanted permissions, it targets the same devices as before and uses the same OpenGL version as before - i.e. everything is back the way it was with Eclipse! Except now the file size of the APK is 1 MB smaller as an added bonus!
For people coming here in the future, you might want to investigate what Google Play Services version numbers you should use at Gradle, please and/or Setting up Google Play Services.
Change it to:
android:targetSdkVersion="22"

SMS_SEND permission causes compile error and alert antivirus

Basically, I searched through all the internet and found big, fat zero about that.
My app is using sms sending service and I need SMS_SEND permission. When I add it and run - Eclipse says that I have errors in my code AND antivirus alert that they blocked Android.Trojan.SMS_SEND.NR. I don't care about the latter - because it doesn't show up without SMS_SEND permission.
All I found is in Lint Error Checking:
"Looks for permissions that are only granted to system apps
Permissions with the protection level signature or signatureOrSystem are only granted to system apps. If an app is a regular non-system app, it will never be able to use these permissions."
BUT what matters the most - other app tha use that permission is fine. So what could happened? I need that service to be in that app.
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.mypackage.etc"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk android:minSdkVersion="16" android:targetSdkVersion="19" />
<uses-permission android:name="android.permission.SEND_SMS" />
<application
android:label="#string/app_name"
android:icon="#drawable/ic_launcher"
android:theme="#style/AppTheme">
<activity
android:name=".MainActivity"
android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
Your Android AV Software (F-Secure?) is blocking the code probably based on heuristics or signature. As most if not all Android AV Software is worthless I'd remove that first. Assuming you are not using a rooted device it must simply be picking this up from a manifest scan or some use of the Package Manager.
The "signature or signatureOrSystem" is not applicable to the SEND_SMS permission and whilst you may find a use for using the signature permission cross (identically signed) applications, it is unlikely you are using this.
Please show us your manifest.

How can I add additional Android permissions for my UI test project only?

I try to write files to the external SD card in a from InstrumentationTestCase2 derived test case for pure testing purposes. This works all well when android.permission.WRITE_EXTERNAL_STORAGE is configured in the AndroidManifest.xml file of the application under test, but does not work if this setting is only present in the AndroidManifest.xml file of the test project.
Naturally, I don't want to add this permission to the main manifest, since I only need this capability during my functional tests. How can I achieve that?
In short you should add the same android:sharedUserId for both application's manifest and test project's manifest and declare necessary permission for the test project.
This workaround comes from the fact that Android actually assigns permissions to linux user accounts (uids) but not to application themselves (by default every application gets its own uid so it looks like permissions are set per an application).
Applictions that are signed with the same certificate can however share the same uid. As a consequence they have a common set of permissions. For example, I can have application A that requests WRITE_EXTERNAL_STORAGE permission and application B that requests INTERNET permission. Both A and B are signed by the same certificate (let's say debug one). In AndroidManifest.xml files for A and B android:sharedUserId="test.shared.id" is declared in <manifest> tag. Then both A and B can access network and write to sdcard even though they declare only part of needed permissions because permissions are assigned per uid. Of course, this works only if both A and B are actually installed.
Here is an example of how to set up in case of the test project. The AndroidManifest.xml for application:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.testproject"
android:versionCode="1"
android:versionName="1.0"
android:sharedUserId="com.example.testproject.uid">
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="16" />
<application
android:icon="#drawable/ic_launcher"
android:label="#string/app_name">
<activity
android:name="com.example.testproject.MainActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
And the AndroidManifest.xml for a test project
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.testproject.test"
android:sharedUserId="com.example.testproject.uid"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk android:minSdkVersion="8" />
<instrumentation
android:name="android.test.InstrumentationTestRunner"
android:targetPackage="com.example.testproject" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<application
android:icon="#drawable/ic_launcher"
android:label="#string/app_name" >
<uses-library android:name="android.test.runner" />
</application>
</manifest>
The drawback of this solution is that the application is able to write to external storage too when test package is installed. If it accidentally writes something to a storage it may remain unnoticed until release when the package will be signed with a different key.
Some additional information about shared UIDs can be found at http://developer.android.com/guide/topics/security/permissions.html#userid.
There is another easy answer.
Set the permission in src/debug/AndroidManifest.xml. If the file doesn't exist, create it.
By default, AndroidTest uses debug as BuildType, so if you define your testing permissions there, then the manifest merging process will add these permissions to your UI test build.
Here is the Manifest with new permissions. Note that I didn't include the package attribute because it will be inherited from lower priority level manifest.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
</manifest>
Also, if you want to apply these permissions to a buildType other than debug, then just move your new AndroidManifest.xml to the folder you want, and use this:
android {
...
testBuildType 'release' // or other buildType you might have like 'testUI'
}

Categories

Resources