私はこのようにWebViewにJavaScript関数を追加しています(Kotlin):
val webView = findViewById(R.id.webview) as WebView
webView.getSettings().setJavaScriptEnabled(true)
webView.addJavascriptInterface(this, "Android")
webView.getSettings().setBuiltInZoomControls(false)
webView.loadUrl(url)
webView.webViewClient = object : WebViewClient() {
override fun onPageFinished(view: WebView, url: String) {
super.onPageFinished(view, url)
webView.loadUrl("javascript:(function captchaResponse (token){" +
" Android.reCaptchaCallbackInAndroid(token);" +
" })()")
}
}
関数は正常に動作しますが、問題は、WebViewに追加するとすぐに実行されることです。私はそれをJavaScript関数として含めたいだけで、ユーザーがreCAPTCHAに入力するときは、HTMLからのみ呼び出す必要があります。どうやってやるの?
このようにスクリプトを挿入してみてください
function addCode(code){
var addedScript= document.createElement('script');
addedScript.text= code;
document.body.appendChild(addedScript);}
次のような関数を呼び出します
val codeToExec = "function captchaResponse (token){" +
"Android.reCaptchaCallbackInAndroid(token);" +
"}";
loadexecのような、
webview.loadUrl("javascript:(function addCode(code){
var addedScript= document.createElement('script');
addedScript.text= code;
document.body.appendChild(addedScript);})(codeToExec));
Javaの場合
MyApplication.Java
public class MyApplication extends Application {
public static final String TAG = MyApplication.class
.getSimpleName();
private RequestQueue mRequestQueue;
private static MyApplication mInstance;
@Override
public void onCreate() {
super.onCreate();
mInstance = this;
}
public static synchronized MyApplication getInstance() {
return mInstance;
}
public RequestQueue getRequestQueue() {
if (mRequestQueue == null) {
mRequestQueue = Volley.newRequestQueue(getApplicationContext());
}
return mRequestQueue;
}
public <T> void addToRequestQueue(Request<T> req, String tag) {
// set the default tag if tag is empty
req.setTag(TextUtils.isEmpty(tag) ? TAG : tag);
getRequestQueue().add(req);
}
public <T> void addToRequestQueue(Request<T> req) {
req.setTag(TAG);
getRequestQueue().add(req);
}
public void cancelPendingRequests(Object tag) {
if (mRequestQueue != null) {
mRequestQueue.cancelAll(tag);
}
}
}
**MainActivity.Java**
public class MainActivity extends AppCompatActivity {
private static final String TAG = MainActivity.class.getSimpleName();
// TODO - replace the SITE KEY with yours
private static final String SAFETY_NET_API_SITE_KEY = " YOUR SITE KEY HEAR";
// TODO - replace the SERVER URL with yours
private static final String URL_VERIFY_ON_SERVER = "https://example.com/index.php";
@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() {
String feedback = inputFeedback.getText().toString().trim();
// checking for empty feedback message
if (TextUtils.isEmpty(feedback)) {
Toast.makeText(getApplicationContext(), "Enter feedback!", Toast.LENGTH_LONG).show();
return;
}
// 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);
}
}
build.gradle
// SafetyNet reCAPTCHA
implementation 'com.google.Android.gms:play-services-safetynet:11.8.0'
// ButterKnife
implementation 'com.jakewharton:butterknife:8.8.1'
annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1'
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<Android.support.design.widget.CoordinatorLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
xmlns:app="http://schemas.Android.com/apk/res-auto"
xmlns:tools="http://schemas.Android.com/tools"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
tools:context=".MainActivity">
<Android.support.design.widget.AppBarLayout
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:theme="@style/AppTheme.AppBarOverlay">
<Android.support.v7.widget.Toolbar
Android:id="@+id/toolbar"
Android:layout_width="match_parent"
Android:layout_height="?attr/actionBarSize"
Android:background="?attr/colorPrimary"
app:popupTheme="@style/AppTheme.PopupOverlay" />
</Android.support.design.widget.AppBarLayout>
<include layout="@layout/content_main" />
</Android.support.design.widget.CoordinatorLayout>
content_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
xmlns:app="http://schemas.Android.com/apk/res-auto"
xmlns:tools="http://schemas.Android.com/tools"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:orientation="vertical"
Android:padding="@dimen/activity_margin"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:context="info.androidhive.recaptcha.MainActivity"
tools:showIn="@layout/activity_main">
<LinearLayout
Android:id="@+id/layout_feedback_form"
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:orientation="vertical">
<TextView
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:text="@string/title_form"
Android:textColor="#666666"
Android:textSize="20dp"
Android:textStyle="bold" />
<TextView
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:text="@string/desc_form" />
<EditText
Android:id="@+id/input_feedback"
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:layout_marginTop="@dimen/activity_margin"
Android:gravity="top"
Android:hint="@string/hint_feedback"
Android:lines="5" />
<Button
Android:id="@+id/btn_send"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:layout_marginTop="@dimen/activity_margin"
style="@style/Widget.AppCompat.Button.Colored"
Android:text="@string/btn_send"
Android:textColor="@Android:color/white" />
</LinearLayout>
<TextView
Android:id="@+id/message_feedback_done"
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:layout_marginTop="40dp"
Android:gravity="center"
Android:padding="@dimen/activity_margin"
Android:text="@string/message_feedback_done"
Android:textSize="22dp"
Android:visibility="gone" />
</LinearLayout>