Unity cannot find classes inside AAR - android

I have a Unity game which uses an Android Library packed in an AAR (library.aar). However, I need to access the Main Activity's lifecycle callbacks (onPause(), onResume(), to name a few).
So I created a new library project in Android Studio (let's call this plugin). I imported library.aar into plugin and added it to the Dependencies. I tested it by calling the functions inside library.aar inside MainActivity. It doesn't throw any errors at this point.
In MainActivity, I called Library.onActivityResult(), Library.onResume(), and Library.onPause() in the respective functions.
Next, I added the classes.jar from Unity/Editor/Data/PlaybackEngines/androidplayer/release/bin into my plugin project. I added the JAR into the dependencies. I tested it by trying to subclass UnityPlayerActivity. Again, no errors yet.
I compile plugin into plugin-debug.aar and put it in Assets/Plugins/Android. I also created an AndroidManifest.xml which I got from the Unity Manual and put it inside Assets/Plugins.
I call the functions from a button in a Unity scene like so:
AndroidJavaClass jc = new AndroidJavaClass("com.alxcyl.plugin.MainActivity");
jc.CallStatic("connect");
// "connect" is a static function in the Java class MainActivity containing
// a short message like so:
// Log.d("My Plugin", "connect() was called");
I build the game and run it on my Android device. If I click the button, MyPlugin.connect() is properly called since it logs the message it's supposed to when clicked.
I think the lifecycle callbacks are properly called but the problem is that it logs an error saying:
I/dalvikvm( 5466): Could not find method com.somecompany.library.Library.onActivityResult, referenced from method com.alxcyl.plugin.MainActivity.onActivityResult
W/dalvikvm( 5466): VFY: unable to resolve virtual method 276: Lcom/somecompany/library/Library;.onActivityResult (IILandroid/content/Intent;)V
I/dalvikvm( 5466): Could not find method com.somecompany.library.Library.onPause, referenced from method com.alxcyl.plugin.MainActivity.onPause
W/dalvikvm( 5466): VFY: unable to resolve virtual method 276: Lcom/somecompany/library/Library;.onPause()V
I/dalvikvm( 5466): Could not find method com.somecompany.library.Library.onResume, referenced from method com.alxcyl.plugin.MainActivity.onResume
W/dalvikvm( 5466): VFY: unable to resolve virtual method 276: Lcom/somecompany/library/Library;.onResume()V
D/MyPlugin( 5466): connect() was called
I'm not sure what causes it. When you build the plugin project, it builds fine without any errors but when you access it through Unity, it doesn't work. I tried to use the same library.aar into a new Android project and Library.onActivityResult(), Library.onPause(), and Library.onResume() definitely exists and are properly called.
Could it be that Unity can't handle AARs that include AARs? Is there a fix for this?

Looks like the .jar file with all your compiled code is missing in the .aar library.
Unity compiles its own .jar file with all .jar files from all plugins together, into one .dex file.
On Unity forums, you posted "class not found" error; here you mention "method not found". Anyway, something seems to be wrong with your .aar file.

Related

Cordova Android app force closes after build

Here's the error details:
12-04 22:00:12.087: E/AndroidRuntime(19113):
java.lang.RuntimeException: Unable to start activity
ComponentInfo{com.package.name.dev/com.package.name.dev.MainActivity}:
java.lang.NullPointerException: Attempt to invoke virtual method 'void
org.apache.cordova.CordovaPlugin.privateInitialize(java.lang.String,
org.apache.cordova.CordovaInterface,
org.apache.cordova.CordovaWebView,
org.apache.cordova.CordovaPreferences)' on a null object reference
Background: I was originally only building the app for Android, but during my last release I had to generate an iOS build as well, which required some extra plugins and configuration tweaks to get functional. Now I'm trying to create a new release for Android, but the new app force closes as soon as it is opened.
In an effort to fix it, I tried to remove all references to the iOS-only plugins from the Android side of the project, but the error persists. I'm not sure what else to try.
What would provoke Cordova to throw this error when initializing plugins?
The issue was that one of the plugins had failed to copy its java classes into the Android app src directory when it was installed. I created the appropriate directory hierarchy and then copied in the java files from the /plugins/ dir.
To figure out which plugin caused the issue, I disabled the onload param from each feature one at a time (in the android.json file in the android platform directory) until the app successfully opened.

qt android ClassNotFoundException

I'm using Qt (qml) to make an android app but I'm getting errors trying to register native methods to be called from java. In one section on my native code I'm calling java static functions with no problems:
void NotificationClient::powerOff() {
QAndroidJniObject::callStaticMethod<void>("com/my_app/Utils",
"powerOff",
"()V"
);
}
Now I'm trying to add some calls from java back to my native code (based on this example) but it fails
QAndroidJniEnvironment env;
jclass objectClass = env->FindClass("com/my_app/Utils");
Results in:
Pending exception java.lang.ClassNotFoundException: Didn't find class "com.my_app.Utils" on path: DexPathList[[directory "."],nativeLibraryDirectories=[/system/lib, /vendor/lib, /system/lib, /vendor/lib]]
I've checked the dexdump from classes.dex and the class string matches. All paths in my AndroidManifest.xml are absolute. I've cleaned and rebuilt. Nothing is getting around that problem and I can't figure out why the static method call works but the object one does not.
(Yes, yet another ClassNotFoundException post but I really have searched for answers already).
edit The original failed method based on creating an object threw a different error so I switched back to use FindClass which gives the ClassNotFound error
UPDATE
OK, so I think I've figured out why FindClass is failing: according to this FindClass will search the callstack to figure out which ClassLoader to use. Normally this is fine but I believe Qt for android loads under a different thread so the wrong ClassLoader is getting called.
The link recommends caching the classes in JNI_onLoad but with Qt that's behind the scenes. Is there some other place where I could cache class id's on the main thread instead of the qt thread?
To answer my own question for completeness ...
The reason it failed to find the classes was Qt runs on a different thread than the main java thread, which caused the java classloader to fail in the lookup (see link in question update).
As a solution I added a JNI_onLoad function in one of my cpp files, which is called on the main java thread so the class lookup works correctly.

Android warning - Could not find method android.widget.LinearLayout$LayoutParams.<init> ref from Android.Support.V7

I'm not sure where this error is generating from. My application works fine and I've not come across any crashing; however I receive the below in my LogCat.
My application uses an ActionBar and ListView. Anyone come across this before?
EDIT: Seems to be only happening when running on Android 2.x
Could not find method android.widget.LinearLayout$LayoutParams., referenced from method android.support.v7.internal.view.menu.ActionMenuView$LayoutParams.
VFY: unable to resolve direct method 8309: Landroid/widget/LinearLayout$LayoutParams;. (Landroid/widget/LinearLayout$LayoutParams;)V
VFY: replacing opcode 0x70 at 0x0000
VFY: dead code 0x0003-0007 in Landroid/support/v7/internal/view/menu/ActionMenuView$LayoutParams;. (Landroid/support/v7/internal/view/menu/ActionMenuView$LayoutParams;)V
This sounds like those classes are missing from your apk. Make sure to include the necessary Jars into your Apk (sounds like the support library).
Also in relation to this error, this is due to the Class Loader trying to resolve the reference in your code to actual operation codes (opcode) that the OS can recognize.
I had somewhat a similar issue. But later I found that I was trying to call a menu which does not exist.

Android NoClassDefFound when referencing class from external libraries (IntelliJ IDEA 12)

I'm having an issue with IntelliJ's dependency handling in regards to external modules. Here's some context:
I'm writing an Android app which implements Google Maps. For my current feature set, I require two external libraries-- Google's Play Services Library and mapex (A third party google map extension library located here https://code.google.com/p/mapex/). I actually built most of this project in Android Studio before I was recommended to move to IntelliJ due to the easier dependency handling. But now I'm here and still having problems.
My Error
When trying to build an object from a class located in the mapex package (com.androidnatic.maps), I get this error when starting the activity the view is contained in (object has not been created yet):
07-03 11:40:35.837: ERROR/dalvikvm(3585): Could not find class 'com.androidnatic.maps.SimpleMapView', referenced from method com.example.myproject.MapActivity.showHeatMap
And then, upon creation, my app force closes and leaves this behind in logcat:
7-03 11:40:45.467: ERROR/AndroidRuntime(3585): FATAL EXCEPTION: main
java.lang.NoClassDefFoundError: com.androidnatic.maps.SimpleMapView
at com.example.myproject.MapActivity.showHeatMap(MapActivity.java:492)
Yet I'm completely stumped because my IDE gives me no sign that anything is wrong! Classes are auto-filled in when trying to access them from MyProject.
ide-fill-in http://www.tonyandrys.com/img/fillin.jpg
No build errors about missing classes, missing modules, class definitions, or anything related.
I get the same results if I try to access the class via its full package name as well.
// No dice.
final SimpleMapView mapView = new SimpleMapView(this, "apikey");
final com.androidnatic.maps.SimpleMapView mapView = new com.androidnatic.maps.SimpleMapView(this, "apikey");
It seems that there's only an issue when the application is running on my phone, as far as my IDE is concerned.
Here's the structure of MyProject:
main-project-structure http://www.tonyandrys.com/img/mainstructure.jpg
Here's my main project's dependency settings (where I assume I screwed up somewhere):
project-structure http://www.tonyandrys.com/img/projectstructure.jpg
And here is the structure of the mapex library module:
mapex-lib http://www.tonyandrys.com/img/mapexstructure.jpg
The class files that I'm trying to access live in MapExLib/gen and MapExLib/src, which are currently marked as source directories (blue).
Does anyone have any ideas on how to proceed from here?
Try to do this :
Android, IntelliJ Idea, changing module type
I had the same error "Could not find class XXX from referenced method XXX" with Intellij, involving an Android Test Module and a test which could not find the Activity class anywhere.
I set inside the Project Structure the main Module's Facet Android to Library Module (checkbox) and it worked...
Let us know

Problems using the EWS Java API on Android

I am trying to use the EWS Java API v1.1.5 (http://archive.msdn.microsoft.com/ewsjavaapi) in an Android application, and have run into a number of issues.
I downloaded the source, and followed the instructions provided to compile the EWS Java API in Eclipse. In those instructions you are told to download and
add the following pre-requiste jar file dependencies:
commons-codec-1.4.jar
commons-httpclient-3.1.jar
commons-logging-1.1.1.jar
jcifs-1.3.15.jar
I did this, and followed the build instructions with produced the following jar files:
EWSAPI-1.1.0.jar
EWSAPIWithJars-1.1.0
Next, I built a brand new Android application, added the appropriate permissions to the manifest, and then added the following source to the primary activity's OnCreate:
ExchangeService service = new ExchangeService();
ExchangeCredentials credentials = new WebCredentials("emailaddress", "password");
service.setCredentials(credentials);
try
{
service.autodiscoverUrl("emailaddress", this);
}
catch (Exception e)
{
e.printStackTrace();
}
I first tried running this application with the EWSAPI-1.1.0.jar file as a dependency. When I did that, I obtained the following fatal error:
Uncaught handler: thread main exiting due to uncaught exception
java.lang.NoClassDefFoundError:
org.apache.commons.httpclient.MultiThreadedHttpConnectionManager at
microsoft.exchange.webservices.data.ExchangeServiceBase.(Unknown
Source) at
microsoft.exchange.webservices.data.ExchangeServiceBase.(Unknown
Source) at
microsoft.exchange.webservices.data.ExchangeService.(Unknown
Source) at
com.meshin.exchange.ExchangeDiscoveryActivity.onCreate(ExchangeDiscoveryActivity.java:40)
From what I've researched, it seems like this error is being generated because Android comes with the Apache HttpClient 4.0, which doesn't appear
to have the MultiThreadedHttpConnectionManager class anymore.
If I instead remove the EWSAPI-1.1.0.jar, and instead use the EWSAPIWithJARS-1.1.0.jar file as a dependency, I get the following error:
VFY: unable to resolve static method 908: Ljavax/xml/stream/XMLOutputFactory;
newInstance()Ljavax/xml/stream/XMLOutputFactory;
VFY: dead code 0x0008-006a in L
microsoft/exchange/webservices/data/EwsUtilities;.formatLogMessage
(Ljava/lang/String;Ljava/lang/String;) Ljava/lang/String;
VFY: unable to find class referenced in signature (Ljavax/xml/stream/XMLStreamWriter;)
And then eventually...
FATAL EXCEPTION: main java.lang.VerifyError:
microsoft.exchange.webservices.data.AutodiscoverService at
microsoft.exchange.webservices.data.ExchangeService.getAutodiscoverUrl(Unknown
Source) at
microsoft.exchange.webservices.data.ExchangeService.autodiscoverUrl(Unknown
Source) at
com.meshin.exchange.ExchangeDiscoveryActivity.onCreate(ExchangeDiscoveryActivity.java:41)
I am assuming because now I am including the HttpClient 3.1 jar and it is conflicting with the HttpClient 4.0 jar included with the Android libraries.
My question is if there is a way for me to use the EWS Java API in an Android project without having to re-write the parts of it which reference
HttpClient 3.1-specific things which are no longer in 4.0.
You can use microsoft's EWS api for android by doing the following steps,
download the source code available in the URL,
http://archive.msdn.microsoft.com/ewsjavaapi
EWSJavaAPI_1.1.5.zip
Make the changes to above api to work for JDK 1.4 in eclipse like remove override annotations e.t.c
Download source code of javax.* package available in below URL,
http://www.java2s.com/Code/JarDownload/jsr173/jsr173_1.0_src.jar.zip
Download source code of stax api available in below URL,
http://dist.codehaus.org/stax/distributions/stax-src-1.2.0.zip
Keep all the sources under the single java project in eclipse
Open the project explorer and select the package which are starts with "javax" and rename to your company name eg: com. Note: Eclipse will ask for all the naming contexts will change then click OK.
Export all the java sources to one single jar file.
Then You good to go to use the jar in Android application with out any problems.
I used the same way explained above and it worked in android application 100% perfectly.
This isn't a useful answer but I've also been struggling to look at the EWS API over the last couple of weeks, with no success.
The main issue I've found is it references a lot of the javax APIs which aren't on Android. There's a hack you can find that explains how to "re-class" these but I've not got it working yet; in addition, the DnsClient references some namespaces that jarsearches only return for rt.jar - the main runtime. And including this in an Android app would just be crazy!
Before finding the API I was trying to use KSOAP to communicate with EWS but again ran into problems - you need to be able to do NTLM and SSL and I couldn't find any way of combining all these with KSOAP in any simple way.
The EWS API looks the way to go (why re-invent the wheel) but getting it working on Android looks very tricky (if not impossible)
Please check this library for the solution

Categories

Resources