14

I am need to publish a Cordova application on Google Play targeting Android 12. When I uploaded my APK file, I get error

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

I did some reaserch on internet and I found, that this configuration should be add to config.xml:

    <edit-config file="app/src/main/AndroidManifest.xml" mode="merge" target="/manifest/application/activity">
        <activity android:exported="true"/>
    </edit-config>  

It works fine for some of my applications, but one of them still shows the error, when uploaded to Google Play. Its AndroidManifest.xml looks like this:

<?xml version='1.0' encoding='utf-8'?>
  <manifest android:hardwareAccelerated="true" android:versionCode="750" android:versionName="7.5.0" package="cz.foxtrot.motoquest" xmlns:android="http://schemas.android.com/apk/res/android">
   <supports-screens android:anyDensity="true" android:largeScreens="true" android:normalScreens="true" android:resizeable="true" android:smallScreens="true" android:xlargeScreens="true" />
   <uses-permission android:name="android.permission.INTERNET" />
   <application android:hardwareAccelerated="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:supportsRtl="true" android:usesCleartextTraffic="true">
       <activity android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|smallestScreenSize|screenLayout|uiMode" android:exported="true" android:label="@string/activity_name" android:launchMode="singleTask" android:name="MainActivity" android:theme="@android:style/Theme.DeviceDefault.NoActionBar" android:windowSoftInputMode="adjustResize">
           <intent-filter android:label="@string/launcher_name">
               <action android:name="android.intent.action.MAIN" />
               <category android:name="android.intent.category.LAUNCHER" />
           </intent-filter>
       </activity>
       <receiver android:enabled="true" android:name="nl.xservices.plugins.ShareChooserPendingIntent">
           <intent-filter>
               <action android:name="android.intent.action.SEND" />
           </intent-filter>
       </receiver>
       <provider android:authorities="${applicationId}.sharing.provider" android:exported="true" android:grantUriPermissions="true" android:name="nl.xservices.plugins.FileProvider">
           <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/sharing_paths" />
       </provider>
       <meta-data android:name="com.transistorsoft.locationmanager.license_key" android:value="b2c8e0bf1863da91b0f941ddf8278f699d320a320182cf7eb1d1e5c660ee17be" />
   </application>
   <uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
   <uses-permission android:name="com.android.vending.BILLING" />
   <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
   <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
</manifest>

Any ideas, what can be wrong?

user3523426
  • 836
  • 3
  • 11
  • 26

7 Answers7

11

Following up to the answer from Carl Smith. You might need to set the exported on more tags. The edit-config tag does as the name says, it edits the XML configuration file after it has been generated. In this case it will add the android:exported tag.

Try adding this to your config.xml file inside the tag:

    <edit-config file="app/src/main/AndroidManifest.xml" target="/manifest/application/activity" mode="merge">
        <activity android:exported="true"/>
    </edit-config>  

    <edit-config file="app/src/main/AndroidManifest.xml" target="/manifest/application/service" mode="merge">
        <service android:exported="true" />
    </edit-config>

    <edit-config file="app/src/main/AndroidManifest.xml" target="/manifest/application/provider" mode="merge">
        <provider android:exported="true" />
    </edit-config>

    <edit-config file="app/src/main/AndroidManifest.xml" target="/manifest/application/receiver" mode="merge">
        <receiver android:exported="true" />
    </edit-config>

It will not only set the flag for the activity and service tags but also for the provider and the receiver.

Notice that this will set the exported flag to true. The best solution is to wait until all maintainers of your plugins have updated the plugin but until then at least you can submit your working apps to the Play Store and confirm to the required use of API 31+.

Please notice that you might not need all these 4 edits for your config. This depends on the plugins you use and how well they are updated. Start with one (from top to bottom) if it doesn't work add more and if it works try to remove the others to find out what the minimum is you need. Don't change more then needed.

pizzamonster
  • 1,141
  • 10
  • 9
5

With the above solutions I get a build error

Unable to graft xml at selector "/manifest/application/service"

My solution after hours of research is quite easy: In AndroidManifest.xml (in platforms/android/app/src/main) I extended the activity tag:

<activity android:configChanges="...." android:exported="true" ....> ...

Now build works fine and I can send the app-release.aab to Google without error.

rob barca
  • 51
  • 1
  • 1
4

try adding this to your cordova config.xml under <platform name="android">:

<edit-config file="app/src/main/AndroidManifest.xml" target="/manifest/application/activity" mode="merge">
  <activity android:exported="true" />
</edit-config>
<edit-config file="app/src/main/AndroidManifest.xml" target="/manifest/application/service" mode="merge">
  <service android:exported="true" />
</edit-config>  
carl smith
  • 65
  • 1
  • 3
  • As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community May 13 '22 at 06:48
  • 14
    I get this error after adding this to config.xml `Unable to graft xml at selector "/manifest/application/service" ` – A.W. Jun 25 '22 at 08:59
  • 2
    @August, don't do it in the config file. In your plugin folder, find plugin.xml file, and add your service within it, with all parameters you need, just like this. – Alexander Gapanowich Jun 29 '22 at 10:21
  • 2
    @AlexanderGapanowich How do you do that it within a Cordova/Ionic Appflow environment? (no access to plugin folder, as it is generated during compiling). I also have the same result as August when adding the answer in the platform tags. – Michael Jul 01 '22 at 21:01
  • @Michael, in my case I just go to the plugin folder with file manager, like this - project_root_folder -> cordova -> plugins -> cordova-plugin-my-plugin-name -> plugin.xml It's not a generated file, it's used for plugin adjustments and can't be the generated one. – Alexander Gapanowich Jul 03 '22 at 12:29
  • 1
    This doesn't actually fix the error – d512 Oct 07 '22 at 21:26
  • @Michael as I have discovered by now, only this is enough: If you get the "Unable to graft xml..." error, the issue is in the socialsharing plugin. I have removed that one and it worked. – DusanV Aug 27 '23 at 11:38
3

I have added the following code in config.xml

<edit-config file="app/src/main/AndroidManifest.xml" mode="merge" target="/manifest/application/activity" xmlns:android="http://schemas.android.com/apk/res/android">
            <activity android:exported="true" />
 </edit-config>

I tried adding <edit-config> for service, provider & receiver but, that was throwing the following error

Unable to graft xml at selector "/manifest/application/receiver"

When I added only for activity, it started working. Also dont forget to include xmlns:android="http://schemas.android.com/apk/res/android" in the <edit-config> for activity

Bimzee
  • 1,138
  • 12
  • 15
2

In my case, I tried to add the changes in config.xml that is in this comment https://stackoverflow.com/a/74278418/7078094, but it didn't work.

The app compiled with out errores, but when I tried to install in a phone with Android 12, it didn't work.

My solution, (in a app that is make with Ionic 3 and Cordova) was:

(If you have some / , remove it)

  1. ionic cordova platform rm android
  2. ionic cordova platform add android
  3. Then, modifiy manually the file app/src/main/AndroidManifest.xml:

In this file, you should have something like this:

<manifest ... />
<supports-screens ... />
<uses-permission ... />
<application ... />
    <activity ... />
        <intent-filter ... />
            <action ... />
            <category ... />
        </intent-filter>
    </activity>
    <provider ... android:exported="false" />
        <meta-data ... />
    </provider>
</application>
<uses-sdk ... />
<uses-permission ... />

Inside from <application ... />, in my case I have , activity and provider. (but I believe that you could also have a service and receiver here )

already have the tag android:exported="false" , so I did not modify it

But , It didn't have none. So, I added android:exported="true"

(If you have someone (provider, activity, service, receiver) that doesn't have this tag, added it like I did with activity )

<manifest ... />
<supports-screens ... />
<uses-permission ... />
<application ... />
    <activity ... android:exported="true"  />
        <intent-filter ... />
            <action ... />
            <category ... />
        </intent-filter>
    </activity>
    <provider ... android:exported="false" />
        <meta-data ... />
    </provider>
</application>
<uses-sdk ... />
<uses-permission ... />

I couldn't automate this change from config.xml, nothing worked. I know it's not the best solution, because it's something you have to do manually after creating the platform, but it works

  1. Then, I built the app with ionic cordova build android --release
  2. Sign the app. (*)

And this work for me.

I could run a app made in Ionic 3 in Android 12,8 y 6

IMPORTANT

To sign the app is necessary do it something like this (maybe can be different , depends the app and sign):

You should have installed SDK 31 and ( Probably at a later date, I will increase the version required.)

Open a console in platforms/android/app/build/outputs/apk/release

zipalign -v 4 app-release-unsigned.apk myapp.apk

apksigner sign --ks my-ks.keystore --ks-pass file:my-passfile.txt --v1-signing-enabled true --v2-signing-enabled true myapp.apk

If when you try execute zipalign or apksigner, and not exist/not found de commmand you can find this directly in the sdk folder and execute like this (on Windows in my case)

C:/Users/[user]/AppData/Local/Android/sdk/build-tools/31.0.0/zipalig -v 4 app-release-unsigned.apk myapp.apk

C:/Users/[user]/AppData/Local/Android/Sdk/build-tools/31.0.0/apksigner sign --ks my-ks.keystore --ks-pass file:my-passfile.txt --v1-signing-enabled true --v2-signing-enabled true myapp.apk

enter image description here

jurcola
  • 359
  • 4
  • 7
  • 1
    i tried that, but in my case, after the build command, the manifest is set back to what it was after add platform android. So that did not work in my case. but i have some older sdk, cordova and android 8.0.0 – Jinxi Mar 13 '23 at 15:07
  • @Jinxi Every time you add the android platform, it will revert to the initial value. With this initial value, you will not be able to compile it. You have to create the platform and once you do it, even if you have some errors, modify or add the fields mentioned in the comment. Then try to compile again. Then you should not need to modify it again. It's not the best solution, but it's the only one that worked for me. Make sure you are modifying the correct file and attributes. I added an image to the comment so you can see the manifest.xml that I have – jurcola Mar 13 '23 at 21:44
  • If i just modify the activity it builds, but I still cant upload to the store with the same error. I tried your quick fix too, but when i build it, then it duplicates the receiver (which has also an intent filter) in my case and removes the exported flag. In the end it throws an error: Element receiver#nl.xservices.plugins.ShareChooserPendingIntent at AndroidManifest.xml:23:9-27:20 duplicated with element declared at AndroidManifest.xml:15:9-19:20 – Jinxi Mar 14 '23 at 13:10
  • Correct just edit `AndroidManifest.xml` file find all ``, `` and `` inside the `` in there see if have some `android:exported` if yes do not modify it if not add `android:exported="true"` save and compile. That's it. – Anthony Sychev Mar 15 '23 at 12:05
  • For prevent app crash the `FileProvider` must be set as ***False***! ```xml ``` – Anthony Sychev Mar 15 '23 at 12:52
  • thanks for all the answers. In my manifest there are 2 intent filters. the activity and the receiver. In the android doc stood (if i remember correctly) that the activity is set to true and the rest to false, thats what i did for my 2 filters. but when I set more than one, i get the graft error: Error: Unable to graft xml at selector "/manifest/application/receiver" (what does that even mean?!?) sooo please can enybody enlighten us? but maybe the receiver plugin is ill(?) in my case it is also the android:name="nl.xservices.plugins.ShareChooserPendingIntent" – Jinxi Apr 17 '23 at 13:48
0

I was facing the same problem, if you are using this plugin cordova-plugin-x-socialsharing

you just need to modify your AndroidManifest.xml and add this property android:exported="true" like This

    <receiver android:enabled="true" android:exported="true" android:name="nl.xservices.plugins.ShareChooserPendingIntent">
        <intent-filter>
            <action android:name="android.intent.action.SEND" />
        </intent-filter>
    </receiver>

To save people some time, the file is in node_modules/cordova-plugin-x-socialsharing/plugin.xml

In the plugin.xml file manually added android:exported="true" to receiver element

<config-file target="AndroidManifest.xml" parent="/*/application">
  <receiver android:name="nl.xservices.plugins.ShareChooserPendingIntent" android:enabled="true" android:exported="true">
    <intent-filter>
      <action android:name="android.intent.action.SEND"/>
    </intent-filter>
  </receiver>
</config-file>
  • I tried your solution, modifying the plugin.xml of the nl.xservice. Unfortunately, it did not influence the manifest.xml – Jinxi May 03 '23 at 12:38
0

I'm using ionic and cordova too. when I added the edit-config to the activity as shown in my config.xml. it could be build. but the error still remains (upload to google), so I added it also for the provider. but then I get the graft error, when adding the android platform fresh.

Unable to graft xml at selector "/manifest/application/provider"

and if I rearrange receiver over provider I get the same error for provider. Only for activity it seams to work.

I also tried to overwrite the xml part instead of merging, but I also get the graft error.

/platforms/android/app/src/main/AndroidManifest.xml Error: Validation failed, exiting FAILURE: Build failed with an exception.

  • What went wrong: Execution failed for task ':app:processReleaseManifest'. Manifest merger failed with multiple errors

config.xml

<platform name="android">
    <preference name="android-targetSdkVersion" value="31" />
    <edit-config file="app/src/main/AndroidManifest.xml" mode="merge" target="/manifest/application" xmlns:android="http://schemas.android.com/apk/res/android">
        <application android:networkSecurityConfig="@xml/network_security_config" />
    </edit-config>
    <edit-config file="app/src/main/AndroidManifest.xml" mode="merge" target="/manifest/application/provider" xmlns:android="http://schemas.android.com/apk/res/android">
        <provider android:exported="false" />
    </edit-config>
    <edit-config file="app/src/main/AndroidManifest.xml" mode="merge" target="/manifest/application/receiver" xmlns:android="http://schemas.android.com/apk/res/android">
        <receiver android:exported="true" />
    </edit-config>
    <edit-config file="app/src/main/AndroidManifest.xml" mode="merge" target="/manifest/application/activity" xmlns:android="http://schemas.android.com/apk/res/android">
        <activity android:exported="true" />
    </edit-config>

Manifest.xml

<application android:hardwareAccelerated="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:networkSecurityConfig="@xml/network_security_config" android:supportsRtl="true">
    <activity android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale" android:exported="true" android:label="@string/activity_name" android:launchMode="singleTop" android:name="MainActivity" android:theme="@android:style/Theme.DeviceDefault.NoActionBar" android:windowSoftInputMode="adjustResize">
        <intent-filter android:label="@string/launcher_name">
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
    <provider android:authorities="${applicationId}.fileOpener2.provider" android:exported="false" android:grantUriPermissions="true" android:name="io.github.pwlin.cordova.plugins.fileopener2.FileProvider">
        <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/opener_paths" />
    </provider>
    <receiver android:enabled="true" android:name="nl.xservices.plugins.ShareChooserPendingIntent">
        <intent-filter>
            <action android:name="android.intent.action.SEND" />
        </intent-filter>
    </receiver>
    <provider android:authorities="${applicationId}.sharing.provider" android:exported="false" android:grantUriPermissions="true" android:name="nl.xservices.plugins.FileProvider">
        <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/sharing_paths" />
    </provider>
</application>

In provider is added twice.. I dont know If that could be a problem.. even If I'm not sure how to resolve. Any ideas. Many thanks.

Jinxi
  • 303
  • 1
  • 13