AOS_iOS_NRE_Sample/NexacroN_V24/Android/README.md

10 KiB

Nexacro N WebView for Android

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 엔진 구조를 참고하여 개발하였습니다.

개선사항

  • 사용자가 만든 SplashView 를 사용할 수 있게 인터페이스를 추가하였습니다.
  • 앱 설치 후에도 Update Type을 server or update, local 변경이 자유롭게 가능하도록 변경하였습니다.
  • Cordova 관련 플러그인 인터페이스를 내장시켜 사용성을 개선하였습니다.

테스트 환경

NEXACRO Studio

  • 툴 작업은 아직 되어 있지 않습니다. 대신 iOS 로 디플로이한 프로젝트를 수정없이 사용 가능합니다.
  • 프레임워크로 사용되는 nexacrolib는 FEATURE/FEATURE_ANDROID_WEBVIEW 브랜치에서 개발되고 있습니다.

Android Studio

  • Android Studio Electric Eel | 2022.1.1 Patch 1 이상 최신 안드로이드 스튜디오 버전을 권장합니다.
    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 에 맞는 인터페이스로 변경하였습니다.
    implementation 'com.google.firebase:firebase-core:21.1.1'
    implementation 'com.google.firebase:firebase-messaging:23.0.8'
  • 일부 디바이스API에서 C++를 java로 포팅하는 과정중에 okhttp3 라이브러리를 사용하게 되었습니다.
    implementation 'com.squareup.okhttp3:okhttp:4.10.0'
  • XPUSH 를 사용하는 경우
    implementation 'org.slf4j:slf4j-api:1.7.36'
  • 전체 의존 라이브러리 리스트
    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 의 onCreate 함수 안에서 deploy 된 주소를 입력합니다.
  • 서버, 업데이트, 로컬 방식을 지원 합니다.
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 를 상속 받아서 개발합니다. (0893991ef4)
  • 진행 상황과 메시지를 setMessage, setProgress 이벤트를 통해서 확인 할수 있습니다.
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을 상속받은 후 필수 함수를 정의하여 개발합니다.
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 이외일때 호출됩니다.
    }
}
  • 결과값 리턴은 아래와 같은 방식으로 개발합니다.
// 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);
}
  • 호출한 액티비티로부터 결과를 받아오는 방법
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
        }
    }
}
  • 권한이 허가 되어 있는지 확인
PermissionHelper.hasPermission(this, Manifest.permission.CAMERA); // 카메라 접근 권한 확인
  • 권한 요청 하기
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 파일에 코르도바 플러그인을 다음과 같이 등록
      <!-- 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. 시작 프로젝트를 동적으로 선택할 수 있습니다.
public class MainActivity extends NexacroActivity {
    boolean dev_ShowAddressBar = true;
    boolean dev_ShowProjectSelector = true;
    ...
}