255 lines
10 KiB
Markdown
255 lines
10 KiB
Markdown
|
<h1 align="center">Nexacro N WebView for Android</h1>
|
||
|
Nexacro N Runtime for Android 버전을 WebView 베이스로 바꾼 버전 입니다.
|
||
|
|
||
|
## Nexacro N Runtime for Android 버전 대비 차이점
|
||
|
- v8, skia, curl 등 네이티브 모듈이 제거 되었습니다. 그리고 현재 까지 구현된 코드에서는 네이티브 코드(c/c++) 하나도 없습니다.
|
||
|
- NexacroUpdatorActivity 가 하던 동작을 NexacroAcitivity 로 이동 시킨후 NexacroUpdatorActivity 를 제거하였습니다.
|
||
|
- start_android.json 을 파싱 하는 로직을 제외한 초기 로딩은 새롭게 구현하였습니다.
|
||
|
- 컨텐츠의 버전 관리를 archiveinfo.xml 대신 Room 을 이용한 DB 로 변경 하였습니다.
|
||
|
- archivefiles.js 생성에 필요한 resource.xml 도 Room 을 이용한 DB 로 변경하였습니다.
|
||
|
- DeviceAPI 가 별도로 배포될수 있도록 nexacroLib 에서 분리하여 프로젝트를 구성하였습니다.
|
||
|
- 일부 DeviceAPI 모듈 및 기존 기능 중 일부(ApkInstall...)에 대해서 리팩토링을 하였습니다.
|
||
|
- [Cordova WebView](https://github.com/apache/cordova-android) 엔진 구조를 참고하여 개발하였습니다.
|
||
|
|
||
|
## 개선사항
|
||
|
- 사용자가 만든 SplashView 를 사용할 수 있게 인터페이스를 추가하였습니다.
|
||
|
- 앱 설치 후에도 Update Type을 server or update, local 변경이 자유롭게 가능하도록 변경하였습니다.
|
||
|
- Cordova 관련 플러그인 인터페이스를 내장시켜 사용성을 개선하였습니다.
|
||
|
|
||
|
## 테스트 환경
|
||
|
`NEXACRO Studio`
|
||
|
- 툴 작업은 아직 되어 있지 않습니다. 대신 iOS 로 디플로이한 프로젝트를 수정없이 사용 가능합니다.
|
||
|
- 프레임워크로 사용되는 nexacrolib는 [FEATURE/FEATURE_ANDROID_WEBVIEW](https://tfs2.tobesoft.com:9443/tfs/XPLATFORM/WORK800/_git/WORK800) 브랜치에서 개발되고 있습니다.
|
||
|
|
||
|
`Android Studio`
|
||
|
- Android Studio Electric Eel | 2022.1.1 Patch 1 이상 최신 안드로이드 스튜디오 버전을 권장합니다.
|
||
|
```sh
|
||
|
classpath 'com.android.tools.build:gradle:7.4.1'
|
||
|
classpath 'com.google.gms:google-services:4.3.15'
|
||
|
```
|
||
|
|
||
|
## 사양
|
||
|
- 안드로이드 5.0 롤리팝 (API Level 21) 이상
|
||
|
- 안드로이드 13.0 티라미수 (API Level 33) 타겟팅
|
||
|
|
||
|
## 의존 라이브러리
|
||
|
- firebase 라이브러리를 NRE 대비 최신 버전으로 업그레이드를 하면서 신규 API 에 맞는 인터페이스로 변경하였습니다.
|
||
|
```sh
|
||
|
implementation 'com.google.firebase:firebase-core:21.1.1'
|
||
|
implementation 'com.google.firebase:firebase-messaging:23.0.8'
|
||
|
```
|
||
|
- 일부 디바이스API에서 C++를 java로 포팅하는 과정중에 okhttp3 라이브러리를 사용하게 되었습니다.
|
||
|
```sh
|
||
|
implementation 'com.squareup.okhttp3:okhttp:4.10.0'
|
||
|
```
|
||
|
- XPUSH 를 사용하는 경우
|
||
|
```sh
|
||
|
implementation 'org.slf4j:slf4j-api:1.7.36'
|
||
|
```
|
||
|
- 전체 의존 라이브러리 리스트
|
||
|
```sh
|
||
|
implementation 'androidx.appcompat:appcompat:1.5.1'
|
||
|
implementation 'com.google.android.material:material:1.6.1'
|
||
|
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
|
||
|
implementation "androidx.room:room-runtime:2.4.3"
|
||
|
implementation 'androidx.exifinterface:exifinterface:1.3.4'
|
||
|
implementation 'com.google.firebase:firebase-core:21.1.1'
|
||
|
implementation 'com.google.firebase:firebase-messaging:23.0.8'
|
||
|
implementation 'com.squareup.okhttp3:okhttp:4.10.0'
|
||
|
implementation 'org.slf4j:slf4j-api:1.7.36'
|
||
|
annotationProcessor "androidx.room:room-compiler:2.4.3"
|
||
|
```
|
||
|
|
||
|
## 테스트 방법
|
||
|
- Nexacro N Runtime for Android 와 거의 동일한 방법으로 구동합니다.
|
||
|
- NexacroActivity 클래스를 상속받은 [MainActivity.java](http://172.10.12.65:22080/nre/Droid-WebView/src/commit/39986984c6528194720724357439532d14f9d456/app/src/main/java/com/example/nexacro/webview/MainActivity.java) 의 onCreate 함수 안에서 deploy 된 주소를 입력합니다.
|
||
|
- 서버, 업데이트, 로컬 방식을 지원 합니다.
|
||
|
```sh
|
||
|
public class MainActivity extends NexacroActivity {
|
||
|
...
|
||
|
@Override
|
||
|
protected void onCreate(Bundle savedInstanceState) {
|
||
|
super.onCreate(savedInstanceState);
|
||
|
|
||
|
// 업데이트 or 서버 방식
|
||
|
setProjectURL("http://172.10.12.59:8080/nexacroN/DroidWebviewSample/_ios_/");
|
||
|
setBootstrapURL("http://172.10.12.59:8080/nexacroN/DroidWebviewSample/_ios_/start_ios.json");
|
||
|
|
||
|
// 로컬 방식 (디플로이된 컨텐츠는 assets/archive 폴더에 위치 시킨다)
|
||
|
setBootstrapURL("file:///android_asset/archive/start_android.json");
|
||
|
}
|
||
|
...
|
||
|
}
|
||
|
```
|
||
|
|
||
|
## 사용자 Splash View 변경 방법
|
||
|
- SplashView.java 를 상속 받아서 개발합니다. (http://172.10.12.65:22080/nre/Droid-WebView/commit/0893991ef48b4fc7e7ba53f19f2d2eacaa645e2a)
|
||
|
- 진행 상황과 메시지를 setMessage, setProgress 이벤트를 통해서 확인 할수 있습니다.
|
||
|
```sh
|
||
|
public class MySplashViewExample extends ConstraintLayout implements SplashView {
|
||
|
...
|
||
|
|
||
|
@Override
|
||
|
public void setMessage(String message) {
|
||
|
TextView textView = getRootView().findViewById(R.id.my_message);
|
||
|
textView.setText(message);
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public void setProgress(int progress) {
|
||
|
ProgressBar progressBar = getRootView().findViewById(R.id.my_progressBar);
|
||
|
progressBar.setProgress(progress);
|
||
|
}
|
||
|
}
|
||
|
```
|
||
|
|
||
|
|
||
|
## 넥사크로 플러그인 개발
|
||
|
- NexacroPlugin을 상속받은 후 필수 함수를 정의하여 개발합니다.
|
||
|
```sh
|
||
|
public class Camera extends NexacroPlugin {
|
||
|
|
||
|
@Override
|
||
|
public void init(JSONObject paramObject) {
|
||
|
// JavaScript에서 exec를 호출할때 method 가 constructor 일때 호출됩니다.
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public void release(JSONObject paramObject) {
|
||
|
// JavaScript에서 exec를 호출할때 method 가 destroy 일때 호출됩니다.
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public void execute(String method, JSONObject paramObject) {
|
||
|
// JavaScript에서 exec를 호출할때 method 가 constructor, destroy 이외일때 호출됩니다.
|
||
|
}
|
||
|
}
|
||
|
```
|
||
|
|
||
|
- 결과값 리턴은 아래와 같은 방식으로 개발합니다.
|
||
|
```sh
|
||
|
// JavaScript 에서 호출한 함수에 대한 리턴값을 즉시 전달할때 ex) TCPClientSocket
|
||
|
{
|
||
|
String resultValue = "문자로된 리턴값";
|
||
|
setReturnValue(resultValue);
|
||
|
}
|
||
|
|
||
|
// JavaScript 에서 호출한 함수에 대한 리턴값을 PluginResult 클래스로 콜백 전달할때
|
||
|
{
|
||
|
// PluginResult(String callbackId, String eventName, String parameters)
|
||
|
PluginResult result = new PluginResult(objectId, "_onsuccess", "JSON 형식의 문자열");
|
||
|
|
||
|
webView.sendPluginResult(result); // sendPluginResult(PluginResult pluginResult);
|
||
|
}
|
||
|
|
||
|
// JavaScript 에서 호출한 함수에 대한 리턴값을 문자열로 콜백 전달할때
|
||
|
{
|
||
|
String script = "nexacro.Device.keyEvent(4)"; // KEYCODE_BACK
|
||
|
webView.sendPluginResult(script); // sendPluginResult(String script);
|
||
|
}
|
||
|
```
|
||
|
|
||
|
- 호출한 액티비티로부터 결과를 받아오는 방법
|
||
|
```sh
|
||
|
public class Sample extends NexacroPlugin {
|
||
|
// 액티비티 호출
|
||
|
{
|
||
|
Intent intent = new Intent();
|
||
|
intent.setAction(MediaStore.ACTION_IMAGE_CAPTURE);
|
||
|
|
||
|
nexacro.startActivityForResult(this, intent, REQUEST_CODE);
|
||
|
}
|
||
|
|
||
|
// 결과 받기
|
||
|
@Override
|
||
|
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||
|
if (resultCode == Activity.RESULT_OK) {
|
||
|
// code here
|
||
|
} else if (resultCode == Activity.RESULT_CANCELED) {
|
||
|
// code here
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
```
|
||
|
|
||
|
- 권한이 허가 되어 있는지 확인
|
||
|
```sh
|
||
|
PermissionHelper.hasPermission(this, Manifest.permission.CAMERA); // 카메라 접근 권한 확인
|
||
|
```
|
||
|
|
||
|
- 권한 요청 하기
|
||
|
```sh
|
||
|
public class Sample extends NexacroPlugin {
|
||
|
// 권한 요청
|
||
|
{
|
||
|
String[] permissions = {};
|
||
|
permissions = new String[]{
|
||
|
Manifest.permission.CAMERA,
|
||
|
Manifest.permission.READ_EXTERNAL_STORAGE,
|
||
|
Manifest.permission.WRITE_EXTERNAL_STORAGE};
|
||
|
PermissionHelper.requestPermissions(this, ACCESS_CAMERA, permissions);
|
||
|
}
|
||
|
|
||
|
// 권한 확인
|
||
|
@Override
|
||
|
public void onRequestPermissionResult(int requestCode,
|
||
|
String[] permissions,
|
||
|
int[] grantResults) throws JSONException {
|
||
|
for (int r : grantResults) {
|
||
|
if (r == PackageManager.PERMISSION_DENIED) {
|
||
|
// permission error
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (requestCode == ACCESS_CAMERA) {
|
||
|
executeCamera(this.method, this.paramObject);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
```
|
||
|
|
||
|
## 코르도바 플러그인 추가 방법
|
||
|
- (개발중인) 코르도바 제네레이터를 사용합니다.
|
||
|
- 코르도바 플러그인 모듈이 생성됩니다.
|
||
|
- 넥사크로 프로젝트 하위 경로로 필요한 플러그인 소스가 복사되어 배치됩니다.
|
||
|
- 넥사크로 프로젝트에 배치된 소스가 앱 프로젝트에 복사됩니다.
|
||
|
- 코르도바 제네레이터가 하지 못하는 작업은 plugin.xml 정보를 바탕으로 아래와 같이 직접 수정합니다.
|
||
|
1. 넥사크로 plugin_config.xml 파일에 코르도바 플러그인을 다음과 같이 등록
|
||
|
```sh
|
||
|
<!-- plugin.xml 파일 정보를 바탕으로 plugin_config.xml 파일에 등록합니다. -->
|
||
|
|
||
|
plugin.xml
|
||
|
<platform name="android">
|
||
|
<config-file target="res/xml/config.xml" parent="/*">
|
||
|
<feature name="StatusBar">
|
||
|
<param name="android-package" value="org.apache.cordova.statusbar.StatusBar" />
|
||
|
<param name="onload" value="true" />
|
||
|
</feature>
|
||
|
<preference name="StatusBarOverlaysWebView" value="true" />
|
||
|
</config-file>
|
||
|
</platform>
|
||
|
|
||
|
==>
|
||
|
|
||
|
plugin_config.xml
|
||
|
<plugin name="StatusBar" class="org.apache.cordova.statusbar.StatusBar" onload="true"/>
|
||
|
<preference name="StatusBarOverlaysWebView" value="true" />
|
||
|
|
||
|
코르도바의 config.xml은 넥사크로의 plugin_config.xml 파일과 동일한 역할을 합니다.
|
||
|
```
|
||
|
2. 앱의 AndroidManifest.xml 에 권한 및 기타 정보 추가
|
||
|
- uses-permission, uses-feature
|
||
|
3. 플러그인의 종류에 따라서 이외의 작업이 있을수 있습니다.
|
||
|
4. 빌드.
|
||
|
|
||
|
## 개발 편의 기능
|
||
|
1. 주소창을 추가하여 폼 이동을 빠르게 할 수 있습니다.
|
||
|
2. 시작 프로젝트를 동적으로 선택할 수 있습니다.
|
||
|
```sh
|
||
|
public class MainActivity extends NexacroActivity {
|
||
|
boolean dev_ShowAddressBar = true;
|
||
|
boolean dev_ShowProjectSelector = true;
|
||
|
...
|
||
|
}
|
||
|
```
|