연구 목적 : 내부 값 난독화 목적

결과 : 값 난독화에는 의미가 적음 // 자체제작 라이브러리 난독화에는 의미가 있음(C++)

- 값은 되도록 서버에 저장

- proguard를 이용

 

여러 사이트를 참고하여 ndk를 이용한 키 난독화 작업을 테스트 해보았음.

다만 구글링으로 구성하려고 하면 쉽지 않다.

오히려 안드로이드스튜디오의 템플레이트로 연습해보는 것이 좋다.

 

Native C++ 프로젝트를 열어보면

아래와 같이 cpp 폴더와 함께 CMake 관련 파일들이 생성된다.

 

native-lib.cpp 파일을 보면

Hello from C++을 리턴하게 되어있다.

 

MainActivity를 열어보면 스태틱으로 네이티브 라이브러리와 함수를 로드하게 되어있고

빌드후 실행해보면 Hello from C++가 나오는 간단한 프로젝트이다.

 

 

난독화로서 의미가 적은 이유

apk파일로 만들고 툴을 이용하여 디컴파일 해보면

아래와 같은 파일들이 만들어진다. (jniLibs)

 

위의 예제와 같은 이름의 프로젝트를 만들고 

Project구조로 변경한뒤 

main 폴더 안에 jniLibs라는 폴더를 만들고 그안에 위 파일들을 넣어준다.

그러고난 뒤 메인액티비티의 xml과 클래스파일을 예제 프로젝트와 똑같이 만든 후

빌드 실행 해보면 함수가 호출되어 같은 값이 출력된다.

(큰 의미 없다는 것)

 

jniLibs에 들어간 것은 so 파일인데

c파일은 so파일로 만들어져도 아래 사이트에 업로드해보면 대충 값을 확인할 수 있다.

onlinedisassembler.com/odaweb/

 

ODA - The Online Disassembler

You need to upgrade your browser or enable javascript to view this site!

onlinedisassembler.com

 

cpp파일은 so파일로 만들어지면 위 사이트로 열어봐도 보기 어렵다.

즉 내부코드를 확인하기는 쉽지 않다는 뜻이다. (코드 보안에는 좋을듯 함)

하지만 apk를 디컴파일하여 해당라이브러리를 사용하는 코드를 확인하여 작동해보면 값은 가져올 수 있다.

 

추가로 proguard 로 앱자체를 난독화하여 찾기 어렵게 만들어도 디컴파일 툴을 이용하면

아래와 같이 큰 힘을 들이지 않아도 찾아 낼 수 있다.

 

아이디어라면 라이브러리 이름과 매서드를 한글자(a 등)로 하여 분석하기 매우 힘들게는 가능 할 것 같다.

 

 

사용한 툴

안드로이드 스튜디오
sublimetext
apktool
dex2jar
jd-gui

 

ndk cmark 사용법 관련 주소

(다시 말씀드리지만 ndk cmark 연습은 샘플프로젝트를 이용하는 것이 가장 빠름)

developer.android.com/studio/projects/install-ndk?hl=ko

 

NDK 및 CMake 설치 및 구성  |  Android 개발자  |  Android Developers

앱의 네이티브 코드를 컴파일하고 디버그하려면 다음 구성요소가 필요합니다. Android 네이티브 개발 키트(NDK): Android에서 C 및 C++ 코드를 사용할 수 있도록 해주는 도구 모음입니다. CMake: Gradle과

developer.android.com

 

developer.android.com/studio/projects/add-native-code?hl=ko

 

C 및 C++ 코드를 프로젝트에 추가  |  Android 개발자  |  Android Developers

C 및 C++ 코드를 Android 프로젝트에 추가하는 방법을 알아보세요.

developer.android.com

 

developer.android.com/ndk/samples/sample_hellojni

 

샘플: hello-jni  |  Android NDK  |  Android Developers

이 샘플에서는 NDK로 빌드한 작은 C/C++ 애플리케이션인 hello-jni를 살펴봅니다. 이 샘플은 android-mk 분기 내 ndk-samples 저장소의 hello-jni 디렉터리에 있습니다. Android.mk 다음 두 줄은 네이티브 소스 파

developer.android.com

 

medium.com/programming-lite/securing-api-keys-in-android-app-using-ndk-native-development-kit-7aaa6c0176be

 

Securing API Keys in Android App using NDK (Native Development Kit)

Securing API keys in Android application has become a challenging by traditional methods (storing them in strings.xml or in Gradle etc.)…

medium.com

 

thepassion.tistory.com/332

 

[Android] ndk-build를 이용한 Native Code 빌드 및 사용방법

ndk-build를 이용한 Native Code 빌드 및 사용방법 다음과 같은 이유로 Android App에서 Native Code(C/C++등)로 코드를 작성하여 사용해야 할 경우가 존재합니다. 처리 속도 및 성능향상 C/C++로 만들어진 코드.

thepassion.tistory.com

 

medium.com/@abhi007tyagi/storing-api-keys-using-android-ndk-6abb0adcadad

 

Securing API Keys using Android NDK

Today there are thousands of third-party libraries and APIs available to developers for creating cool, amazing mobile apps. These APIs are…

medium.com

 

blog.mindorks.com/securing-api-keys-using-android-ndk

 

Securing API Keys using Android NDK (Native Development Kit)

In this blog, we will learn how to secure our API Keys that are used in Android applications using the Android NDK (Native Development Kit). We have created a detailed blog of securing the API Keys.

blog.mindorks.com

 

yoo-hyeok.tistory.com/72

 

[Android] NDK를 이용한 C/C++ 연동 개발

NDK란 무엇인가? Android NDK는 C와 C++ 같은 네이티브 코드 언어를 사용하여 앱의 일부를 구현하는 도구모음입니다. 어떤 유형의 앱에서는 네이티브 코드 언어로 작성된 코드 라이브러리를 재사용하

yoo-hyeok.tistory.com

 

 

 

1. app 단위 gradle에서 minifyEnabled true 세팅

 

2. proguard-rules.pro 파일을 수정

외부 라이브러리 등의 난독화 설정을 해줘야한다.
라이브러리 docs에 proguard 관련 내용이 있으니 참고하면 된다.

또한 retrofit2와 rxjava 등을 사용한다면 통신에 필요한 모델들도 난독화에서 제외해야한다.

인텔리제이에서 아래와 같이 빨간줄이 뜨지만 정상작동한다.
(오히려 빨간줄을 없애려고 * 하나 줄이는 등의 작업을 하면 빌드 후 문제가 발생하는 듯 하다.)

 

3. 빌드 후 테스트하여 에러 등을 확인한다.

 

4. apktool / dex2jar / jd-gui 등의 디컴파일 툴 등을 이용하여 디컴파일해서 난독화가 잘되었는지 확인한다.

 

5. 기타

아래는 proguard-rules.pro파일을 수정할 때 필요한 코드 등을 정리한 것이다.
아래 내용에 없는 라이브러리는 해당 라이브러리 사이트나 docs에서 proguard 설정 코드를 찾아본다.
그래도 안된다면 구글링을 하여 선배님들이 만들어 놓은 코드를 사용하자.

더보기
# If you keep the line number information, uncomment this to
# hide the original source file name.
# 소스 파일 변수 명 바꾸는 옵션
-renamesourcefileattribute SourceFile

# Uncomment this to preserve the line number information for
# debugging stack traces.
# 소스 파일의 라인을 섞지 않는 옵션 (이거 안해주면 나중에 stacktrace보고 어느 line에서 오류가 난 것인지 확인 불가)
-keepattributes SourceFile,LineNumberTable

# Retrofit2
# Retrofit does reflection on generic parameters. InnerClasses is required to use Signature and
# EnclosingMethod is required to use InnerClasses.
-keepattributes Signature, InnerClasses, EnclosingMethod

# Retrofit does reflection on method and parameter annotations.
-keepattributes RuntimeVisibleAnnotations, RuntimeVisibleParameterAnnotations

# Retain service method parameters when optimizing.
-keepclassmembers,allowshrinking,allowobfuscation interface * {
    @retrofit2.http.* <methods>;
}

# Ignore annotation used for build tooling.
-dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement

# Ignore JSR 305 annotations for embedding nullability information.
-dontwarn javax.annotation.**

# Guarded by a NoClassDefFoundError try/catch and only used when on the classpath.
-dontwarn kotlin.Unit

# Top-level functions that can only be used by Kotlin.
-dontwarn retrofit2.KotlinExtensions
-dontwarn retrofit2.KotlinExtensions$*

# With R8 full mode, it sees no subtypes of Retrofit interfaces since they are created with a Proxy
# and replaces all potential values with null. Explicitly keeping the interfaces prevents this.
-if interface * { @retrofit2.http.* <methods>; }
-keep,allowobfuscation interface <1>
# Retrofit2

# 카카오 지도 앱 (빨간줄 뜨지만 정상)
-keep class net.daum.** {*;}
-keep class android.opengl.** {*;}
-keep class com.kakao.util.maps.helper.** {*;}
-keepattributes Signature
-keepclassmembers class * {
    public static <fields>;
    public *;
}
# 카카오 지도 앱 (빨간줄 뜨지만 정상)

# 카카오 로그인
-keep class com.kakao.sdk.**.model.* { <fields>; }
-keep class * extends com.google.gson.TypeAdapter
# 카카오 로그인

# 네이버 로그인
-keep public class com.nhn.android.naverlogin.** {
       public protected *;
}
# 네이버 로그인

# firebase 구글 로그인
-keepattributes Signature
-keepattributes *Annotation*
# firebase 구글 로그인

# sqlite
-keep class org.sqlite.** { *; }
-keep class org.sqlite.database.** { *; }
-keep class net.sqlcipher.** { *; }
-dontwarn net.sqlcipher.**
# sqlite

# roomdb (androidx)
-keep class * extends androidx.room.RoomDatabase
-dontwarn androidx.room.paging.**
# roomdb

#glide
-keep public class * implements com.bumptech.glide.module.GlideModule
-keep public class * extends com.bumptech.glide.module.AppGlideModule
-keep public enum com.bumptech.glide.load.ImageHeaderParser$** {
  **[] $VALUES;
  public *;
}
#glide


# okhttp3
-dontwarn okhttp3.**
-dontwarn okio.**
-dontnote okhttp3.**
# okhttp3


# support v4 ,v7
-dontwarn android.support.**
# support v4 ,v7


## gson (gson 컨버터와 다른 것)
###---------------Begin: proguard configuration for Gson  ----------
## Gson uses generic type information stored in a class file when working with fields. Proguard
## removes such information by default, so configure it to keep all of it.
#-keepattributes Signature
#
## For using GSON @Expose annotation
#-keepattributes *Annotation*
#
## Gson specific classes
#-dontwarn sun.misc.**
##-keep class com.google.gson.stream.** { *; }
#
## Application classes that will be serialized/deserialized over Gson
#-keep class com.google.gson.examples.android.model.** { *; }
#
## Prevent proguard from stripping interface information from TypeAdapterFactory,
## JsonSerializer, JsonDeserializer instances (so they can be used in @JsonAdapter)
#-keep class * implements com.google.gson.TypeAdapterFactory
#-keep class * implements com.google.gson.JsonSerializer
#-keep class * implements com.google.gson.JsonDeserializer
#
###---------------End: proguard configuration for Gson  ----------
## gson (gson 컨버터와 다른 것)

 

 

참고 사이트들

medium.com/ics-lab/%EC%95%88%EB%93%9C%EB%A1%9C%EC%9D%B4%EB%93%9C-%EC%95%B1-%EB%82%9C%EB%8F%85%ED%99%94-proguard-dexguard-%EB%A5%BC-%ED%95%B4%EB%B3%B4%EC%9E%90-1-%ED%94%84%EB%A1%9C%EA%B0%80%EB%93%9C-%ED%8E%B8-799999a43c4d

 

안드로이드 앱 난독화(Proguard & Dexguard)를 해보자! 1. 프로가드 편

Google play store에서 앱을 받아 apk 파일을 추출하는 어플을 사용하면 쉽게 apk을 얻을 수 있다.

medium.com

 

black-jin0427.tistory.com/89

 

[Android, Proguard] 안드로이드 프로가드 설정하기

안녕하세요. 블랙진입니다. 이번에는 코드 난독화 및 APK 최적화를 위한 프로가드에 대해 알아보겠습니다. Android Proguard 가 필요한 이유 1. 코드 난독화를 통해 디컴파일시 본인의 코드가 노출되

black-jin0427.tistory.com

 

namget.tistory.com/entry/%EC%95%88%EB%93%9C%EB%A1%9C%EC%9D%B4%EB%93%9C-proguard-%EC%A0%81%EC%9A%A9%ED%95%98%EA%B8%B0-retrofitgsonzxingglideokhttp3supportrxjava

 

안드로이드 proguard 적용하기 (retrofit,gson,zxing,glide,okhttp3,support,rxjava)

안녕하세요 남갯입니다 오늘은 안드로이드 proguard 적용 (난독화)하는 방법에대해 알려드리겠습니다. 일단 release { minifyEnabled true proguardFiles getDefaultProguardFile('proguard-android.txt'), 'progu..

namget.tistory.com

 

bigmatch.i-um.net/2016/08/05/retrofit2-rxjava-proguard-settings/

 

Retrofit2 + RxJava proguard 설정하기

안녕하세요, 이음소시어스에서 안드로이드 앱 개발을 맡고 있는 김범준(준) 입니다. 최근 안드로이드 HTTP Client 라이브러

bigmatch.i-um.net

 

developer88.tistory.com/118

 

ProGuard Rules 정리 (Retrofit & OkHttp, JSoup, GSon, RxJava, Glide etc)

다양한 라이브러리를 사용하는 만큼, 다양한 ProGuard를 사용해야 합니다. 그런데, 어떤 라이브러리는 이 부분에 대해서 명확히 정리하고 있고, 또 어떤 라이브러리는 그렇지 못합니다. 오늘은 제

developer88.tistory.com

 

gogorchg.tistory.com/entry/Android-Project%EC%97%90-Proguard-%EC%A0%81%EC%9A%A9-%ED%95%98%EA%B8%B0

 

[Android] Project에 Proguard 적용 하기

ProGuard를 적용하는 방법은 쉽습니다. build.gradle 파일 에 아래 소스만 넣어주면 땡입니다. buildTypes { release { minifyEnabled true proguardFiles getDefaultProguardFile('proguard-android.txt'), 'pro..

gogorchg.tistory.com

 

 

 

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

위 코드는 매니페스트에 하나만 있어야한다

그렇지 않으면 앱이 2개가 깔려버린다

 

해당 프로젝트

https://github.com/jaybon1/androidwork/tree/master/serviceCounterApp

 

jaybon1/androidwork

Contribute to jaybon1/androidwork development by creating an account on GitHub.

github.com

 

안드로이드 4대 컴포넌트 알아둬야함 
액티비티
서비스
컨텐트프로바이더 (연락처앱에 접근 하는 등)
브로드캐스팅

 

AIDL을 만들 수 있으면 컨텐트 프로바이더를 만들 수 있다
다른 앱이 원할 때 내 앱의 함수를 실행

책 552페이지

 

--

 

 

뷰 만들기

--

 

 

서비스 생성

--

 

 

1초에 한번씩 count가 증가하도록 세팅

--

 

 

메인액티비티에서 서비스를 실행해본다

--

 

 

로그에 잘 보인다

--

 

 

서비스에서 조건을 건다

--

 

 

멈췄다 실행해보면 아래와같이 나온다

--

 

 

한계 :
메인 액티비티에서 해당 값을 가져올 수 없다(ui갱신을 할수 없다)
값이 보존이 되지 않는다 (일시정지가 안됨)

---------

 

AIDL 생성

 

 

 

ctrl + f9 : 빌드 하면 아래와 같이 BuildConfig와 인터페이스가 만들어진다

--

 

 

서비스에서 아래와 같이 입력( retrun 0을 count로 바꾸자)

--

 

 

서비스에서 onBind를 호출하면 바인더를 리턴 받을 수 있다

--

 

 

멈출때 디스트로이 쓰지 않고 온 언바인드 사용

--

 

 

--

 

 

--

 

바인더는 서비스변수를 참조할 수 있다

--

 

서비스

1. BindService -> onCreate /onBind 실행
2. 스레드 실행

--

 

 

for문 대신 while 문을 사용

--

 

 

서비스를 startService 대신 bindService를 이용해서 실행한다

 

또한 화면에 서비스에서 받아온 값을 입력하기위해 쓰레드를 만들고

핸들러를 이용하여 ui에 접근하여 글자를 변경한다

--

 

 

재실행시 메인에서 count값을 받아온다

--

 

 

테스트

 

 

 

 

 

 

 

 

 

 

참고

blog.naver.com/getinthere/221695417720

 

안드로이드 6강 - (1) 서비스

1. 서비스 생명주기2. MP3 플레이어 만들기서비스는 액티비티가 죽어도 명시적으로 죵료하지 않으면 계속...

blog.naver.com

--

 

현재프로젝트

https://github.com/jaybon1/androidwork/tree/master/serviceTest

 

jaybon1/androidwork

Contribute to jaybon1/androidwork development by creating an account on GitHub.

github.com

 

 

서비스 최초실행시에는 startService(onStartCommand) // 재실행시에는 bindService(onBind) // 종료시에는 unBind

--

 

 

백그라운드 실행, 알림 등

--

 

 

--

 

 

--

 

 

--

 

 

서비스 - 이렇게 생성해야 매니페스트에 등록된다

--

 

 

--

 

 

연습을 위해 함수들에 로그를 입력하자

--

 

 

뷰 세팅

--

 

 

메인액티비티에서 뷰를 연결하고

--

 

 

서비스를 실행해본다

--

 

 

실행해보면 로그에 보인다

--

 

 

서비스엣어 미디어플레이어 레퍼런스 생성 

 

음악을 실행하는 방법 (MyService파일)

 

음악종료시 (MyService파일)

--

 

 

메인액티비티에서 서비스의 레퍼런스를 받을 수 있는 방법이 없다
서비스에서 메인액티비티의 레퍼런스를 받을 수 있는 방법이 없다
서로 제어권이 없다(다른애플리케이션이라고 봐야됨)

---

 

--

 

 

지금 상태는 서비스를 날리는 것이기 때문에 음악 일시정지를 할 수 없다

바인더를 이용해야한다

--

 

 

마샬링

ex) user.java 의 필드가 있다면 직렬화하여 json으로 받아오면된다(메모리를 가져오는 것이아니라 데이터를 가져오는것)
메서드는 문자열로 가져오면 원복이 안된다

이때 마샬링 기법을 사용한다(오브젝트를 들고 오는 것)
서로의 메서드가 동기화 되어있어서 동적인 메서드 사용가능

- MBV(Marshal By Value)

- MBR(Marshal By Reference)

안드로이드에서는 마샬링 대신 AIDL을 사용

https://developer.android.com/guide/components/aidl?hl=ko

 

안드로이드 인터페이스 정의 언어(AIDL)  |  Android 개발자  |  Android Developers

AIDL(Android Interface Definition Language)은 전에 다뤄본 다른 IDL과 유사합니다. 클라이언트와 서비스가 모두 동의한 프로그래밍 인터페이스를 정의하여 프로세스 간 통신(IPC)으로 서로 통신하게 할 수 �

developer.android.com

 클라이언트와 서비스가 모두 동의한 프로그래밍 인터페이스를 정의하여 프로세스 간 통신(IPC)으로 서로 통신하게 할 수 있습니다.

인터페이스를 정의하고 추상메서드를 만든다
그리고 정보만 받아서 바인드하여 사용

메서드를 여러개 만들어도 되지만

메서드 하나만 만들어서 this를 리턴하면 레퍼런스에 접근할 수 있다

--

 

 

 

 

 

 

 

 

 

 

 

 

 

앱 수준 gradle에 글라이드 의존성추가

--

 

 

매니페스트 파일에
인터넷 권한 코드와
ClearTextTraffic 코드를 입력

--

 

 

xml파일에 이미지뷰 세팅

--

 

 

메인액티비티에서 글라이드 코드 입력

--

 

 

테스트 결과

 

 

 

 

 

 

 

 

해당 프로젝트

https://github.com/jaybon1/androidwork/tree/master/mvvmBindingFirestore1

 

jaybon1/androidwork

Contribute to jaybon1/androidwork development by creating an account on GitHub.

github.com

 

 

뷰모델 구조

 

 

데이터바인딩

 

앱 수준의 gradle에 데이터 바인딩을 허용하는 코드 추가

    // 데이터 바인딩
    dataBinding {
        enabled = true
    }

--

 

 

데이터를 받아올 모델 생성

--

 

 

데이터를 출력할 액티비티를 세팅한다

1. layout으로 바깥을 감싼다
2. 데이터 바인딩을 위해 연결한다
3. 원하는 뷰에 데이터를 연결한다

--

 

바인딩 타입 생성을 위해 리빌드를 해준다

--

 

 

데이터 바인딩을 사용할 클래스에서 데이터바인딩을 한 XML파일의 이름을 파스칼표기법으로 불러보면
아래와 같이 XML파일이름+Binding으로 타입을 불러올 수 있다

1. 데이터바인딩을 위해 변수생성
2. 바인딩 변수를 설정한다 (상위컨텍스트와 mxl레이아웃을 입력한다)
3. 연습용 데이터를 입력한다

--

 

 

테스트
정상적으로 출력된다

--

 

파이어스토어

 

참고

https://ondolroom.tistory.com/745

 

파이어스토어 문서

https://firebase.google.com/docs/firestore/quickstart?authuser=0#%EC%9E%90%EB%B0%94

 

Cloud Firestore 시작하기  |  Firebase

빠른 시작에서는 Cloud Firestore를 설정하고 데이터를 추가한 후 Firebase Console에서 방금 추가한 데이터를 확인하는 방법을 볼 수 있습니다. Cloud Firestore 데이터베이스 만들기 Firebase 프로젝트를 아직

firebase.google.com

 

매니페스트 파일에 인터넷 권한을 설정한다

--

 

 

프로젝트 수준의 gradle에 파이어 스토어 관련 클래스패스를 추가

        // 파이어스토어
        classpath 'com.google.gms:google-services:4.3.3'

--

 

 

앱 수준의 gradle에 파이어스터오 플러그인 추가

// 파이어스토어
apply plugin: 'com.google.gms.google-services'

--

 

 

 

FireStore에 SHA1입력시 사용

--

 

 

프로젝트의 app 안에 fireStore에서 제공한 파일 넣기

--

 

 

파이어스토어에 테스트용 필드 추가

--

 

 

!! 지금 부터 테스트해보는데 오류가 나거나 안된다면 에뮬레이터에서 앱을 지우고 다시 실행해보자

 

 

데이터바인딩 테스트용 코드 주석처리

--

 

 

메인 액티비티에 파이어스토어 레퍼런스 추가

 

onCreate에서 파이어스토어 객체 가져오기(연습)

 

파이어스토어에서 데이터 가져오기 (연습) - 주석처리하자

 

파이어스토어에 빨대꼽기(푸시방식)

https://firebase.google.com/docs/firestore/query-data/listen?authuser=0

 

Cloud Firestore로 실시간 업데이트 가져오기  |  Firebase

onSnapshot() 메서드로 문서를 수신 대기할 수 있습니다. 사용자가 제공하는 콜백이 최초로 호출될 때는 단일 문서의 현재 내용으로 문서 스냅샷이 즉시 생성됩니다. 그런 다음 내용이 변경될 때마�

firebase.google.com

 

앱이 처음 켜질때 1번 실행되고
데이터가 변경 되었을 때 한 번 더 실행되었다

--

 

 

모델에 빈생성자를 만들어주어야 빨대가 작동한다
(아래에 나오는 Name name = snapshot.toObject(Name.class);)

--

 

 

빨대가 꽂아졌다면 해당 이벤트 실행시 데이터바인딩을 연동시켜보자

--

 

 

테스트
실행해보면 fireStore에 저장된 데이터가 화면에 출력된다.
(fireStore에서 데이터를 변경하면 자동으로 변경된다.)

--

 

 

MVVM

 

앱 수준의 gradle에 디펜던시를 추가한다
(뷰모델 프로바이더를 호출하기 위함)

    // LifeCycle
    def lifecycle_version = "2.0.0"
    implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle_version"
    annotationProcessor "androidx.lifecycle:lifecycle-compiler:$lifecycle_version"

 

xml에 글자 입력칸과 버튼을 하나 추가하자

--

 

 

메인액티비티에서 테스트용으로 만들었던 파이어베이스 객체를 주석처리하거나 삭제하자

--

 

 

리파지토리를 생성하고 파이어베이스 객체를 생성하는 코드를 입력

(initPush는 빨대꼽기 가동 함수이다. 아래에서 확인)

--

 

 

1. 라이브데이터를 리턴한다.
2. 이름을 변경하는 함수
3. 파이어스토어 빨대꼽기를 실행하는 함수 (push 가동)

--

 

 

뷰모델에 AndroidViewModel을 상속해주고
LiveData를 리턴해주는 구독()함수
이름을 변경해주는 이름바꾸기()함수를 추가해준다.

--

 

 

1. 첫째줄은 뷰모델 프로바이더 객체에서 뷰모델 인스턴스를 얻는 과정이다
뷰모델 인스턴스를 얻은후 뷰모델의 구독함수를 observe 해놓으면 LiveData의 데이터가 바뀔 때마다 onChanged함수가 실행된다.
2. 버튼을 누르면 뷰모델의 이름바꾸기 함수가 실행된다. (뷰모델엔 빨대가 꽂혀있으니 뷰모델의 이름만 바꿔도 옵저버가 발동하여 onChanged가 실행된다)

--

 

 

테스트

이 화면에서는 보이지 않지만, 다른 기기에서도 새로고침 없이 데이터가 바뀌어버린다

 

 

 

+ Recent posts