NoClassDefFoundError and ClassNotFoundException for a Unity plugin

I am developing an Android plugin for a Unity application in Android Studio. The plugin aims to access the Google Fit API, and provide information that can then be displayed in the Unity application. I have included my Java file below, and my Gradle file and Manifest files at the end of this post.

UnityPlayerActivity.java file

package com.kasperiekqvist.player;

import android.Manifest;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.support.v4.app.ActivityCompat;

import com.google.android.gms.common.api.GoogleApiClient;
import com.unity3d.player.UnityPlayer;

import java.text.SimpleDateFormat;
import java.util.Date;

public class UnityPlayerActivity extends com.unity3d.player.UnityPlayerActivity {

    private GoogleApiClient mClient = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        logInUnity("onCreate", null);
        super.onCreate(savedInstanceState);
        checkPermissions();
    }

    /* SNIP */

    private boolean checkPermissions() {
        int permissionState = ActivityCompat.checkSelfPermission(this,
                Manifest.permission.ACCESS_FINE_LOCATION);
        boolean hasPermission = permissionState == PackageManager.PERMISSION_GRANTED;
        logInUnity("checkPermissions", new String[] { "ACCESS_FINE_LOCATION:" + hasPermission });
        return hasPermission;
    }

    private void logInUnity(String methodName, String[] linesToLog) {
        if(methodName != null) {
            String message = "UnityPlayerActivity:" + methodName + " was called at ";
            message += new SimpleDateFormat("MM-dd HH:mm:ss").format(new Date());
            if(linesToLog != null) {
                    for(int i = 0; i < linesToLog.length; i++) {
                        message += ";" + linesToLog[i];
                    }
            }
            UnityPlayer.UnitySendMessage("JavaCallback", "LogInUnity", message);
        }
    }
}

The logInUnity() method gets called properly. I am logging things using the Debug.Log() method inside my LogInUnity() method in my C# script. I can see everything in the Command Prompt when using the command adb logcat -s Unity delvikvm DEBUG.

The problem is accessing the Android Support Library. When I call ActivityCompat.checkSelfPermission() in my checkPermissions method, my Activity is force finished immediately. I have included the information on the crash below.

Crash info

10-15 19:57:53.843 18197 18197 E AndroidRuntime: FATAL EXCEPTION: main
10-15 19:57:53.843 18197 18197 E AndroidRuntime: Process: com.kasperiekqvist.androidpluginproject, PID: 18197
10-15 19:57:53.843 18197 18197 E AndroidRuntime: java.lang.Error: FATAL EXCEPTION [main]
10-15 19:57:53.843 18197 18197 E AndroidRuntime: Unity version     : 2017.2.0f3
10-15 19:57:53.843 18197 18197 E AndroidRuntime: Device model      : OnePlus ONEPLUS A5000
10-15 19:57:53.843 18197 18197 E AndroidRuntime: Device fingerprint: OnePlus/OnePlus5/OnePlus5:7.1.1/NMF26X/09131759:user/release-keys
10-15 19:57:53.843 18197 18197 E AndroidRuntime: 
10-15 19:57:53.843 18197 18197 E AndroidRuntime: Caused by: java.lang.NoClassDefFoundError: Failed resolution of: Landroid/support/v4/app/ActivityCompat;
10-15 19:57:53.843 18197 18197 E AndroidRuntime:    at com.kasperiekqvist.player.UnityPlayerActivity.checkPermissions(UnityPlayerActivity.java:74)
10-15 19:57:53.843 18197 18197 E AndroidRuntime:    at com.kasperiekqvist.player.UnityPlayerActivity.onCreate(UnityPlayerActivity.java:27)
10-15 19:57:53.843 18197 18197 E AndroidRuntime:    at android.app.Activity.performCreate(Activity.java:6743)
10-15 19:57:53.843 18197 18197 E AndroidRuntime:    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1134)
10-15 19:57:53.843 18197 18197 E AndroidRuntime:    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2715)
10-15 19:57:53.843 18197 18197 E AndroidRuntime:    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2848)
10-15 19:57:53.843 18197 18197 E AndroidRuntime:    at android.app.ActivityThread.-wrap12(ActivityThread.java)
10-15 19:57:53.843 18197 18197 E AndroidRuntime:    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1552)
10-15 19:57:53.843 18197 18197 E AndroidRuntime:    at android.os.Handler.dispatchMessage(Handler.java:102)
10-15 19:57:53.843 18197 18197 E AndroidRuntime:    at android.os.Looper.loop(Looper.java:154)
10-15 19:57:53.843 18197 18197 E AndroidRuntime:    at android.app.ActivityThread.main(ActivityThread.java:6334)
10-15 19:57:53.843 18197 18197 E AndroidRuntime:    at java.lang.reflect.Method.invoke(Native Method)
10-15 19:57:53.843 18197 18197 E AndroidRuntime:    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
10-15 19:57:53.843 18197 18197 E AndroidRuntime:    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)
10-15 19:57:53.843 18197 18197 E AndroidRuntime: Caused by: java.lang.ClassNotFoundException: Didn't find class "android.support.v4.app.ActivityCompat" on path: DexPathList[[zip file "/data/app/com.kasperiekqvist.androidpluginproject-2/base.apk"],nativeLibraryDirectories=[/data/app/com.kasperiekqvist.androidpluginproject-2/lib/arm, /data/app/com.kasperiekqvist.androidpluginproject-2/base.apk!/lib/armeabi-v7a, /system/lib, /vendor/lib]]
10-15 19:57:53.843 18197 18197 E AndroidRuntime:    at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56)
10-15 19:57:53.843 18197 18197 E AndroidRuntime:    at java.lang.ClassLoader.loadClass(ClassLoader.java:380)
10-15 19:57:53.843 18197 18197 E AndroidRuntime:    at java.lang.ClassLoader.loadClass(ClassLoader.java:312)
10-15 19:57:53.843 18197 18197 E AndroidRuntime:    ... 14 more
10-15 19:57:53.843 18197 18197 D AppTracker: App Event: crash
10-15 19:57:53.846  1804 16770 W ActivityManager:   Force finishing activity com.kasperiekqvist.androidpluginproject/com.kasperiekqvist.player.UnityPlayerActivity
10-15 19:57:53.848  1804 16770 D ActivityTrigger: ActivityTrigger activityPauseTrigger 
10-15 19:57:53.849 18197 18197 I Process : Sending signal. PID: 18197 SIG: 9
10-15 19:57:53.851  4741  6303 D OPReportService: addMonitorFolder onEvent [email protected]_57_53_851.txt, event:128
10-15 19:57:53.860  1804  4733 D EmbryoManager: prepare com.kasperiekqvist.androidpluginproject
10-15 19:57:53.860  1804  4733 I ActivityManager: Process com.kasperiekqvist.androidpluginproject (pid 18197) has died
10-15 19:57:53.860  1804  4733 D ActivityManager: get process top duration : com.kasperiekqvist.androidpluginproject, duration : 45
10-15 19:57:53.860  1804  4733 D ActivityManager: cleanUpApplicationRecord -- 18197

I have included compile 'com.android.support:support-v4:25.3.1' in the dependencies of my gradle file. Based on the research I’ve done, I think the problem is that the Android Support Library is not included in my jar file as it should be. I could be wrong about that, though.

Nevertheless, I am running out of things to try. I found many similar problems with the same errors on Stack Overflow, and I tried to solve my issue using many of the things suggested in the answers of those questions. However, so far none of them have worked.

And just to clarify, everything worked properly before adding the ActivityCompat.checkSelfPermission() method call. So, the problem must be with the Support Library.

build.gradle file

apply plugin: 'com.android.library'

android {
    compileSdkVersion 25
    buildToolsVersion "26.0.2"

    defaultConfig {
        minSdkVersion 16
        targetSdkVersion 25
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"

    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })
    compile 'com.android.support:appcompat-v7:25.3.1'
    testCompile 'junit:junit:4.12'
    compile 'com.google.android.gms:play-services-fitness:11.0.4'
    compile 'com.android.support:support-v4:25.3.1'
}

AndroidManifest.xml file

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.kasperiekqvist.androidpluginproject" xmlns:tools="http://schemas.android.com/tools" android:versionName="1.0" android:versionCode="1" android:installLocation="preferExternal">
  <supports-screens android:smallScreens="true" android:normalScreens="true" android:largeScreens="true" android:xlargeScreens="true" android:anyDensity="true" />
  <application android:theme="@style/UnityThemeSelector" android:icon="@drawable/app_icon" android:label="@string/app_name" android:debuggable="false" android:isGame="true" android:banner="@drawable/app_banner">
    <activity android:name="com.kasperiekqvist.player.UnityPlayerActivity" android:label="@string/app_name" android:screenOrientation="fullSensor" android:launchMode="singleTask" android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|orientation|screenLayout|uiMode|screenSize|smallestScreenSize|fontScale|layoutDirection|density">
      <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
        <category android:name="android.intent.category.LEANBACK_LAUNCHER" />
      </intent-filter>
      <meta-data android:name="unityplayer.UnityActivity" android:value="true" />
    </activity>
    <meta-data android:name="unity.build-id" android:value="c9792a78-0123-4f4b-be86-1b85de56f689" />
    <meta-data android:name="unity.splash-mode" android:value="0" />
    <meta-data android:name="unity.splash-enable" android:value="True" />
    <meta-data android:name="android.max_aspect" android:value="2.1" />
  </application>
  <uses-sdk android:minSdkVersion="16" android:targetSdkVersion="25" />
  <uses-feature android:glEsVersion="0x00020000" />
  <uses-feature android:name="android.hardware.vulkan" android:required="false" />
  <uses-feature android:name="android.hardware.touchscreen" android:required="false" />
  <uses-feature android:name="android.hardware.touchscreen.multitouch" android:required="false" />
  <uses-feature android:name="android.hardware.touchscreen.multitouch.distinct" android:required="false" />
  <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
</manifest>

Answer

I managed to solve my problem by using the Play Services Resolver for Unity. I followed the steps detailed in the README.md file, and included the *Dependencies.xml file with the following content:

<dependencies>
  <androidPackages>
    <androidPackage spec="com.android.support:support-v4:25.3.1">
      <androidSdkPackageIds>
        <androidSdkPackageId>extras-android-m2repository</androidSdkPackageId>
      </androidSdkPackageIds>
      <repositories>
        <repository>https://maven.google.com</repository>
      </repositories>
    </androidPackage>
  </androidPackages>
</dependencies>

After the Resolver had done its work, my Project files ended up looking like this:

enter image description here

In hindsight, I wonder if it would have been enough to import these files from the files found under the Android SDK folder. I think I tried including the support-v4-25.3.1 previously already, but for some reason I remember that not working.

After this and after explicitly giving the ACCESS_FINE_LOCATION permission to the app, I managed to get the following output in my Command Prompt which proved that everything now works:

10-15 23:43:26.574  3438  3693 I Unity   : UnityPlayerActivity:checkPermissions was called at 10-15 23:43:23
10-15 23:43:26.574  3438  3693 I Unity   : ACCESS_FINE_LOCATION:true
10-15 23:43:26.574  3438  3693 I Unity   :  
10-15 23:43:26.574  3438  3693 I Unity   : (Filename: ./artifacts/generated/common/runtime/DebugBindings.gen.cpp Line: 51)
10-15 23:43:26.574  3438  3693 I Unity   : 

Leave a Reply

Your email address will not be published. Required fields are marked *