comment obtenir du contenu html à partir d'une vue Web?

123

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. Veuillez mentionner une manière exacte.

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");

}

}
Hope4You
la source

Réponses:

107

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

  • Ce premier est presque le même que le vôtre, je suppose que nous l'avons obtenu à partir 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 récupérez le html via javascript. Ce n'est pas la plus jolie façon mais lorsque vous avez votre interface javascript, vous pouvez ajouter d'autres méthodes pour la bricoler.


  • Une autre façon consiste à utiliser un HttpClient comme ici .

L'option que vous choisissez dépend aussi, je pense, de ce que vous comptez faire avec le html récupéré ...

Sephy
la source
quand exécuter cette ligne, webview.loadUrl("javascript:window.HtmlViewer.showHTML" + "('<head>'+document.getElementsByTagName('html')[0].innerHTML+'</head>');");le programme agit comme la fonction finish (), et arrête cette activité. pourquoi? comment la résoudre?
7
webview.addJavascriptInterface Fonctionne uniquement sur Jelly Beans et version inférieure.
xtr
32
Deux modifications importantes apportées au code ci-dessus pour Jellybean et versions ultérieures: 1. Supprimez "window". à partir de la ligne webview.loadUrl - l'interface javascript est attachée différemment lors du ciblage de Jellybean. 2. Mettez @JavascriptInterface avant "public void showHTML" - c'est nécessaire car c'est un risque pour la sécurité de ne pas autoriser seulement certaines méthodes à être appelées.
karlbecker_com
1
Ne fonctionne toujours pas pour moi (5.1.1) .. Lorsque j'ajoute MyJavaScriptInterface (avec des conseils @karlbecker_com) lorsque je clique sur quelque chose sur le système de page chargé, je me demande de choisir le navigateur. Lorsque je supprimerai cela, il ne me le demandera plus.
Makalele
1
Ici, j'ai activé le débogage à distance, il a montré Uncaught ReferenceError: HtmlViewer is not defined, peu importe avec ou sans@JavascriptInterface
MewX
55

Dans KitKat et au-dessus, vous pouvez utiliser la evaluateJavascriptméthode sur la vue 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 cette réponse pour plus d'exemples

Akash Kurian Jose
la source
c'est de loin la solution la plus simple à utiliser ici
Billy
9
FYI - Nécessite l'API 19.
Joel
7
N'oubliez pas de mettre cela dans la méthode onPageFinished.
Cédric Portmann
@Joel Comment y parvenir en dessous de l'API 19?
Pratik Saluja le
1
@PratikSaluja extrêmement désolé si mon commentaire véhiculait la mauvaise idée. La réponse avec la plupart des votes positifs ici est beaucoup plus ancienne que ma propre réponse et fonctionnerait probablement pour vous. Cela ne voulait rien dire au-delà de ça. Très heureux que vous ayez trouvé la réponse en regardant ailleurs BTW.
Akash Kurian Jose le
41

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

user1842354
la source
1
Fonctionne pour Android 4.2 et AU-DESSUS.
Cédric Portmann
10

Android WebView n'est qu'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 sais pas pourquoi vous devez obtenir la page rendue (ou la capture d'écran) à partir de WebView. Pour la plupart des situations, ce n'est pas nécessaire. Vous pouvez toujours obtenir directement le contenu HTML brut du serveur HTTP.

Il y a déjà des réponses publiées sur l'obtention du flux brut à l'aide de HttpUrlConnection ou HttpClient. Alternativement, il existe une bibliothèque très pratique pour l'analyse / processus de contenu HTML sur Android: JSoup , il fournit une API très simple pour obtenir le contenu HTML du serveur HTTP et fournit une représentation abstraite du document HTML pour nous aider à 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();

C'est pratique lorsque, par exemple, vous souhaitez télécharger d'abord un document HTML, puis y ajouter du CSS ou du javascript personnalisé avant de le transmettre à WebView pour le rendu. Beaucoup plus sur leur site Web officiel, cela vaut la peine de le vérifier.

Yorkw
la source
5

Un point de contact que j'ai trouvé qui doit être mis en place est «caché» dans la configuration de Proguard. Alors que le lecteur HTML appelle très bien via l'interface javascript lors du débogage de l'application, cela ne fonctionne plus dès que l'application a été exécutée via Proguard, à moins que la fonction de lecture HTML ne soit déclarée dans le fichier de configuration Proguard, comme ceci:

-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.

user1756541
la source
4

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

Au lieu de cela, vous devez attraper le texte affiché dans la vue Web avant qu'il ne soit affiché. Si vous ne voulez pas configurer un gestionnaire de réponse (comme pour les autres réponses), j'ai trouvé ce correctif avec quelques recherches sur Google:

URL url = new URL("/programming/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 il strcontiendra le même html dessiné dans la vue Web. Cette réponse provient du moyen le plus simple de charger correctement le code HTML d'une page Web dans une chaîne en Java et devrait également fonctionner sur Android. Je ne l'ai pas testé et je ne l'ai pas écrit moi-même, mais cela pourrait vous aider.

De plus, l'URL extraite est codée en dur, vous devrez donc la modifier.

troisième
la source
1

Pourquoi ne pas obtenir le code HTML d'abord, 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 ce que vous voulez faire. Il est adapté de Est-il possible d'obtenir le code HTML de WebView et criez à https://stackoverflow.com/users/325081/aymon-fournier pour sa réponse.

Karl L
la source
HttpClient a été déconseillé au niveau API 22 et supprimé au niveau API 23. Ainsi, les classes mentionnées dans votre code ne peuvent pas être importées dans les fichiers java.
Dhananjay M
1

Je suggère qu'au lieu d'essayer d'extraire le HTML de WebView, vous extrayez le HTML de l'URL. Par cela, je veux dire utiliser une bibliothèque tierce telle que JSoup pour parcourir le HTML pour vous. Le code suivant obtiendra le 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;
    }
Mimminito
la source
Supposons que l'URL obtenue soit atteinte en publiant des données. cette méthode échouera.
Jafar Ali
Et qu'en est-il des cookies?
Keith Adler
0

C'est simple à mettre en œuvre Il suffit d'avoir besoin de méthodes javasript dans votre html pour obtenir la valeur 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 ceci vous aidera.

M. Sajid Shaikh
la source
qu'est-ce que cela signifie. & Make sure you calling callme like below in htmlAvez-vous voulu placer la balise d'entrée sous le script dans un fichier html? Thank You
pas de mec, vous devez appeler la méthode javasript callme () onblur du texte de type d'entrée dans la balise html.
M. Sajid Shaikh
alors où ajouter cette balise d'entrée. Ce bouton est-il visible?
ce code fonctionne comme, lors du chargement de l'activité, il y a une zone de texte dans la vue Web et le texte tapé s'affiche dans la zone de texte.Mais je veux le code html dans la vue Web.
pouvez-vous m'aider à résoudre ce problème? Thank you very much
0

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

À partir de la loadUrl()méthode de la android.webkit.WebViewclasse:

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.BrowserFramequi appelle la nativeLoadUrl()méthode native:

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!

capitaine lechuck
la source
-1

essayez d'utiliser HttpClient comme Sephy l'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;
}
Christoper Hans
la source
pouvez-vous montrer un exemple de travail simple.Je ne peux pas implémenter votre code dans l'exemple de
sephy
cette méthode obtiendra la source html de l'url donnée. ie getHtml ( google.com ); vous obtiendrez la source de la page principale de google
Christoper Hans
son ok.y a-t-il une option pour obtenir la source de la vue Web. THANKS
KIRAN KJ
Cela n'a pas fonctionné un peu pour moi. Je n'ai reçu aucun contenu d'un site de test dont le contenu était "bonjour le monde".
Momro
-2

les méthodes ci-dessus sont pour si vous avez une URL Web, mais si vous avez un html local, vous pouvez également avoir du html par ce code

AssetManager mgr = mContext.getAssets();
             try {
InputStream in = null;              
if(condition)//you have a local html saved in assets
                            {
                            in = mgr.open(mFileName,AssetManager.ACCESS_BUFFER);
                           }
                            else if(condition)//you have an url
                            {
                            URL feedURL = new URL(sURL);
                  in = feedURL.openConnection().getInputStream();}

                            // here you will get your html
                 String sHTML = streamToString(in);
                 in.close();

                 //display this html in the browser or web view              


             } catch (IOException e) {
             // TODO Auto-generated catch block
             e.printStackTrace();
             }
        public static String streamToString(InputStream in) throws IOException {
            if(in == null) {
                return "";
            }

            Writer writer = new StringWriter();
            char[] buffer = new char[1024];

            try {
                Reader reader = new BufferedReader(new InputStreamReader(in, "UTF-8"));

                int n;
                while ((n = reader.read(buffer)) != -1) {
                    writer.write(buffer, 0, n);
                }

            } finally {

            }

            return writer.toString();
        }
vipin
la source