Search code examples
javaandroidandroid-intentsecurityexceptionandroid-productflavors

Error: java.lang.SecurityException: Permission Denial: starting Intent with another flavor


I'm working on an application that has 2 flavors, free and pro. The free seems to work fine but when i try to go from the preference activity Settings to the activity names It appears this error:

-12 00:41:49.473  18533-18533/com.albertoha94.apps.DuelHelperReloaded.Pro E/AndroidRuntime? FATAL EXCEPTION: main
Process: com.albertoha94.apps.DuelHelperReloaded.Pro, PID: 18533
java.lang.SecurityException: Permission Denial: starting Intent { act=android.intent.action.VIEW cmp=com.albertoha94.apps.DuelHelperReloaded/.NameList } from ProcessRecord{9f48ed8 18533:com.albertoha94.apps.DuelHelperReloaded.Pro/u0a59} (pid=18533, uid=10059) not exported from uid 10060
        at android.os.Parcel.readException(Parcel.java:1599)
        at android.os.Parcel.readException(Parcel.java:1552)
        at android.app.ActivityManagerProxy.startActivity(ActivityManagerNative.java:2611)
        at android.app.Instrumentation.execStartActivity(Instrumentation.java:1502)
        at android.app.Activity.startActivityForResult(Activity.java:3825)
        at android.app.Activity.startActivityForResult(Activity.java:3785)
        at android.app.Activity.startActivity(Activity.java:4100)
        at android.app.Activity.startActivity(Activity.java:4068)
        at android.preference.Preference.performClick(Preference.java:1012)
        at android.preference.PreferenceScreen.onItemClick(PreferenceScreen.java:214)
        at android.widget.AdapterView.performItemClick(AdapterView.java:309)
        at android.widget.AbsListView.performItemClick(AbsListView.java:1156)
        at android.widget.AbsListView$PerformClick.run(AbsListView.java:3071)
        at android.widget.AbsListView$3.run(AbsListView.java:3899)
        at android.os.Handler.handleCallback(Handler.java:739)
        at android.os.Handler.dispatchMessage(Handler.java:95)
        at android.os.Looper.loop(Looper.java:148)
        at android.app.ActivityThread.main(ActivityThread.java:5401)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:725)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:615)

The structure of my module is something like this:

src
  -debug
      -java->package->Namelist
  -main
      -java->package->SettingsDuel
                      NameListStructure(A class that extends arrayAdapter, i use it to show the list in a format i want)
  -pro
      -layout->mainscreen(used in Dhmain)
  -prodebug
      -java->...DHMain
  -prorelease
      -java->...DHMain
  -release
      -java->...NameList

Didn't show the free version structure as i dont think its necessary, its working fine.

NameList is in both debug in release, they both have minor changes and i created that directory so i dont need to have a copy in the free/pro directories.

DHMain changes depending if its free/pro and debug/release.

SettingsDuel is in main only and it never changes.

I access the activity NameList through SettingsDuel this way:

<Preference
        android:enabled="true"
        android:title="@string/Names">
        <intent
            android:action="android.intent.action.VIEW"
            android:targetPackage="com.albertoha94.apps.DuelHelperReloaded"
            android:targetClass="com.albertoha94.apps.DuelHelperReloaded.NameList"/>
    </Preference>

This is in an xml file in the main directory, it never changes. Also its the only way to access the NameList activity.

And finally, the appid changes according to the app flavor (i think this could be causing the problem because the free version doesnt change its id and it works fine):

free:

applicationId 'com.albertoha94.apps.DuelHelperReloaded'

pro:

applicationId 'com.albertoha94.apps.DuelHelperReloaded.Pro'

I've tried the following:

-Add android:exported="true" in class SettingsDuel.

-Add android:exported="true" in class NameList.

-Add android:exported="true" in class Both classes.

-Add the class NameList to the pro packages (prodebug and proRelease)

-Cleaning the project.

-Rebuild project.

At this point i dont know what else to try.

EDIT:

After doing what Minhtdh told in his answer it sort of worked. The activity NameList works ONLY if i have the free version installed to.

If i try to access activity NameList with the pro version only it shows this error:

    android.content.ActivityNotFoundException: Unable to find explicit activity class {com.albertoha94.apps.DuelHelperReloaded/com.albertoha94.apps.DuelHelperReloaded.NameList}; have you declared this activity in your AndroidManifest.xml?
        at android.app.Instrumentation.checkStartActivityResult(Instrumentation.java:1782)
        at android.app.Instrumentation.execStartActivity(Instrumentation.java:1507)
        at android.app.Activity.startActivityForResult(Activity.java:3825)
        at android.app.Activity.startActivityForResult(Activity.java:3785)
        at android.app.Activity.startActivity(Activity.java:4100)
        at android.app.Activity.startActivity(Activity.java:4068)
        at android.preference.Preference.performClick(Preference.java:1012)
        at android.preference.PreferenceScreen.onItemClick(PreferenceScreen.java:214)
        at android.widget.AdapterView.performItemClick(AdapterView.java:309)
        at android.widget.AbsListView.performItemClick(AbsListView.java:1156)
        at android.widget.AbsListView$PerformClick.run(AbsListView.java:3071)
        at android.widget.AbsListView$3.run(AbsListView.java:3899)
        at android.os.Handler.handleCallback(Handler.java:739)
        at android.os.Handler.dispatchMessage(Handler.java:95)
        at android.os.Looper.loop(Looper.java:148)
        at android.app.ActivityThread.main(ActivityThread.java:5401)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:725)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:615)

It says it cant find the activity NameList even if though i have it in the manifest (the manifest is in the main directory):

        <activity
        android:name=".NameList"
        android:label="@string/Names"
        android:exported="true">
        <meta-data
            android:name="android.support.PARENT_ACTIVITY"
            android:value="com.albertoha94.apps.DuelHelperReloaded.SettingsDuel" />
    </activity>

Solution

  • I think your problem is: your pro version is trying to start an service in free version.
    And from your description, I guess you only rebuild the pro version, right?
    If that true, you should try this:

    • Add android:exported="true" in class NameList.
    • Then rebuild and install free version.
    • Then run and test with the pro version.

    Hope this works.
    Update
    Your free version app id is com.albertoha94.apps.DuelHelperReloaded
    and pro version is com.albertoha94.apps.DuelHelperReloaded.Pro
    Because of the intent in SettingsDuel preference:

    <intent
            android:action="android.intent.action.VIEW"
            android:targetPackage="com.albertoha94.apps.DuelHelperReloaded"
            android:targetClass="com.albertoha94.apps.DuelHelperReloaded.NameList"/>
    

    That intent will try to open activity from the free app (class name and action are same in both apps, but the targetPackage retrict intent to open free version only)
    -> So when open from pro app, you will have permission error (due different process) or activitynotfound if don't install free app.

    If you want to open the activity from pro version, just use different targetPackage for each app.(for pro version use android:targetPackage="com.albertoha94.apps.DuelHelperReloaded.Pro")