WebView를 활용한 안드로이드와 자바스크립트 통신
안드로이드 애플리케이션에서 동적인 UI를 구현하거나 서버에서 관리하는 콘텐츠를 실시간으로 반영해야 할 경우, HTML과 JavaScript 기반의 웹뷰를 사용하는 것이 효과적인 접근 방식이 될 수 있다. 이를 통해 네이티브 코드 재배포 없이도 인터페이스 변경이나 콘텐츠 업데이트가 가능하다. 아래는 안드로이드와 JavaScript가 서로 메서드를 호출하는 방법을 설명한다.
기본 설정: WebView에 JavaScript 활성화
웹뷰에서 JavaScript를 실행하려면 먼저 설정에서 해당 기능을 허용해야 한다. 다음 코드를 통해 JavaScript 실행을 활성화할 수 있다.
WebSettings settings = webView.getSettings();
settings.setJavaScriptEnabled(true);
HTML 콘텐츠 로드
로컬 assets 폴더에 저장된 HTML 파일을 로드하려면 다음과 같은 URL 형식을 사용한다.
webView.loadUrl("file:///android_asset/page.html");
또는 원격 서버의 웹 페이지를 로드할 수도 있다.
자바스크립트에서 안드로이드 메서드 호출하기
자바스크립트가 네이티브 안드로이드 코드를 호출하려면 addJavascriptInterface 메서드를 사용해 특정 Java 객체를 JavaScript에 노출시켜야 한다.
webView.addJavascriptInterface(new BridgeObject(), "nativeBridge");
상호 호출 예제
다음은 전화번호 목록을 JSON 형식으로 전달하고, 사용자가 링크를 클릭하면 전화 앱을 실행하는 예제이다.
Java 코드 (MainActivity.java)
public class MainActivity extends AppCompatActivity {
private WebView webView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
webView = findViewById(R.id.webView);
WebSettings webSettings = webView.getSettings();
webSettings.setJavaScriptEnabled(true);
webView.loadUrl("file:///android_asset/contacts.html");
webView.addJavascriptInterface(new NativeController(), "nativeBridge");
}
public class NativeController {
// JavaScript에서 전화 걸기 요청 시 호출
@JavascriptInterface
public void initiateCall(String number) {
Intent callIntent = new Intent(Intent.ACTION_CALL);
callIntent.setData(Uri.parse("tel:" + number));
if (callIntent.resolveActivity(getPackageManager()) != null) {
startActivity(callIntent);
}
}
// HTML 페이지 로드 후 JS로 데이터 전달
@JavascriptInterface
public void fetchContactList() {
String data = "[{\"name\": \"김민수\", \"balance\": \"5000000\", \"phone\": \"01012345678\"}]";
webView.post(() -> webView.loadUrl("javascript:renderContacts('" + data + "')"));
}
}
}
HTML 및 JavaScript 코드 (assets/contacts.html)
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>연락처 목록</title>
<script type="text/javascript">
function renderContacts(jsonInput) {
let contacts = JSON.parse(jsonInput);
let table = document.getElementById("contactTable");
contacts.forEach(function(person) {
let row = table.insertRow();
let cellName = row.insertCell(0);
let cellBalance = row.insertCell(1);
let cellPhone = row.insertCell(2);
cellName.textContent = person.name;
cellBalance.textContent = person.balance;
cellPhone.innerHTML = '<a href="#" onclick="nativeBridge.initiateCall(\'' + person.phone + '\')">' + person.phone + '</a>';
});
}
</script>
</head>
<body onload="nativeBridge.fetchContactList()">
<table width="100%" id="contactTable" border="1">
<tr>
<th>이름</th>
<th>잔액</th>
<th>전화번호</th>
</tr>
</table>
</body>
</html>
권한 추가
전화 기능을 사용하려면 매니페스트에 권한을 선언해야 한다.
<uses-permission android:name="android.permission.CALL_PHONE" />
안드로이드 6.0(API 레벨 23) 이상에서는 런타임 권한 요청도 필요할 수 있다.