AOS_iOS_NRE_Sample/NexacroN_V24/Android/README.md

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;
...
}
```