Search code examples
androidunity-game-enginepluginsandroid-manifestandroid-unity-plugin

Unity ignores android plugin manifest file leading to missing <service> element in its android manifest


I have created an Android plugin for Unity3D. This plugin starts a background service by calling bindService(). To declare this service, I have put the <service> element as a child of the <application> element in the AndroidManifest.xml file of my android module. Then I created a jar file from the module and put it in Assets\Plugins\Android folder.

The problem is that the <service> element is missing in the AndroidManifest file created by Unity. why is that?

Unity should have extracted my manifest from the jar file and have merged it with its own manifest file according to Unity documentation:

You can drop pre-compiled Android library projects into the Assets->Plugins->Android folder. Pre-compiled means all .java files must have been compiled into jar files located in either the bin/ or the libs/ folder of the project. AndroidManifest.xml from these folders will get automatically merged with the main manifest file when the project is built.

So the result manifest file should contain the <service> element (but it does not as said before).

The following is my module and its manifest file:

enter image description here I used the following gradle code (from here) to convert the module into a jar file:

task createJar(type: Copy) {
    from('build/intermediates/bundles/default/')
    into('libs/jars/')
    include('classes.jar')
    rename('classes.jar', 'locationPlugin.jar')
}

Note: My question is not a duplicate of this question. I'm not making custom manifest and I'm not modifying the manifest made by Unity. My question is about why unity does not merge the manifest of my compiled module (.jar file) into its own manifest.


Solution

  • I figured it out. The Jar file I created does not contain the manifest file (I verified that by opening the .jar file by 7zip). So Unity does not see any manifest file in the first place to be able to merge it into its own manifest file.

    To fix this issue, I created an Android Archive (AAR) file instead of jar file as follows:

    1. Open the build.gradle file for the existing app module. At the top, you should see the following:

      apply plugin: 'com.android.application'

    2. Change the plugin assignment as shown here:

      apply plugin: 'com.android.library'

    3. Click Sync Project with Gradle Files.

    Now build the module by going into 'Gradle Projects' pane (in the right) and find the related gradle module and go to Tasks > build > build. Run it by double-clicking on it. The .aar file is built now.

    1) find the .aar file of this module (it is located in mylibrary\build\outputs\aar folder). I chose the release one. It was called mylibrary-release.aar. You can open it by 7zip to verify that the Android manifest file is there.

    2) Copy the .aar file into Assets\Plugins\Android folder.

    That's it! Unity now merges the manifest file of the module into its own manifest. You can find the resultant manifest file in Temp\StagingArea of your Unity project.

    One very important thing is that make sure your <service> element contains the fully qualified name of the service class which means package name + class name :

    <service android:name="com.servicelocation.zerokey.mylibrary.MyLocationService"/>
    

    For an example of this approach, you can create an empty project in Unity and install the Google Cast Remote Display android plugin from the asset store. You can see that google has put its .aar file under Assets > Plugins > Android and this file contains:

    enter image description here

    and the following is the content of this manifest:

    enter image description here