정상에서 IT를 외치다

[Android, JavascriptInterface] 웹뷰와 앱간의 통신 예제 본문

안드로이드

[Android, JavascriptInterface] 웹뷰와 앱간의 통신 예제

Black-Jin 2020. 7. 22. 15:59
반응형

안녕하세요. 블랙진입니다.


웹뷰를 사용하는 앱을 개발하다 보면 웹뷰와 앱간의 통신이 필요한 경우가 있습니다. 더 자세히 말하자면 웹뷰의 자바스크립트와 안드로이드의 클라이언트 코드의 통신이 필요합니다. 이를 위한 방법으로 javasriptInterface를 사용할 수 있는데요. 그럼 이와 관련된 구글 가이드에 있는 예제를 확인해 보겠습니다.



구글 예제


1. javaScriptEnabled를 활성화 시켜준다.


val myWebView: WebView = findViewById(R.id.webview)
myWebView
.settings.javaScriptEnabled = true



2. @JavascriptInterface 함수를 생성해준다.


/** Instantiate the interface and set the context  */
class WebAppInterface(private val mContext: Context) {

   
/** Show a toast from the web page  */
   
@JavascriptInterface
   
fun showToast(toast: String) {
       
Toast.makeText(mContext, toast, Toast.LENGTH_SHORT).show()
   
}
}



3. 위에서 생성한 클래스를 웹뷰에 추가해준다.


val webView: WebView = findViewById(R.id.webview)
webView
.addJavascriptInterface(WebAppInterface(this), "Android")



4. 자바스크립트에서 안드로이드에 선언한 함수를 호출할 수 있다.


<input type="button" value="Say hello" onClick="showAndroidToast('Hello Android!')" />

<script type="text/javascript">
   
function showAndroidToast(toast) {
       
Android.showToast(toast);
   
}
</script>



위 예제 그대로 실재 프로젝트에서 어떻게 테스트 할 수 있는지 직접 코드로 확인해 보겠습니다.



프로젝트 코드


1. MainActivity


class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)

//웹뷰의 자바스크립트 기능을 활성화 시킵니다.
webview.settings.javaScriptEnabled = true


//BlackJin 명의 JavascriptInterface 를 추가해 줍니다.
webview.addJavascriptInterface(WebAppInterface(this), "BlackJin")


//assets에 있는 sample.html을 로딩합니다.
webview.loadUrl("file:///android_asset/sample.html")
}

/** Instantiate the interface and set the context */
class WebAppInterface(private val mContext: Context) {

/** Show a toast from the web page */
@JavascriptInterface
fun showToast(toast: String) {
Toast.makeText(mContext, toast, Toast.LENGTH_SHORT).show()
}
}
}


구글 예제에서는 인터페이스 명을 Android 라고 했지만 저는 BlackJin 으로 변경했습니다.

webview.addJavascriptInterface(WebAppInterface(this), "BlackJin")



2. activity_main


<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal"
tools:context=".MainActivity">

<WebView
android:id="@+id/webview"
android:layout_width="match_parent"
android:layout_height="match_parent" />

</FrameLayout>



3. sample.html 을 생성 후 assets 폴더에 추가해줍니다.



위와 같은 방법으로 클라이언트 코드에서 sample.html을 불러와 테스트 할 수 있습니다. 또한 필요한 경우 얼마든지 html와 script 코드를 수정할 수 있습니다.



sample.html


<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="initial-scale=1.0">
<meta charset="utf-8">
</head>
<body>
<p>
로딩이 완료된 웹뷰 입니다.
</p>
<input type="button" value="Say hello" onClick="showAndroidToast('Hello Black Jin World!')"/>
<script type="text/javascript">
function showAndroidToast(toast) {
BlackJin.showToast(toast);
}

</script>
</body>
</html>


우리는 1번에서 인터페이스 명을 BlackJin으로 명명했습니다. 그러므로 아래와 같이 {인터페이스명}.{함수} 형식으로 호출해 주면 웹뷰에서 클라이언트에 선언된 코드를 호출할 수 있게 됩니다.

<script type="text/javascript">
function showAndroidToast(toast) {
BlackJin.showToast(toast);
}

</script>



동작





웹뷰의 say hello 버튼을 누르면 toast가 나오는 것을 확인할 수 있습니다. 지금까지 구글의 간단한 예제를 살펴보았는데요. 


이는 웹뷰에서 클라이언트 코드만을 호출하는 단순한 예제였습니다.


이번에는 클라이언트의 값을 전달받아 이를 웹뷰에서 가공 후 출력하는 예제를 만들어 보겠습니다. 동작은 아래와 같습니다.



동작





edittext에서 숫자를 받아 button을 클릭하면 입력된 값의 2를 곱한 값을 textview에 출력해 줍니다.




구현



1. activity_main




화면은 위와 같이 웹뷰 영역과 클라이언트 영역으로 나뉩니다. 코드는 아래와 같습니다.


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

<WebView
android:id="@+id/webview"
android:layout_width="match_parent"
android:layout_height="100dp" />

<EditText
android:layout_marginTop="20dp"
android:id="@+id/edittext"
android:gravity="center"
android:inputType="number"
android:layout_width="200dp"
android:layout_height="wrap_content"/>

<Button
android:layout_marginTop="20dp"
android:id="@+id/button"
android:text="button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>

<TextView
android:layout_marginTop="20dp"
android:id="@+id/textview"
android:text="result"
android:textSize="20dp"
android:gravity="center"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>



2. 웹뷰 관련 코드는 아래와 같이 2개의 파일를 준비합니다.



이번에는 html 코드와 js 코드를 분리했습니다.



exam.html


<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="initial-scale=1.0">
<meta charset="utf-8">
</head>
<body>
화면에 입력한 숫자의 곱하기 2의 값이 화면에 출력됩니다.
<script type="text/javascript" src="exam_script.js"></script>
</body>
</html>


exam_script.js


var exam_script = {
plus_num: function(num){
try{
var result = num * 2
BlackJin.getDoubleNum(result)
}catch(err){
console.log(">> [exam_script.plus_num()] " + err)
}
}
}


자바 스크립트 코드를 보면 num이라는 파라미터를 받아 BlackJin 이름의 인터페이스가 있으면 getDoubleNum 함수를 실행함을 알 수 있습니다. 



3. MainAcitivity


class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)

//웹뷰의 자바스크립트 기능을 활성화 시킵니다.
webview.settings.javaScriptEnabled = true

//BlackJin 명의 JavascriptInterface 를 추가해 줍니다.
webview.addJavascriptInterface(WebViewJavascriptBridge(), "BlackJin")

//assets에 있는 exam.html을 로딩합니다.
webview.loadUrl("file:///android_asset/exam.html")

button.setOnClickListener {
webview.loadUrl("javascript:exam_script.plus_num(" + edittext.text + ")")
}
}

inner class WebViewJavascriptBridge {
@JavascriptInterface
fun getDoubleNum(num: Int) {
textview.text = num.toString()
}
}
}


여기서 중요하게 볼점은 클라이언트 코드에서 웹뷰의 자바스크립트를 호출할 때는 아래와 같은 방식으로 하면 됩니다.


button.setOnClickListener {
webview.loadUrl("javascript:exam_script.plus_num(" + edittext.text + ")")
}


버튼을 클릭하면 자바스크립트의 plus_num을 호출하고 인자로 exittext에 입력된 숫자를 받고 있습니다.




정리


웹뷰와 앱간의 통신하는 방법에 대해서 확인해 보았는데요. 이를 다시 정리하면 아래와 같습니다.


웹뷰 -> 클라이언트 코드 호출


@JavascriptInterface 를 이용한다.


/** Instantiate the interface and set the context  */
class WebAppInterface(private val mContext: Context) {

   
/** Show a toast from the web page  */
   
@JavascriptInterface
   
fun showToast(toast: String) {
       
Toast.makeText(mContext, toast, Toast.LENGTH_SHORT).show()
   
}
}



클라이언트 코드 -> 웹뷰의 자바스크립트 호출


javascript 함수를 loadUrl에서 호출해준다.


webview.loadUrl("javascript:exam_script.plus_num(" + edittext.text + ")")



<참고예제>


웹뷰를 이용한 간단한 자바스크립트 통신

반응형
Comments