반응형
안드로이드 웹뷰 예제
- assets에 있는 로컬 html을 불러오는 예제
- 리모트 웹을 불러오는 예제
- Javascript alert을 이용한 웹뷰 -> 네이티브 콜(Json데이터 이용)
- 네이티브에서 웹의 자바스크립트 호출
AndroidManifest.xml
- 인터넷 허용 퍼미션 추가
- 웹페이지 접속 가능 속성 추가(usesCleartextTraffic)
<!-- 인터넷 허용 -->
<uses-permission android:name="android.permission.INTERNET" />
<!-- 모든 웹페이지 접속가능하게 usesCleartextTraffic 속성 추가 -->
<application
...
android:usesCleartextTraffic="true">
...
</application>
MainActivity.java
package com.srctree.webview;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import android.content.DialogInterface;
import android.graphics.Bitmap;
import android.os.Build;
import android.os.Bundle;
import android.view.View;
import android.webkit.JavascriptInterface;
import android.webkit.WebChromeClient;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import org.json.JSONObject;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
ImageView iv_back;
Button btn_webview_local;
Button btn_js_call;
Button btn_webview;
WebView webview;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
iv_back = findViewById(R.id.iv_back);
btn_webview_local = findViewById(R.id.btn_webview_local);
btn_js_call = findViewById(R.id.btn_js_call);
btn_webview = findViewById(R.id.btn_webview);
webview = findViewById(R.id.webview);
iv_back.setOnClickListener(this);
btn_webview_local.setOnClickListener(this);
btn_js_call.setOnClickListener(this);
btn_webview.setOnClickListener(this);
//웹뷰 설정
webview.getSettings().setBuiltInZoomControls(false);
if(Build.VERSION.SDK_INT > Build.VERSION_CODES.HONEYCOMB) {
webview.getSettings().setDisplayZoomControls(false);
}
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
webview.getSettings().setTextZoom(100);
}
webview.getSettings().setJavaScriptEnabled(true);
//AndroidBridge 인터페이스 추가
webview.addJavascriptInterface(new AndroidBridge(), "Android");
//웹뷰 페이지 로딩시작, 종료 이벤트
webview.setWebViewClient(new WebViewClient() {
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
super.onPageStarted(view, url, favicon);
Toast.makeText(MainActivity.this, "onPageStarted", Toast.LENGTH_SHORT).show();
}
@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
Toast.makeText(MainActivity.this, "onPageFinished", Toast.LENGTH_SHORT).show();
}
});
//웹뷰 자바스크립트 얼럿, 컨펌 구현
webview.setWebChromeClient(new WebChromeClient() {
//return true: 커스텀 얼럿을 사용, false: 웹의 얼럿을 사용
public boolean onJsAlert(WebView view, String url, String message, final android.webkit.JsResult result) {
//message를 json으로 받아 커스텀 처리
if(message.indexOf("\"action\"") >= 0) {
try {
JSONObject jsonObject = new JSONObject(message);
final String action = (String)jsonObject.get("action");
String msg = (String)jsonObject.get("msg");
new AlertDialog.Builder(MainActivity.this)
.setTitle("알림")
.setMessage(msg)
.setPositiveButton(android.R.string.ok, new AlertDialog.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
result.confirm();
if("finish".equals(action)) {
finish();
}
}
}).setCancelable(false).create().show();
} catch (Exception e) {
}
//아래를 호출해줘야 웹의 블럭이 풀림
result.confirm();
} else {
new AlertDialog.Builder(MainActivity.this)
.setTitle("알림")
.setMessage(message)
.setPositiveButton(android.R.string.ok, new AlertDialog.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
result.confirm();
}
}).setCancelable(false).create().show();
}
return true;
};
public boolean onJsConfirm(WebView view, String url, String message, final android.webkit.JsResult result) {
new AlertDialog.Builder(MainActivity.this)
.setTitle("알림")
.setMessage(message)
.setPositiveButton(android.R.string.ok, new AlertDialog.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
result.confirm();
}
})
.setNegativeButton(android.R.string.cancel, new AlertDialog.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
result.cancel();
}
}).setCancelable(false).create().show();
return true;
}
});
//기기정보 UserAgent에 추가
String userAgent = webview.getSettings().getUserAgentString();
webview.getSettings().setUserAgentString(userAgent + " Android_Mobile");
}
@Override
public void onClick(View view) {
if(view == iv_back) {
if(webview.canGoBack()) {
webview.goBack();
}
}
else if(view == btn_webview_local) {
webview.loadUrl("file:///android_asset/www/index.html");
}
else if(view == btn_js_call) {
webview.loadUrl("javascript:nativeCallFunc('웹뷰통신 테스트')");
}
if(view == btn_webview) {
webview.loadUrl("https://www.google.com");
}
}
public class AndroidBridge {
@JavascriptInterface
public void bridgeNativeCall(String msg) {
Toast.makeText(MainActivity.this, "bridgeNativeCall : " + msg, Toast.LENGTH_SHORT).show();
}
}
}
activity_main.xml
<?xml version="1.0" encoding="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">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="50dp"
android:orientation="horizontal">
<ImageView
android:id="@+id/iv_back"
android:layout_width="50dp"
android:layout_height="50dp"
android:src="@drawable/icon_back"
android:padding="10dp"/>
<Button
android:id="@+id/btn_webview_local"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:layout_marginLeft="10dp"
android:text="웹뷰(로컬)"/>
<Button
android:id="@+id/btn_js_call"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:layout_marginLeft="10dp"
android:text="스크립트"/>
<Button
android:id="@+id/btn_webview"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:layout_marginLeft="10dp"
android:text="웹뷰"/>
<Space
android:layout_width="10dp"
android:layout_height="match_parent"/>
</LinearLayout>
<WebView
android:id="@+id/webview"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
assets/www/index.html
<!DOCTYPE html>
<html>
<head>
<meta name="format-detection" content="telephone=no">
<meta name="msapplication-tap-highlight" content="no">
<meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width">
<link rel="stylesheet" type="text/css" href="css/index.css">
<title>Local Test Page</title>
</head>
<body>
<div style="padding:10px;">
<h2>Local Test Html Page</h2>
<button onclick="myAlert();">Alert</button>
<button onclick="myConfirm();">Confirm</button>
<button onclick="myCustomAlert();">Custom Alert</button>
<br>
<br>
<button onclick="bridgeCall();">Android Bridge Call</button>
</div>
</body>
<script type="text/javascript">
function myAlert() {
alert('My Alert!');
}
function myConfirm() {
if(confirm('My Confirm?')) {
alert('YES');
} else {
alert('NO');
}
}
function myCustomAlert() {
var customStr = '{"action":"finish", "msg":"Activity will be close!"}';
alert(customStr);
}
function bridgeCall() {
window.Android.bridgeNativeCall("Android Bridge Call");
}
function nativeCallFunc(msg) {
alert("Native Call : " + msg);
}
</script>
</html>
프로젝트 소스 다운↓↓↓
반응형
'안드로이드' 카테고리의 다른 글
Android Fragment (0) | 2021.11.14 |
---|---|
Android ViewPager (0) | 2021.11.14 |
Android Keyboard Show/Hide 이벤트 수신 (0) | 2021.11.14 |
Android Permission(권한 요청) (0) | 2021.11.14 |
Android adb 사용 (0) | 2021.11.14 |
최근댓글