Android Custom Permission Fails Based on App Insta

2020-02-25 08:10发布

问题:

Having issues with my apps on Google Play. I have a free app which utilizes a custom permission. This permission allows access to paid apps. These paid apps act as "keys" and unlock features in the free app. Basically the free app will attempt to start the intent of one of the paid apps. The paid app will do some stuff and return saying whether the free app should unlock features or not.

Problem arises based on the order of app installation. If the free app is installed first then a paid app, the free app can't start the intent. Returns permission denial. If the paid app is installed first then the free app, the free app can start the intent no problem. Rebooting the device and/or force stopping the apps doesn't resolve the issue. I'm attaching the relavent code. Something tells me I'm doing something incorrectly.

  • Free App Manifest (relevant code):

    ...
    <uses-permission android:name="com.company.license.PERMISSION" />
    ...
    
  • Free App Code to check intent (relevant code):

    Intent KeyApp = new Intent("com.company.license.action.AUTH_1");
    KeyApp.putExtra("com.company.license.challenge", 1);
    
    //If free app is installed first, an exception is thrown for not having the proper permission. If paid app is installed first, no exception is thrown
    try {
        startActivityForResult(KeyApp, COMMING_FROM_KEYAPP);
    } catch (Exception e) {
        cancelStartUp();
    }
    
  • Paid App Manifest (relevant code):

    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.company.installer.1"
    ...
    <permission
        android:name="com.company.license.PERMISSION"
        android:icon="@drawable/icon"
        android:label="@string/app_name"
        android:protectionLevel="normal" >
    </permission>
    
    <application
        android:icon="@drawable/icon"
        android:label="@string/app_name"
        android:theme="@android:style/Theme.NoDisplay" >
    
        <activity
            android:name="com.company.license.auth"
            android:configChanges="keyboardHidden|orientation"
            android:exported="true"
            android:permission="com.company.license.PERMISSION"
            android:theme="@style/Theme.Transparent" >
            <intent-filter>
                <action android:name="com.company.license.action.AUTH_1" />
    
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </activity>
    
        <activity
            android:name="com.company.installer.redirect"
            android:configChanges="keyboardHidden|orientation"
            android:exported="true"
            android:theme="@style/Theme.Transparent" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
    
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
    
    </manifest>
    

回答1:

Put the same <permission> element in both apps. Also, since this is specific to your two apps, I would use android:protectionLevel="signature" instead of normal -- this means the user will never need to approve the permission and nobody else will be able to request the permission. And, this recipe will allow installation in either order.

UPDATE: Note, however, that the use of custom permissions opens up potential vulnerabilities, due to Android's "first one in wins" approach.

UPDATE #2: And this is now no longer supported as of Android 5.0, as two apps cannot both have the same <permission> element unless they are signed by the same signing key.



回答2:

I was able to work around the issue @CommonsWare mentioned in his Update #2. Simply by only declaring the permission in the app which will be installed first.

Explanation: I have app A and app B, signed with different signatures. App A needs to use app B to login, but app A gets installed first and makes sure the user installs app B.

Because app B seems to be the (login)service I declared the custom permission in app B. App B has a (intent)service which other apps may use, as long as they use the permission and are in our whitelist. So app B had the service and permission declared.

But because app A is installed before app B I discovery I needed to add the permission as well to app A. Otherwise app A didn't seem to have the permission after installing app B. My best guess is that this is because the permission stuff is done at installation. And since app A didn't declare the permission, at install nothing happened. But then app B is installed which has the permission but app A still doesn't receive this permission.

But then I tested on Android 5 and ran into their unique permission changes. So I tested some flows and permission declarations and came up with a working solution: Declare the custom permission in the app that gets installed first! Of course this only work when you know which app is going to be installed first. But in my case, where app A is dependant on app B ánd app A installs app B, this was the solution :)