Unity Android: Can't build Firebase and Mapbox Project - android

I'm currently trying to build a Unity project for Android, which utilizes Mapbox, Firebase, Unity's in-built AR Foundation, and a bunch of smaller packages from the Asset Store, which cannot be the source of the problem.
I built the project before adding Firebase successfully, but now I get the following error:
D8: Program type already present: com.google.gson.FieldNamingPolicy$5
(full version posted here pastebin because it's a lengthy one)
Version Numbers:
Unity 2019.3.0f6
Firebase Unity SDK 6.14.0
Mapbox Unity SDK 2.1.1
As far as I can tell, the problem is based on Mapbox and Firebase having dependency issues with each other. However, I have no clue how to fix them.
I tried every plausible solution I could find, including custom-grade templates, Gradle settings, trying internal builds on an older version of Unity (2018.3.14f1), exporting the project to Android Studio, then building from there and more.
None of this worked for me, sadly.
Are there any other methods I could try to fix this?
Thank you in advance!
P.S.: If I try to disable R8 as proposed in the error message, I get a java.io.IOException about a read error related to the "Duplicate jar entry [com/google/d/d$5.class]", but in general, no matter what fix I try, I usually end up with a different error message than with the other approaches.

I have an idea about what may be happening, but don't have an immediate way to test this solution.
It looks like there are two copies of the Google gson library included in your build. Inspecting mapbox-unity-sdk_v2.1.1, I see that there is a file gson-2.8.5.jar included in the unity package. Since the build is apparently including gson as a side effect, you may be good just deleting this file. But I suspect that the support libraries that are also included may cause an issue.
Given this, I would suggest three avenues of remediation:
1) you may want to use the External Dependency Manager for Unity to resolve these files for you. This is included in the Firebase SDK (and is a completely open source project so you may want to request that MapBox use it in the future).
I would recommend reading this article to fully understand what's happening, but what you want to do is create a MapboxDependencies.xml file in an Editor folder (ex: Assets/Mapbox/Editor/MapboxDependencies.xml) and include all the dependencies under Mapbox/Core/Plugins/Android:
<dependencies>
<androidPackages>
<androidPackage spec="com.google.code.gson:gson:2.8.6"/>
</androidPackages>
</dependencies>
And delete the related jar/aar files when you're done.
Note that you will have to track down maven repositories for these, otherwise I would include a complete xml file for you.
Now libraries that may cause you issues are all the support libraries. It looks like Mapbox may still be using the old support libraries prior to Android Jetpack. There are mappings here, so I'll take a first stab at their Dependencies.xml entries for you:
<dependencies>
<androidPackages>
<androidPackage spec="com.google.code.gson:gson:2.8.6"/>
<androidPackage spec="androidx.appcompat:appcompat:1.1.0"/>
<androidPackage spec="androidx.legacy:legacy-support-core-ui:1.1.0"/>
<androidPackage spec="androidx.legacy:legacy-support-core-utils:1.1.0"/>
<androidPackage spec="androidx.media:media:1.1.0"/>
<androidPackage spec="androidx.legacy:legacy-support-v4:1.1.0"/>
<androidPackage spec="androidx.vectordrawable:vectordrawable:1.1.0"/>
</androidPackages>
</dependencies>
The other problem you would typically run into is that under normal circumstances, you'd have to recompile all the libraries that relied on the old support libraries to reference the new androidx ones. Jetpack did come with a tool called Jetifier that should do this automatically if you enable it in the External Dependency Manager:
Although you may run into this issue on some configurations of Unity 2019.3 and later (workaround in the issue thread).
2) Alternatively you can add a mainTemplate.gradle to achieve the same goals. I would recommend using the ExternalDependencyManager, but by deleting the aar/jar libraries and adding them as dependencies in mainTemplate you'll effectively achieve the same outcome.
3) If you resolve your dependencies without mainTemplate.gradle - all of Firebase's aar/jar files will get added to Assets/Plugins/Android/Firebase. If you deleted all of the conflicts with Mapbox libraries, you may get to the same point. This feels a bit more dangerous to me and the support libraries may be harder to work with (you'd have to track down the androidx libraries on your own for instance) - but might remove some of the moving pieces if the dependency managers are new to you.
I hope that all helps!
--Patrick

Related

Discovering an artefacts' native dependencies

I have recently begun maintaining an Android app that is not compliant with Google's requirement for 64-bit native libraries. The app itself does not directly depend on native code but in the generated apk a native library named libcproxy gets included. I can only assume that this is needed by one of the apps dependencies but so far I have not had any luck in finding the artefact in question. The shared library also seems a bit elusive as I have not been able to find many references to it online.
Is there perchance a gradle command or similar that can shed some light on which artefact includes the library?
I have tried excluding the shared library in the hope, that I might get an unsatisfied link error but so far I have not been able to make the app crash due to missing the library.
You can display a dependency tree with :
gradlew app:dependencies

"Uses reserved file or directory name 'lib'" error when trying to build android app bundle

I'm trying to build an app bundle but I'm getting the following error:
File 'root/lib/x86_64-MacOSX-gpp/jni/libjunixsocket-native-2.0.4.jnilib' uses reserved file or directory name 'lib'.
For what I've seen from similar questions, this issue is normally solved juggling dependencies or files in the project structure, but in this case it seems to point to a native library involved in app architecture if i'm not mistaken. Any ideas how to solve this?
It looks like you are adding a dependency as a jar instead of an aar.
The aar contains the information of what files should be considered as Android resources, native libraries, etc. in the app. A jar is just a plain list of files without Android concept. Because the jar you're depending on contains a directory lib, the files would normally end up being considered as native libraries, but because the files come from a jar instead of an aar, the build system warns that it's unlikely to be a native library and may have unintended consequences at runtime.
Try to package that library as an .aar instead of a .jar. See this documentation: https://developer.android.com/studio/projects/android-library
Edit:
Note that this file could not be loaded by the Android platform if it was included as is in the APK, so even though the previous build systems would allow you to put anything in an APK, the Android App Bundle is more restrictive to ensure that you don't accidentally put unnecessary files which would increase unnecessarily the size of your app.
Ok it is working now! Steps I used to found the problem (thanks for pointing me in the right direction #Pierre)
Run a gradle build --scan from your terminal or go to the Gradle tab in Android Studio, select :app, help , androidDependencies to see your dependency graph.
Search the dependency graph for the library name related to the problem ( in my case I searched for socket, there was no match for libjunixsocket for example).
Going upwards on the dependency tree I realized it was caused by the 'io.voucherify.android.client:voucherify-android-sdk:2.1.0' dependency.
I just added #aar at the end of the dependency implementation, and I managed to build the app bundle.
implementation 'io.voucherify.android.client:voucherify-android-sdk:2.1.0#aar'

Cost of importing libraries

I've been working on an Android app project. I'm using quite a few libraries (because why redo work that someone else has done to make other people's life easier?).
My question is: what are the costs of importing libraries in a project? (I'm talking about the implementation XXX.YYY:v2.0.0 type of line added in the build.gradle dependencies list.)
Just as an example (though please provide a more encompassing answer): when compiling and publishing my application, does it take all of the libraries' classes and methods and put them in my application, thus making it much heavier than it would need to be?
Each library dependency requires an additional download while you compile your app. So these will increase the amount of time required to compile.
The code for each library is included in your final APK so they will increase the size.
For Every Library a download is necessary In order to built your app.
e.g If you want Libraries regarding to Firebase then You download the Library by adding the Firebase Project to your App. In build.gradle File you see the dependencies after you add them to Your Project App.

If the package is removed from Gradle, what will happen with my project?

I don't have much experiences with Android development and I have a doubt about the dependencies using Gradle. For example:
If I construct an Android app using Gradle dependecies and the package provider (for example picasso) remove the package from the repository, what will happens with my project? Will I lose the components? Or It makes a local copy of the binaries and my project will kept working normally?
Thanks a lot for help me to understand better how does it works.
You should keep a backup copy of the library you are installing as a dependency, but you shouldn't really worry about it ahead of the time that much.
It is quite rare, but it could get removed due to many reasons. There have been such instances in other cases where someone responsible for managing some package has just decided to remove it or alter it.
This does not just apply to Gradle but to any such dependency your application depends on, from any hosted package management solution. This same advice therefore applies to systems like NPM as well.
What you should ask yourself at some point in the development would be "Can I build this in 5 years again to fix a bug on a fresh machine with all the data I have and probably still have access to in 5 years?", because your local dependency cache might be long gone at that point anyways and the downloads for the library might be gone from the internet as well. It is a good practice to tuck them away somewhere in the same repository as the rest of the code, just in case.
Gradle downloads and caches all the dependencies when you perform Sync, you can see it at the bottom of your Android Studio.
If in the new version of library was deleted some packages, we have two options:
You update library version in your project and this package was removed for your project too
You use the old version of library and package still accessible from your project.
First, you should read that :
What is dependency management ?
The dependency cache
Short answer to your question : your project will still build unless your cache is cleared or if the dependency's version changes
But a package usually does not disappear from a repository (edit : as lu.koerfer underlined it in a comment, packages are not deleted from repository). If so, there might be a replacement package with a different name/group and you should update your dependencies to make it build properly again instead of relying on the cache.
If you will remove the dependency that you using, your project will still be able to use the library you willing to use.
until other dependency with same name / group will override your older dependency
You can read more about how gradle works, and how gradle manage his cache dependencies

Import excel (.xlsx) file data in android

I have a problem regarding Excel(.xlsx) file import in Android SQLite database, I am using Poi jar file but finding following Runtime error.
java.lang.VerifyError: org/apache/poi/xssf/usermodel/XSSFWorkbook
How can i resolve this problem ? please help me.
If you are using maven try the following
<!-- http://mvnrepository.com/artifact/org.apache.poi/poi-ooxml -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.14</version>
</dependency>
if not just download the jar file and add in your built path.
Java on Android has some intricacies which require some more work due to duplicate classes in some jars, the number of methods that POI has and some javax.* code that is included via transitive dependencies.
There are multiple approaches that were used by others over time:
Recently I prepared a sample at https://github.com/centic9/poi-on-android/ which allows to build a combined jar-file which includes everything needed for Apache POI in a way that also works on Android
The project at https://github.com/andruhon/android5xlsx tries to provide ready-made jar-files that are patched and adjusted to work on Android
Previously for Android versions below 5, https://github.com/andruhon/AndroidReadXLSX did provide a slightly approach, still with ready-made jar-files being provided
Please try to use one of those and report back if you succeed. The first one is a rather new approach, but it would allow to re-package newer versions of Apache POI rather quickly compared to the other two which are a few versions behind already.

Categories

Resources