반응형

 

안드로이드 웹뷰 예제

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

 

프로젝트 소스 다운↓

webview.zip
0.59MB

 

반응형

'안드로이드' 카테고리의 다른 글

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
  • 네이버 블러그 공유하기
  • 네이버 밴드에 공유하기
  • 페이스북 공유하기
  • 카카오스토리 공유하기