Program Tip

WebView의 HTTP 요청 가로 채기 및 재정의

programtip 2020. 12. 3. 19:08
반응형

WebView의 HTTP 요청 가로 채기 및 재정의


내 응용 프로그램에 일부 사이트가 열리는 WebView가 있습니다 (항상 동일하며 내 페이지입니다). 사이트에는 원격 호스트에서 일부 이미지를로드하는 JS 코드가 있습니다.

이러한 이미지에 대한 요청을 (URL 패턴으로) 가로 채고 내 콘텐츠 (예 : 다른 이미지)를 반환하거나 내부 애플리케이션 논리에 따라 요청을 그대로두고 싶습니다.

그렇게 할 수 있습니까?

편집 : 질문의 현재 상태 ...

WebViewWebViewClient(Axarydax에서 언급했듯이) 설정하는 기능이 있습니다. WebViewClient두 가지 유용한 방법이있다

  • shouldOverrideUrlLoading
  • onLoadResource

shouldOverrideUrlLoading페이지 상호 작용에 의해로드가 트리거되는 경우 (예 : 페이지의 링크를 클릭하면 WebView.loadURL ( "")이이 메소드를 트리거하지 않음) URL로드를 가로 챌 수 있습니다. false를 반환하여 URL 로딩을 취소 할 수도 있습니다. 이 접근 방식은 사용할 수 없습니다. 페이지 리소스로드를 가로 챌 수 없습니다 (그리고 가로 채야하는 이미지는 이러한 페이지 리소스 임).

onLoadResource페이지 리소스 (및 이미지! thx에서 jessyjones까지)가로드 될 때마다 트리거되지만 취소 할 방법은 없습니다. 이 방법은 내 작업에도 적합하지 않습니다.


API 레벨 11이 필요한 것을 지원하는 것 같습니다. 을 참조하십시오 WebViewClient.shouldInterceptRequest().


이것을 시도해보십시오. 개인 위키와 같은 앱에서 사용했습니다.

webView.setWebViewClient(new WebViewClient() {
    @Override
    public boolean shouldOverrideUrlLoading(WebView view, String url) {
        if (url.startsWith("foo://")) {
            // magic
            return true;
        }
        return false;
    }
});

내가 아는 한 shouldOverrideUrlLoading은 이미지가 아니라 하이퍼 링크에 대해 호출됩니다. 적절한 방법은 다음과 같습니다.

@Override public void onLoadResource(WebView view, String url)

이 메서드는 웹뷰에 의해로드되는 모든 리소스 (이미지, 스타일 시트, 스크립트)에 대해 호출되지만 무효이기 때문에 해당 URL을 변경하고 로컬 리소스를로드하도록 대체하는 방법을 찾지 못했습니다.


내 앱에 사용하는 솔루션은 다음과 같습니다.

css / js / img anf 글꼴 파일이있는 여러 자산 폴더가 있습니다.

응용 프로그램은 모든 파일 이름을 가져와이 이름의 파일이 요청되었는지 확인합니다. 그렇다면 자산 폴더에서로드합니다.

//get list of files of specific asset folder
        private ArrayList listAssetFiles(String path) {

            List myArrayList = new ArrayList();
            String [] list;
            try {
                list = getAssets().list(path);
                for(String f1 : list){
                    myArrayList.add(f1);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            return (ArrayList) myArrayList;
        }

        //get mime type by url
        public String getMimeType(String url) {
            String type = null;
            String extension = MimeTypeMap.getFileExtensionFromUrl(url);
            if (extension != null) {
                if (extension.equals("js")) {
                    return "text/javascript";
                }
                else if (extension.equals("woff")) {
                    return "application/font-woff";
                }
                else if (extension.equals("woff2")) {
                    return "application/font-woff2";
                }
                else if (extension.equals("ttf")) {
                    return "application/x-font-ttf";
                }
                else if (extension.equals("eot")) {
                    return "application/vnd.ms-fontobject";
                }
                else if (extension.equals("svg")) {
                    return "image/svg+xml";
                }
                type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
            }
            return type;
        }

        //return webresourceresponse
        public WebResourceResponse loadFilesFromAssetFolder (String folder, String url) {
            List myArrayList = listAssetFiles(folder);
            for (Object str : myArrayList) {
                if (url.contains((CharSequence) str)) {
                    try {
                        Log.i(TAG2, "File:" + str);
                        Log.i(TAG2, "MIME:" + getMimeType(url));
                        return new WebResourceResponse(getMimeType(url), "UTF-8", getAssets().open(String.valueOf(folder+"/" + str)));
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
            return null;
        }

        //@TargetApi(Build.VERSION_CODES.LOLLIPOP)
        @SuppressLint("NewApi")
        @Override
        public WebResourceResponse shouldInterceptRequest(final WebView view, String url) {
            //Log.i(TAG2, "SHOULD OVERRIDE INIT");
            //String url = webResourceRequest.getUrl().toString();
            String extension = MimeTypeMap.getFileExtensionFromUrl(url);
            //I have some folders for files with the same extension
            if (extension.equals("css") || extension.equals("js") || extension.equals("img")) {
                return loadFilesFromAssetFolder(extension, url);
            }
            //more possible extensions for font folder
            if (extension.equals("woff") || extension.equals("woff2") || extension.equals("ttf") || extension.equals("svg") || extension.equals("eot")) {
                return loadFilesFromAssetFolder("font", url);
            }

            return null;
        }

API 버전은 언급하지 않았지만 API 11부터 WebViewClient.shouldInterceptRequest 메서드가 있습니다.

이게 도움이 될까요?


궁극적 인 해결책은 루프백시 '비밀'포트에서 수신하는 간단한 http 서버를 포함하는 것입니다. 그런 다음 일치하는 이미지 src URL을 http : // localhost : 123 /.../ mypic.jpg 와 같이 대체 할 수 있습니다 .


This may helps:

@TargetApi(Build.VERSION_CODES.LOLLIPOP)
@Override
public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
    String url = request.getUrl().toString();
    WebResourceResponse response = super.shouldInterceptRequest(view, request);
    // load native js
    if (url != null && url.contains(INJECTION_TOKEN/* scheme define */)) {

        response = new WebResourceResponse(
                "text/javascript",
                "utf-8",
                loadJsInputStream(url, JsCache.getJsFilePath(path) /* InputStream */));
    }
    return response;
}

참고URL : https://stackoverflow.com/questions/4780899/intercept-and-override-http-requests-from-webview

반응형