web-dev-qa-db-ja.com

WebViewにJavaScript関数を追加し、reCAPTCHAの送信時にHTMLから後で呼び出す方法

私はこのように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からのみ呼び出す必要があります。どうやってやるの?

11
Zohab Ali

このようにスクリプトを挿入してみてください

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>
0
Viral Patel