簡體   English   中英

在WebView中注入Javascript橋

[英]Injecting Javascript bridge in WebView

我想從Android的網頁中提取一些內容。 我知道有解析HTML的庫,但我想也許我可以作弊。

這就是我在做什么..

  1. 使用應用程序上下文以編程方式創建WebView,因此不必在UI中顯示。
  2. 加載網頁
  3. 附加JS接口
  4. 注入一些Javascript以與主機應用程序進行交互

這是一些代碼......

    public void getLatestVersion(){
        Log.e("Testing", "getLatestVersion called...");
        WebView webview = new WebView(context.getApplicationContext());
        webview.loadUrl("https://example.com");
        webview.addJavascriptInterface(new jsInterface(), "Droid");
        webview.loadUrl("javascript: window.onload=function(){ Droid.showToast('testing!'); }");
    }

    class jsInterface{
        @JavascriptInterface
        public void showToast(String message){
            Log.e("Testing", message);
            Toast.makeText(context, message, Toast.LENGTH_LONG).show();
        }
    }

由於WebView在UI中不可見,因此很難分辨哪個部分正在破壞。 我所知道的是調用了第一個調用的Log,但是JavascriptInterface中的Log和Toast從未顯示過。

我正在努力做甚么可能嗎? 如果是這樣,我做錯了什么? 如果沒有,為什么不呢?

編輯

將視圖保留在UI中進行測試,顯然第二次調用loadUrl不起作用。 無論我嘗試注入什么Javascript,它都不起作用。

編輯2

忘記啟用Javascript我感到愚蠢,但它仍然沒有工作..我添加了以下行...

    WebSettings webSettings = webview.getSettings();
    webSettings.setJavaScriptEnabled(true);
    webview.loadUrl("javascript: alert('farts0');");

    webview.loadUrl("https://example.com");
    setContentView(webview);

    String js = "document.body.innerHTML = '<p>test<p>';";
    if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
        webview.evaluateJavascript(js, null);
    }else{
        webview.loadUrl("javascript: "+js);
    }

編輯3

感謝大家的建議,你一直很有幫助,但到目前為止它還沒有工作,所以除非有人在下一個小時提供工作代碼,否則Nainal將得到一半的賞金。 如果是這樣,我不確定我是否會被允許再給它一個賞金,因為問題仍然沒有得到解決。

到目前為止,這是我的完整代碼,考慮了此頁面上的建議,並嘗試了我不太了解的手冊中的幾個設置。

import android.graphics.Bitmap;
import android.os.Bundle;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.webkit.JavascriptInterface;
import android.webkit.WebChromeClient;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

    WebView webView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        webView = new WebView(getApplicationContext());


        if(android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN)
            webView.getSettings().setAllowFileAccessFromFileURLs(true);

        if(android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN)
            webView.getSettings().setAllowUniversalAccessFromFileURLs(true);

        webView.getSettings().setDomStorageEnabled(true);
        webView.getSettings().setJavaScriptEnabled(true);
        try {
            webView.setWebContentsDebuggingEnabled(true);
        }catch(Exception e){}
        webView.setWebChromeClient(new WebChromeClient());
        webView.setWebViewClient(new WebViewClient() {
            @Override
            public void onPageStarted(WebView view, String url, Bitmap favicon) {
                webView.setVisibility(View.GONE);

            }
            @Override
            public void onPageFinished(final WebView view, String url) {
                Log.e("checking", "MYmsg");
                Log.e("content-url", webView.getSettings().getAllowContentAccess()?"y":"n");
                webView.loadUrl("javascript: void window.CallToAnAndroidFunction.setVisible(document.getElementsByTagName('body')[0].innerHTML);");



            }
        });
        webView.setVisibility(View.INVISIBLE);
        webView.addJavascriptInterface(new myJavaScriptInterface(), "CallToAnAndroidFunction");
        webView.loadUrl("http://example.com");
    }
    public class myJavaScriptInterface {
        @JavascriptInterface
        public void setVisible(final String aThing) {
            Handler handler = new Handler();
            Runnable runnable = new Runnable() {
                @Override
                public void run() {

                    MainActivity.this.runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            webView.setVisibility(View.VISIBLE);
                            Toast.makeText(MainActivity.this, "Reached JS: "+aThing, Toast.LENGTH_LONG).show();

                        }
                    });


                }
            };handler.postDelayed(runnable,2000);

        }}



}

編輯4

開始新的賞金並將獎勵增加到100分。 奈納爾獲得了最有益的最后獎勵,而不是解決問題。

請嘗試這個,它調用javascript函數並顯示toast消息。

public class Main3Activity extends AppCompatActivity {
     WebView webView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main3);
        webView = new WebView(getApplicationContext());
        webView.getSettings().setJavaScriptEnabled(true);

        webView.setWebViewClient(new WebViewClient() {
            @Override
            public void onPageStarted(WebView view, String url, Bitmap favicon) {
                webView.setVisibility(View.GONE);

            }
            @Override
            public void onPageFinished(final WebView view, String url) {
                Log.e("checking", "MYmsg");
                webView.loadUrl("javascript:(function() { " +
                        "document.body.innerHTML = '<p>test<p>';" + "})()");
                webView.loadUrl("javascript: window.CallToAnAndroidFunction.setVisible()");



            }
        });
        webView.setVisibility(View.INVISIBLE);
        webView.addJavascriptInterface(new myJavaScriptInterface(), "CallToAnAndroidFunction");
        webView.loadUrl("https://example.com");
    }
    public class myJavaScriptInterface {
        @JavascriptInterface
        public void setVisible() {

            Handler handler = new Handler();
            Runnable runnable = new Runnable() {
                @Override
                public void run() {

                    Main3Activity.this.runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            webView.setVisibility(View.VISIBLE);
                            Log.e("Testing", "no");
                            Toast.makeText(Main3Activity.this, "Reached JS", Toast.LENGTH_LONG).show();

                        }
                    });


                }
            };handler.postDelayed(runnable,2000);

        }}
}

它不會在UI中顯示webView,因為webview未在xml布局中定義。

突然出現在我身上的一些事情。

  1. 在加載任何URL之前,應該附加JavaScript接口。

  2. 可以在加載原始URL之后分配第二個loadURL window.onload 調用setWebViewClient()並調用Droid.showToast('testing!');會更有意義Droid.showToast('testing!'); onPageFinished方法內部。

  3. @JavascriptInterface不會在主UI線程上運行,這會阻止你的@JavascriptInterface運行。

  4. 你的第二個編輯的innerHTML代碼不起作用的問題與第2點有關。你在同步單個塊中進行調用,而它應該是在頁面dom加載了AKA onPageFinished()

webview.addJavascriptInterface(new jsInterface(), "Droid"); 必須在webview.loadUrl("https://example.com");之前來webview.loadUrl("https://example.com");

然后使用Webview Listener。 onFinish()方法..然后注入你的webview.loadUrl("javascript: window.onload=function(){ Droid.showToast('testing!'); }"); 在onFinish方法

我已經做了大量的webview注入修改web ..我認為它應該工作..

編輯
使用chrome://inspect/#devices在webview加載時檢查您的應用

這是一個清理版本,最大限度地減少了不需要的代碼。 這適用於API級別18和23仿真器(以及我的6.0.1手機)。 WebView永遠不會添加到視圖層次結構中。 吐司顯示從網站上拉出的HTML。 使用Java 8針對A​​PI 25進行編譯。

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.webkit.JavascriptInterface;
import android.webkit.WebChromeClient;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

    WebView webView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        webView = new WebView(getApplicationContext());

        webView.getSettings().setJavaScriptEnabled(true);
        webView.setWebChromeClient(new WebChromeClient());

        webView.setWebViewClient(new WebViewClient() {
            @Override
            public void onPageFinished(final WebView view, String url) {
                webView.loadUrl("javascript: void AndroidHook.showToast(document.getElementsByTagName('body')[0].innerHTML);");
            }
        });

        webView.addJavascriptInterface(new JSInterface(), "AndroidHook");
        webView.loadUrl("http://example.com");
    }

    public class JSInterface {
        @JavascriptInterface
        public void showToast(final String html) {

            MainActivity.this.runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    Toast.makeText(MainActivity.this, "Reached JS: " + html, Toast.LENGTH_LONG).show();
                }
            });
        }
    }
}

這是布局。

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="16dp"
    android:paddingLeft="16dp"
    android:paddingRight="16dp"
    android:paddingTop="16dp"
    tools:context="com.foo.jsinjectiontest.MainActivity">

</RelativeLayout>

最后清單。

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.foo.jsinjectiontest">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

    <uses-permission android:name="android.permission.INTERNET"/>

</manifest>

如何在WebChromeClient使用onProgressChanged()

我已經將Edit 3一些代碼Edit 3為這樣,

webView.setWebChromeClient(new WebChromeClient(){
        @Override
        public void onProgressChanged(WebView view, int newProgress) {
            super.onProgressChanged(view, newProgress);
            if(newProgress == 100){
                webView.loadUrl("javascript: void window.CallToAnAndroidFunction.setVisible(document.getElementsByTagName('body')[0].innerHTML);");
            }
        }
    });

更改是您在progress==100而不是onPageFinished()時調用javascript

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM