web-dev-qa-db-fra.com

Comment obtenir du contenu HTML à partir d'une webview?

Quelle est la méthode la plus simple pour obtenir du code HTML à partir d’une vue Web? J'ai essayé plusieurs méthodes de stackoverflow et google, mais je ne trouve pas de méthode exacte. S'il vous plaît mentionner un moyen exact.

public class htmldecoder extends Activity implements OnClickListener,TextWatcher
{
TextView txturl;
Button btgo;
WebView wvbrowser;
TextView txtcode;
ImageButton btcode;
LinearLayout llayout;
int flagbtcode;
public void onCreate(Bundle savedInstanceState)
{
            super.onCreate(savedInstanceState);
                setContentView(R.layout.htmldecoder);

    txturl=(TextView)findViewById(R.id.txturl);

    btgo=(Button)findViewById(R.id.btgo);
    btgo.setOnClickListener(this);

    wvbrowser=(WebView)findViewById(R.id.wvbrowser);
    wvbrowser.setWebViewClient(new HelloWebViewClient());
    wvbrowser.getSettings().setJavaScriptEnabled(true);
    wvbrowser.getSettings().setPluginsEnabled(true);
    wvbrowser.getSettings().setJavaScriptCanOpenWindowsAutomatically(true);
    wvbrowser.addJavascriptInterface(new MyJavaScriptInterface(),"HTMLOUT");
    //wvbrowser.loadUrl("http://www.google.com");
    wvbrowser.loadUrl("javascript:window.HTMLOUT.showHTML('<html>'+document.getElementsByTagName('html')[0].innerHTML+'</html>');");


    txtcode=(TextView)findViewById(R.id.txtcode);
    txtcode.addTextChangedListener(this);

    btcode=(ImageButton)findViewById(R.id.btcode);
    btcode.setOnClickListener(this);

    }

public void onClick(View v)
{
    if(btgo==v)
    {
        String url=txturl.getText().toString();
        if(!txturl.getText().toString().contains("http://"))
        {
            url="http://"+url;
        }
        wvbrowser.loadUrl(url);
        //wvbrowser.loadData("<html><head></head><body><div style='width:100px;height:100px;border:1px red solid;'></div></body></html>","text/html","utf-8");
    }
    else if(btcode==v)
    {
        ViewGroup.LayoutParams params1=wvbrowser.getLayoutParams();
        ViewGroup.LayoutParams params2=txtcode.getLayoutParams();
        if(flagbtcode==1)
        {
            params1.height=200;
            params2.height=220;
            flagbtcode=0;
            //txtcode.setText(wvbrowser.getContentDescription());
        }
        else
        {
            params1.height=420;
            params2.height=0;
            flagbtcode=1;
        }
        wvbrowser.setLayoutParams(params1);
        txtcode.setLayoutParams(params2);

    }
}

public class HelloWebViewClient extends WebViewClient {
    @Override
    public boolean shouldOverrideUrlLoading(WebView view, String url) {

        view.loadUrl(url);
        return true;
    }
    /*@Override
    public void onPageFinished(WebView view, String url)
    {
        // This call inject JavaScript into the page which just finished loading. 
        wvbrowser.loadUrl("javascript:window.HTMLOUT.processHTML('<head>'+document.getElementsByTagName('html')[0].innerHTML+'</head>');");
    }*/

}
class MyJavaScriptInterface
{
    @SuppressWarnings("unused")
    public void showHTML(String html)
    {

        txtcode.setText(html);
    }
}

public void afterTextChanged(Editable s) {
    // TODO Auto-generated method stub

}

public void beforeTextChanged(CharSequence s, int start, int count,
        int after) {
    // TODO Auto-generated method stub

}

public void onTextChanged(CharSequence s, int start, int before, int count) {
    wvbrowser.loadData("<html><div"+txtcode.getText().toString()+"></div></html>","text/html","utf-8");

}

}
109
user765970

En fait, cette question a beaucoup de réponses. En voici 2:

  • Ce premier est presque le même que le vôtre, je suppose que nous l’avons tiré du même tutoriel.

public class TestActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.webview);
        final WebView webview = (WebView) findViewById(R.id.browser);
        webview.getSettings().setJavaScriptEnabled(true);
        webview.addJavascriptInterface(new MyJavaScriptInterface(this), "HtmlViewer");

        webview.setWebViewClient(new WebViewClient() {
            @Override
            public void onPageFinished(WebView view, String url) {
                webview.loadUrl("javascript:window.HtmlViewer.showHTML" +
                        "('<html>'+document.getElementsByTagName('html')[0].innerHTML+'</html>');");
            }
        });

        webview.loadUrl("http://Android-in-action.com/index.php?post/" +
                "Common-errors-and-bugs-and-how-to-solve-avoid-them");
    }

    class MyJavaScriptInterface {

        private Context ctx;

        MyJavaScriptInterface(Context ctx) {
            this.ctx = ctx;
        }

        public void showHTML(String html) {
            new AlertDialog.Builder(ctx).setTitle("HTML").setMessage(html)
                    .setPositiveButton(Android.R.string.ok, null).setCancelable(false).create().show();
        }

    }
}

De cette façon, vous saisissez le code HTML via JavaScript. Pas la meilleure façon, mais lorsque vous avez votre interface javascript, vous pouvez ajouter d'autres méthodes pour le bricoler.


  • Un autre moyen consiste à utiliser un HttpClient comme .

L’option que vous choisissez dépend aussi, je pense, de ce que vous avez l’intention de faire avec le HTML récupéré ...

103
Sephy

Pour Android 4.2, n'oubliez pas d'ajouter @JavascriptInterface à toutes les fonctions javascript.

40
user1842354

Dans KitKat et les versions ultérieures, vous pouvez utiliser la méthode evaluateJavascript sur la visualisation Web.

wvbrowser.evaluateJavascript(
        "(function() { return ('<html>'+document.getElementsByTagName('html')[0].innerHTML+'</html>'); })();",
         new ValueCallback<String>() {
            @Override
            public void onReceiveValue(String html) {
                Log.d("HTML", html); 
                // code here
            }
    });

Voir this answer pour plus d'exemples

39
Akash Kurian Jose

Android WebView est juste un autre moteur de rendu qui rend le contenu HTML téléchargé à partir d'un serveur HTTP, un peu comme Chrome ou FireFox. Je ne connais pas la raison pour laquelle vous devez obtenir la page rendue (ou la capture d'écran) à partir de WebView. Dans la plupart des cas, cela n'est pas nécessaire. Vous pouvez toujours obtenir le contenu HTML brut directement du serveur HTTP.

Il y a déjà des réponses postées qui parlent d'obtenir le flux brut en utilisant HttpUrlConnection ou HttpClient. Alternativement, il existe une bibliothèque très pratique pour l’analyse/le traitement du contenu HTML sous Android: JSoup , elle fournit une API très simple pour obtenir le contenu HTML du serveur HTTP et fournit une représentation abstraite du document HTML. Aidez-nous à gérer l’analyse HTML non seulement dans un style plus OO mais aussi beaucoup plus facilement:

// Single line of statement to get HTML document from HTTP server.
Document doc = Jsoup.connect("http://en.wikipedia.org/").get();

Il est pratique lorsque, par exemple, vous souhaitez télécharger un document HTML en premier, puis lui ajouter des fichiers css ou javascript personnalisés avant de le transmettre à WebView pour le rendu. Beaucoup plus sur leur site web officiel, vaut la peine de vérifier.

10
yorkw

Un point de contact que j'ai trouvé qui doit être mis en place est "caché" dans la configuration Proguard. Alors que le lecteur HTML appelle via l'interface javascript correctement lors du débogage de l'application, cela ne fonctionne plus dès que l'application est exécutée via Proguard, sauf si la fonction de lecteur HTML est déclarée dans le fichier de configuration Proguard, comme suit:

-keepclassmembers class <your.fully.qualified.HTML.reader.classname.here> {
    public *; 
}

Testé et confirmé sur Android 2.3.6, 4.1.1 et 4.2.1.

5
user1756541

Android ne vous laissera pas faire cela pour des raisons de sécurité. Un développeur maléfique pourrait très facilement voler les informations de connexion saisies par l’utilisateur.

Au lieu de cela, vous devez capturer le texte affiché dans la vue Web avant de l’afficher. Si vous ne voulez pas configurer un gestionnaire de réponses (comme dans les autres réponses), j'ai trouvé ce correctif avec un peu de google:

URL url = new URL("https://stackoverflow.com/questions/1381617");
URLConnection con = url.openConnection();
Pattern p = Pattern.compile("text/html;\\s+charset=([^\\s]+)\\s*");
Matcher m = p.matcher(con.getContentType());
/* If Content-Type doesn't match this pre-conception, choose default and 
 * hope for the best. */
String charset = m.matches() ? m.group(1) : "ISO-8859-1";
Reader r = new InputStreamReader(con.getInputStream(), charset);
StringBuilder buf = new StringBuilder();
while (true) {
  int ch = r.read();
  if (ch < 0)
    break;
  buf.append((char) ch);
}
String str = buf.toString();

C'est beaucoup de code, et vous devriez pouvoir le copier/coller, et à la fin de celui-ci, str contiendra le même code HTML dessiné dans la vue Web. Cette réponse provient de Le moyen le plus simple de charger correctement le code HTML d'une page Web dans une chaîne en Java et il devrait également fonctionner sur Android. Je n'ai pas testé cela et je ne l'ai pas écrit moi-même, mais cela pourrait vous aider.

En outre, l'URL extraite est codée en dur, vous devrez donc changer cela.

4
edthethird

Pourquoi ne pas obtenir le code HTML en premier, puis le transmettre à la vue Web?

private String getHtml(String url){
    HttpGet pageGet = new HttpGet(url);

    ResponseHandler<String> handler = new ResponseHandler<String>() {
        public String handleResponse(HttpResponse response) throws ClientProtocolException, IOException {
            HttpEntity entity = response.getEntity();
            String html; 

            if (entity != null) {
                html = EntityUtils.toString(entity);
                return html;
            } else {
                return null;
            }
        }
    };

    pageHTML = null;
    try {
        while (pageHTML==null){
            pageHTML = client.execute(pageGet, handler);
        }
    } catch (ClientProtocolException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    return pageHTML;
}

@Override
public void customizeWebView(final ServiceCommunicableActivity activity, final WebView webview, final SearchResult mRom) {
    mRom.setFileSize(getFileSize(mRom.getURLSuffix()));
    webview.getSettings().setJavaScriptEnabled(true);
    WebViewClient anchorWebViewClient = new WebViewClient()
    {

        @Override
        public void onPageStarted(WebView view, String url, Bitmap favicon) {
            super.onPageStarted(view, url, favicon);

            //Do what you want to with the html
            String html = getHTML(url);

            if( html!=null && !url.equals(lastLoadedURL)){
                lastLoadedURL = url;
                webview.loadDataWithBaseURL(url, html, null, "utf-8", url);
            }
}

Cela devrait faire à peu près ce que vous voulez faire. Il est adapté de Est-il possible d'obtenir le code HTML de WebView et de crier à https://stackoverflow.com/users/325081/aymon-fournier pour sa réponse .

1
Karl L

Je suggérerais au lieu d'essayer d'extraire le code HTML de la WebView, vous extrayez le code HTML de l'URL. J'entends par là l'utilisation d'une bibliothèque tierce telle que JSoup pour parcourir le code HTML à votre place. Le code suivant obtiendra le code HTML d'une URL spécifique pour vous

public static String getHtml(String url) throws ClientProtocolException, IOException {
        HttpClient httpClient = new DefaultHttpClient();
        HttpContext localContext = new BasicHttpContext();
        HttpGet httpGet = new HttpGet(url);
        HttpResponse response = httpClient.execute(httpGet, localContext);
        String result = "";

        BufferedReader reader = new BufferedReader(
            new InputStreamReader(
                response.getEntity().getContent()
            )
        );

        String line = null;
        while ((line = reader.readLine()) != null){
            result += line + "\n";
        }
        return result;
    }
1
Mimminito

Il est simple à mettre en œuvre. Il vous suffit d’utiliser des méthodes javasript dans votre code HTML pour obtenir une valeur optimale du contenu HTML. Comme ci-dessus votre code, quelques modifications sont nécessaires.

  public class htmldecoder extends Activity implements OnClickListener,TextWatcher
    {
    Button btsubmit; // this button in your xml file
    WebView wvbrowser;
    public void onCreate(Bundle savedInstanceState)
    {
                super.onCreate(savedInstanceState);
                    setContentView(R.layout.htmldecoder);



        btsubmit=(Button)findViewById(R.id.btsubmit);
        btsubmit.setOnClickListener(this);

        wvbrowser=(WebView)findViewById(R.id.wvbrowser);
        wvbrowser.setWebViewClient(new HelloWebViewClient());
        wvbrowser.getSettings().setJavaScriptEnabled(true);
        wvbrowser.getSettings().setPluginsEnabled(true);
        wvbrowser.getSettings().setJavaScriptCanOpenWindowsAutomatically(true);
        MyJavaScriptInterface myinterface=new MyJavaScriptInterface();
        wvbrowser.addJavascriptInterface(myinterface,"interface");
        webView.loadUrl("file:///Android_asset/simple.html");  //use one html file for //testing put your html file in assets. Make sure that you done JavaScript methods to get //values for html content in html file . 
   }
   public void onClick(View v)
{
    if(btsubmit==v)
    {

        webView.loadUrl("javascript:showalert()");// call javascript method.  
        //wvbr
    }
}

final class MyJavaScriptInterface {



        MyJavaScriptInterface() {

        }

        public void sendValueFromHtml(String value) {
           System.out.println("Here is the value from html::"+value);
        }

    }

}

Votre javascript en html

 <script type="text/javascript">
    //<![CDATA[
    var n1;
    function callme(){
    n1=document.getElementById("FacadeAL").value;
    }
    function showalert(){
     window.interface.sendValueFromHtml(n1);// this method calling the method of interface which //you attached to html file in Android. // & we called this showalert javasript method on //submmit buttton click of Android. 
    }
    //]]>
    </script>

& Assurez-vous d’appeler callme comme ci-dessous en html

<input name="FacadeAL" id="FacadeAL" type="text" size="5" onblur="callme()"/>
J'espère que cela vous aidera.

0
Mr. Sajid Shaikh

Je suggère d'essayer une approche de réflexion, si vous avez du temps à consacrer au débogueur (désolé mais je n'en avais pas).

À partir de la méthode loadUrl() de la classe Android.webkit.WebView:

http://grepcode.com/file/repository.grepcode.com/Java/ext/com.google.Android/android/2.2_r1.1/Android/webkit/WebView.Java#WebView.loadUrl%28Java .lang.String% 2Cjava.util.Map% 29

Vous devriez arriver sur le Android.webkit.BrowserFrame qui appelle la méthode native nativeLoadUrl():

http://grepcode.com/file/repository.grepcode.com/Java/ext/com.google.Android/android/2.2_r1.1/Android/webkit/BrowserFrame.Java#BrowserFrame.nativeLoadUrl%28Java .lang.String% 2Cjava.util.Map% 29

L'implémentation de la méthode native devrait être ici:

http://gitorious.org/0xdroid/external_webkit/blobs/a538f34148bb04aa6ccfbb89dfd5fd784a4208b1/WebKit/Android/jni/WebCoreFrameBridge.cpp

Je vous souhaite bonne chance!

0
lechuckcaptain

essayez d'utiliser HttpClient comme Sephy a dit:

public String getHtml(String url) {
    HttpClient vClient = new DefaultHttpClient();
    HttpGet vGet = new HttpGet(url);
    String response = "";    

    try {
        ResponseHandler<String> vHandler = new BasicResponseHandler();
        response = vClient.execute(vGet, vHandler);
    } catch (Exception e) {
        e.printStackTrace();
    }
    return response;
}
0
Christoper Hans