이제 많은 APP에는 HTML5 페이지가 포함되어 있습니다. 일부 페이지에는 HTML5의 js와 상호작용하기 위해 기본 Java가 필요합니다. 다음은 Android에서 HTML5 사용에 대한 소개입니다.
1. HTML5 쿠키에 대하여사용자 정보와 같은 많은 매개변수가 웹페이지에 사용될 수 있습니다. 이 정보를 쿠키에 미리 저장할 수 있는 방법은 다음과 같습니다.
public static void addCookies(Context context, WebView webView, String url) { String url=https://www.xxxx.com/xx/xx/ String 프로토콜 = ; String Authority = ; ; 프로토콜 = urlObj.getProtocol(); 권위 = urlObj.getAuthority() } catch (예외 e) { e.printStackTrace() } String ua = webView.getSettings().getUserAgentString(); webView.getSettings().setUserAgentString(Constant.PROJECT_NAME + / + ParamHandler.getVersion(context) + ( + ua + ; HFWSH)) if (!TextUtils.isEmpty(url) && !TextUtils.isEmpty(프로토콜) && !TextUtils.isEmpty(authority)) { if (protocol.equals(https) && Authority.indexOf(liepin.com) > -1) { CookieSyncManager.createInstance(context); CookieManager cookieManager = CookieManager.setAcceptCookie; (참); 시도 { List<String> data = getCookiesString(); (!ListUtils.isEmpty(data)) { for (문자열 값 : 데이터) { cookieManager.setCookie(url, value); } } cookieManager.setCookie(url, client_id= + Constant.CLIENT_ID + ;path=/;domain=. XXXX.com); cookieManager.setCookie(url, appVersion= + 상수 .VERSION + ;path=/;domain=.XXXX.com); CookieSyncManager.getInstance().sync(); } catch (예외 e) { LogUtils.e(예외: + e.getMessage()) } } } } public List<String> getCookiesString() { ArrayList data = new ArrayList(); this.clearExpired(); 컬렉션 값 = this.mCookies.values(); () ) { SwiftCookie c = (SwiftCookie)var3.next(); data.add(c.toCookieString()); }mWebView.loadUrl(Url) 앞에 쿠키를 추가하면 웹페이지는 쿠키를 통해 해당 매개변수 값을 얻을 수 있습니다.
2. js의 보안 문제에 대하여Node.js는 4.2 이전에도 취약점이 있었습니다.
JavaScript를 통해 현재 장치의 SD 카드에 있는 모든 내용, 심지어 연락처 정보, 문자 메시지 등에도 액세스할 수 있습니다. 자, 이 오류가 어떻게 발생했는지 살펴보겠습니다.
1. WebView는 JavaScript 개체를 추가하고 현재 애플리케이션에는 SDCard를 읽고 쓸 수 있는 권한이 있습니다. 즉, android.permission.WRITE_EXTERNAL_STORAGE
2. JS에서는 getClass 메서드를 사용하여 창 개체를 순회하여 개체를 찾은 다음 리플렉션 메커니즘을 통해 Runtime 개체를 얻은 다음 정적 메서드를 호출하여 파일 액세스 명령과 같은 일부 명령을 실행할 수 있습니다.
3. 그런 다음 명령을 실행한 후 반환된 입력 스트림에서 문자열을 가져오면 파일 이름 정보를 얻을 수 있습니다. 그렇다면 당신이 원하는 것은 무엇이든 할 수 있습니다. 그것은 매우 위험합니다. 핵심 JS 코드는 다음과 같습니다.
functionexecute(cmdArgs) { for (var obj in window) { if (getClass in window[obj]) { Alert(obj); return window[obj].getClass().forName(java.lang.Runtime) .getMethod( getRuntime,null).invoke(null,null).exec(cmdArgs) } } } 해결책: 1. Android 4.2 이상 시스템Android 4.2 이상에서 Google은 다음 코드와 같이 Java의 원격 메서드에 @JavascriptInterface를 선언하여 수정했습니다.
class JsObject { @JavascriptInterface public String toString() { returnjectedObject; } } webView.addJavascriptInterface(new JsObject(), 주입된Object) webView.loadUrl(javascript:alert(injectedObject. toString())); 2. Android 4.2 이하의 시스템이 문제는 해결하기가 더 어렵지만 불가능한 것은 아닙니다.
우선, 더 이상 addJavascriptInterface 메소드를 호출할 수 없습니다. 이 문제와 관련하여 가장 중요한 것은 JS 이벤트의 동작을 아는 것입니다. JS와 Java 사이에는 프롬프트, 경고 등과 같은 상호 작용 유형이 있다는 것을 알고 있습니다.
이러한 작업은 WebChromeClient 클래스의 해당 메서드에 해당합니다. 프롬프트의 경우 해당 메서드는 onJsPrompt 메서드입니다.
public boolean onJsPrompt(WebView 뷰, 문자열 URL, 문자열 메시지, 문자열 defaultValue, JsPromptResult 결과)
이 방법을 통해 JS는 정보(텍스트)를 Java로 전달할 수 있고, Java도 JS로 정보(텍스트)를 전달할 수 있습니다.
몇 가지 시행착오와 분석 끝에 우리는 더 실현 가능한 솔루션을 찾았습니다. 다음 사항을 참조하십시오.
[1] JS가 Javascript 메소드를 호출하도록 합니다. 이 메소드에서는 JS의 정보가 프롬프트를 통해 전달됩니다. 이 정보는 특정 식별자, 메소드 이름을 포함할 수 있는 의미 있는 텍스트여야 합니다. , 매개변수 등
onJsPrompt 메소드에서는 전달된 텍스트를 구문 분석하여 메소드 이름, 매개변수 등을 가져온 다음 리플렉션 메커니즘을 통해 지정된 메소드를 호출하여 Java 객체의 메소드를 호출합니다.
[2] 반환값은 프롬프트를 통해 반환할 수 있어, 자바에서 메소드의 처리 결과를 Js로 반환할 수 있다.
[3] Javascript 메소드를 선언하는 JS 스크립트를 동적으로 생성하고 이를 loadUrl을 통해 로드한 후 html 페이지에 등록해야 합니다. 구체적인 코드는 다음과 같습니다.
javascript:(function JsAddJavascriptInterface_(){ if (typeof(window.jsInterface)!='undefine') { console.log('window.jsInterface_js_interface_name이 존재합니다!!');} else { window.jsInterface = { onButtonClick:function( arg0) { 반환 프롬프트('MyApp:'+JSON.stringify({obj:'jsInterface',func:'onButtonClick',args:[arg0]})) }, onImageClick:function(arg0,arg1,arg2) { 프롬프트('MyApp:'+JSON.stringify({obj:'jsInterface',func:'onImageClick',args:[arg0,arg1,arg2]})) }, } } )()설명하다:
1. 위 코드의 jsInterface는 등록할 객체의 이름입니다. onButtonClick(arg0), onImageClick(arg0, arg1, arg2) 두 가지 메소드를 등록합니다. 반환값이 있는 경우 return을 추가합니다.
2. 프롬프트는 우리가 동의한 문자열로, 특정 식별자 MyApp:이 포함되어 있고 그 뒤에 메서드 이름, 매개변수, 개체 이름 등이 포함된 JSON 문자열 문자열이 옵니다.
3. JS가 onButtonClick 또는 onImageClick을 호출하면 Java 계층의 onJsPrompt 메소드를 다시 호출합니다. 그런 다음 메소드 이름, 매개변수, 객체 이름을 구문 분석한 다음 반사적으로 메소드를 호출합니다.
4. window.jsInterface는 윈도우에 Js 객체가 선언되었음을 의미합니다. 선언된 메소드의 형식은 메소드 이름: 함수(매개변수 1, 매개변수 2)입니다.
3. html5에서 java와 js의 상호작용1), 방법 1:
mWebView.getSettings().setJavaScriptEnabled(true);mWebView.addJavascriptInterface(this, xxx);
그런 다음 현재 클래스에서 다음 메서드를 구현합니다.
@JavascriptInterface public void callbackFromH5(final String j) { //TODO }callbackFromH5의 이름은 웹페이지의 js 메소드 이름과 동일해야 합니다.
Java는 js 메소드를 호출합니다.
mWebView.loadUrl(String.format(javascript:java2js(0)));//여기에 Java 측에서 webview를 호출하기 위한 JS가 있습니다.
js 메소드 이름은 웹페이지와 일치해야 합니다.
2) 방법 2:
jsbridge 방법(https://github.com/lzyzsd/JsBridge)
Android JsBridge는 Android 앱의 기본 Java 코드와 Javascript 코드 간의 통신(호출) 브리지를 구축하는 데 사용되는 보조 도구입니다.
1 프로젝트에 jsBridge.jar을 도입합니다.
안드로이드 스튜디오:
저장소 { // ... maven { url https://jitpack.io } } 종속성 { compile 'com.github.lzyzsd:jsbridge:1.0.4' }2. 레이아웃 파일
<?xml 버전=1.0 인코딩=utf-8?> <LinearLayout xmlns:android=http://schemas.android.com/apk/res/android android:layout_width=match_parent android:layout_height=match_parent android:orientation=vertical > <!-- Java 호출 웹을 보여주는 버튼 --> <Button android:id=@+id/button android:layout_width=match_parent android:text=@string/button_name android:layout_height=dp /> <!-- webview는 웹 호출 Java를 보여줍니다 --> <com.github.lzyzsd.jsbridge.BridgeWebView android:id=@+id/ webView 안드로이드:layout_width=match_parent android:layout_height=match_parent > </com.github.lzyzsd.jsbridge.BridgeWebView> </LinearLayout>
3. 자바 코드
//서버 웹페이지 로드 webView.loadUrl(https://www.baidu.com); //js 함수와 이름이 동일해야 합니다. webView.registerHandler(submitFromWeb, new BridgeHandler() { @Override public void handler(String data, CallBackFunction function) { String str = java로 반환된 HTML 데이터: + data; makeText(MainActivity.this, str, LENGTH_SHORT).show( ) ; Log.i(TAG, 핸들러 = submitFromWeb, 웹의 데이터 = + data) function.onCallBack( str + , Java 처리 후: + str.substring(,)); } }); //로컬 위치를 얻기 위해 사용자 user = new User() Location location = new Location(); user.location = 위치; user.name = Bruce webView.callHandler(functionInJs, new Gson().toJson(user), new CallBackFunction() { @Override public void onCallBack(String data) makeText(MainActivity.this, 웹페이지에서 정보를 가져오는 중입니다. LENGTH_SHORT).show() } }); webView.callHandler(functionInJs, Java의 데이터, new CallBackFunction() { @Override public void onCallBack(String data) { // TODO 자동 생성된 메서드 스텁 Log.i(TAG, js의 응답 데이터 + 데이터); } }) ;js 호출
var str1 = document.getElementById(text1).value; var str2 = document.getElementById(text2).value; //로컬 Java 메소드 호출 window.WebViewJavascriptBridge.callHandler( 'submitFromWeb' , {'param': str} , 함수 ( responseData) { document.getElementById(show).innerHTML = java에서 responseData 가져오기 보내기, 데이터 = + responseData } ); //이벤트 수신 등록 document.addEventListener( 'WebViewJavascriptBridgeReady' , function() { callback(WebViewJavascriptBridge) }, false ) //연결 시 콜백 함수를 등록하고 초기화 함수 connectWebViewJavascriptBridge(function(bridge) 호출 처음으로 bridge.init(function(message, responseCallback) { console.log('JS에서 메시지를 받았습니다', message); var data = { 'Javascript 응답': 'Wee!' }; console.log('JS 응답', responseCallback(data); }); innerHTML = (Java의 데이터: = + data); var responseData = Javascript는 바로 responseCallback(responseData) }); })4. webView 최적화에 대하여
1. WebView 캐시 모드 설정
private void initWebView() { mWebView.getSettings().setJavaScriptEnabled(true); mWebView.getSettings().setRenderPriority(RenderPriority.HIGH); mWebView.getSettings().setCacheMode(WebSettings.LOAD_DEFAULT); DOM 저장소 API 활성화 Function mWebView.getSettings().setDomStorageEnabled(true); //데이터베이스 저장 API 활성화 function mWebView.getSettings().setDatabaseEnabled(true); String 캐시DirPath = getFilesDir().getAbsolutePath()+APP_CACAHE_DIRNAME; getCacheDir().getAbsolutePath()+Constant.APP_DB_DIRNAME; Log.i(TAG, 캐시DirPath=+cacheDirPath); //데이터베이스 캐시 경로 설정 mWebView.getSettings().setDatabasePath(cacheDirPath); //애플리케이션 캐시 캐시 디렉토리 설정 mWebView.getSettings().setAppCachePath(cacheDirPath); //애플리케이션 캐시 활성화 function mWebView.getSettings().setAppCacheEnabled(true);2. 캐시 지우기
/** * WebView 캐시 지우기*/ public voidclearWebViewCache(){ //Webview 캐시 데이터베이스 지우기 try { deleteDatabase(webview.db) deleteDatabase(webviewCache.db) } catch (Exception e) { e.printStackTrace(); } //WebView 캐시 파일 파일 appCacheDir = new File(getFilesDir().getAbsolutePath()+APP_CACAHE_DIRNAME); Log.e(TAG, appCacheDir 경로=+appCacheDir.getAbsolutePath()); File webviewCacheDir = new File(getCacheDir().getAbsolutePath()+/webviewCache) Log.e(TAG, webviewCacheDir 경로=+webviewCacheDir.getAbsolutePath() ); //웹뷰 삭제 캐시 디렉토리 if(webviewCacheDir.exists()){ deleteFile(webviewCacheDir) } //웹뷰 캐시 캐시 디렉토리 삭제 if(appCacheDir.exists()){ deleteFile(appCacheDir) } }3. WebView를 사용하여 웹 페이지를 로드할 때 js/css/images와 같은 일부 고정 리소스 파일과 기타 리소스가 네트워크에서 직접 로드되면 페이지 로드 속도가 느려지고 트래픽이 더 많이 소모됩니다. 따라서 이러한 파일은 자산에 배치되고 앱과 함께 패키지되어야 합니다.
이 문제를 해결하려면 API 11(HONEYCOMB)에서 제공하는 shouldInterceptRequest(WebView view, String url) 함수를 사용하여 로컬 리소스를 로드합니다.
API 21에서는 이 메소드를 다시 사용하지 않으며 새로운 shouldInterceptRequest를 오버로드했습니다. 필수 매개변수가 url을 요청으로 대체했습니다.
예를 들어, xxxxx.png 사진이 있습니다. 이 사진은 이제 외부 HTML이 로드되었으므로 네트워크에서 다시 가져오지 않고도 자산의 사진을 직접 가져와 로드해야 합니다. 물론 html의 이미지 링크를 file:///android_asset/xxxxx.png로 변경할 수 있습니다.
하지만 이 HTML은 Android, iOS, WAP에서는 공유할 수 없습니다.
webView.setWebViewClient(new WebViewClient() { @Override public WebResourceResponse shouldInterceptRequest(WebView view, String url) { WebResourceResponse 응답 = null; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB){ 응답 = super.shouldInterceptRequest(view ,url); if (url.contains(xxxxx.png)){ 시도 { response = new WebResourceResponse(image/png,UTF-8,getAssets().open(xxxxx.png)) } catch (IOException e) { e.printStackTrace() } } } // return super.shouldInterceptRequest(view , url); 응답 반환 } @TargetApi(Build.VERSION_CODES.LOLLIPOP) @Override 공개 WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) { WebResourceResponse 응답 = null; response = super.shouldInterceptRequest(view, request); if (url.contains(xxxxx.png)){ try { response = new WebResourceResponse(image/png,UTF) -,getAssets().open(xxxxx.png)) } catch (IOException e) { e.printStackTrace(); } } 응답을 반환합니다.위의 내용은 이 기사의 전체 내용입니다. 모든 분들의 학습에 도움이 되기를 바랍니다. 또한 모든 분들이 VeVb Wulin Network를 지지해 주시길 바랍니다.