안드로이드 5.0 롤리팝을 맞이하는 개발자를 위한 안내서
2014년 11월 13일 목요일
안녕하세요. 구글 Developer Advocate 양찬석입니다. 많은 개발자 분들이 기다리셨던 안드로이드 5.0 롤리팝 정식 버전의 시스템 이미지가 구글 개발자 사이트를 통해 마침내 공개되었습니다. 새로운 넥서스 9 태블릿 혹은 넥서스 5, 7 (Wi-Fi), 10 디바이스를 갖고 계신 개발자 분들은 바로 지금 시스템 이미지를 다운받고, 안드로이드 5.0 롤리팝을 직접 사용해보실 수 있습니다. 시스템 이미지를 덮어쓰는 방법은 이전에 공유해드린 블로그 포스트의 내용을 참고하시면 좋을 것 같습니다. 다만, 팩토리 이미지를 적용하게 되면, 기존 디바이스에 설치되어있던 앱 정보를 비롯하여 개인 데이터가 초기화 됨으로 중요한 데이터는 꼭 백업해 두시기 바랍니다.
시스템 이미지 공개와 함께, 일반 사용자들을 대상으로 OTA 가 점진적으로 진행 중입니다. 다시 말해, 이제 사용자들이 달콤한 안드로이드 롤리팝 버전 위에서 여러분의 앱을 사용할 시간이 코 앞으로 다가왔습니다. 롤리팝 위에서도 멋진 여러분의 앱이 잘 동작할 수 있도록 개발자 여러분이 꼭 확인하셔야 할 내용을 정리해 보았습니다. 무엇보다도, 혹시 플랫폼 공개와 함께 업데이트된 안드로이드 5.0 의 주요 변경 사항 내용을 확인하지 못한 개발자 분들은 그 내용을 먼저 살펴 보시면 좋을 것 같습니다Read More
안녕하세요. 구글 Developer Advocate 양찬석입니다. 많은 개발자 분들이 기다리셨던 안드로이드 5.0 롤리팝 정식 버전의 시스템 이미지가 구글 개발자 사이트를 통해 마침내 공개되었습니다. 새로운 넥서스 9 태블릿 혹은 넥서스 5, 7 (Wi-Fi), 10 디바이스를 갖고 계신 개발자 분들은 바로 지금 시스템 이미지를 다운받고, 안드로이드 5.0 롤리팝을 직접 사용해보실 수 있습니다. 시스템 이미지를 덮어쓰는 방법은 이전에 공유해드린 블로그 포스트의 내용을 참고하시면 좋을 것 같습니다. 다만, 팩토리 이미지를 적용하게 되면, 기존 디바이스에 설치되어있던 앱 정보를 비롯하여 개인 데이터가 초기화 됨으로 중요한 데이터는 꼭 백업해 두시기 바랍니다.
시스템 이미지 공개와 함께, 일반 사용자들을 대상으로 OTA 가 점진적으로 진행 중입니다. 다시 말해, 이제 사용자들이 달콤한 안드로이드 롤리팝 버전 위에서 여러분의 앱을 사용할 시간이 코 앞으로 다가왔습니다. 롤리팝 위에서도 멋진 여러분의 앱이 잘 동작할 수 있도록 개발자 여러분이 꼭 확인하셔야 할 내용을 정리해 보았습니다. 무엇보다도, 혹시 플랫폼 공개와 함께 업데이트된 안드로이드 5.0 의 주요 변경 사항 내용을 확인하지 못한 개발자 분들은 그 내용을 먼저 살펴 보시면 좋을 것 같습니다
테스트, 테스트 그리고 다시 한번 테스트
안드로이드 5.0 롤리팝은 구글의 새로운 디자인 시스템인 머티리얼 디자인이 적용되었고, 새로운 안드로이드 런타임 (ART) 과 미디어 플레이어등 플랫폼 전체적으로 정말로 많은 부분에 걸쳐 다양한 발전이 있었습니다. 그런 만큼, 지금 서비스하고 있거나 개발 중인 앱이 새로운 안드로이드 5.0 에서 올바르고 멋지게 동작하는지 테스트 해보시기 바랍니다. 테스트의 중요성은 아무리 강조해도 지나치지 않습니다.ART 호환성 관련 이슈
새로운 안드로이드 런타임 ART는 안드로이드가 보다 빠르고 효율적으로 동작할 수 있도록 돕습니다. 플랫폼 SDK와 표준 개발도구를 사용해 제작된 어플리케이션의 경우 별 다른 문제없이 ART 위에서 잘 동작하지만, NDK 를 사용하거나 보안 혹은 그외 다른 이유로 DEX 포맷을 변조해서 사용하거나 제 3자가 제공하는 개발도구를 사용하고 있는 경우라면 ART 위에서 앱이 문제 없이 동작하는지 확인해보셔야 합니다. 안드로이드 5.0 부터는 ART 가 기본 런타임으로 적용되며 Dalvik 런타임은 더이상 포함되지 않습니다.
몇 가지 ART 호환성 이슈를 정리해보면 다음과 같습니다.
1. Ahead-Of-Time (AOT) 컴파일 이슈
ART 는 더욱 엄밀하게 bytecode 의 무결성을 검증합니다. 보안 등 여러가지 이유로 외부 도구들을 사용하여 앱을 빌드하는 경우 새로운 문제가 발생할 수 있습니다. 구글은 지난 킷캣버전에서 ART 가 처음 소개된 이 후, 다양한 솔루션 업체들과 ART 호환성 이슈를 해결하기 위해 노력해 왔습니다. 혹시 여러분이 사용하고 계신 도구에서 ART 호환성 이슈가 발생하는 경우, 해당 도구가 업데이트되었는지 확인해보시기 바랍니다. 최신 버전의 도구를 사용하면 문제가 해결 될 수 있습니다. 또한 앱 실행시 DEX 포맷을 OAT 포맷으로 변경하는 과정에서 문제가 발생하는 경우 Reporting Problems 링크를 통해 구글에 문제를 알려주시기 바랍니다.
2. GC(Garbage Collection) 관련
ART 에서는 GC 성능이 더욱 향상되었기 때문에 GC_FOR_ALLOC 이벤트가 발생하는 빈도를 줄이기 위해여 명시적으로 System.gc()메서드를 호출할 필요가 없습니다. System.getProperty("java.vm.version") 메서드를 통해 현재 동작하는 VM 버전을 확인할 수 있으며, 결과 값이 '2.0.0' 이상인 경우 ART 런타임이 사용되고 있는 것 임으로, 명시적으로 GC 를 호출하지 않도록 코드를 수정하는 것을 권장 드립니다.
3. JNI 관련
무엇보다도 먼저 JNI 코드 상에서 문제가 발생할 수 있는 부분들은 안드로이드 개발자 도구에 포함된 CheckJNI 툴을 이용하여 확인할 수 있습니다. 아래와 명령어를 실행 한 후,adb shell setprop debug.checkjni 1
앱을 실행하시면, 위험성이 있는 JNI 코드가 실행되는 경우 다음과 같이 상세한 경고 메세지가 출력됩니다.W JNI WARNING: method declared to return 'Ljava/lang/String;' returned '[B'
W failed in LJniTest;.exampleJniBug
I "main" prio=5 tid=1 RUNNABLE
I | group="main" sCount=0 dsCount=0 obj=0x40246f60 self=0x10538
I | sysTid=15295 nice=0 sched=0/0 cgrp=default handle=-2145061784
I | schedstat=( 398335000 1493000 253 ) utm=25 stm=14 core=0
I at JniTest.exampleJniBug(Native Method)
I at JniTest.main(JniTest.java:11)
I at dalvik.system.NativeStart.main(Native Method)
I
E VM aborting
또한, ART 의 GC 기능을 더욱 향상 시키기 위해 AOSP 상에서 개발중인 Compacting GC 기능을 지원할 예정입니다. 이 경우, 네이티브 코드상에서 Get...ArrayElements() 메서등을 통해 반환되는 주소 값은 실제 메모리 블럭의 주소가 아닌 복제된 메모리 블럭의 주소 값을 갖게 되며, 메모리 블럭의 주소를 참조하여 직접 값을 변경하는 경우, 값을 수정한 후 올바르게 Release...ArrayElements() 메서드를 호출하지 않으면 값이 정상적으로 반영되지 않을 수 있습니다.
ART 에서는 보다 엄밀하게 JNI 코드 상의 오류를 체크하며, 기존에는 별다른 예외 없이 진행되었던 다음과 같은 경우에도 오류가 발생할 수 있습니다.
- 존재하지 않는 메서드를 대상으로 RegisterNatives 메서드를 호출하는 경우 NoSuchMethodError 예외가 발생합니다. 예를 들어, Proguard 의 최적화 과정에서 해당 메서드가 제거되었을 수 있습니다.
- 존재하지 않는 필드 이름을 GetFieldID() 혹은 GetStaticFieldID() 메서드로 참조하려고 하는 경우 NoSuchMethodError 예외가 발생합니다.
- JNI 스펙에 따라
CallNonvirtual...Method()
를 호출 할 때는, 해당 메서드를 선언하고 있는 클래스가 사용되어야 하며 해당 클래스를 확장한 자식 클래스가 사용될 수 없습니다.
4. Object 모델 변경
Object 클래스의 필드 값들이 private 속성으로 변경되었습니다. 이에 따라, Object 클래스의 Field 를 Reflection 패키지를 통해 접근하고 있는 경우 문제가 발생할 수 있습니다. 대표적으로 객체를 직렬화(Object Serialization) 하기 위하여, 특정 객체의 부모 클래스로 거슬러 올라가며 데이터를 확인하는 경우, 다음과 같이 Class.getSuperClass() 메서드가 java.lang.Object.class 를 반환 하는 경우 탐색을 멈춰야 합니다. 이전과 달리 null을 반환할 때 까지 반복문을 도는 경우 오류가 발생할 수 있습니다.Class.getSuperclass() == java.lang.Object.class
중복된 커스텀 퍼미션 선언 이슈
안드로이드 5.0 에서는 특정 커스텀 퍼미션은 오직 하나의 앱 혹은 해당 앱과 동일한 사인키를 이용해 사인된 앱에서만 선언할 수 있도록 변경되었습니다. 이 원칙에 따라, 만일 이미 동일한 이름의 커스텀 퍼미션을 선언한 앱이 단말에 설치되어 있다면, 같은 이름의 퍼미션을 선언하고 있는 다른 앱은 디바이스에 설치될 수 없습니다.<permission android:name= "com.example.gcm.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
따라서, 위와 같이 일반적이거나 다른 예제 코드에서 따온 퍼미션 이름을 사용하는 경우 문제가 발생할 수 있습니다. 이 변경 사항은 메니페스트의 targetSDK 버전과는 관계없이 일괄적으로 적용되며, 따라서 앱 개발자 분들은 다음과 같은 사항을 꼭 확인해 보셔야 합니다.
- 커스텀 퍼미션을 사용하고 있다면, 해당 퍼미션이 어디서 부터 유래한 것인지, 그리고 정말 필요한 것인지 고민해야 합니다. 여러분의 앱의 특정 기능을 제공하기 위해 꼭 필요한 경우가 아니라면 모든 <permission> 태그를 삭제하는 것이 좋습니다.
- 가능한 경우 여러분의 커스텀 퍼미션을 시스템 기본 퍼미션으로 대체하는 편이 좋습니다.
- 커스텀 퍼미션을 꼭 사용해야 하는 경우 해당 퍼미션의 이름이 다른 앱에서 선언한 퍼미션 이름과 동일하지 않도록 이름을 잘 지어야 합니다. 예를 들어 여러분 앱의 패키지 이름을 활용할 수 있습니다.
- 만일 여러 앱을 묶음으로 제공하며, 각각의 앱들간에 특정 기능을 공유하기 위해서 커스텀 퍼미션을 활용하고 있다면, 모든 앱들이 동일한 사인키로 사인되도록 주의를 기울이거나 아니면 커스텀 퍼미션이 오직 한 번만 선언되도록 잘 관리해야합니다.
커스텀 퍼미션의 중복 사용 문제에 관한 보다 자세한 내용은 안드로이드 개발자 사이트의 Uniqueness Requirement for Custom Permissions 항목을 참고하시기 바랍니다.
서비스 바인드는 명시적 인텐트만을 사용해야 합니다.
안드로이드 5.0 부터 서비스에 바인드 하기 위해서는 반드시 명시적 인텐트를 사용해야 합니다. 만일 암시적 인텐트를 이용해 bindService() 를 호출하는 경우 예외가 발생할 수 있습니다.Intent intent = new Intent(this, LocalService.class); bindService(intent, mConnection, Context.BIND_AUTO_CREATE);Intent intent = new Intent(MY_BIND_ACTION_STRING); bindService(intent, mConnection, Context.BIND_AUTO_CREATE);