We have recently released our game to the Playstore and i found out (From coments) that people running Android 12 can’t install the game. The game has more than 2k installs on other devices running Android 11 or earlier.
The message that the users get is: “Can’t Install”
“Try again, and if it still doesn’t work, see common ways to fix the problem”
Does anyone experience similar problem? The game was build with Unity 2019…
Most likely the issue is not having exported flag for the unity activity which is a requirement from Android 12. This can be solved by updating your unity to latest version.
If you can’t update or if unity hasn’t back-ported to 2019, you can try the below script.
Note that this is picked from our plugin Cross Platform Native Plugins : Essential Kit and adapted to avoid any compilation errors.
//Taken from Cross Platform Native Plugins : Essential Kit (https://link.voxelbusters.com/essential-kit)
#if UNITY_EDITOR && UNITY_ANDROID
using System.IO;
using System.Text;
using System.Xml;
using UnityEditor.Android;
//Reference : https://github.com/Over17/UnityAndroidManifestCallback
namespace VoxelBusters.EssentialKit.Editor.Android
{
public class AndroidManifestPostProcessor : IPostGenerateGradleAndroidProject
{
public void OnPostGenerateGradleAndroidProject(string basePath)
{
AndroidManifest androidManifest = new AndroidManifest(GetManifestPath(basePath));
//For forcing android hardwareAccelerated flag
//(Comment the hardwareAccelerated lines if you really don't care. We use it for our Webview feature for rendering videos in webview)
androidManifest.SetApplicationAttribute("hardwareAccelerated", "true");
androidManifest.SetStartingActivityAttribute("hardwareAccelerated", "true");
//For forcing debuggable flag
androidManifest.SetApplicationAttribute("debuggable", UnityEditor.EditorUserBuildSettings.development ? "true" : "false");
// For API 31+ support (Need explicit exported flag for entries having intent-filter tags)
androidManifest.SetStartingActivityAttribute("exported", "true");
androidManifest.Save();
}
public int callbackOrder { get { return 1; } }
private string _manifestFilePath;
private string GetManifestPath(string basePath)
{
if (string.IsNullOrEmpty(_manifestFilePath))
{
StringBuilder pathBuilder = new StringBuilder(basePath);
pathBuilder.Append(Path.DirectorySeparatorChar).Append("src");
pathBuilder.Append(Path.DirectorySeparatorChar).Append("main");
pathBuilder.Append(Path.DirectorySeparatorChar).Append("AndroidManifest.xml");
_manifestFilePath = pathBuilder.ToString();
}
return _manifestFilePath;
}
}
internal class AndroidXmlDocument : XmlDocument
{
private string m_Path;
protected XmlNamespaceManager nsMgr;
public readonly string AndroidXmlNamespace = "http://schemas.android.com/apk/res/android";
public AndroidXmlDocument(string path)
{
m_Path = path;
using (var reader = new XmlTextReader(m_Path))
{
reader.Read();
Load(reader);
}
nsMgr = new XmlNamespaceManager(NameTable);
nsMgr.AddNamespace("android", AndroidXmlNamespace);
}
public string Save()
{
return SaveAs(m_Path);
}
public string SaveAs(string path)
{
using (var writer = new XmlTextWriter(path, new UTF8Encoding(false)))
{
writer.Formatting = Formatting.Indented;
Save(writer);
}
return path;
}
}
internal class AndroidManifest : AndroidXmlDocument
{
private readonly XmlElement ApplicationElement;
public AndroidManifest(string path) : base(path)
{
ApplicationElement = SelectSingleNode("/manifest/application") as XmlElement;
}
private XmlAttribute CreateAndroidAttribute(string key, string value)
{
XmlAttribute attr = CreateAttribute("android", key, AndroidXmlNamespace);
attr.Value = value;
return attr;
}
internal XmlNode GetActivityWithLaunchIntent()
{
return SelectSingleNode("/manifest/application/activity[intent-filter/action/@android:name='android.intent.action.MAIN' and " +
"intent-filter/category/@android:name='android.intent.category.LAUNCHER']", nsMgr);
}
internal void SetApplicationTheme(string appTheme)
{
ApplicationElement.Attributes.Append(CreateAndroidAttribute("theme", appTheme));
}
internal void SetStartingActivityName(string activityName)
{
GetActivityWithLaunchIntent().Attributes.Append(CreateAndroidAttribute("name", activityName));
}
internal void SetApplicationAttribute(string key, string value)
{
ApplicationElement.Attributes.Append(CreateAndroidAttribute(key, value));
}
internal void SetStartingActivityAttribute(string key, string value)
{
XmlNode node = GetActivityWithLaunchIntent();
if(node != null)
{
XmlAttributeCollection attributes = node.Attributes;
attributes.Append(CreateAndroidAttribute(key, value));
}
}
}
}
#endif
How to use?
Copy the contents of the share code into AndroidManifestPostProcessor.cs file
Place it under your Assets/Editor folder. (this is folder of your unity project)
I’ve updated to 2020.3.25.f1 and I still have get the error when I try to update one existing app: “You uploaded an APK or Android App Bundle which has an activity, activity alias, service or broadcast receiver with intent filter, but without ‘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”
Also, I’ve selected “Custom Main Manifest” (Project Settings > Player > Android > Publishing Settings > Build), and added android:exported=“false” (one time) and android:exported=“true” (another time) in AndroidManifest.xml, but still same error. Tried this with 2020.3.25.f1 and 2019.4.28f1.
I want to try your method, but I’m not very advanced… From my undestanding you said to create a c# file and to add the code you posted? if yes, then where exactly that file need to be placed?
Thanks for the code but it throws compilation errors on anything referencing “EssentialKit”, starting with
namespace VoxelBusters.EssentialKit.Editor.Android. Is there a way to fix this ?
Hello, thanks for your help, I followed the steps but I had these errors, any solution? I will be grateful.
Assets\Editor\AndroidManifestPostProcessor.cs.cs(21,24): error CS0103: The name ‘EssentialKitSettingsEditorUtility’ does not exist in the current context
Assets\Editor\AndroidManifestPostProcessor.cs.cs(15,13): error CS0246: The type or namespace name ‘EssentialKitSettings’ could not be found (are you missing a using directive or an assembly reference?)
Can you please explain me what exactly you did?
My issue is that if I try to upload my app bundle to the Play Store, I get this error: "You uploaded an APK or Android App Bundle which has an activity, activity alias, service or broadcast receiver with intent filter, but without 'android:exported' property set. This file can't be installed on Android 12 or higher."
I tried to insert android:exported=“true” into AndroidManifest.xml but it didn’t solve the issue.
I tried to insert the code above (deleted the part you also deleted) into the Assets > Editor subfolder, but it didn’t solve the issue.
I did the same exact thing, no success. Can you share your AndroidManifest.xml file which is inside Assets > Plugin > Android?
Maybe there is something inside which I might have wrong…
Does your game use Google Play Services (achievements or leaderboard)?
Thanks for pointing the compilation error. I should have removed it earlier but was in rush
Anyways, I removed those lines and it should be fine for anyone now.
I tried everything but unable to upload publish on Google Play.
What I did?
1- Update my unity version
2- I added android:exported=“true” in manifest
3- I added your script in editor folder
I didn’t understand what I have to do ? Very annoying issue…
Problem is here csharp** **<receiver android:name="com.unity.androidnotifications.UnityNotificationRestartOnBootReceiver" android:enabled="false"> <intent-filter> <action android:name="android.intent.action.BOOT_COMPLETED"/> </intent-filter> </receiver>** **
Your mobile notifications need to have android:exported flag as its using intent-filter as per Android 12.
Try checking if you see an update from that plugin. It should resolve it.
Thank you very much. I removed Mobile Notifications package and it’s fixed. I think this package coming as default. If you don’t use you should remove that.