Search Unity

ClassNotFoundException with Google Maps plugin

Discussion in 'Android' started by FlorianTuttiFrutti, Dec 5, 2016.

  1. FlorianTuttiFrutti

    FlorianTuttiFrutti

    Joined:
    Sep 29, 2016
    Posts:
    13
    Hi everybody !
    I'm currently working on an app that will display a GMap view inside Unity. So i have to use the Android SDK of GMaps with Android Studio to create a plugin that'll do the trick.

    But I ran into a problem that get me stuck for a while, when I try to call my plugin inside Unity with
    Code (CSharp):
    1.  AndroidJavaClass _class = new AndroidJavaClass ("net.tuttifruttigames.mapsplugin.MapsPlugin");
    I have this error : AndroidJavaException: java.lang.ClassNotFoundException: net.tuttifruttigames.mapsplugin.MapsPlugin.

    The definition of my java class is :
    Code (CSharp):
    1. package net.tuttifruttigames.mapsplugin;
    2.  
    3. public class MapsPlugin extends FragmentActivity implements OnMapReadyCallback
    I followed this tutorial http://eppz.eu/blog/unity-android-plugin-tutorial-2/ to do a basic Android plugin (that was working), then I customized it to display a map (that is not working).
    This allowed me to found the problem come from the classes FragmentActivity and OnMapReadyCallback. If I remove both of them, my class is found by Unity but I need to implement and extend them to display my map. So I'm kind of stuck since I didn't find any satisfying answer on the forums.

    Does anyone know where this problem can come from and how to solve it?

    Thanks !
     
  2. liortal

    liortal

    Joined:
    Oct 17, 2012
    Posts:
    3,562
    It's hard to tell why it's not working without seeing the full runtime logs.

    The error message you posted means that at runtime, your plugin class cannot be located. This can happen due to several different reasons, listing a few from the top of my head:
    1. You forgot to include the plugin code into your Unity project and does not get built into the .apk
    2. There's some reason why it's not being included into the compiled .apk
    3. A name mismatch (the full class name doesn't match the name you specified to the AndroidJavaClass constructor).
    Please share some more logs and verify if you're really including the plugin code in your project.

    Shameless Plug: I can provide a professional service for dealing with this kind of Android plugin and SDK integrations. In case you're interested, please contact me here.
     
  3. FlorianTuttiFrutti

    FlorianTuttiFrutti

    Joined:
    Sep 29, 2016
    Posts:
    13
    Hi liortal, thanks for your answer. To respond to your interrogations :

    Here's the runtime log I get when I launch the app on an Android phone (not sure it will help):
    Code (CSharp):
    1. 12-06 09:25:30.477 7038-7071/? I/Unity: AndroidJavaException: java.lang.ClassNotFoundException: net.tuttifruttigames.mapsplugin.MapsPlugin
    2.                                         java.lang.ClassNotFoundException: net.tuttifruttigames.mapsplugin.MapsPlugin
    3.                                             at java.lang.Class.classForName(Native Method)
    4.                                             at java.lang.Class.forName(Class.java:308)
    5.                                             at java.lang.Class.forName(Class.java:272)
    6.                                             at com.unity3d.player.UnityPlayer.nativeRender(Native Method)
    7.                                             at com.unity3d.player.UnityPlayer.a(Unknown Source)
    8.                                             at com.unity3d.player.UnityPlayer$b$1.handleMessage(Unknown Source)
    9.                                             at android.os.Handler.dispatchMessage(Handler.java:98)
    10.                                             at android.os.Looper.loop(Looper.java:145)
    11.                                             at com.unity3d.player.UnityPlayer$b.run(Unknown Source)
    12.                                          Caused by: java.lang.ClassNotFoundException: Didn't find class "net.tuttifruttigames.mapsplugin.MapsPlugin" on path: DexPathList[[zip file "/data/app/net.tuttifruttigames.mapsplugin-2/base.apk"],nativeLibraryDirectories=[/data/app/net.tuttifruttigames.mapsplugin-2/lib/arm, /vendor/lib, /system/lib]]
    13.                                            at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.ja
    At first I didn't include the .java files into the Assets/Plugins/Android folder, but I copied the .aar file of my plugin into this folder and with the tutorial I followed, it was enough to make it work. Anyway, I tried copying my .java file into the folder but no changes, still the same error.

    There's no name mismatch. As I said, I only have this error when I try to extend my class from FragmentActivity or when I make it implement OnMapReadyCallback. If I remove these 2 class calls, the error is gone.
     
  4. FlorianTuttiFrutti

    FlorianTuttiFrutti

    Joined:
    Sep 29, 2016
    Posts:
    13
    I also tried something else, declaring directly a Fragment Activity object and a OnMapReadyCallBack object inside the java code without extending or implementing the classes, like this :
    Code (CSharp):
    1. FragmentActivity fragmentActivity = new FragmentActivity();
    2.         OnMapReadyCallback onMapReadyCallback = new OnMapReadyCallback() {
    3.             @Override
    4.             public void onMapReady(GoogleMap googleMap) {
    5.                 Log.d("Unity_MapsPlugin", "Map ready");
    6.             }
    7.         };
    And this time, the ClassNotFoundException is gone so my class is found and instead I get a NoClassDefFoundError at the declaration of my FragmentActivity object. And if I put the OnMapReadyCallback object first, it's it that got the NoClassDefFoundError. Here's the log :
    Code (CSharp):
    1. 12-06 09:49:50.672 9178-9225/? I/Unity: AndroidJavaException: java.lang.NoClassDefFoundError: Failed resolution of: Landroid/support/v4/app/FragmentActivity;
    2.                                         java.lang.NoClassDefFoundError: Failed resolution of: Landroid/support/v4/app/FragmentActivity;
    3.                                             at net.tuttifruttigames.mapsplugin.MapsPlugin.Start(MapsPlugin.java:52)
    4.                                             at net.tuttifruttigames.mapsplugin.MapsPlugin.Init(MapsPlugin.java:37)
    5.                                             at com.unity3d.player.UnityPlayer.nativeRender(Native Method)
    6.                                             at com.unity3d.player.UnityPlayer.a(Unknown Source)
    7.                                             at com.unity3d.player.UnityPlayer$b$1.handleMessage(Unknown Source)
    8.                                             at android.os.Handler.dispatchMessage(Handler.java:98)
    9.                                             at android.os.Looper.loop(Looper.java:145)
    10.                                             at com.unity3d.player.UnityPlayer$b.run(Unknown Source)
    11.                                          Caused by: java.lang.ClassNotFoundException: Didn't find class "android.support.v4.app.FragmentActivity" on path: DexPathList[[zip file "/data/app/net.tuttifruttigames.mapsplugin-1/base.apk"],nativeLibraryDirectories=[/data/app/net.tuttifruttigames.mapsplugin-1/lib/arm, /vendor/lib, /system/lib]]
    12.                                            at dalvik.system.BaseDe
     
  5. liortal

    liortal

    Joined:
    Oct 17, 2012
    Posts:
    3,562
    you never copy the .java files since i don't think Unity will compile them. It only packages compiled code/resources into the .apk.

    Regarding your issue - hard to tell without looking at the project structure and more logs (there could be other logs before the one you showed, for example - logs from the JVM about the class failing to load because of missing dependencies, etc).
     
  6. FlorianTuttiFrutti

    FlorianTuttiFrutti

    Joined:
    Sep 29, 2016
    Posts:
    13
    I uploaded a screenshot of the structure of my Android project.
    Unity side, the structure is really basic since I created a new project just for that, with in Assets folder only a Test scene, a Test script and a Plugins/Android/MyPlugin folder where I put my .aar file.

    Concerning the logs, I didn't find some about the JVM or missing dependencies but here you can see all the logs before the error concerning my plugin :
    Code (CSharp):
    1. 12-06 11:57:29.411 325-325/? I/Timeline: Timeline: Activity_launch_request id:net.tuttifruttigames.mapsplugin time:85631002
    2. 12-06 11:57:29.421 2721-5484/? D/GameManagerService: identifyGamePackage. net.tuttifruttigames.mapsplugin
    3. 12-06 11:57:29.421 2721-5484/? D/MultiWindowPolicy: Gamemode - return 0,  when calling  identifyForegroundApp(net.tuttifruttigames.mapsplugin)
    4. 12-06 11:57:29.421 2721-5484/? V/WindowManager: addAppToken: AppWindowToken{d03df7868 token=Token{a519f8b ActivityRecord{193315a u0 net.tuttifruttigames.mapsplugin/com.unity3d.player.UnityPlayerActivity t3894}}} to stack=1 task=3894 at 0
    5. 12-06 11:57:29.431 2721-4959/? D/MountService: getExternalStorageMountMode : final mountMode=1, uid : 10234, packageName : net.tuttifruttigames.mapsplugin
    6. 12-06 11:57:29.451 6764-6764/? W/SELinux: SELinux: seapp_context_lookup: seinfo=default, level=s0:c512,c768, pkgname=net.tuttifruttigames.mapsplugin
    7. 12-06 11:57:29.451 2721-4959/? I/ActivityManager: Start proc 6764:net.tuttifruttigames.mapsplugin/u0a234 for activity net.tuttifruttigames.mapsplugin/com.unity3d.player.UnityPlayerActivity
    8. 12-06 11:57:29.471 2721-2846/? V/WindowStateAnimator: Finishing drawing window Window{751e2b9 u0 d0 p2721 Starting net.tuttifruttigames.mapsplugin}: mDrawState=DRAW_PENDING
    9. 12-06 11:57:29.571 2721-8003/? D/ActivityManager:  Launching net.tuttifruttigames.mapsplugin, updated priority
    10. 12-06 11:57:29.571 2721-2721/? D/GameManagerService: NotifyRunnable. pkg: net.tuttifruttigames.mapsplugin, type: 4, isMinimized: false, isTunableApp: false
    11. 12-06 11:57:29.581 2721-2773/? V/MARsPolicyManager: updatePackagesScore PackageInfo name -- net.tuttifruttigames.mapsplugin
    12. 12-06 11:57:29.591 2721-7938/? D/GameManagerService: identifyGamePackage. net.tuttifruttigames.mapsplugin
    13. 12-06 11:57:29.601 2721-7938/? D/GameManagerService: identifyGamePackage. net.tuttifruttigames.mapsplugin
    14. 12-06 11:57:29.601 2721-2774/? D/StatusBarManagerService: manageDisableList userId=0 what=0x0 pkg=Window{751e2b9 u0 d0 p2721 Starting net.tuttifruttigames.mapsplugin}
    15. 12-06 11:57:29.881 2721-2774/? D/StatusBarManagerService: manageDisableList userId=0 what=0x0 pkg=Window{6cd817b u0 d0 p6764 net.tuttifruttigames.mapsplugin/com.unity3d.player.UnityPlayerActivity}
    16. 12-06 11:57:29.991 2721-5484/? V/WindowStateAnimator: Finishing drawing window Window{6cd817b u0 d0 p6764 net.tuttifruttigames.mapsplugin/com.unity3d.player.UnityPlayerActivity}: mDrawState=DRAW_PENDING
    17. 12-06 11:57:30.001 2721-2846/? I/ActivityManager: Displayed net.tuttifruttigames.mapsplugin/com.unity3d.player.UnityPlayerActivity: +568ms
    18. 12-06 11:57:30.001 2721-2846/? I/Timeline: Timeline: Activity_windows_visible id: ActivityRecord{193315a u0 net.tuttifruttigames.mapsplugin/com.unity3d.player.UnityPlayerActivity t3894} time:85631596
    19. 12-06 11:57:30.011 2721-2736/? V/WindowStateAnimator: Finishing drawing window Window{6cd817b u0 d0 p6764 net.tuttifruttigames.mapsplugin/com.unity3d.player.UnityPlayerActivity}: mDrawState=HAS_DRAWN
    20. 12-06 11:57:30.321 6764-6778/? D/libGLESv2: DTS_GLAPI : DTS is not allowed for Package : net.tuttifruttigames.mapsplugin
    21. 12-06 11:57:35.341 6764-6778/? I/art: Rejecting re-init on previously-failed class java.lang.Class<net.tuttifruttigames.mapsplugin.MapsPlugin>
    22. 12-06 11:57:35.341 6764-6778/? I/art: Rejecting re-init on previously-failed class java.lang.Class<net.tuttifruttigames.mapsplugin.MapsPlugin>
    23. 12-06 11:57:35.571 6764-6778/? I/Unity: AndroidJavaException: java.lang.ClassNotFoundException: net.tuttifruttigames.mapsplugin.MapsPlugin
    24.                                         java.lang.ClassNotFoundException: net.tuttifruttigames.mapsplugin.MapsPlugin
    25.                                             at java.lang.Class.classForName(Native Method)
    26.                                             at java.lang.Class.forName(Class.java:324)
    27.                                             at java.lang.Class.forName(Class.java:285)
    28.                                             at com.unity3d.player.UnityPlayer.nativeRender(Native Method)
    29.                                             at com.unity3d.player.UnityPlayer.a(Unknown Source)
    30.                                             at com.unity3d.player.UnityPlayer$b$1.handleMessage(Unknown Source)
    31.                                             at android.os.Handler.dispatchMessage(Handler.java:98)
    32.                                             at android.os.Looper.loop(Looper.java:148)
    33.                                             at com.unity3d.player.UnityPlayer$b.run(Unknown Source)
    34.                                          Caused by: java.lang.ClassNotFoundException: Didn't find class "net.tuttifruttigames.mapsplugin.MapsPlugin" on path: DexPathList[[zip file "/data/app/net.tuttifruttigames.mapsplugin-2/base.apk"],nativeLibraryDirectories=[/data/app/net.tuttifruttigames.mapsplugin-2/lib/arm, /data/app/net.tuttifruttigames.mapsplugin-2/base.apk!/lib/armeabi-v7a, /vendor/lib, /system/lib
    35.  
     

    Attached Files:

  7. FlorianTuttiFrutti

    FlorianTuttiFrutti

    Joined:
    Sep 29, 2016
    Posts:
    13
    Here's my gradle file, maybe it can help
    Code (CSharp):
    1. apply plugin: 'com.android.library'
    2.  
    3. android {
    4.     compileSdkVersion 24
    5.     buildToolsVersion "25.0.1"
    6.  
    7.     defaultConfig {
    8.         minSdkVersion 19
    9.         targetSdkVersion 24
    10.         versionCode 1
    11.         versionName "1.0"
    12.  
    13.     }
    14.     buildTypes {
    15.         release {
    16.             minifyEnabled false
    17.             proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
    18.         }
    19.     }
    20. }
    21.  
    22. dependencies {
    23.     compile 'com.google.android.gms:play-services:10.0.1'
    24.     compile 'com.android.support:appcompat-v7:24.2.1'
    25.     provided files('./libs/UnityClasses.jar') // Avoid redundant Unity Player in final application APK
    26. }
    27.  
    28. //The following part is used to automatically copy the .aar file into my plugin folder in Unity
    29. android.libraryVariants.all { variant ->
    30.     // Task names.
    31.     String variantName = "${variant.name.capitalize()}"; // Like 'Debug'
    32.     String deployTaskGroup = "plugin";
    33.     String deployTaskName = "deploy${variantName}PluginArchive"; // Like 'deployDebugPluginArchive'
    34.     String dependencyTaskName = "assemble${variantName}"; // Like 'assembleDebug'
    35.     // Source.
    36.     String sourceAARFolder = "${buildDir.getPath()}/outputs/aar/";
    37.     String sourceAARName = "${project.name}-${variant.name}.aar";
    38.     // Target.
    39.     String targetAssetFolder = "Assets/Plugins/Android/MyPlugin";
    40.     String targetAARFolder = "${rootDir.getPath()}/../../${targetAssetFolder}"; // Navigate into 'Assets'
    41.     String targetAARName = "MyPluginAndroid.aar"; // The form you ship your plugin
    42.     // Create task.
    43.     task(deployTaskName, dependsOn: dependencyTaskName, type: Copy) {
    44.         from(sourceAARFolder)
    45.         into(targetAARFolder)
    46.         include(sourceAARName)
    47.         rename(sourceAARName, targetAARName)
    48.     }.group = deployTaskGroup;
    49. }
    50.  
     
  8. liortal

    liortal

    Joined:
    Oct 17, 2012
    Posts:
    3,562
    1. 12-06 11:57:35.341 6764-6778/? I/art: Rejecting re-init on previously-failed class java.lang.Class<net.tuttifruttigames.mapsplugin.MapsPlugin>
    2. 12-06 11:57:35.341 6764-6778/? I/art: Rejecting re-init on previously-failed class java.lang.Class<net.tuttifruttigames.mapsplugin.MapsPlugin>
    Like i suspected it appears that this class is not properly initialized.. I think the log is still not complete though.
     
  9. FlorianTuttiFrutti

    FlorianTuttiFrutti

    Joined:
    Sep 29, 2016
    Posts:
    13
    Here, I uploaded all the logs from the launch of the app until the error. I don't know it you can find something interesting in it since there is a lot of noise from all the phone listener (wallpaper, sensor, orientation,...) compared from the previous logs I gave you.
    I retrieve the logs through Android Studio but maybe there is a better way to do or a better tool, I don't know.

    Do you have any idea how I can solve this "Rejecting re-init on previously-failed class..." messages ?
    When I remove the call to the 2 problematic classes, these messages are gone, so it might come from there.
     

    Attached Files:

    • logs.txt
      File size:
      33.9 KB
      Views:
      1,044
  10. liortal

    liortal

    Joined:
    Oct 17, 2012
    Posts:
    3,562
    Sorry, but i don't really what could lead to this. What devices have you tested on ? (device model + android versions) ?
     
  11. FlorianTuttiFrutti

    FlorianTuttiFrutti

    Joined:
    Sep 29, 2016
    Posts:
    13
    I tested on a Galaxy S4 (Android 5.0.1) and a Galaxy A5 2016 (Android 6.0.1)
     
  12. liortal

    liortal

    Joined:
    Oct 17, 2012
    Posts:
    3,562
    I actually ran into a similar issue today (had the same error message as you posted).
    This error is definitely related to missing dependencies. the problem is there's no other information that is shown previously to let you know what exactly is missing.

    You can look at how you're building your library (see the compile time dependencies). Some of them are probably not included in the project and so are missing at runtime. That's probably your problem.
     
  13. FlorianTuttiFrutti

    FlorianTuttiFrutti

    Joined:
    Sep 29, 2016
    Posts:
    13
    Yes that's the thing I figured out yestersday. I analyzed my final apk with Android Studio and in the classes.dex, there were no GMaps class (com.google.android.gms.maps) so I added manually the corresponding jar to the Plugins/Android folder and now the google class are here, so no more problem with OnMapReadyCallback.
    But I still have the problem with FragmentActivity even if its class (android.support.v4.app) is also present in the apk.
    I uploaded the content of my apk's classes.dex if you want to see.

    But I don't think it's the right thing to do to copy the jar manually so maybe you know how to add external librairies directly to the jar/aar file directly in Android Studio?
    I tried this and I also tried to copy the jar inside the libs folder of my android project but it doesn't solve my problem.
     

    Attached Files:

    Last edited: Dec 8, 2016
  14. liortal

    liortal

    Joined:
    Oct 17, 2012
    Posts:
    3,562
    How are you looking at the contents of the classes.dex ?
     
  15. Hemaolle

    Hemaolle

    Joined:
    Jun 25, 2013
    Posts:
    10
    I experienced a java.lang.ClassNotFoundException with an Android plugin some time ago and got it solved by moving my plugin .jar file directly under Assets/Plugins/Android instead of placing it under a subdirectory there.
     
  16. FlorianTuttiFrutti

    FlorianTuttiFrutti

    Joined:
    Sep 29, 2016
    Posts:
    13
    I moved my jar directly under the Plugins/Android folder by it didn't solve my problem.
     
  17. FlorianTuttiFrutti

    FlorianTuttiFrutti

    Joined:
    Sep 29, 2016
    Posts:
    13
    In Android Studio, Build/Analyze APK then you choose your apk and finally click on dex.classes
     
  18. liortal

    liortal

    Joined:
    Oct 17, 2012
    Posts:
    3,562
    Thanks i didn't know about this option!
    You don't want to know how i used to decompile apk's until now :)
     
  19. iamsidv

    iamsidv

    Joined:
    Jan 24, 2013
    Posts:
    17
    Hi, did you manage to solve your problem by any chance?
    I am also facing the same issue with Google Sign In feature that I am trying to implement.