webview에서 html 콘텐츠를 얻는 방법?


123

웹뷰에서 html 코드를 얻는 가장 간단한 방법은 무엇입니까? stackoverflow 및 google에서 여러 가지 방법을 시도했지만 정확한 방법을 찾을 수 없습니다. 정확한 방법을 말씀해주세요.

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

}

}

답변:


107

사실이 질문에는 많은 답이 있습니다. 그중 2 개는 다음과 같습니다.

  • 첫 번째는 당신의 것과 거의 같습니다. 같은 튜토리얼에서 얻은 것 같습니다.

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();
        }

    }
}

이렇게하면 자바 스크립트를 통해 html을 잡을 수 있습니다. 가장 예쁜 방법은 아니지만 자바 스크립트 인터페이스가있을 때 다른 방법을 추가하여 수정할 수 있습니다.


  • 다른 방법은 거기 와 같은 HttpClient를 사용하는 입니다.

선택하는 옵션은 검색된 html로 무엇을 하려는지에 따라 달라집니다.


이 줄을 실행할 때 webview.loadUrl("javascript:window.HtmlViewer.showHTML" + "('<head>'+document.getElementsByTagName('html')[0].innerHTML+'</head>');");프로그램은 함수 finish ()처럼 작동하고 해당 활동을 중지합니다. 왜 해결 방법?

7
webview.addJavascriptInterface Jelly Beans 이하 버전에서만 작동합니다.
xtr 2013 년

32
Jellybean 이상에 대한 위 코드의 두 가지 중요한 변경 사항 : 1. "window"를 제거하십시오. webview.loadUrl 행에서-Jellybean을 타겟팅 할 때 자바 스크립트 인터페이스가 다르게 연결됩니다. 2. @JavascriptInterface를 "public void showHTML"앞에 두십시오. 이것은 특정 메소드가 호출되도록 허용하는 것이 아니라 보안 위험이 있기 때문에 필요합니다.
karlbecker_com 2013 년

1
여전히 나를 위해 작동하지 않습니다 (5.1.1) ..로드 된 페이지 시스템에서 무언가를 클릭 할 때 MyJavaScriptInterface (@karlbecker_com 힌트 포함)를 추가 할 때 브라우저를 선택하라는 메시지가 표시됩니다. 이것을 제거하면 다시 묻지 않습니다.
Makalele 2015 년

1
여기에 나는 없었다, 원격 디버깅을 활성화 Uncaught ReferenceError: HtmlViewer is not defined하거나하지 않고 상관없이@JavascriptInterface
MewX

55

KitKat 이상에서는 evaluateJavascriptwebview에서 메소드를 사용할 수 있습니다.

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

더 많은 예를 보려면 답변을 참조하십시오.


이것은 여기에서 사용하기 가장 쉬운 솔루션입니다
Billy

9
참고 - API (19)가 필요합니다
조엘

7
이것을 onPageFinished 메소드에 넣어야합니다.
Cédric Portmann 2016

@Joel API 19 아래에서 이것을 달성하는 방법은 무엇입니까?
Pratik Saluja

1
@PratikSaluja 내 의견이 잘못된 생각을 전달했다면 매우 죄송합니다. 여기에서 대부분의 찬성 투표에 대한 답변은 내 답변보다 훨씬 오래되었으며 아마도 당신에게 도움이 될 것입니다. 그 이상의 의미는 없습니다. 다른 곳에서 BTW를 찾아 답을 찾으 셨다니 매우 기쁩니다.
Akash Kurian Jose

41

Android 4.2의 경우 모든 javasscript 함수에 @JavascriptInterface를 추가하는 것을 잊지 마십시오.


1
Android 4.2 이상에서 작동합니다.
Cédric Portmann 2016

10

Android WebView는 Chrome 또는 FireFox와 같이 HTTP 서버에서 다운로드 한 HTML 콘텐츠를 렌더링하는 또 다른 렌더링 엔진입니다. WebView에서 렌더링 된 페이지 (또는 스크린 샷)를 가져와야하는 이유를 모르겠습니다. 대부분의 경우 이것은 필요하지 않습니다. 항상 HTTP 서버에서 직접 원시 HTML 콘텐츠를 가져올 수 있습니다.

HttpUrlConnection 또는 HttpClient를 사용하여 원시 스트림을 얻는 것에 대해 이미 게시 된 답변이 있습니다. 또는 Android에서 HTML 콘텐츠 파싱 / 프로세스를 처리 할 때 매우 편리한 라이브러리가 있습니다. JSoup , HTTP 서버에서 HTML 콘텐츠를 가져 오는 매우 간단한 API를 제공하고 HTML 파싱을 관리하는 데 도움이되는 HTML 문서의 추상 표현을 제공합니다. 좀 더 OO 스타일이지만 훨씬 쉽게 :

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

예를 들어 HTML 문서를 먼저 다운로드 한 다음 렌더링을 위해 WebView에 전달하기 전에 사용자 지정 CSS 또는 자바 스크립트를 추가하려는 경우에 편리합니다. 공식 웹 사이트에서 훨씬 더 많은 것을 확인할 가치가 있습니다.


5

제자리에 배치해야하는 한 가지 터치 포인트는 Proguard 구성에서 "숨겨져"있습니다. HTML 리더는 앱을 디버깅 할 때 자바 스크립트 인터페이스를 통해 정상적으로 호출되지만, 다음과 같이 HTML 리더 기능이 Proguard 구성 파일에 선언되지 않는 한 Proguard를 통해 앱이 실행 되 자마자 더 이상 작동하지 않습니다.

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

Android 2.3.6, 4.1.1 및 4.2.1에서 테스트 및 확인되었습니다.


4

Android에서는 보안 문제로이 작업을 수행 할 수 없습니다. 악의적 인 개발자는 사용자가 입력 한 로그인 정보를 매우 쉽게 훔칠 수 있습니다.

대신 웹보기에 표시되는 텍스트가 표시되기 전에 포착해야합니다. 응답 핸들러를 설정하고 싶지 않다면 (다른 답변에 따라) 인터넷 검색 으로이 수정을 찾았습니다.

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

이것은 많은 코드이며 복사 / 패스 터링 할 수 있어야하며 마지막 str에는 webview에 그려진 동일한 html이 포함됩니다. 이 답변은 웹 페이지의 html을 Java의 문자열로 올바르게로드하는 가장 간단한 방법 이며 Android에서도 작동합니다. 나는 이것을 테스트하지 않았고 직접 작성하지 않았지만 도움이 될 수 있습니다.

또한이 URL은 하드 코딩되어 있으므로 변경해야합니다.


1

먼저 html을 가져온 다음 웹보기로 전달하지 않는 이유는 무엇입니까?

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

이것은 대략 당신이 원하는 것을해야합니다. 그것은 WebView에서 HTML 코드를 가져 와서 https://stackoverflow.com/users/325081/aymon-fournier 에 외칠 수 있습니까?


HttpClient는 API 레벨 22에서 더 이상 사용되지 않고 API 레벨 23에서 제거되었습니다. 따라서 코드에 언급 된 클래스를 Java 파일로 가져올 수 없습니다.
Dhananjay M

1

WebView에서 HTML을 추출하는 대신 URL에서 HTML을 추출하는 것이 좋습니다. 이것은 JSoup과 같은 타사 라이브러리를 사용하여 HTML을 탐색하는 것을 의미합니다. 다음 코드는 특정 URL에서 HTML을 가져옵니다.

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;
    }

데이터를 게시하여 URL 획득에 도달했다고 가정합니다. 이 방법은 실패합니다.
Jafar Ali

또한 쿠키는 어떻습니까?
Keith Adler

0

구현이 간단합니다. html 콘텐츠의 가치를 얻으려면 html에서 javasript 메소드가 필요합니다. 코드 위와 같이 몇 가지 변경이 필요합니다.

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

    }

}

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>

& HTML에서 아래와 같이 callme를 호출하는지 확인하십시오.

<input name="FacadeAL" id="FacadeAL" type="text" size="5" onblur="callme()"/>
이것이 당신을 도울 수 있기를 바랍니다.


이것이 의미하는 & Make sure you calling callme like below in html바는 .html 파일의 스크립트 아래에 input 태그를 배치한다는 의미입니까? Thank You

html 태그에서 입력 유형 텍스트의 javasript 메소드 callme () onblur를 호출 할 필요가 없습니다.
Mr. Sajid Shaikh

이 입력 태그를 어디에 추가 할 수 있습니까?이 버튼이 보이나요?

이 코드는 활동을로드 할 때 webview에 텍스트 상자가 있고 입력 한 텍스트가 텍스트 상자에 표시됩니다.하지만 webview에 html 코드가 필요합니다.

이 문제를 해결하는 데 도움이 될 수 있습니까? Thank you very much

0

디버거에 시간을 할애 할 시간이 있다면 몇 가지 Reflection 접근 방식을 시도해 볼 것을 제안합니다 (죄송합니다.

loadUrl()방법 에서 시작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

네이티브 메서드 android.webkit.BrowserFrame를 호출하는 에 도착해야합니다 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

네이티브 메서드의 구현은 여기에 있어야합니다.

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

행운을 빕니다!


-1

Sephy가 말한 것처럼 HttpClient를 사용해보십시오.

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;
}

간단한 작업 예제를 보여줄 수 있습니까? sephy의 예제에서는 코드를 구현할 수 없습니다
KIRAN KJ

이 메소드는 주어진 URL의 html 소스를 가져옵니다. 즉, getHtml ( google.com ); 구글 메인 페이지의 소스를 얻을 것입니다
Christoper Hans

괜찮습니다. webview 소스를 얻는 옵션이 있습니다. THANKS
KIRAN KJ 2012

이것은 나에게 다소 효과가 없었습니다. 나는 내용이 "hello world"인 테스트 사이트에서 어떤 내용도 얻지 못했습니다.
Momro 2013 년

-2

위의 방법은 웹 URL이있는 경우를위한 것이지만 로컬 html이있는 경우이 코드로 html을 가질 수도 있습니다.

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();
        }
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.