Unity Error: Unable to convert classes into dex format - unity3d

I have created an Android Unity plugin (.aar file) which provides some custom positioning data to my Unity game. In my Unity script, I use,
var x = customClass.CallStatic<float>("getHeadX");
In order to get some location data. This method is called per frame to get the updated data (polling method) which makes it inefficient. Instead, I decided to call a C# method in my Unity script from my java code (plugin side) when the updated data is ready. To do this, in my java plugin, I wrote,
import com.unity3d.player.UnityPlayer;
...
UnityPlayer.UnitySendMessage("Manager", // gameObject name
"PluginCallback", // this is a callback in C#
"Hello from android plugin"); // msg which is not needed actually
However, the compiler complained that the package com.unity3d.player.UnityPlayer does not exist. So I copied classes.jar file from
C:\Program Files
(x86)\Unity\Editor\Data\PlaybackEngines\AndroidPlayer\Variations\mono\Release\Classes
\classes.jar
into the 'libs' folder of my android plugin's project. I built it successfully and copied the generated .aar file (mylibrary-release.aar) into Assets\Plugins\Android folder of my Unity project.
When I build the Unity project (Using 'Internal' build system), it gives me this error:
IOException: Failed to Move File / Directory from
'Temp/StagingArea\android-libraries\mylibrary-release\classes.jar' to
'Temp/StagingArea\android-libraries\mylibrary-release\libs\classes.jar'.
UnityEditor.Android.PostProcessor.Tasks.ProcessAAR.Execute
...
This error happens because the classes.jar dependency has name conflict with classes.jar (made by unity out of my plugin). So I changed the dependency name to unity_classes.jar and this resolved the issue but now I'm getting a new error when building my unity application:
CommandInvokationFailure: Unable to convert classes into dex format.
C:/Program Files/Java/jdk1.8.0_102\bin\java.exe -Xmx2048M
Dcom.android.sdkmanager.toolsdir="C:/Users/kamran.shamloo/AppData/Local/Android/Sdk\tools"
-Dfile.encoding=UTF8 -jar "C:\Program Files (x86)\Unity\Editor\Data\PlaybackEngines\AndroidPlayer/Tools\sdktools.jar"
stderr[ Uncaught translation error:
java.lang.IllegalArgumentException: already added:
Lbitter/jnibridge/JNIBridge; Uncaught translation error:
java.lang.IllegalArgumentException: already added:
Lbitter/jnibridge/JNIBridge$a; Uncaught translation error:
java.lang.IllegalArgumentException: already added:
Lcom/unity3d/player/NativeLoader; Uncaught translation error:
java.lang.IllegalArgumentException: already added:
Lcom/unity3d/player/ReflectionHelper; Uncaught translation error:
java.lang.IllegalArgumentException: already added:
Lcom/unity3d/player/ReflectionHelper$1; Uncaught translation error:
java.lang.IllegalArgumentException: already added:
Lcom/unity3d/player/ReflectionHelper$a; Uncaught translation error:
java.lang.IllegalArgumentException: already added:
Lcom/unity3d/player/UnityPlayer; Uncaught translation error:
java.lang.IllegalArgumentException: already added:
Lcom/unity3d/player/UnityPlayer$1; Uncaught translation error:
java.lang.IllegalArgumentException: already added:
Lcom/unity3d/player/UnityPlayer$10;
...

The classes.jar (which you later renamed it to 'unity_classes.jar') gets automatically included into the built .apk by Unity, so you shouldn't include it yourself again (in your Android plugin), even under a different name.
In other words, first your android plugin "embeds" this .jar file inside itself. Then, when Unity adds your plugin into the game project, it also adds its own copy of that .jar file (it does that for all android projects). Consequently, Unity essentially ends up having 2 copies of the same .jar file in the project and complains by saying 'unable to convert classes into dex format'.
So although you have to use this library (.jar file) in your project but you should not bundle this library with your project. How to do that? If you're using Android studio, you can achieve this by marking the .jar file as a dependency with the provided scope.
To do this, you can:
1) Go to 'build.gradle' of your module and change this:
compile files('libs/jars/unity_classes.jar')
to this:
provided files('libs/jars/unity_classes.jar')
Or
2) you can right-click on the module (in Android pane) and choose Open Module Settings. Then go to Dependencies tab. Find the Unity module (which I renamed it to unity_classes.jar) and change its scope to Provided.

Related

Unable to open .erl file using "Erlang Editor" in Eclipse

I have installed Erlang OTP 25.0, erlide 0.56.0, Eclipse 2022-09 & Java 18. I have created a new Erlang project and module. When I tried to open the .erl file by clicking on "Open", I am getting an exception shown below.
Failed to create the part's controls.
java.lang.IllegalArgumentException: The file's actual encoding doesn't match the declared one
at org.erlide.ui.editors.erl.ErlangEditor.filterUTF8Exception(ErlangEditor.java:979)
at org.erlide.ui.editors.erl.ErlangEditor.createPartControl(ErlangEditor.java:940)
at org.eclipse.ui.internal.e4.compatibility.CompatibilityPart.createPartControl(CompatibilityPart.java:158)
.....
Caused by: java.lang.IllegalArgumentException: Argument not valid
at org.eclipse.swt.SWT.error(SWT.java:4899)
at org.eclipse.swt.SWT.error(SWT.java:4833)
However, I am able to open the .erl file using RightClick-->OpenWith-->TextEditor. But, it does not highlight the code based on syntax.

How to remedy error caused by guava: Program type already present: com.google.common.util.concurrent.internal.InternalFutures

An AAR library already uses com.google.guava.
If an app includes the following in its build.gradle:
api 'com.google.guava:guava:27.0-android'
Building the app generates the following error:
Execution failed for task ':app:transformDexArchiveWithExternalLibsDexMergerForDebug'.
> com.android.builder.dexing.DexArchiveMergerException: Error while merging dex archives: ...
Learn how to resolve the issue at https://developer.android.com/studio/build/dependencies#duplicate_classes.
Program type already present: com.google.common.util.concurrent.internal.InternalFutures
If I do not include "api 'com.google.guava:guava:27.0-android'", the app can be built, but it has runtime error of java.lang.NoClassDefFoundError when it reaches the point of using the Guava method: Iterables.find
I had to update to version 27.0.1, at the time of writing they still haven't updated the README with this new version.
implementation 'com.google.guava:guava:27.0.1-android'
Since Guava 27.0, ListenableFuture is located in separate artifact, see the announcement. You can try two things (one at a time):
Exclude "listenablefuture" module (group "com.google.guava") and build your project again.
I don't know the AAR specifics, but it could be that 27.0-android doesn't work with AAR, so you should try 26.0-android instead.

Debugging OfBiz in Eclipse gives MissingResourceException

I downloaded the OfBiz Java application and the following line throws an MissingResourceException:
ResourceBundle res = ResourceBundle.getBundle(settingsResourceName);
The value of settingsResourceName is "cache", but I cannot find any file called cache.properties or cache_en.properties.
Where should I be looking? I'm new to Java. All my research on SO says there should be such a file.
I imported OfBiz in Eclipse using the Import menu option and selecting Existing Project from File System (I'm not in front of my dev machine so I don't remember the exact wording). But I chose the root folder of the downloaded OfBiz.
I then added the appropriate VM Arguments in the Run Configuration to get it to run properly at least. And that's it, on the first Run I got the above error. I think it has to do with a missing class path but I don't know what to add to class path.
Here is the stack trace:
ERROR StatusLogger No log4j2 configuration file found. Using default configuration: logging only errors to the console.
Exception in thread "main" java.lang.ExceptionInInitializerError
at org.apache.ofbiz.base.util.Debug.<clinit>(Debug.java:68)
at org.apache.ofbiz.base.container.ContainerLoader.load(ContainerLoader.java:61)
at org.apache.ofbiz.base.start.StartupControlPanel.loadStartupLoaders(StartupControlPanel.java:202)
at org.apache.ofbiz.base.start.StartupControlPanel.start(StartupControlPanel.java:69)
at org.apache.ofbiz.base.start.Start.main(Start.java:84)
Caused by: java.util.MissingResourceException: Can't find bundle for base name cache, locale en
at java.util.ResourceBundle.throwMissingResourceException(ResourceBundle.java:1564)
at java.util.ResourceBundle.getBundleImpl(ResourceBundle.java:1387)
at java.util.ResourceBundle.getBundle(ResourceBundle.java:773)
at org.apache.ofbiz.base.util.cache.UtilCache.setPropertiesParams(UtilCache.java:174)
at org.apache.ofbiz.base.util.cache.UtilCache.setPropertiesParams(UtilCache.java:170)
at org.apache.ofbiz.base.util.cache.UtilCache.setPropertiesParams(UtilCache.java:166)
at org.apache.ofbiz.base.util.cache.UtilCache.<init>(UtilCache.java:124)
at org.apache.ofbiz.base.util.cache.UtilCache.createUtilCache(UtilCache.java:769)
at org.apache.ofbiz.base.util.UtilProperties.<clinit>(UtilProperties.java:75)
... 5 more
UPDATE:
My mistake, I found two files both called cache.properties in the following folders:
ofbiz-trunk/build/resources/main
ofbiz-trunk/framework/base/config
But these are folders, not packages. I tried putting them in the .classpath but that did not work, I still kept getting the same error.
As suspected, I knew it was because of a missing reference to a class path. After looking at a section on this page: http://www.opensourcestrategies.com/ofbiz/ofbiz_eclipse.php, I learned that I was supposed to go to the Java Build Path and in the Libraries tab, click on Add Class Folder, then point that to ofbiz-trunk/framework/base/config. Which is where I have one of the cache.properties files.

Bundling app with SystemJS using 3rd party library?

How can I get the systemjs builder to ignore third party libraries? We are evaluating wijmo controls for use in an app and they provide wijmo.angular2.min.js, wijmo.input.min.js and wijmo.min.js. We load these after SystemJS in our web page and that works fine because those files register the wijmo modules. However, when we try to bundle it throws an error because it cannot find the files. Sample error:
Unhandled rejection Error on fetch for vendor/wijmo/wijmo.angular2.input.js
at file:///C:/git/prj/dist/vendor/wijmo/wijmo.angular2.input.js
I can add this path to my config but then I get a different error:
'wijmo/*': 'vendor/wijmo/wijmo.angular2.min.js'
Error:
Unhandled rejection TypeError: Error compiling register module "wijmo/wijmo.angular2.input"
at vendor\wijmo\wijmo.angular2.min.js
Source vendor\wijmo\wijmo.angular2.min.js is already a bundle file, so can't
be built as a module.
Edit
Adding this path lets bundling work (at least it builds the bundles), but keeping the line in my config causes the app to error out, apparently being unable to find the class I'm importing (throws unexpected directive 'undefined')...
'wijmo/wijmo.angular2.input': 'vendor/wijmo/wijmo.input.min.js'
I got it to work by adding a 'meta' section to my SystemJS config that told it not to build that path:
var meta = {
'wijmo/*': {
format: 'global',
build: false,
}
};

How can I remove a library from the aar using gradle?

I'm currently building an android plugin for Unity. Because of that I need to include unity's classes.jar, which provides me with some methods in the com.unity3d.player package.
However when i do ./gradlew assemble it also packages the classes.jar into the .aar file under libs/classes.jar.
Now when I add this .aar to Unity and try to build, I get the following error:
Uncaught translation error: java.lang.IllegalArgumentException: already added: Lcom/unity3d/player/a$1;
Uncaught translation error: java.lang.IllegalArgumentException: already added: Lcom/unity3d/player/a$2;
Uncaught translation error: java.lang.IllegalArgumentException: already added: Lcom/unity3d/player/a$a;
Uncaught translation error: java.lang.IllegalArgumentException: already added: Lcom/unity3d/player/a;
Uncaught translation error: java.lang.IllegalArgumentException: already added: Lcom/unity3d/player/b$1;
Uncaught translation error: java.lang.IllegalArgumentException: already added: Lcom/unity3d/player/b$2;
Uncaught translation error: java.lang.IllegalArgumentException: already added: Lcom/unity3d/player/b;
Uncaught translation error: java.lang.IllegalArgumentException: already added: Lcom/unity3d/player/c;
Uncaught translation error: java.lang.IllegalArgumentException: already added: Lcom/unity3d/player/d$1;
UNEXPECTED TOP-LEVEL EXCEPTION:
java.lang.RuntimeException: Translation has been interrupted
at com.android.dx.command.dexer.Main.processAllFiles(Main.java:608)
at com.android.dx.command.dexer.Main.runMonoDex(Main.java:311)
at com.android.dx.command.dexer.Main.run(Main.java:277)
at com.android.dx.command.dexer.Main.main(Main.java:245)
at com.android.dx.command.Main.main(Main.java:106)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at SDKMain.main(SDKMain.java:129)
Unity tries to add the classes.jar to it's android build again, but because the classes.jar is already in the .aar, this fails.
How can I exclude the classes.jar from the .aar?
EDIT
This is what I can do with the command line to remove the classes.jar
zip --delete tapfortapunity-release.aar "libs/*"
How do I call this with gradle?
UPDATE: I just found out that this problem solves itself if I just remove the unity.jar dependency from my build.gradle file:
//dependencies {
// compile files('src/main/libs/unity.jar')
//}
(the code compiles just fine, strangely, and no unity.jar in the .aar file...).
(just noticed that the code compiled because there was no reference to UnityPlayer* stuff...)
Same issue here. I browsed a bit and it seems like there is no clean way to solve the problem (yet!), so I guess it all boils down to this:
create a chain of tasks for the installation of your unity plugin (a task to create the Plugin/Android directory for instance, one to Copy the AAR file and native libraries, if any, etc)
remove the file from the zip using a task the previous one will dependsOn
Step 2 can be carried out in one of those following ways:
create an Exec task that will just execute the command you pointed out (this is probably what I'll end up doing, as I'm not really proficient with gradle...). Easy but not portable (relies on an extra utility).
create a JavaExectask and use Java7 support for zips to remove the entry (probably the best solution, but I don't really have much experience here).
try creating a new jar using the suggestion pointed out in this post: Post on gradle-user describing how to create a jar (or aar...) using gradle as Gradle supports zip files, but cannot change them in place (which implies it cannot remove stuff from them). Harder, but will not rely on external tools, so you'll get portability as a result.
It might not be an elegant solution and probably better ones exist, but it's a very simple, and works well
Hope this helps