인스턴트 앱(Instant App) 샘플
진행할 항목
- 샘플 프로젝트 준비
- 인스턴트 앱 구조에 맞춰 프로젝트 변경
- 안드로이드 스튜디오에서 실행해보기
- Heroku 구성
1. 샘플 프로젝트 준비
Android Architecture Blueprints 프로젝트로 샘플 프로젝트 준비
- 참고 : https://github.com/googlesamples/android-architecture
- git URL : https://github.com/googlesamples/android-architecture.git
git clone https://github.com/googlesamples/android-architecture.git
git checkout -t origin/todo-mvp
구글의 인스턴트 앱 예제를 보고 싶다면
2. 인스턴트 앱 구조에 맞춰 프로젝트 변경
가. 기존 app 모듈명을 base feature명으로 수정 (ex. base_module)
Project 창에서 모듈 선택 후 우클릭 Refactor - Rename - Rename module 선택 후 변경
app/build.gradle 수정 (
apk_module
은 추가할 APK Module명) applicationId, applicationIdSuffix 항목 주석 처리 room schemaLocation 오류 수정을 위해 javaCompileOptions 추가// apply plugin: 'com.android.application' apply plugin: 'com.android.feature' ... android { ... baseFeature true ... defaultConfig { //applicationId "com.example.android.architecture.blueprints.todomvp" ... javaCompileOptions { annotationProcessorOptions { arguments = ["room.schemaLocation": "$projectDir/schemas".toString()] } } } ... // If you need to add more flavors, consider using flavor dimensions. productFlavors { mock { dimension "default" //applicationIdSuffix = ".mock" } prod { dimension "default" } } ... } dependencies { application project(":apk_module") }
base_module/src/main/AndroidManifest.xml 수정
<manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" package="com.example.android.architecture.blueprints.todoapp"> ... </manifest>
나. APK Module 추가 (ex. apk_module)
Module 추가 (File > New > New Module)
Phone & Table Module 선택
모듈명 기입.(ex. apk_module)
앱 이름 및 최소 SDK 버전 등을 확인해야 함.
Add No Activity 선택.
values/strings.xml 에서 app_name 리소스 주석 처리
<resources> <!--<string name="app_name">APK Module</string>--> </resources>
apk_module에 base_module/proguard-rules.pro와 proguardTest-rules.pro를 복사
apk_module/build.gradle 수정 buildTypes나 Flavors는 base_module에 있던 내용을 사용 base_module에서 주석처리한 applicationId, applicationIdSuffix 항목 사용
android { ... defaultConfig { // applicationId "com.mycompany.apk_module" applicationId "com.example.android.architecture.blueprints.todomvp" ... } ... /* buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } */ buildTypes { debug { minifyEnabled true // Uses new built-in shrinker http://tools.android.com/tech-docs/new-build-system/built-in-shrinker useProguard false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' testProguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguardTest-rules.pro' } release { minifyEnabled true useProguard true proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' testProguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguardTest-rules.pro' } } flavorDimensions "default" // If you need to add more flavors, consider using flavor dimensions. productFlavors { mock { dimension "default" applicationIdSuffix = ".mock" } prod { dimension "default" } } // Remove mockRelease as it's not needed. android.variantFilter { variant -> if (variant.buildType.name == 'release' && variant.getFlavors().get(0).name == 'mock') { variant.setIgnore(true) } } // Always show the result of every unit test, even if it passes. testOptions.unitTests.all { testLogging { events 'passed', 'skipped', 'failed', 'standardOut', 'standardError' } } } ... dependencies { implementation project(':base_module') }
apk_module/src/main/AndroidManifest.xml 수정
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.nobasedev.apk_module"> </manifest>
gradle sync 중 아래 에러 로그시
Manifest merger failed : Attribute application@allowBackup value=(true) from AndroidManifest.xml:5:9-35 is also present at [:base_module] AndroidManifest.xml:28:9-36 value=(false). Suggestion: add 'tools:replace="android:allowBackup"' to <application> element at AndroidManifest.xml:4:5-10:43 to override.
apk_module/src/main/AndroidManifest.xml의 allowBackup 옵션을 base_module과 동일하게 설정
<application android:allowBackup="false" ... />
gradle sync 후 apk_module 빌드 및 run 시켜서 동작 확인 아래와 같은 에러들이 발생할 경우 있음.
Compilation failed; see the compiler error output for details. error: constant expression required
보통 아래와 같은 구문에서 오류로 base_module로 변경된 부분들에서 주로 발생함. 이유는 안드로이드 리소스 id를 switch ~ case 문으로 비교 처리하는 부분인데, base_module로 변경되며 기존 application 모듈이 feature 모듈로 변경되었고, 이에 R.java 값들이 final로 선언되지 않기 때문에 if ~ else로 변경해야 함. (라이브러리 프로젝트에서 주로 발생하는 문제)
switch문 앞에 커서를 놓고
alt
+Enter
후Replace 'switch' with 'if'
선택
다. Instant App Module 만들기
Module 추가 (File > New > New Module)
Instant App 선택
모듈명 기입. (ex. instant_module)
instantapp 모듈의 build.gradle에 아래와 같이 추가
apply plugin: 'com.android.instantapp' android { flavorDimensions "default" productFlavors { prod { dimension "default" } } } dependencies { implementation project(':base_module') }
Instant App에서 사용 가능한 권한 확인
- ACCESS_COARSE_LOCATION
- ACCESS_FINE_LOCATION
- ACCESS_NETWORK_STATE
- BILLING
- CAMERA
- INSTANT_APP_FOREGROUND_SERVICE (API level 26 or higher)
- INTERNET
- READ_PHONE_NUMBERS (API level 26 or higher)
- RECORD_AUDIO
- VIBRATE
3. 안드로이드 스튜디오에서 실행해보기
base_module 매니페스트에 인스턴트 앱 구동할 URL 정의 추가
<manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" package="com.example.android.architecture.blueprints.todoapp"> ... <activity android:name="com.example.android.architecture.blueprints.todoapp.tasks.TasksActivity" android:theme="@style/AppTheme.OverlapSystemBar"> ... <intent-filter android:autoVerify="true"> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> <data android:scheme="http" android:host="todoapp.com" android:pathPrefix="/tasks" /> <data android:scheme="https" /> </intent-filter> </activity> ... <activity android:name="com.example.android.architecture.blueprints.todoapp.statistics.StatisticsActivity" android:parentActivityName=".tasks.TasksActivity" tools:ignore="UnusedAttribute"> ... <intent-filter android:autoVerify="true"> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> <data android:scheme="http" android:host="todoapp.com" android:pathPrefix="/stats" /> <data android:scheme="https" /> </intent-filter> </activity>
Run
메뉴의Edit Configurations...
선택Android App
의instant_module
선택 후Launch Options
의URL
항목 입력Run 하여 동작 확인.
apk_module과 instant_module의 차이는 멀티태스킹 화면에서 확인 가능 (인스턴트 앱의 경우 앱 아이콘 우측 하단의 번개 표시됨)
4. Heroku 구성
Heroku 회원가입 및 로그인
New
-Create new app
선택App name
지정 (ex. testinstant) 후Create app
버튼 클릭Settings
탭 메뉴에서Buildpacks
메뉴의Add buildpakc
선택nodejs
선택 후Save changes
버튼 클릭Deploy
탭 메뉴에서Heroku Git
선택 후 하단의 설명대로 git 설정Heroku CLI
설치 (https://devcenter.heroku.com/articles/heroku-command-line)로컬에 저장할 폴더 생성 (ex. heroku_todo_sample) 후 그 경로에서 cmd 띄움.
아래 명령으로 로그인 시도 및 완료
> heroku login
git 초기화
> git init > heroku git:remote -a testinstant
nodejs 테스트 코드 작성
package.json
{ "name": "express-tutorial", "version": "1.0.0", "dependencies": { "express": "~4.13.1", "ejs": "~2.4.1" } }
Procfile
web: node index.js
index.js
var express = require('express') var app = express() app.set('port', (process.env.PORT || 5000)) app.use(express.static(__dirname + '/public')) app.set('views', __dirname + '/views'); app.set('view engine', 'ejs'); app.engine('html', require('ejs').renderFile); app.get('/', function(request, response) { console.log("\n *index START* \n"); response.send('it\'s index'); console.log("\n *index EXIT* \n"); }) app.get('/.well-known/assetlinks.json',function(request, response){ //response.render('assetlinks.json'); var fs = require("fs"); console.log("\n *START* \n"); var content = fs.readFileSync("assetlinks.json"); response.setHeader('Content-Type', 'application/json'); response.send(content); console.log("Output Content : \n"+ content); console.log("\n *EXIT* \n"); }); app.listen(app.get('port'), function() { console.log("Node app is running at localhost:" + app.get('port')) })
assetlinks.json 만들기 참고 : https://developers.google.com/digital-asset-links/tools/generator 위 링크에서
Hosting site domain
,App package name
,App package fingerprint (SHA256)
등을 입력하고GENERATE STATEMENT
버튼을 누르면 아래와 같은 형태를 출력해주며, 그 내용을 assetlinks.json 파일로 만들면 됨.[{ "relation": ["delegate_permission/common.handle_all_urls"], "target": { "namespace": "android_app", "package_name": "com.sample.app", "sha256_cert_fingerprints": ["75:D1:12:1A:85:EC:C7:2E...53:3E:84:E3:8C:0B"] } }]
그리고
TEST STATEMENT
버튼을 눌러서 실제 서버에 json파일이 있는지 확인해볼 수 있음. (아래 과정 진행 후 테스트)git commit 및 push (push시 Heroku에서 자동으로 deploy됨)
> git add . > git commit -am "just do it" > git push heroku master
위 과정 중 git push 안될 경우 (회사 보안으로 안되는 경우가 있는듯) 아래 명령 실행 후 token 복사
> heroku auth:token ed2e5b99-97bc-...
다시 git push heroku master 시도 후 Windows 보안 팝업이 뜨면 사용자 이름 없이 암호만 token 입력 후 확인하면 됨.
브라우저에서 아래 링크들 확인
base_module 매니페스트에서 정의한 URL 인텐트 필터들의 URL 주소를 수정함.
5. 주의할 점
Google Play 배포시 인스턴트 앱을 따로 배포함.
안드로이드 스튜디오의 Buid
- Generate Signed APK...
메뉴에서 instant_module을 선택하여 생성함.
인스턴트 앱용 파일은 apk가 아니라 zip 형태로 나오며, 이를 Google Play 인스턴트 앱 배포 메뉴에서 올림.
실제 배포 요청시 base_module 매니페스트에 정의된 인텐트 필터의 URL 경로를 확인함.
해당 URL의 ./well-known/assetlinks.json이 확인 안된다면 배포가 안됨.
배포 후에도 단말마다 되는 경우가 있고, 안되는 경우가 있어 확인이 필요함.
'Android개발' 카테고리의 다른 글
[Android] OS 9 Pie 기능들 (0) | 2018.08.17 |
---|---|
[Android] Android OS 9 Pie 주요 기능들 (0) | 2018.08.09 |
[Android][InstantApp] 인스턴트 앱 2 (0) | 2018.07.24 |
[Android][InstantApp] 인스턴트 앱 1 (0) | 2018.07.24 |
[개인정보처리방침] NB Flash 개인정보 취급방침 (1) | 2018.07.09 |