| page.title=동작 변경 사항 |
| page.keywords=preview, sdk, 호환성 |
| meta.tags="preview", "compatibility" |
| page.tags="preview", "developer preview" |
| page.image=images/cards/card-n-changes_2x.png |
| @jd:body |
| |
| |
| <div id="qv-wrapper"> |
| <div id="qv"> |
| |
| <h2>이 문서의 내용</h2> |
| |
| <ol> |
| <li><a href="#perf">성능 향상</a> |
| <ol> |
| <li><a href="#doze">잠자기 모드</a></li> |
| <li><a href="#bg-opt">백그라운드 최적화</a></li> |
| </ol> |
| </li> |
| <li><a href="#perm">권한 변경</a> |
| </li> |
| <li><a href="#sharing-files">앱 사이의 파일 공유</a></li> |
| <li><a href="#accessibility">접근성 향상</a> |
| <ol> |
| <li><a href="#screen-zoom">화면 확대/축소</a></li> |
| <li><a href="#vision-settings">설정 마법사의 Vision Settings</a></li> |
| </ol> |
| </li> |
| <li><a href="#ndk">플랫폼 라이브러리에 연결되는 NDK 앱</a></li> |
| <li><a href="#afw">Android for Work</a></li> |
| <li><a href="#annotations">주석 보존</a></li> |
| <li><a href="#other">기타 중요한 사항</a></li> |
| </ol> |
| |
| <h2>참고 항목</h2> |
| <ol> |
| <li><a href="{@docRoot}preview/api-overview.html"> |
| Android N API 개요</a></li> |
| </ol> |
| |
| </div> |
| </div> |
| |
| |
| <p> |
| Android N에는 새로운 기능 및 특징과 더불어 |
| 다양한 시스템 변경 사항 및 API 동작 변경 사항이 포함되어 있습니다. 이 문서에서는 |
| 여러분이 앱에서 숙지하고 고려해야 하는 몇 가지 |
| 주요 변경 사항을 소개하겠습니다. |
| </p> |
| |
| <p> |
| 이전에 Android용 앱을 게시한 적이 있으신 경우, 이와 같은 |
| 플랫폼 변경으로 인해 앱이 영향을 받을 수 있다는 점을 유의하세요. |
| </p> |
| |
| |
| <h2 id="perf">배터리와 메모리</h2> |
| |
| <p> |
| Android N에는 기기의 배터리 수명을 연장하고 RAM 사용량을 감소시키기 위한 |
| 시스템 동작 변경 사항이 포함됩니다. 이러한 변경 사항은, 앱이 특정한 암시적 인텐트를 통해 |
| 다른 앱과 상호 작용하는 방식과 함께, 시스템 리소스에 대한 |
| 앱의 액세스에 영향을 미칠 수 있습니다. |
| </p> |
| |
| <h3 id="doze">잠자기 모드</h3> |
| |
| <p> |
| Android 6.0(API 레벨 23)에 도입된 잠자기 모드는 사용자가 기기의 |
| 플러그를 뽑고 정지 상태에서 화면이 꺼져 있을 때 CPU 및 |
| 네트워크 액티비티를 지연시켜서 배터리 수명을 개선해 줍니다. Android N에서는 |
| 기기의 플러그를 뽑고 화면이 꺼져 있는 동안 |
| CPU 및 네트워크 제한의 하위 세트를 적용하여 잠자기 모드를 더욱 |
| 향상시켜 주지만, 반드시 정지 상태일 필요는 없습니다(예: 핸드셋을 사용자의 주머니에 넣고 다니는 경우). |
| </p> |
| |
| |
| <img src="{@docRoot}preview/images/doze-diagram-1.png" alt="" height="251px" id="figure1" /> |
| <p class="img-caption"> |
| <strong>그림 1.</strong> 잠자기 모드에서 배터리 수명을 개선하기 위해 첫 번째 레벨의 시스템 액티비티 제한을 |
| 적용하는 방법에 대한 그림. |
| </p> |
| |
| <p> |
| 기기가 배터리 전원에 연결되고 일정 시간 동안 화면이 꺼져 있는 경우 |
| 기기가 잠자기 모드로 전환되고 첫 번째 하위 세트의 제한을 적용합니다. 기기는 앱 |
| 네트워크 액세스를 차단하고, 작업과 동기화를 지연시킵니다. 기기가 잠자기 모드로 |
| 전환된 후 일정 시간 동안 정지 상태에 있으면, 시스템은 잠자기 모드의 나머지 제한 사항을 {@link android.os.PowerManager.WakeLock}, |
| {@link android.app.AlarmManager} 알람, GPS 및 Wi-Fi 스캔에 |
| 적용합니다. 일부 잠자기 모드 제한이 |
| 적용되든 모든 잠자기 모드 제한이 적용되든 상관없이, |
| 시스템은 잠시 동안의 유지 관리 기간 중에 기기를 깨우며, 이 기간 중에는 |
| 애플리케이션의 네트워크 액세스가 허용되고 지연된 작업/동기화가 실행됩니다. |
| </p> |
| |
| |
| <img src="{@docRoot}preview/images/doze-diagram-2.png" alt="" id="figure2" /> |
| <p class="img-caption"> |
| <strong>그림 2.</strong> 기기가 일정 시간 동안 정지 상태에 있은 후에 |
| 잠자기 모드에서 두 번째 레벨의 시스템 액티비티 제한을 적용하는 방법에 대한 그림. |
| </p> |
| |
| <p> |
| 화면을 활성화하거나 기기의 플러그를 꽂으면 잠자기 모드가 |
| 종료되고 이러한 처리 제한이 제거됩니다. <a href="{@docRoot}training/monitoring-device-state/doze-standby.html">잠자기 및 앱 대기 |
| 모드 최적화</a>에서 설명한 대로, Android 6.0(API 레벨 23)에 도입된 |
| 이전 버전의 잠자기 모드에 맞춰 앱을 조정할 경우에는 이러한 추가적인 동작이 |
| 권장 사항 및 모범 |
| 사례에 영향을 미치지 않습니다. 하지만 |
| 여전히 해당 권장 사항을 따라야 합니다. 예를 들어, GCM(Google Cloud Messaging)을 사용하여 메시지를 |
| 송수신하고 추가적인 잠자기 모드 동작을 수용하기 위한 업데이트 계획을 |
| 시작해야 합니다. |
| </p> |
| |
| |
| <h3 id="bg-opt">Project Svelte: 백그라운드 최적화</h3> |
| |
| <p> |
| Android N에서는 메모리 사용량 및 전원 소비량을 최적화하기 위해 |
| 세 가지 암시적 브로드캐스트를 제거합니다. 이렇게 변경해야 하는 |
| 이유는, 암시적 브로드캐스트는 백그라운드에서 브로드캐스트를 |
| 수신하도록 등록된 앱을 자주 시작하기 때문입니다. 이들 브로드캐스트를 제거하면 기기 성능과 사용자 환경이 |
| 상당히 향상될 수 있습니다. |
| </p> |
| |
| <p> |
| 모바일 기기의 경우 연결 변경이 자주 나타납니다(예: Wi-Fi와 |
| 모바일 데이터 간의 이동 시). 현재는 |
| 암시적 {@link |
| android.net.ConnectivityManager#CONNECTIVITY_ACTION} 브로드캐스트의 수신기를 |
| 매니페스트에 등록하여 앱이 이러한 연결 변경을 모니터링할 수 있습니다. 많은 앱들이 이 브로드캐스트를 수신하도록 |
| 등록하기 때문에, 단일 네트워크 스위치가 모든 앱을 깨우고 이들 앱이 해당 브로드캐스트를 |
| 동시에 처리하도록 할 수 있습니다. |
| </p> |
| |
| <p> |
| 마찬가지로, 이전 버전의 Android에서는 앱이 다른 앱(예: 카메라)에서 암시적 {@link |
| android.hardware.Camera#ACTION_NEW_PICTURE} 및 {@link |
| android.hardware.Camera#ACTION_NEW_VIDEO} 브로드캐스트를 |
| 수신하도록 등록할 수 있었습니다. 사용자가 카메라 앱으로 사진을 찍으면, 이들 앱이 깨어나서 해당 브로드캐스트를 |
| 처리합니다. |
| </p> |
| |
| <p> |
| 이런 문제를 완화하기 위해, Android N은 다음과 같은 최적화를 |
| 적용합니다. |
| </p> |
| |
| <ul> |
| <li>Android N을 대상으로 하는 앱은 해당 이벤트의 알림을 요청하는 매니페스트 항목이 있더라도 {@link |
| android.net.ConnectivityManager#CONNECTIVITY_ACTION} 브로드캐스트를 |
| 수신하지 않습니다. 실행 중인 |
| 앱은 {@link android.content.BroadcastReceiver}로 알림을 요청하면 |
| 여전히 기본 스레드에서 {@code CONNECTIVITY_CHANGE}를 수신할 수 있습니다. |
| </li> |
| |
| <li>앱은 {@link |
| android.hardware.Camera#ACTION_NEW_PICTURE} 또는 {@link |
| android.hardware.Camera#ACTION_NEW_VIDEO} 브로드캐스트를 송수신할 수 없습니다. 이 최적화는 Android N을 대상으로 |
| 하는 앱뿐 아니라 모든 앱에 영향을 미칩니다. |
| </li> |
| </ul> |
| |
| <p>앱이 이들 인텐트 중 하나라도 사용하는 경우에는, |
| Android N 기기를 올바로 대상으로 삼을 수 있도록 이들 인텐트에 대한 종속성을 최대한 빨리 제거해야 합니다. |
| Android 프레임워크는 이러한 암시적 브로드캐스트의 |
| 필요성을 줄이기 위한 여러 가지 해결책을 제공합니다. 예를 들어, {@link |
| android.app.job.JobScheduler} API는 지정된 조건(예: |
| 고정 요금제 네트워크에 연결)이 충족될 경우 네트워크 운영을 예약할 수 있는 |
| 강력한 메커니즘을 제공합니다. 심지어 {@link |
| android.app.job.JobScheduler}를 사용하여 콘텐츠 공급자의 변경 사항에 대응할 수도 있습니다. |
| </p> |
| |
| <p> |
| N에서 백그라운드 최적화와 앱을 조정하는 방법에 대한 자세한 내용은 |
| <a href="{@docRoot}preview/features/background-optimization.html">백그라운드 최적화</a>를 |
| 참조하세요. |
| </p> |
| |
| <h2 id="perm">권한 변경</h2> |
| |
| <p> |
| Android N에는 앱에 영향을 미칠 수도 있는 권한 변경이 포함되어 있습니다. |
| </p> |
| |
| <h3 id="permfilesys">파일 시스템 권한 변경</h3> |
| |
| <p> |
| 개인 파일의 보안을 강화하기 위해, Android N 이상을 대상으로 하는 앱의 개인 |
| 디렉터리는 액세스가 제한됩니다(<code>0700</code>). |
| 이 설정은 크기 또는 |
| 존재 여부와 같은 개인 파일의 메타데이터 유출을 막아줍니다. 이러한 권한 변경은 여러 가지 부작용이 있습니다. |
| </p> |
| |
| <ul> |
| <li> |
| 소유자가 개인 파일의 파일 권한을 |
| 더 이상 완화해서는 안 되며, |
| {@link android.content.Context#MODE_WORLD_READABLE} 및/또는 |
| {@link android.content.Context#MODE_WORLD_WRITEABLE}을 사용하여 권한을 완화하려고 시도하면 |
| {@link java.lang.SecurityException}이 트리거됩니다. |
| <p class="note"> |
| <strong>참고:</strong> 아직까지는 이 제한이 완전히 적용되지 않습니다. |
| 앱이 여전히 기본 |
| API 또는 {@link java.io.File File} API를 사용하여 개인 디렉터리에 대한 권한을 수정할 수도 있습니다. 하지만 |
| 개인 디렉터리에 대한 권한은 부득이한 경우가 아니라면 완화하지 않는 것이 좋습니다. |
| </p> |
| </li> |
| <li> |
| 패키지 도메인 외부에서 <code>file://</code> URI를 전달하면 수신기가 액세스 불가능한 경로로 |
| 남아 있을 수 있습니다. 따라서 |
| <code>file://</code> URI를 전달하려고 시도하면 |
| <code>FileUriExposedException</code>이 트리거됩니다. 개인 파일의 내용을 공유하기 위해 |
| 권장되는 방법은 {@link |
| android.support.v4.content.FileProvider}를 사용하는 것입니다. |
| </li> |
| <li> |
| {@link android.app.DownloadManager}는 비공개로 |
| 저장된 파일을 더 이상 파일 이름별로 공유할 수 없습니다. 레거시 애플리케이션은 {@link |
| android.app.DownloadManager#COLUMN_LOCAL_FILENAME}에 액세스할 때 |
| 액세스가 불가능한 경로가 될 수 있습니다. Android N 이상을 |
| 대상으로 하는 앱은 {@link android.app.DownloadManager#COLUMN_LOCAL_FILENAME}에 액세스할 때 {@link java.lang.SecurityException}을 |
| 트리거합니다. |
| |
| |
| {@link |
| android.app.DownloadManager.Request#setDestinationInExternalFilesDir |
| DownloadManager.Request.setDestinationInExternalFilesDir()} 또는 |
| {@link |
| android.app.DownloadManager.Request#setDestinationInExternalPublicDir |
| DownloadManager.Request.setDestinationInExternalPublicDir()} |
| 을 사용하여 다운로드 |
| 위치를 공용 위치로 설정하는 레거시 애플리케이션은 |
| {@link android.app.DownloadManager#COLUMN_LOCAL_FILENAME}에 있는 경로에 여전히 액세스할 수 있지만, 이 |
| 메서드는 부득이한 경우가 아니라면 사용하지 않는 것이 좋습니다. {@link android.app.DownloadManager}에 의해 노출되는 파일에 |
| 액세스하는 좋은 방법은 |
| {@link android.content.ContentResolver#openFileDescriptor |
| ContentResolver.openFileDescriptor()}를 사용하는 것입니다. |
| </li> |
| </ul> |
| |
| <h2 id="sharing-files">앱 사이의 파일 공유</h2> |
| |
| <p> |
| Android N을 대상으로 하는 앱의 경우, Android 프레임워크는 앱 외부에서 {@code file://} URI의 노출을 |
| 금지하는 {@link android.os.StrictMode} API 정책을 |
| 적용합니다. 파일 URI를 포함하는 인텐트가 앱을 떠나면 |
| {@code FileUriExposedException} 예외가 생기면서 앱에 오류가 발생합니다. |
| </p> |
| |
| <p> |
| 애플리케이션 간에 파일을 공유하려면 {@code content://} URI를 |
| 보내고 이 URI에 대해 임시 액세스 권한을 부여해야 합니다. 이 권한을 가장 쉽게 부여하는 방법은 |
| {@link android.support.v4.content.FileProvider} 클래스를 사용하는 방법입니다. 권한과 파일 공유에 |
| 대한 자세한 |
| 내용은 <a href="{@docRoot}training/secure-file-sharing/index.html">파일 공유</a>를 참조하세요. |
| </p> |
| |
| <h2 id="accessibility">접근성 향상</h2> |
| |
| <p> |
| Android N에는 시력이 나쁘거나 손상된 사용자를 위해 플랫폼의 |
| 사용성을 개선하기 위한 변경 사항이 포함되어 있습니다. 이러한 변경 사항에서는 일반적으로 |
| 앱의 코드를 변경할 필요가 없지만, 사용자 환경에 |
| 미치는 잠재적인 영향을 평가하기 위해 이들 기능을 검토하고 |
| 앱으로 테스트해야 합니다. |
| </p> |
| |
| |
| <h3 id="screen-zoom">화면 확대/축소</h3> |
| |
| <p> |
| Android N에서는 사용자가 <strong>Display size</strong>를 설정할 수 |
| 있으며, 이 설정에서 화면의 모든 요소를 확대하거나 축소할 수 있으므로, 시력이 |
| 나쁜 사용자의 기기 접근성이 향상됩니다. 최소 화면 너비인 <a href="http://developer.android.com/guide/topics/resources/providing-resources.html">sw320dp</a>를 초과하는 화면은 사용자가 확대/축소할 |
| 수 없으며, 이 너비는 일반적인 중간 크기 전화기인 Nexus 4의 |
| 너비입니다. |
| </p> |
| |
| <div class="cols"> |
| |
| <div class="col-6"> |
| <img src="{@docRoot}preview/images/screen-zoom-1.png" alt="" height="XXX" id="figure1" /> |
| </div> |
| <div class="col-6"> |
| <img src="{@docRoot}preview/images/screen-zoom-2.png" alt="" height="XXX" id="figure1" /> |
| </div> |
| |
| </div> <!-- end cols --> |
| <p class="img-caption"> |
| <strong>그림 3.</strong> 오른쪽 화면은 Android N 시스템 이미지가 |
| 실행 중인 기기의 Display size를 늘릴 때의 효과를 보여줍니다. |
| </p> |
| |
| |
| <p> |
| 기기 밀도가 변경되면 시스템은 다음과 같은 방식으로 실행 중인 |
| 앱에게 알립니다. |
| </p> |
| |
| <ul> |
| <li>앱이 API 레벨 23 이하를 대상으로 하는 경우 시스템에서는 |
| 모든 백그라운드 프로세스를 자동으로 종료합니다. 즉, 사용자가 이들 |
| 앱으로부터 전환하여 <em>Settings</em> 화면을 |
| 열고 <strong>Display size</strong> 설정을 변경하면, 시스템은 저용량 메모리 |
| 상황에서와 동일한 방식으로 앱을 종료합니다. 앱에 포그라운드 프로세스가 |
| 있는 경우, <a href="{@docRoot}guide/topics/resources/runtime-changes.html">런타임 변경 처리</a>에 설명된 대로, 시스템은 |
| 마치 기기의 방향이 변경된 |
| 것처럼 구성 변경을 해당 프로세스에 알립니다. |
| </li> |
| |
| <li>앱이 Android N을 대상으로 하는 경우, |
| <a href="{@docRoot}guide/topics/resources/runtime-changes.html">런타임 변경 처리</a>에 설명된 |
| 대로, 구성 변경을 모든 프로세스(포그라운드 및 백그라운드)에 |
| 알립니다. |
| </li> |
| </ul> |
| |
| <p> |
| 앱이 Android 모범 사례를 따르기만 한다면, 대부분의 앱은 이 기능을 |
| 지원하기 위해 어떠한 변경도 수행할 필요가 없습니다. 확인할 사항은 구체적으로 다음과 같습니다. |
| </p> |
| |
| <ul> |
| <li>화면 너비가 <code><a href= |
| "{@docRoot}guide/topics/resources/providing-resources.html">sw320dp</a></code>인 기기에서 앱을 테스트하고 적절하게 작동하는지 |
| 확인하세요. |
| </li> |
| |
| <li>기기 구성이 변경되는 경우, 밀도에 종속된 모든 캐시된 |
| 정보(예: 캐시된 비트맵 또는 네트워크에서 로드된 리소스)를 |
| 업데이트하세요. 앱이 일시 정지 상태에서 다시 시작하는 경우 구성 |
| 변경을 확인하세요. |
| <p class="note"> |
| <strong>참고:</strong> 구성에 종속된 데이터를 캐시하는 경우, |
| 해당 데이터에 적절한 화면 크기 또는 픽셀 밀도와 같은 관련 메타데이터를 |
| 포함시키는 것이 좋습니다. 이 메타데이터를 저장해 놓으면, |
| 구성이 변경된 후에 캐시된 데이터를 새로 고칠지 여부를 |
| 결정할 수 있습니다. |
| </p> |
| </li> |
| |
| <li>픽셀 단위는 화면 밀도에 따라 |
| 변하지 않으므로, 이 단위로 치수를 지정하지 마세요. 그 대신, <a href="{@docRoot}guide/practices/screens_support.html">밀도에 독립적인 픽셀</a>(<code>dp</code>) 단위로 |
| 치수를 지정하세요. |
| </li> |
| </ul> |
| |
| <h3 id="vision-settings">설정 마법사의 Vision Settings</h3> |
| |
| <p> |
| Android N에는 Welcome 화면에 Vision Settings가 포함되어 |
| 있으며, 여기서 사용자는 |
| <strong>Magnification gesture</strong>, <strong>Font size</strong>, |
| <strong>Display size</strong> 및 <strong>TalkBack</strong>의 접근성 설정을 새 기기에 구성할 수 있습니다. 이러한 |
| 변경은 다른 화면 설정에 관련된 버그의 가시성을 증대시킵니다. 이 기능의 영향을 평가하려면, |
| 이들 설정을 활성화하여 앱을 |
| 테스트해야 합니다. 이 설정은 <strong>Settings > |
| Accessibility</strong> 아래에 있습니다. |
| </p> |
| |
| <h2 id="ndk">플랫폼 라이브러리에 연결되는 NDK 앱</h2> |
| |
| <p> |
| 비공개 API가 로드되는 것을 막기 위해 Android N에는 네임스페이스 변경이 포함되어 있습니다. |
| NDK를 사용하는 경우에는 Android 플랫폼에서 |
| 공개 API를 사용해야만 합니다. Android의 다음 번 공식 릴리스에서 비공개 API를 사용하면 앱 작동이 중단될 수 |
| 있습니다. |
| </p> |
| |
| <p> |
| 비공개 API의 사용을 여러분에게 경고하기 위해, Android N 기기에서 실행 |
| 중인 앱은 어떤 앱이 비공개 API를 호출할 때 logcat 출력에 오류를 생성합니다. |
| 또한, 이런 상황이 잘 인식될 수 있도록 |
| 이 오류가 기기 화면에도 메시지로 표시됩니다. 여러분이 앱 코드를 검토하여 |
| 비공개 플랫폼 API의 사용을 제거해야 하며, 프리뷰 기기 또는 |
| 에뮬레이터를 사용하여 앱을 철저히 테스트해야 합니다. |
| </p> |
| |
| <p> |
| 앱이 플랫폼 라이브러리에 종속된 경우, 개인 API를 이와 동등한 |
| 공개 API로 바꾸기 위한 일반적인 수정 사항을 NDK 문서에서 참조하세요. |
| 또한, 자신도 모르는 사이에 플랫폼 라이브러리에 |
| 연결되어 있을 수가 있으며, 특히 여러분의 앱이 사용하는 라이브러리가 플랫폼의 |
| 일부(예: <code>libpng</code>)이지만 NDK의 일부가 아닌 경우에는 더 그렇습니다. 이 경우에는 연결에 |
| 필요한 모든 .so 파일이 APK에 포함되어 있는지 확인하세요. |
| </p> |
| |
| <p class="caution"> |
| <strong>주의:</strong> 일부 타사 라이브러리가 비공개 API에 |
| 연결될 수도 있습니다. 앱이 이들 라이브러리를 사용하는 경우, Android의 |
| 다음 번 공식 릴리스에서 실행할 때 앱 작동이 중단될 수 있습니다. |
| </p> |
| |
| <p> |
| 앱은 NDK에 포함되지 않은 고유 라이브러리를 사용하거나 |
| 이에 종속되어서는 안 됩니다. 왜냐하면 이 라이브러리는 특정 |
| Android 릴리스에서 다른 릴리스로 변경되거나 제거될 수 있기 때문입니다. OpenSSL에서 BoringSSL로의 전환은 이러한 변경의 한 예입니다. |
| 또한, NDK에 포함되지 않은 |
| 플랫폼 라이브러리에는 호환성 요구 사항이 없기 때문에, 다른 장치에서는 |
| 호환성 레벨이 다를 수도 있습니다. 구형 기기에 있는 비 NDK 라이브러리에 액세스해야 하는 경우 |
| Android API 레벨에 따라 로드를 수행하세요. |
| </p> |
| |
| <p> |
| 이러한 유형의 문제를 진단하는 데 도움을 주기 위해, 여기서는 |
| Android N으로 앱을 빌드할 때 발생할 수 있는 Java 및 NDK 오류의 몇 가지 예를 보여줍니다. |
| </p> |
| |
| <p>Java 오류의 예:</p> |
| <pre class="no-pretty-print"> |
| java.lang.UnsatisfiedLinkError: dlopen failed: library "/system/lib/libcutils.so" |
| is not accessible for the namespace "classloader-namespace" |
| </pre> |
| |
| <p>NDK 오류의 예:</p> |
| <pre class="no-pretty-print"> |
| dlopen failed: cannot locate symbol "__system_property_get" referenced by ... |
| </pre> |
| |
| |
| <p> |
| 다음은 이러한 유형의 오류가 발생한 앱의 몇 가지 일반적인 수정사항입니다. |
| </p> |
| |
| <ul> |
| <li>libandroid_runtime.so에서 getJavaVM 및 getJNIEnv 사용은 표준 |
| JNI 함수로 교체될 수 있습니다. |
| <pre class="no-pretty-print"> |
| AndroidRuntime::getJavaVM -> GetJavaVM from <jni.h> |
| AndroidRuntime::getJNIEnv -> JavaVM::GetEnv or |
| JavaVM::AttachCurrentThread from <jni.h>. |
| </pre> |
| </li> |
| |
| <li>{@code libcutils.so}에서 {@code property_get} 기호 사용은 공개 |
| {@code alternative __system_property_get}으로 교체될 수 있습니다. |
| 이렇게 하려면, 다음의 include와 함께 {@code __system_property_get}을 사용하세요. |
| <pre> |
| #include <sys/system_properties.h> |
| </pre> |
| </li> |
| |
| <li>{@code libcrypto.so}에서 {@code SSL_ctrl} 기호 사용은 앱 |
| 로컬 버전으로 교체되어야 합니다. 예를 들어, {@code .so} 파일에서 |
| {@code libcyrpto.a}를 정적으로 링크하거나 BoringSSL 또는 OpenSSL에서 |
| {@code libcrypto.so}를 동적으로 앱에 포함시켜야 합니다. |
| </li> |
| </ul> |
| |
| <h2 id="afw">Android for Work</h2> |
| <p> |
| Android N에는 Android for Work를 대상으로 하는 앱에 대한 변경 사항이 |
| 포함되어 있습니다. 인증서 설치, 비밀번호 재설정, |
| 보조 사용자 관리 및 기기 식별자 액세스에 대한 변경 사항이 이에 포함됩니다. Android for Work 환경용 앱을 빌드하는 경우에는 이러한 |
| 변경 사항을 검토하고 그에 따라 |
| 앱을 수정해야 합니다. |
| </p> |
| |
| <ul> |
| <li>DPC가 인증서를 설정할 수 있으려면, 위임된 인증서 설치 관리자를 여러분이 먼저 |
| 설치해야 합니다. N SDK를 대상으로 하는 프로필 소유자 |
| 앱 및 기기 소유자 앱의 경우, 기기 정책 컨트롤러(DPC)가 <code>DevicePolicyManager.setCertInstallerPackage()</code>를 호출하기 |
| 전에, 위임된 인증서 설치 관리자를 여러분이 먼저 |
| 설치해야 합니다. 아직 설치 관리자가 |
| 설치되지 않은 경우 시스템에서 <code>IllegalArgumentException</code>이 |
| 발생합니다. |
| </li> |
| |
| <li>이제 기기 관리자의 비밀번호 재설정 제한이 프로필 소유자에게도 |
| 적용됩니다. 기기 관리자는 이미 설정된 암호를 변경하거나 |
| 지우기 위해 {@code DevicePolicyManager.resetPassword()}를 더 이상 사용할 |
| 수 없습니다. 기기 관리자는 |
| 기기에 비밀번호, PIN 또는 패턴이 없는 경우에만 비밀번호를 설정할 수 있습니다. |
| </li> |
| |
| <li>제한이 설정되어 있더라도 기기 소유자 및 프로필 소유자는 |
| 계정을 관리할 수 있습니다. <code>DISALLOW_MODIFY_ACCOUNTS</code> 사용자 |
| 제한이 있더라도 기기 소유자 및 프로필 소유자는 계정 관리 API를 호출할 수 있습니다. |
| </li> |
| |
| <li>기기 소유자는 보조 사용자를 보다 쉽게 관리할 수 있습니다. 기기가 |
| 기기 소유자 모드에서 실행 중인 경우 <code>DISALLOW_ADD_USER</code> 제한이 |
| 자동으로 설정됩니다. 이렇게 하면 사용자는 관리되지 않는 보조 사용자를 생성할 수 |
| 없습니다. 또한, <code>CreateUser()</code> 및 |
| <code>createAndInitializeUser()</code> 메서드가 사용 중단되었으며, 새로운 |
| <code>DevicePolicyManager.createAndManageUser()</code> 메서드로 대체되었습니다. |
| </li> |
| |
| <li>기기 소유자는 기기 식별자에 액세스할 수 있습니다. 기기 |
| 소유자는 <code>DevicePolicyManagewr.getWifiMacAddress()</code>를 사용하여 기기의 |
| Wi-Fi MAC 주소에 액세스할 수 있습니다. 기기에서 |
| Wi-Fi가 활성화된 적이 없는 경우 이 메서드는 {@code null} 값을 반환합니다. |
| </li> |
| |
| <li>Work Mode 설정은 업무용 앱에 대한 액세스를 제어합니다. 작업 모드가 해제되면 |
| 시스템 런처에서는 업무용 앱을 회색으로 표시하여 해당 앱이 사용될 수 없음을 나타냅니다. 작업 모드를 |
| 다시 활성화하면 정상적인 동작이 복원됩니다. |
| </ul> |
| |
| <p> |
| Android N에서 Android for Work의 변경 사항에 대한 자세한 내용은 |
| <a href="{@docRoot}preview/features/afw.html">Android for Work 업데이트</a>를 참조하세요. |
| </p> |
| |
| <h2 id="annotations">주석 보존</h2> |
| |
| <p> |
| Android N에서는 주석의 표시 여부가 무시되던 버그가 수정되었습니다. 이 문제로 인해 런타임이 액세스할 수 없어야 하는 주석에 액세스할 수 있었습니다. |
| |
| 이러한 주석으로는 다음이 포함됩니다. |
| </p> |
| |
| <ul> |
| <li>{@code VISIBILITY_BUILD}: 빌드 시에만 표시되어야 합니다.</li> |
| <li>{@code VISIBILITY_SYSTEM}: 런타임에 |
| 기본 시스템에만 표시되어야 합니다.</li> |
| </ul> |
| |
| <p> |
| 앱이 이 동작에 의존했다면, 런타임에 사용할 수 있어야 하는 |
| 주석에 보존 정책을 추가하세요. {@code @Retention(RetentionPolicy.RUNTIME)}을 사용하여 추가하면 됩니다. |
| </p> |
| |
| <h2 id="other">기타 중요한 사항</h2> |
| |
| <ul> |
| <li>앱이 Android N에서 실행 중일 때 API 레벨이 낮고 사용자가 표시 |
| 크기를 변경하는 경우, 해당 앱 프로세스가 종료됩니다. 앱은 이 |
| 시나리오를 매끄럽게 처리할 수 있어야 합니다. 그렇지 않으면 사용자가 Recents에서 |
| 앱을 복원할 때 앱 작동이 중단됩니다. |
| |
| <p> |
| 이러한 동작이 발생하지 않도록 앱을 테스트해야 합니다. |
| DDMS를 통해 수동으로 앱을 종료할 때 |
| 동일한 작동 중단을 유발시킴으로써 테스트를 수행할 |
| 수 있습니다. |
| </p> |
| |
| <p> |
| N 이상을 대상으로 하는 앱은 밀도 변경 시에 자동으로 종료되지 않지만, |
| 구성 변경에는 제대로 응답하지 못할 수도 있습니다. |
| </p> |
| </li> |
| |
| <li> |
| Android N에서 앱은 구성 변경을 매끄럽게 처리할 수 있어야 하며, |
| 이후에 시작할 때도 작동이 중단되어서는 안 됩니다. 글꼴 |
| 크기(<strong>Setting</strong> > |
| <strong>Display</strong> > <strong>Font size</strong>)를 변경하여 앱 동작을 검사한 다음, Recents에서 |
| 앱을 복원할 수 있습니다. |
| </li> |
| |
| <li> |
| 이전 버전의 Android에서는 버그 때문에, 시스템이 주 스레드에서 |
| TCP 소켓에 대한 쓰기를 엄격 모드 위반으로서 플래그하지 못했습니다. Android N에서는 이 버그가 수정되었습니다. |
| 이 동작을 보이는 앱에서는 이제 {@code android.os.NetworkOnMainThreadException}이 발생합니다. |
| 일반적으로, 주 스레드에서 네트워크 작업을 수행하면 일반적으로 |
| 테일 지연 시간이 길어져 ANR 및 쟁크(jank)를 유발하므로, 이런 작업은 수행하지 않는 것이 좋습니다. |
| </li> |
| |
| <li> |
| {@code Debug.startMethodTracing()} 계열에 속하는 메서드는, |
| SD 카드의 최상위 레벨에 저장하는 것이 아니라, 이제 공유 저장소의 |
| 패키지별 디렉터리에 출력을 기본적으로 |
| 저장합니다. 즉, 앱은 이들 API를 사용하기 위해 {@code WRITE_EXTERNAL_STORAGE} 권한을 요청할 필요가 더 이상 없습니다. |
| </li> |
| |
| <li> |
| 상당수 플랫폼 API는 이제 대용량 |
| 페이로드가 {@link android.os.Binder} 트랜잭션을 통해 전송되는 것을 확인하기 시작했으며, 시스템에서는 |
| 이제 {@code TransactionTooLargeExceptions}를 |
| 자동으로 로깅하거나 억제하는 대신 {@code RuntimeExceptions}로 다시 발생시킵니다. 한 가지 |
| 공통적인 예는 |
| {@link android.app.Activity#onSaveInstanceState Activity.onSaveInstanceState()}에 |
| 너무 많은 데이터를 저장하는 바람에, 앱이 Android N을 대상으로 할 때 {@code ActivityThread.StopInfo}가 |
| {@code RuntimeException}을 발생시키는 경우입니다. |
| </li> |
| |
| <li> |
| 앱이 {@link java.lang.Runnable} 작업을 {@link android.view.View}에 게시하고 |
| {@link android.view.View}가 |
| 창에 연결되지 않은 경우, 시스템에서는 |
| {@link android.view.View}가 있는 {@link java.lang.Runnable} 작업을 큐에 넣으며, |
| {@link java.lang.Runnable} 작업은 |
| {@link android.view.View}가 창에 연결될 때까지 |
| 실행되지 않습니다. 이 동작은 다음과 같은 버그를 수정합니다. |
| <ul> |
| <li>의도한 창의 UI 스레드가 아닌 다른 스레드에서 {@link android.view.View}에 앱이 게시된 경우, |
| 결과적으로 {@link java.lang.Runnable}이 잘못된 스레드에서 실행될 수 있습니다. |
| </li> |
| <li>{@link java.lang.Runnable} 작업이 루퍼 스레드가 아닌 다른 스레드에서 |
| 게시되었다면 해당 앱이 {@link java.lang.Runnable} 작업을 노출시킬 수도 있습니다.</li> |
| </ul> |
| </li> |
| |
| <li> |
| {@link android.Manifest.permission#DELETE_PACKAGES DELETE_PACKAGES} |
| 권한이 |
| 있는 Android N 상의 앱이 패키지를 삭제하려고 하지만, 해당 패키지를 다른 앱이 설치한 경우에는 |
| 사용자의 확인이 필요합니다. 이 시나리오에서는 앱이 |
| {@link android.content.pm.PackageInstaller#uninstall PackageInstaller.uninstall()}을 호출할 때 |
| {@link android.content.pm.PackageInstaller#STATUS_PENDING_USER_ACTION STATUS_PENDING_USER_ACTION}을 |
| 반환 상태로 예상해야 합니다. |
| </li> |
| |
| </ul> |
| |