Search Unity

Simple Android Plugin not working! Any idea ?!

Discussion in 'Android' started by G3R1, Aug 15, 2018.

  1. G3R1

    G3R1

    Joined:
    Sep 3, 2016
    Posts:
    33
    Hi everyone,

    I am trying to make an android plugin for unity that simply displays a dialog box to enable gps.

    Below is the Java code inside the gpsplugin.jar file:

    Code (CSharp):
    1.  
    2. package com.ultimategames.gpslib;
    3.  
    4. import android.app.Activity;
    5. import android.content.IntentSender;
    6.  
    7. import com.google.android.gms.appindexing.AppIndex;
    8. import com.google.android.gms.common.api.GoogleApiClient;
    9. import com.google.android.gms.common.api.PendingResult;
    10. import com.google.android.gms.common.api.ResultCallback;
    11. import com.google.android.gms.common.api.Status;
    12. import com.google.android.gms.location.LocationRequest;
    13. import com.google.android.gms.location.LocationServices;
    14. import com.google.android.gms.location.LocationSettingsRequest;
    15. import com.google.android.gms.location.LocationSettingsResult;
    16. import com.google.android.gms.location.LocationSettingsStates;
    17. import com.google.android.gms.location.LocationSettingsStatusCodes;
    18. import com.unity3d.player.UnityPlayer;
    19. import com.unity3d.player.UnityPlayerActivity;
    20.  
    21. import java.io.DataOutputStream;
    22.  
    23. public class GPSClass extends UnityPlayerActivity {
    24.  
    25.     GoogleApiClient googleApiClient;
    26.     LocationRequest locationRequest;
    27.  
    28.     public void AskToEnableGPS(final Activity activity) {
    29.  
    30.         if (googleApiClient == null) {
    31.             googleApiClient = new GoogleApiClient.Builder(activity.getApplicationContext()).addApi(LocationServices.API).build();
    32.             googleApiClient.connect();
    33.  
    34.             locationRequest = LocationRequest.create();
    35.             locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
    36.             locationRequest.setInterval(30 * 1000);
    37.             locationRequest.setFastestInterval(5 * 1000);
    38.  
    39.             LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder().addLocationRequest(locationRequest);
    40.  
    41.             builder.setAlwaysShow(true);
    42.  
    43.             PendingResult<LocationSettingsResult> result =
    44.                     LocationServices.SettingsApi.checkLocationSettings(googleApiClient, builder.build());
    45.  
    46.             result.setResultCallback(new ResultCallback<LocationSettingsResult>() {
    47.                 @Override
    48.                 public void onResult(LocationSettingsResult result) {
    49.                     final Status status = result.getStatus();
    50.                     final LocationSettingsStates state = result.getLocationSettingsStates();
    51.                     switch (status.getStatusCode()) {
    52.                         case LocationSettingsStatusCodes.SUCCESS:
    53.                             break;
    54.                         case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
    55.                             try {
    56.                                 status.startResolutionForResult((Activity) activity.getApplicationContext(), 1000);
    57.                             } catch (IntentSender.SendIntentException e) {
    58.                             }
    59.                             break;
    60.                         case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
    61.                             break;
    62.                     }
    63.                 }
    64.             });
    65.         }
    66.     }
    67. }
    68.  
    And here you have the code on Testing.cs script that I am using to access the plugin:
    Code (CSharp):
    1.  
    2. using UnityEngine;
    3.  
    4. public class Testing : MonoBehaviour {
    5.  
    6.     #if UNITY_ANDROID
    7.  
    8.     AndroidJavaObject javaObject;
    9.     AndroidJavaClass unityClass;
    10.     AndroidJavaObject unityActivity;
    11.  
    12.     private void Start()
    13.     {
    14.         javaObject = new AndroidJavaObject("com.ultimategames.gpslib.GPSClass");
    15.         unityClass = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
    16.         unityActivity = unityClass.GetStatic<AndroidJavaObject>("currentActivity");
    17.     }
    18.  
    19.     public void AskforGPS()
    20.     {
    21.         javaObject.Call("AskToEnableGPS", unityActivity);
    22.     }
    23.  
    24. #endif
    25. }
    26.  
    The code is working fine when I run it as an application in android studio to my device but when I use the plugin in Unity it doesn't work on my device. Also, I have searched on google and I haven't found a solution for this.

    I would appreciate any help or idea guys.

    Thank you,
    Gerald
     
  2. G3R1

    G3R1

    Joined:
    Sep 3, 2016
    Posts:
    33
    This is the error that I get from Logcat:

    Code (CSharp):
    1. 08-15 20:55:53.436 4847-4865/? E/Unity: AndroidJavaException: java.lang.NoClassDefFoundError: Failed resolution of: Lcom/google/android/gms/common/api/GoogleApiClient$Builder;
    2.     java.lang.NoClassDefFoundError: Failed resolution of: Lcom/google/android/gms/common/api/GoogleApiClient$Builder;
    3.         at com.ultimategames.gpslib.GPSClass.AskToEnableGPS(GPSClass.java:82)
    4.         at com.unity3d.player.UnityPlayer.nativeRender(Native Method)
    5.         at com.unity3d.player.UnityPlayer.c(Unknown Source)
    6.         at com.unity3d.player.UnityPlayer$e$2.queueIdle(Unknown Source)
    7.         at android.os.MessageQueue.next(MessageQueue.java:392)
    8.         at android.os.Looper.loop(Looper.java:143)
    9.         at com.unity3d.player.UnityPlayer$e.run(Unknown Source)
    10.      Caused by: java.lang.ClassNotFoundException: Didn't find class "com.google.android.gms.common.api.GoogleApiClient$Builder" on path: DexPathList[[zip file "/data/app/com.ultimategames.testing-1/base.apk"],nativeLibraryDirectories=[/data/app/com.ultimategames.testing-1/lib/arm, /data/app/com.ultimategames.testing-1/base.apk!/lib/armeabi-v7a, /vendor/lib, /system/l
    11.  
    o_O:confused::mad:
     
  3. G3R1

    G3R1

    Joined:
    Sep 3, 2016
    Posts:
    33
    I managed to solve this by myself. :eek:
     
  4. sripadkowshik

    sripadkowshik

    Joined:
    Oct 23, 2017
    Posts:
    3
    Hi @G3R1. If you can post the solution that you found it would be great. I myself am trying to learn about plugins and stuff in Unity and I believe your solution would help me in future.
    Thanks.
     
  5. G3R1

    G3R1

    Joined:
    Sep 3, 2016
    Posts:
    33
    Sure.
    The solution:
    1- Make sure to copy your android plugin .jar file into Assets/Plugins/Android folder in Unity.
    2- Download Google Play Game Services for Unity and then import all the dependencies in Unity using the unity package inside "current-build" folder that is inside the package you download from GitHub.
    3- Go to menu Assets-> Play Services Resolver-> Android Resolver -> Force Resolve.
    After you have clicked Force Resolve Unity will generate the necessary .aar and .jar files for Google Play Services.
    At this moment you can copy the version number of the .aar files, for ex: "com-google-android-gms-play-services:11.6.2". You need to copy the number "11.6.2".
    4- Then go back to your plugin on Android Studio and open build.gradle (module: yourpluginname) and change the version of Play Services as below:
    Code (CSharp):
    1.  
    2. dependencies {
    3.     implementation fileTree(include: ['*.jar'], dir: 'libs')
    4.     implementation 'com.android.support:appcompat-v7:25.2.0'
    5.     implementation 'com.android.support:support-v4:25.2.0'
    6.     testImplementation 'junit:junit:4.12'
    7.     androidTestImplementation 'com.android.support.test:runner:1.0.2'
    8.     androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
    9.     implementation files('/Applications/Unity/PlaybackEngines/AndroidPlayer/Variations/mono/Release/Classes/classes.jar')
    10.     implementation 'com.google.android.gms:play-services:11.6.2'
    11. }
    5- After you have changed the version number of dependecies on your plugin you have to build the plugin module again and copy it to Assets/Plugins/Android and the error :
    Code (CSharp):
    1. Caused by: java.lang.ClassNotFoundException: Didn't find class "com.google.android.gms.common.api.GoogleApiClient$Builder"
    will not appear anymore and the plugin should work just fine.

    If the error says that another class is missing, you just have to download the .jar file of that class and include it to Assets/Plugins/Android in Unity and build it again to see if the error is gone.

    I don't have much time to give you a detailed solution but this should work 100%. :rolleyes:
     
    rosssssss and sripadkowshik like this.
  6. G3R1

    G3R1

    Joined:
    Sep 3, 2016
    Posts:
    33
    Also, you can download .jar classes from here https://mvnrepository.com.
    Search the name of the class and then download the .jar or .aar file. If you download the .aar file you need to get the .jar class file inside the .aar package and then paste it into Assets/Plugins/Android.

    Hope it helps! ;)
     
    rosssssss and sripadkowshik like this.
  7. sripadkowshik

    sripadkowshik

    Joined:
    Oct 23, 2017
    Posts:
    3
    Thanks a lot! It did help me.
     
    G3R1 likes this.
  8. vasanthbalaji

    vasanthbalaji

    Joined:
    Nov 15, 2014
    Posts:
    34
  9. G3R1

    G3R1

    Joined:
    Sep 3, 2016
    Posts:
    33
    Can you provide the code you are using to achieve this plugin ? I need to see your code and compare it and then see if there is any mistake.
     
  10. vasanthbalaji

    vasanthbalaji

    Joined:
    Nov 15, 2014
    Posts:
    34
    @G3R1 please find the code below

    package com.jazzigames.gpsenabledialog;

    import android.content.Intent;
    import android.support.annotation.NonNull;
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.app.Activity;
    import android.content.IntentSender;
    import android.widget.Toast;

    //import com.google.android.gms.appindexing.AppIndex;
    import com.google.android.gms.common.api.ApiException;
    import com.google.android.gms.common.api.GoogleApiClient;
    import com.google.android.gms.common.api.GoogleApiClient.Builder;
    import com.google.android.gms.common.api.PendingResult;
    import com.google.android.gms.common.api.ResolvableApiException;
    import com.google.android.gms.common.api.ResultCallback;
    import com.google.android.gms.common.api.Status;
    import com.google.android.gms.location.LocationListener;
    import com.google.android.gms.location.LocationRequest;
    import com.google.android.gms.location.LocationServices;
    import com.google.android.gms.location.LocationSettingsRequest;
    import com.google.android.gms.location.LocationSettingsResult;
    import com.google.android.gms.location.LocationSettingsStates;
    import com.google.android.gms.location.LocationSettingsStatusCodes;
    import com.google.android.gms.location.LocationSettingsResponse;
    import com.google.android.gms.tasks.Task;
    import com.google.android.gms.tasks.OnCompleteListener;
    import com.google.android.gms.common.api.GoogleApiClient.OnConnectionFailedListener;
    import com.unity3d.player.UnityPlayer;
    import com.unity3d.player.UnityPlayerActivity;



    public class MainActivity extends UnityPlayerActivity {

    GoogleApiClient googleApiClient;
    LocationRequest locationRequest;
    int REQUEST_CHECK_SETTINGS = 100;

    public void AskToEnableGPS(final Activity activity) {

    if (googleApiClient == null) {
    googleApiClient = new GoogleApiClient.Builder(activity.getApplicationContext()).addApi(LocationServices.API).build();
    googleApiClient.connect();

    locationRequest = LocationRequest.create();
    locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
    locationRequest.setInterval(30 * 1000);
    locationRequest.setFastestInterval(5 * 1000);

    LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder().addLocationRequest(locationRequest);

    builder.setAlwaysShow(true);


    Task<LocationSettingsResponse> result = LocationServices.getSettingsClient(this).checkLocationSettings(builder.build());

    // LocationServices.SettingsApi.checkLocationSettings(googleApiClient, builder.build());
    // LocationServices.SettingsApi.checkLocationSettings(googleApiClient, builder.build());

    result.addOnCompleteListener(new OnCompleteListener<LocationSettingsResponse>() {
    @override
    public void onComplete(Task<LocationSettingsResponse> task) {
    try {
    LocationSettingsResponse response = task.getResult(ApiException.class);
    // All location settings are satisfied. The client can initialize location
    // requests here.

    } catch (ApiException exception) {
    switch (exception.getStatusCode()) {
    case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
    // Location settings are not satisfied. But could be fixed by showing the
    // user a dialog.
    try {
    // Cast to a resolvable exception.
    ResolvableApiException resolvable = (ResolvableApiException) exception;
    // Show the dialog by calling startResolutionForResult(),
    // and check the result in onActivityResult().
    resolvable.startResolutionForResult(
    MainActivity.this,
    101);
    } catch (IntentSender.SendIntentException e) {
    // Ignore the error.
    } catch (ClassCastException e) {
    // Ignore, should be an impossible error.
    }
    break;
    case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
    // Location settings are not satisfied. However, we have no way to fix the
    // settings so we won't show the dialog.
    break;
    }
    }
    }
    });
    }
    }

    @override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == REQUEST_CHECK_SETTINGS) {

    if (resultCode == RESULT_OK) {

    Toast.makeText(getApplicationContext(), "GPS enabled", Toast.LENGTH_LONG).show();
    } else {

    Toast.makeText(getApplicationContext(), "GPS is not enabled", Toast.LENGTH_LONG).show();
    }

    }
    }
    }



    Dependencies

    apply plugin: 'com.android.library'


    android {
    compileSdkVersion 26
    defaultConfig {

    minSdkVersion 16
    targetSdkVersion 26
    versionCode 1
    versionName "1.0"
    multiDexEnabled true
    testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
    release {
    minifyEnabled false
    proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
    }
    }
    productFlavors {
    }
    }

    dependencies {
    implementation fileTree(include: ['*.jar'], dir: 'libs' )//, exclude: ['classes.jar'])

    implementation 'com.android.support:appcompat-v7:26.1.0'
    implementation 'com.android.support:support-annotations:28.0.0'
    implementation 'com.android.support:multidex:1.0.3'

    implementation 'com.android.support.constraint:constraint-layout:1.1.3'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
    implementation 'com.google.android.gms:play-services-location:11.0.4'
    compileOnly files('libs/classes.jar')
    }

    task deleteOldJar(type: Delete) {
    delete 'release/GpsEnable.jar'
    }

    //task to export contents as jar
    task exportJar(type: Copy) {
    from('build/intermediates/packaged-classes/release/')
    into('release/')
    include('classes.jar')
    ///Rename the jar
    rename('classes.jar', 'GpsEnable.jar')
    }

    exportJar.dependsOn(deleteOldJar, build)



    Im getting following error in it after checking log
    12-17 12:01:30.191 8735 8751 E Unity : AndroidJavaException: java.lang.NoClassDefFoundError: Failed resolution of: Lcom/google/android/gms/common/api/Api$zzf;
    12-17 12:01:30.191 8735 8751 E Unity : java.lang.NoClassDefFoundError: Failed resolution of: Lcom/google/android/gms/common/api/Api$zzf;
    12-17 12:01:30.191 8735 8751 E Unity : at com.google.android.gms.location.LocationServices.<clinit>(Unknown Source)
    12-17 12:01:30.191 8735 8751 E Unity : at com.jazzigames.gpsenabledialog.MainActivity.AskToEnableGPS(MainActivity.java:44)
    12-17 12:01:30.191 8735 8751 E Unity : at com.unity3d.player.UnityPlayer.nativeRender(Native Method)
    12-17 12:01:30.191 8735 8751 E Unity : at com.unity3d.player.UnityPlayer.c(Unknown Source)
    12-17 12:01:30.191 8735 8751 E Unity : at com.unity3d.player.UnityPlayer$e$2.queueIdle(Unknown Source)
    12-17 12:01:30.191 8735 8751 E Unity : at android.os.MessageQueue.next(MessageQueue.java:397)
    12-17 12:01:30.191 8735 8751 E Unity : at android.os.Looper.loop(Looper.java:148)
    12-17 12:01:30.191 8735 8751 E Unity : at com.unity3d.player.UnityPlayer$e.run(Unknown Source)
    12-17 12:01:30.191 8735 8751 E Unity : Caused by: java.lang.ClassNotFoundException: Didn't find class "com.google.android.gms.common.api.Api$zzf" on path: DexPathList[[zip file "/data/app/com.jazzigames.gps-2/base.apk"],nativeLibraryDirectories=[/data/app/com.jazzigames.gps-2/lib/arm, /data/app/com.jazzigames.gps-2/base.apk!/lib/armeabi-v7a,
     
  11. G3R1

    G3R1

    Joined:
    Sep 3, 2016
    Posts:
    33
    Unfortunately, I didn't find my project for this plugin but I found the .jar classes that I have been using for that project and the error you get is related to the missing of one of the .jar classes. I guess you haven't donwload all the necessary classes from https://mvnrepository.com.

    Below I am attaching the .jar classes that you need to copy and paste into the "Plugins/Android" folder.
    Copy only the .jar classes and make sure you save them because I may remove them from google drive in the future.

    https://drive.google.com/drive/folders/1Gq6qvTRr0jPTrqI0dsMOD98fafDUrP2K?usp=sharing

    I will try and remake this plugin in the next days.;)