Hi guys! I’m trying to get this thing to work and my lack of knowledge of building Android plugin doesn’t help it ether. So here is situation:
- I followed some tutorial of implementing Google reCaptcha for Android Studio and app itself works.
- Next I build .jar from Android Studio and placed it inside Unity’s Plugin/Android.
- I also placed play-services-safetynet-17.0.0.aar file inside Unity’s Plugin/Android and I also placed butterknife-10.0.0.aar and volley-1.1.0.aar even though I dont think its needed.
Now the problem is that Im getting this error in Logcat when I call validateCaptcha():
E/Unity: AndroidJavaException: java.lang.NoClassDefFoundError: Failed resolution of: Lcom/google/android/gms/common/api/Api$ClientKey;
Here are the codes:
package com.example.recaptchaunity;
import android.os.Bundle;
import androidx.appcompat.widget.Toolbar;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import com.android.volley.Request;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.StringRequest;
import com.google.android.gms.common.api.ApiException;
import com.google.android.gms.common.api.CommonStatusCodes;
import com.google.android.gms.safetynet.SafetyNet;
import com.google.android.gms.safetynet.SafetyNetApi;
import com.google.android.gms.tasks.OnFailureListener;
import com.google.android.gms.tasks.OnSuccessListener;
import com.unity3d.player.UnityPlayerActivity;
import com.unity3d.player.UnityPlayer;
import com.unity3d.player.UnityPlayerNativeActivity;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.HashMap;
import java.util.Map;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
public class pluginCaptcha extends UnityPlayerActivity {
private static final String TAG = pluginCaptcha.class.getSimpleName();
// TODO - replace the SITE KEY with yours
private static final String SAFETY_NET_API_SITE_KEY = "I inserted the right key";
// TODO - replace the SERVER URL with yours
private static final String URL_VERIFY_ON_SERVER = "I inserted the right url";
// @BindView(R.id.input_feedback)
EditText inputFeedback;
// @BindView(R.id.layout_feedback_form)
LinearLayout layoutFeedbackForm;
// @BindView(R.id.message_feedback_done)
TextView messageFeedbackDone;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
// Toolbar toolbar = findViewById(R.id.toolbar);
// setSupportActionBar(toolbar);
// getSupportActionBar().setTitle(getString(R.string.feedback));
// getSupportActionBar().setDisplayHomeAsUpEnabled(true);
// Toast.makeText(getApplicationContext(), "Always check Android Studio `LogCat` for errors!", Toast.LENGTH_LONG).show();
}
// @OnClick(R.id.btn_send)
public void validateCaptcha() {
// Showing reCAPTCHA dialog
SafetyNet.getClient(this).verifyWithRecaptcha(SAFETY_NET_API_SITE_KEY)
.addOnSuccessListener(this, new OnSuccessListener<SafetyNetApi.RecaptchaTokenResponse>() {
@Override
public void onSuccess(SafetyNetApi.RecaptchaTokenResponse response) {
Log.d(TAG, "onSuccess");
if (!response.getTokenResult().isEmpty()) {
// Received captcha token
// This token still needs to be validated on the server
// using the SECRET key
verifyTokenOnServer(response.getTokenResult());
}
}
})
.addOnFailureListener(this, new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
if (e instanceof ApiException) {
ApiException apiException = (ApiException) e;
Log.d(TAG, "Error message: " +
CommonStatusCodes.getStatusCodeString(apiException.getStatusCode()));
} else {
Log.d(TAG, "Unknown type of error: " + e.getMessage());
}
}
});
}
/**
* Verifying the captcha token on the server
* Post param: recaptcha-response
* Server makes call to https://www.google.com/recaptcha/api/siteverify
* with SECRET Key and Captcha token
*/
public void verifyTokenOnServer(final String token) {
Log.d(TAG, "Captcha Token" + token);
StringRequest strReq = new StringRequest(Request.Method.POST,
URL_VERIFY_ON_SERVER, new Response.Listener<String>() {
@Override
public void onResponse(String response) {
Log.d(TAG, response.toString());
try {
JSONObject jsonObject = new JSONObject(response);
boolean success = jsonObject.getBoolean("success");
String message = jsonObject.getString("message");
if (success) {
// Congrats! captcha verified successfully on server
// TODO - submit the feedback to your server
layoutFeedbackForm.setVisibility(View.GONE);
messageFeedbackDone.setVisibility(View.VISIBLE);
} else {
Toast.makeText(getApplicationContext(), message, Toast.LENGTH_LONG).show();
}
} catch (JSONException e) {
e.printStackTrace();
Toast.makeText(getApplicationContext(), "Json Error: " + e.getMessage(), Toast.LENGTH_LONG).show();
}
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Log.e(TAG, "Error: " + error.getMessage());
}
}) {
@Override
protected Map<String, String> getParams() {
Map<String, String> params = new HashMap<>();
params.put("recaptcha-response", token);
return params;
}
};
MyApplication.getInstance().addToRequestQueue(strReq);
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PluginWrapper : MonoBehaviour
{
private AndroidJavaObject javaClass;
AndroidJavaObject javaObject;
AndroidJavaClass unityClass;
AndroidJavaObject unityActivity;
// Start is called before the first frame update
void Start()
{
javaClass = new AndroidJavaObject("com.example.recaptchaunity.MyApplication");
javaClass.Call("ShowDebug");
}
public void Captcha()
{
// javaClass = new AndroidJavaObject("com.example.recaptchaunity.MainActivity");
// javaClass.Call("validateCaptcha");
javaObject = new AndroidJavaObject("com.example.recaptchaunity.pluginCaptcha");
// unityClass = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
// unityActivity = unityClass.GetStatic<AndroidJavaObject>("currentActivity");
javaObject.Call("validateCaptcha");
}
}
As you can see from my commented lines I’ve trying different ways to call plugin’s function, at the end I managed by creating new class “pluginCaptcha” and copied things from MainActivity class
I’ve been trying fro days to get this thing to work, in meantime I made a progress but I gor stuck on this part, please help. Thanks in advance!