01. Android 개발 가이드


준비사항

HONE Smart Platform의 Android Client 를 적용하기 위해서는 다음과 같은 개발 도구 및 요구 조건을 만족 해야 한다.

개발도구

Operating System

  • Windows 7 (64-bit) 이상
  • Mac OS X 10.8.5 이상 (x86 only)
  • Linux GNOME or KDE Desktop (64-bit)
  • GNU C Library (glibc) 2.11 or later is required.

JDK

  • JDK 8 이상

SDK

  • 23 API Level 부터 33 API Level 까지 지원

Android 13 이상에서 실행되거나 Android 13 이상을 타겟팅하는 앱은 실행 시 알람 허용 여부 권한을 설정해야 한다. 

<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>

Android 12 이상에서 실행되거나 Android 12 이상을 타겟팅하는 앱은,
android:allowBackup="false"를 지정하면 Google Drive 백업이 사용 중지되지만 앱의 D2D 전송은 사용 중지되지 않는다.
매니페스트 파일에서 android:dataExtractionRules 속성을 사용하여 앱이 새 XML 구성 메커니즘으로 포함 및 제외 규칙을 지정해야 한다.

2020년 8월 부터 신규앱을 마켓에 업로드하기 위해서는 구글 안드로이드의 정책에 따라  타깃을 30 이상으로, 업그레이드의 경우 11월까지 지원해야 한다. 

API Level 28 부터 TLS 통신(https)이 기본 통신 형태로 변경되었으며 CLEARTEXT (http) 로는 별도의 옵션을 (networkSecurityConfig 이나 android:targetSandboxVersion="1" 와 android:usesCleartextTraffic="true") AndroidManifest.xml 에 추가해야지만 동작 한다. 

API Level 28 부터 Apache HTTP 이 bootclasspath 에서 제거 되며 기본적으로 앱에서 사용할수 없도록 변경 되었다. Apache HTTP 를 사용하기 위해서는 아래의 내용을 AndroidManifest.xml 에 추가해야 한다. 

<uses-library android:name="org.apache.http.legacy" android:required="false"/>

android:required="false" 어트리뷰트는 23 이하의 최소 SDK가 있는 앱에 필요하며 API Level 24 보다 낮은 기기에서는 org.apache.http.legacy 라이브러리가 제공되지 않는다. 


기타 설정

에뮬레이터 설정 방법

안드로이드의 다양한 버전을 테스트 하기 위해서는 단말보다는 에뮬레이터를 이용하여 테스트를 진행 하는 것이 용이 하므로 에뮬레이터 환경을 미리 구축 해두는 것이 좋다. 

picture1.png

Figure. AVD Manager Icon

에뮬레이터를 생성 하기 위해서는 툴 바에 AVD Manager 를 선택 하여 띄운 후 왼쪽 하단의 Create Virtual Device 버튼을 선택 한다.

이후 화면에 나타난 프리셋 정보를 기준으로 에뮬레이터를 생성할 수 있는데, 사용자가 원하는 단말을 선택 한 이후 단말에 적용될 시스템 레벨을 선택하여 사용하면 된다.
 

CPU/ABI 는 x86 또는 x86_64를 선택해야 하드웨어 가속이 되어 에뮬레이터가 빠르게 동작 된다.

Picture2.png

Figure. Your Virtual Devices Window

 

select hardware.png

Figure. Select Hardware Window

 

system image.png

Figure. Select a system image

 

avd.png

Figure. Android Virtual Device

 

실제 기기 사용법

실제 단말을 이용하여 앱을 구동하기 위해서는 미리 설정해야 하는 항목이 존재하는데 갤럭시 S20 (Android 11) 를 기준으로 설정 방법을 설명 한다.

먼저 해야 할 일은 개발자 모드를 활성화 시켜야 하는데 설정 -> 휴대전화 정보 -> 소프트웨어 정보를 선택 한 후 빌드 번호를 7번 연타 한다.

Picture6.png

Figure. Enable Developer Option

 

연타 후 설정 메뉴로 돌아가게 되면 이전과 다르게 개발자 옵션이라는 메뉴가 나타나고 개발자 옵션 메뉴를 선택 하면 USB 디버깅 옵션이 나타나게 된다.

이를 활성화 시켜주면 PC 와 단말간의 연결을 위한 작업이 완료 된 것이므로 이후 USB 케이블을 연결 하고 Android Studio 에서 구동을 하면 개발하는 앱을 설치/실행 하게 된다. 


프로젝트 생성

Android Studio 를 이용한 프로젝트 생성

Eclipse 에서 Android Studio 로 개발 환경이 변경되면서 프로젝트 생성에 대한 방법이 많이 변경 되었다. 기존에는 isLibrary 로 생성한 라이브러리 프로젝트를 기반으로 HONE Smart Platform 라이브러리가 배포되었지만 현재는 Android Studio 에 AAR(Library Project) 형태로 배포 된다. 이와 관련된 내용을 설명 한다.
프로젝트를 생성하기 위해서는 먼저 File -> New -> New Project 를 선택 하여 프로젝트의 속성을 설정하는 윈도우를 띄운다. HONE Smart Platform 을 이용하기 위해 Empty Activity 를 선택 한다. 이후 Next 버튼을 선택 한다.

new project.png

Figure. Select a Project Template

 

Application Name 과 Package Name 을 설정 후 프로젝트 파일을 생성할 위치인 Save location 을 지정 하고, Minimum SDK 버전을 선택 한다. 현재 HONE Smart Platform 은 최소 23 (Marshmallow) 에서 최대 33 (Android 13) 을 지원 한다. 모두 기본 값으로 두고 Finish버튼을 선택 하면 Android Studio 가 프로젝트에 필요한 기본 파일들을 생성하게 된다.

empty activity.png

Figure. Configure Your Project

 

Picture9.png

Figure. Android Studio Project Files

 

이렇게 생성된 프로젝트에 이제 HONE Smart Platform 라이브러리를 추가하여야 하는데 Android Studio 패키지 관리자에서 프로젝트를 선택 한다. 그런 다음 프로젝트 수준에서 libs 라는 새 디렉토리를 생성 한다.

Picture10.png

Figure. make a new directory

 

생성된 libs 폴더에 libhone-release.aar 파일을 붙여 넣는다.

Picture11.png

Figure. paste here your .aar file.Select 

 

Android 라이브러리의 코드를 다른 앱 모듈에 사용하려면 아래의 과정을 거쳐야 한다.

  • File > Project Structure > Dependencies로 이동 한다.
  • Declared Dependencies 탭에서 +를 클릭하고 드롭다운에서 JAR/AAR Dependency를 선택 한다.

     

Picture12.png

Figure. Declared Dependencies

 

  • Add Jar/Aar Dependency 대화상자에서 먼저 .aar 또는 .jar 파일 경로를 입력하고 종속 항목이 적용되는 구성을 선택 한다. 라이브러리를 모든 구성에서 사용할 수 있어야 하면 '구현' 구성을 선택 한다.

 

Picture13.png

Figure. Add Aar Dependency

 

라이브러리를 Modules 에 등록한 이후에 HONE Smart Platform 에서 사용하고 있는 외부 라이브러리 정보와 방금 추가한 HONE Smart Platform 라이브러리를 사용자가 생성한 app 에 해당하는 build.gradle 파일 내 dependencies 에 추가 한다. 


// KOTLIN
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.8.0"

implementation "androidx.appcompat:appcompat: 1.5.1"
implementation "androidx.legacy:legacy-support-v4:1.0.0"
implementation "androidx.vectordrawable:vectordrawable-animated:1.1.0 "
implementation "androidx.media:media:1.6.0"
implementation "com.google.android.material:material:1.8.0"
implementation "androidx.exifinterface:exifinterface:1.3.6"
implementation "androidx.multidex:multidex:2.0.1"
implementation "androidx.constraintlayout:constraintlayout:2.1.4"
implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.5.1"
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.5.1 "
implementation "androidx.lifecycle:lifecycle-process:2.5.1"
implementation "androidx.lifecycle:lifecycle-common-java8:2.5.1"
implementation "androidx.lifecycle:lifecycle-viewmodel-savedstate:2.5.1 "
implementation "androidx.work:work-runtime:2.8.1"
implementation "androidx.work:work-runtime-ktx:2.8.1 "
implementation "androidx.concurrent:concurrent-futures:1.1.0 "
implementation "androidx.concurrent:concurrent-futures-ktx:1.1.0"
implementation "androidx.window:window:1.0.0"
implementation "androidx.window:window-java:1.0.0"
implementation "androidx.window:window-rxjava2:1.0.0 "
implementation "androidx.webkit:webkit:1.6.1"

implementation "org.slf4j:slf4j-api:2.0.7"
implementation "com.github.tony19:logback-android:3.0.0"
implementation "com.fasterxml.jackson.core:jackson-core:2.13.3"
implementation "com.fasterxml.jackson.core:jackson-annotations:2.13.3"
implementation "com.fasterxml.jackson.core:jackson-databind:2.13.3"
implementation "com.squareup.okhttp3:okhttp:3.11.0"
implementation "com.j256.ormlite:ormlite-android:6.1"
implementation "io.reactivex.rxjava2:rxjava:2.2.21"
implementation "io.reactivex.rxjava2:rxandroid:2.1.1"

// For libhone-barcode library
api 'com.google.zxing:core:3.2.1'

// For libhone-beacon library
implementation "org.altbeacon:android-beacon-library:2.19.5"

// For libhone-gallery library
implementation "com.github.bumptech.glide:glide:4.15.1"
kapt "com.github.bumptech.glide:compiler:4.15.1"

// For libhone-nfc library
implementation "com.google.guava:guava:31.1-jre"

implementation files('libs/libhone-release.aar')
implementation files('libs/libhone-core-interface-release.aar')
implementation files('libs/libhone-permission-release.aar')
implementation files('libs/libhone-plugin-interface-release.aar')
implementation files('libs/libhone-util-release.aar')
implementation "androidx.appcompat:appcompat: 1.3.0"
implementation "androidx.legacy:legacy-support-v4:1.0.0"
implementation "androidx.media:media:1.3.1"
implementation "com.google.android.material:material:1.3.0"
implementation "androidx.exifinterface:exifinterface:1.3.2"
implementation "androidx.multidex:multidex:2.0.1"
implementation "androidx.constraintlayout:constraintlayout:2.0.4"
implementation "androidx.lifecycle:lifecycle-extensions:2.2.0"
implementation "androidx.webkit:webkit:1.4.0"

implementation "org.slf4j:slf4j-api:1.7.30"
implementation "com.github.tony19:logback-android:2.0.0"
implementation "com.fasterxml.jackson.core:jackson-core:2.12.3"
implementation "com.fasterxml.jackson.core:jackson-annotations:2.12.3"
implementation "com.fasterxml.jackson.core:jackson-databind:2.12.3"
implementation "com.squareup.okhttp3:okhttp:3.11.0"
implementation "com.j256.ormlite:ormlite-android:6.1"
implementation "io.reactivex.rxjava2:rxjava:2.2.21"
implementation "io.reactivex.rxjava2:rxandroid:2.1.1"
implementation "com.github.bumptech.glide:glide:4.12.0"

implementation files('libs/libhone-release.aar')
implementation files('libs/libhone-core-interface-release.aar')
implementation files('libs/libhone-permission-release.aar')
implementation files('libs/libhone-plugin-interface-release.aar')
implementation files('libs/libhone-util-release.aar')

람다와 메소드 레퍼런스 등의 기능을 이용하기 위해 android 항목 내에 JAVA 1.8 컴파일 옵션을 추가 하고 Android Architecture 항목을 이용하기 위한 dataBinding 을 활성화 시킨다. 

android {
    // ...

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }

    kotlinOptions {
        jvmTarget = "1.8"
    }

    buildFeatures {
        dataBinding true
        viewBinding true
   }
}

마지막으로 android 항목에 컴파일 시 무시해야 할 파일 정보를 선언한다.

android {
 ...

    packagingOptions {
        exclude 'META-INF/NOTICE'
        exclude 'META-INF/LICENSE'
        exclude 'META-INF/license.txt'
        exclude 'META-INF/notice.txt'

        // secure storage 이용시 아래 내용 추가
        exclude "lib/mips/librealm-jni.so"
        exclude "lib/armeabi/librealm-jni.so"
    }
}

이렇게 HONE Smart Platform 을 사용하기 위한 설정이 완료 되면 컴파일을 위한 환경이 완료 되고 이후에는 화면에 나타낼 요소와 환경 요소들을 추가하면 된다. 

제공 라이브러리 목록

HONE Smart Platform은 고객사의 편의를 위해 일부 기능들을 선 개발하여 제공 하고 있으며 그 항목은 아래와 같다. 

M : Mandatory, O : Optional 

Library NameRemarkVersionM/O
libhone-release.aarHSP 기본 라이브러리▲2.6.0M
libhone-core-interface-release.aarHSP 와 라이브러리간 연동용 인터페이스 라이브러리 ▲3.0.0M
libhone-plugin-interface-release.aarHSP Plug-in 인터페이스 라이브러리▲3.0.0M
libhone-permission-release.aarRuntime Permission  지원을 위한 라이브러리▲3.0.0M
libhone-util-release.aarHSP 공용 유틸 라이브러리▲3.1.1M
libhone-applinker-release.aar앱 호출을 위한 라이브러리▲3.0.0O
libhone-barcode-release.aarBarcode 리더 라이브러리▲2.6.4O
libhone-beacon-release.aar비콘 라이브러리▲4.2.8O
libhone-clipboard-release.aar클립보드 관리 라이브러리▲3.0.0O
libhone-crashreport-release.aar비정상 종료 및 예외 수집 라이브러리▲4.7.15O
libhone-fingerprint-release.aar지문인식 라이브러리▲3.0.0O
libhone-flashlight-release.aar카메라 조명 관리 라이브러리▲3.0.0O
libhone-gallery-release.aar다중 선택 갤러리 라이브러리▲3.0.0O
libhone-lockscreen-release.aar화면 잠금 관리 라이브러리▲3.1.1O
libhone-log-release.aar로그 메시지 관리 라이브러리▲3.0.0O
libhone-motion-release.aar단말 움직임 관리 라이브러리▲3.0.0O
libhone-nfc-release.aarNfc 라이브러리▲4.2.8O
libhone-notice-release.aar공지사항 라이브러리▲2.6.4O
libhone-openapi-release.aarOpen API 지원 라이브러리▲3.7.13O
libhone-screen-release.aar화면 밝기 관리 라이브러리▲3.0.0O
libhone-secure-storage-release.aar암호화 DB 라이브러리▲3.1.1O
libhone-vibrator-release.aar단말 진동 관리 라이브러리▲3.0.0O
    

configuration 파일 생성

HONE Smart Platform 은 assets 내에 config 디렉터리에 환경 정보를 가지는 json 파일을 두고 초기화 시 이를 읽어 화면을 구성 한다.
파일 경로는 $(project)/src/main/assets/config 경로에 아래의 파일들을 생성해 두어야 한다. 

  1. preConfiguration.json
  2. configuration.json
  3. actionflow.json
  4. plugin.json
  5. window.json

 

각각의 config 와 관련된 json 파일의 세부 속성은 Configuration Data 항목을 참조 하여 생성 하면 된다.

Application 생성

HSP 에서는 Application 객체를 상속 받아 HoneMobile 을 Application 내에서 초기화 하는 과정이 필요 하다. 

Example

 

class MainApp : Application {
    override fun onCreate() {
       super.onCreate()

        HoneMobile.get().setContext(this)
   }
}

 

public class MainApp extends Application {
   @Override
   public void onCreate() {
       super.onCreate();

        HoneMobile.get().setContext(this);
   }
}

타 라이브러리가 Application 을 선점 하고 있다면 외부 Application 라이브러리를  extends 하여 사용할 수도 있다. 

Application 객체를 extends 하였다면 반드시 AndroidManifest.xml 에 등록해 주어야 하며 application 테그 내 일부 옵션들을 넣어주어야 올바르게 작동하는데, 이중 allowBackup 은 반드시 false 로 설정하도록 한다. 

<manifest
   package="com.hanwha.example"
   xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:tools="http://schemas.android.com/tools"
   android:installLocation="preferExternal">
   
   <uses-feature android:name="android.hardware.location.gps" />

   <uses-permission android:name="android.permission.CAMERA" />
   <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
   <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
   <uses-permission android:name="android.permission.GET_ACCOUNTS"/>
   <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
   <uses-permission android:name="android.permission.READ_PHONE_NUMBERS" />
   <uses-permission android:name="android.permission.READ_CONTACTS"/>
   <uses-permission android:name="android.permission.WRITE_CONTACTS"/>
   <uses-permission android:name="android.permission.READ_MEDIA_IMAGES"/>
   <uses-permission android:name="android.permission.READ_MEDIA_VIDEO"/>

   <!-- For libhone-beacon library -->
   <uses-permission android:name="android.permission.BLUETOOTH"/>
   <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
   <uses-permission android:name="android.permission.BLUETOOTH_CONNECT"/>
   <uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE"/>
   <uses-permission android:name="android.permission.BLUETOOTH_SCAN"/>

   <!-- API 26+ -->
   <!-- oprations 을 통한 앱 배포 및  설치 시 아래의 권한을 설정해야 한다. -->
   <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />

   <!-- Android 13 (API level 33) 앱 실행 시 알람 허용 여부 권한 설정 필요; -->
   <uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>

   <application
       android:name=".MainApp"
       android:allowBackup="false"
       android:fullBackupContent="false"
       android:dataExtractionRules="@xml/data_extraction_rules"
       android:hardwareAccelerated="true"
       android:icon="@mipmap/ic_launcher"
       android:roundIcon="@mipmap/ic_launcher_round"
       android:largeHeap="true"
       android:label="@string/app_name"
       android:theme="@style/HoneTheme"
       android:requestLegacyExternalStorage="true"
       android:preserveLegacyExternalStorage="true"
       android:networkSecurityConfig="@xml/network_security_config"
       tools:ignore="GoogleAppIndexingWarning">

       <activity
           android:name=".MainActivity"
           android:exported="true"
           android:label="@string/app_name"
           android:theme="@style/HoneSplash"
           android:screenOrientation="portrait">

           <intent-filter>
               <action android:name="android.intent.action.MAIN"/>

               <category android:name="android.intent.category.LAUNCHER"/>
           </intent-filter>
       </activity>

       <provider
           android:name="android.support.v4.content.FileProvider"
           android:authorities="${applicationId}.fileprovider"
           android:exported="false"
           android:grantUriPermissions="true">
           <meta-data
               android:name="android.support.FILE_PROVIDER_PATHS"
               android:resource="@xml/provider_paths" />
       </provider>
   </application>

</manifest>

Layout XML 변경

HSP 에서는 내장되어 있는 layout 을 통해 화면을 출력 한다. 만약 사용자가 커스텀 layout 을 이용해야할 경우 layout 아이디를 변경하여 사용할 수 있도록 method 를 제공 하며 그 예는 아래와 같다. 

Example

override fun getHoneLayout() =
    R.layout.activity_main

override fun getMainLayoutId() =
    R.id.main_layout
@Override
protected int getHoneLayout() {
   return R.layout.activity_main;
}

@Override
public int getMainLayoutId() {
   return R.id.main_layout
}

android_main.xml

<layout>
   <androidx.constraintlayout.widget.ConstraintLayout
       xmlns:android="http://schemas.android.com/apk/res/android"
       xmlns:tools="http://schemas.android.com/tools"
       android:id="@+id/base_layout"
       android:layout_width="match_parent"
       android:layout_height="match_parent"
       tools:context="honemobile.client.core.HoneMobileActivity">

       <androidx.constraintlayout.widget.ConstraintLayout
           android:id="@+id/main_layout"
           android:layout_width="match_parent"
           android:layout_height="match_parent"/>

   </androidx.constraintlayout.widget.ConstraintLayout>
</layout>