하이브리드 앱_플레인

소정·2023년 5월 24일

WEB_FRONT

목록 보기
16/20

하이브리드 앱

[1] 동작 (플레인)방법

xml 화면

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="16dp"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <WebView
        android:id="@+id/wv"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_weight="1"/>

    <!-- 네이티브 코드로 자바스크립트 제어 -->
    <EditText
        android:id="@+id/et"
        android:hint="웹뷰에 보낼 메세지"
        android:inputType="text"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

    <Button
        android:id="@+id/btn"
        android:text="send"
        android:layout_gravity="right"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>

<!--  2) JS에서 Native 코드 제어  -->
    <TextView
        android:id="@+id/tv"
        android:textStyle="bold"
        android:textColor="#FF0000FF"
        android:padding="8dp"
        android:text="message"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

</LinearLayout>

1. Native App - JS -> Web

  • JS의 특정 함수를 호출하여 대신 제어하기
  • loadUrl 를 사용하여 자바스크립 함수에 접근

사용방법

1. index.html

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, inital-scale=1.0">

        <!--    부트스트랩 CSS 라이브러리 적용   -->
        <link href="./bootstrap.min.css" rel="stylesheet">

        <!--  내부 스크립트  -->
        <script>

            // Native Android에서 호출 할 함수 - 파라미터로 값 전달 받기
            function setMessage(msg){
                document.getElementById('aa').innerHTML = msg;
            }


        </script>
    </head>

    <body>

        <h5>Native Android로 부터 받는 메세지</h5>
        <h6 id="aa">WAIT...</h6>


        <h5 class="mt-5">Native Android로 보낼 메세지 입력</h5>
        <input class="form-control mt-3" type="text" id="in1" placeholder="메세지 입력">

        <!--   d-grid : 한줄에 하나씩    a-grid : 한줄에 4개씩   -->
        <div class="d-grid gap-2">
            <button class="btn btn-primary btn-block mt-3" onclick="aaa()">send to native android</button>
            <button class="btn btn-success btn-block mt-2" onclick="bbb()">open Gallery</button>
        </div>

    </body>

</html>

2. main.kt

package com.bsj0420.ex96hybrdapp

import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.webkit.JavascriptInterface
import android.webkit.WebChromeClient
import android.webkit.WebViewClient
import com.bsj0420.ex96hybrdapp.databinding.ActivityMainBinding

class MainActivity : AppCompatActivity() {

    lateinit var binding : ActivityMainBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)

        //웹뷰 설정들
        //1. JS 사용 허용
        binding.wv.settings.javaScriptEnabled = true
        //2.원래 ajax 기술은 서버사이드(http://) 에서 동작한다
        //이걸 로컬(asset)에서 동작하도록 허용
        binding.wv.settings.allowFileAccess = true
        //3. 웹뷰 안에서 웹문서 열리도록 하는 넘
        binding.wv.webViewClient = WebViewClient()
        //4. alert 같은 거 되게
        binding.wv.webChromeClient = WebChromeClient()
        
        //html 문서 생성
        //웹뷰가 보여줄 문서(html) 로드하기 - assets폴더에 위치 시키고 불러올것임
        binding.wv.loadUrl("file:///android_asset/index.html")

        //1) 네이티브에서 웹 UI 제어하기
        binding.btn.setOnClickListener {
            //HTML을 직접 제어는 불가능, JS의 특정 함수를 호출하여 대신 제어하기

            var msg:String = binding.et.text.toString()
            //loadUrl 를 사용하여 자바스크립 함수에 접근
            binding.wv.loadUrl("javascript:setMessage('${msg}')")
            binding.et.setText("")
        }

    }

}



2. Web - JS(@JavascriptInterface) -> Native App

  • 웹뷰에 JS에서 호출할 수 있는 메소드를 모아둔 클래스 설계 : 웹뷰에서 쓰기 위해 @JavascriptInterface를 쓴 함수를 설계함
  • 웹뷰에서 사용할 메소드들을 가지고 있는 중계인 객체 생성 및 웹뷰에 설정
    (설정한 이름이 웹문서의 window객체(BOM)의 멤버변수자동 추가된다)
binding.wv.addJavascriptInterface(WebViewConnector(), "Droid")

사용방법

1. index.html

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, inital-scale=1.0">

        <!--    부트스트랩 CSS 라이브러리 적용   -->
        <link href="./bootstrap.min.css" rel="stylesheet">

        <!--  내부 스크립트  -->
        <script>

            // Native Android로 메세지 보내기
            function aaa() {
                //input 요소에 써있는 글씨 얻어오기
                var msg = document.getElementById('in1').value;

                //안드로이드의 중계인 객체에게 원하는 기능을 요청
                //코틀린에서 중계인객체를 등록하면서 지정한 "Droid"라는 이름이
                // JS의 최상위 객체(BOM)인 window의 멤버 속성으로 자동 추가됨
                Droid.showMsg(msg);

            }

            //사진선택 앱을 여는 기능 함수
            function bbb(){
                Droid.openPhtoApp();
            }

        </script>
    </head>

    <body>

        <h5>Native Android로 부터 받는 메세지</h5>
        <h6 id="aa">WAIT...</h6>


        <h5 class="mt-5">Native Android로 보낼 메세지 입력</h5>
        <input class="form-control mt-3" type="text" id="in1" placeholder="메세지 입력">

        <!--   d-grid : 한줄에 하나씩    a-grid : 한줄에 4개씩   -->
        <div class="d-grid gap-2">
            <button class="btn btn-primary btn-block mt-3" onclick="aaa()">send to native android</button>
            <button class="btn btn-success btn-block mt-2" onclick="bbb()">open Gallery</button>
        </div>

    </body>

</html>

2. main.kt

package com.bsj0420.ex96hybrdapp

import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.webkit.JavascriptInterface
import android.webkit.WebChromeClient
import android.webkit.WebViewClient
import com.bsj0420.ex96hybrdapp.databinding.ActivityMainBinding

class MainActivity : AppCompatActivity() {

    lateinit var binding : ActivityMainBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)

        //웹뷰 설정들
        //1. JS 사용 허용
        binding.wv.settings.javaScriptEnabled = true
        //2.원래 ajax 기술은 서버사이드(http://) 에서 동작한다
        //이걸 로컬(asset)에서 동작하도록 허용
        binding.wv.settings.allowFileAccess = true
        //3. 웹뷰 안에서 웹문서 열리도록 하는 넘
        binding.wv.webViewClient = WebViewClient()
        //4. alert 같은 거 되게
        binding.wv.webChromeClient = WebChromeClient()
        
        //html 문서 생성
        //웹뷰가 보여줄 문서(html) 로드하기 - assets폴더에 위치 시키고 불러올것임
        binding.wv.loadUrl("file:///android_asset/index.html")

        //2) 웹뷰에서 사용할 메소드들을 가지고 있는 중계인 객체 생성 및 웹뷰에 설정
        binding.wv.addJavascriptInterface(WebViewConnector(), "Droid")
        //Droid라는 이름이 웹문서의 window객체(BOM)의 멤버변수로 자동 추가된다
        

    }

    // 2) 웹뷰에 JS에서 호출할 수 있는 메소드를 모아둔 클래스 설계
    //inner = 아웃터의 기능을 내것인양 쓸수 있음
    inner class WebViewConnector {

        //javascript 에서 호출할 수 있는 메소드
        @JavascriptInterface
        fun showMsg(msg : String){
            binding.tv.text = "웹뷰로부터 받은 메세지 : ${msg}"
        }
        
        //디바이스의 고유기능인 사진선택 앱을 알려주는 기능 메소드
        @JavascriptInterface
        fun openPhtoApp(){
            val intent = Intent(Intent.ACTION_PICK)
            intent.type = "image/*"
            startActivity(intent) //원래는 startActivityForResult
            
            //선택한 사진을 웹서버에 전송하고 웹문서에서 업로드된 사진파일을 보여주는 방식으로 코딩

        }

    }

}



profile
보조기억장치

0개의 댓글