Android
api
NDK
n
non-public

Android N で注意すること その2 (NDKを使っているアプリ)

More than 1 year has passed since last update.

Overview

3/9(US時間) に、Android N Developer Previewが出ました。

と、同時に developer.android.com において、behavior change が出ましたので、少しずつ読み解いていきたいと思います。

前回は、

NDKの挙動の変更

http://developer.android.com/preview/behavior-changes.html#ndk

結論から書くと、NDKで非公開のAPI使っていると、動かないよ、ということです。

Android N includes namespace changes to prevent loading of non-public APIs. If you use the NDK, you should only be using public APIs from the Android platform. Using non-public APIs in the next official release of Android can cause your app to crash.

抄訳:

Android Nは、non-public APIの読み出しを阻害するためのnamespaceの変更を含みます。もしあなたがNDKを使っているならば、Android Platformのpublic APIのみを使ってください。非公開APIを使っている場合、次のAndroidの公式リリースでは、あなたのアプリはクラッシュします。

In order to alert you to use of non-public APIs, apps running on an Android N device generate an error in logcat output when an app calls a non-public API. This error is also displayed on the device screen as a message to help raise awareness of this situation. You should review your app code to remove use of non-public platform APIs and thoroughly test your apps using a preview device or emulator.

抄訳:

非公開APIを使っていることをあなたに警告するために、appが非公開APIを呼び出した時に、Android Nデバイスで動いているアプリは、logcatの出力にerrorを生成します。このerrorは、この状況を気づいてもらうために、そのデバイスの画面にも表示されます。あなたのアプリにおいて、非公開APIの利用を削除するために、preview deviceかemulatorを使ってアプリをテストして、アプリのcodeをreviewすべきです。

If your app depends on platform libraries, see the NDK documentation for typical fixes for replacing common private APIs with public API equivalents. You may also be linking to platform libraries without realizing it, especially if your app uses a library that is part of the platform (such as libpng), but is not part of the NDK. In that case, ensure that your APK contains all the .so files you intended to link against.

抄訳:

アプリが、platformのlibraryに依存しているならば、よく使われているprivate APIに関しては、等価なpublic APIに交換するという典型的な修正についてのNDKのdocumentを参照してください。注意としては、あなたが気づかずに、platformのlibraryをlinkしているということがあるかもしれないということです。特に、platformの一部であるlibraryを使うケースです。例えば、libpngのような。(NDKの一部ではないことに注意してください)。このようなケースでは、apkの中に必要なすべてのsoを含める必要があります。

Caution: Some third-party libraries may link to non-public APIs. If your app uses these libraries, your app may crash when running on the next official release of Android.

抄訳:

注意ですが、いくつかの3rd partyのライブラリは、非公開APIをlinkしているかもしれません。あなたのアプリがこれらのライブラリを使っている場合は、あなたのアプリは、次の公式リリースのAndroidでは、クラッシュするかもしれません。

典型的なエラーlogの例がでています。

build時のエラー

Example Java error:

java.lang.UnsatisfiedLinkError: dlopen failed: library "/system/lib/libcutils.so"
is not accessible for the namespace "classloader-namespace"

Example NDK error:

dlopen failed: cannot locate symbol "__system_property_get" referenced by ...

getJavaVM や getJNIEnv を libandroid_runtime.soから使うケース

標準のJNIの関数に置換してください。

AndroidRuntime::getJavaVM -> GetJavaVM from <jni.h>
AndroidRuntime::getJNIEnv -> JavaVM::GetEnv or
JavaVM::AttachCurrentThread from <jni.h>.

libcutils.soから、property_getを使うケース

publicな別の__system_property_getを使ってください。そのためには以下を追加します。

#include <sys/system_properties.h>

libcrypto.soから、SSL_ctrl symbolを使うケース

アプリローカルなversionに交換してください。

例えば、libcyrpto.aをあなたの.so fileにstatic linkするか、アプリ独自にBoringSSLまたはOpenSSL由来のlibcrypto.soを内包するなど。。。