AndroidアプリのOSアップデート対応をした際に、非SDKインターフェースについて疑問に思ったことが多かったので、調べた情報をまとめました。
非SDKインターフェースとは
非SDKインターフェースとは、Googleから公式に公開されていないクラスやメソッドのこと。(hidden API や 内部API と呼ばれたりする)
反対に通常のSDKインターフェースは、GoogleがAndroidアプリ開発者向けに、正式に公開・サポートしているクラスやメソッドのこと。
ContextやActivity, Viewなどが挙げられます。
非SDKインターフェースはなぜ制限されるのか
公式にサポートされていないため、急に使えなくなる可能性があります。
OSアップデートによりアプリがクラッシュしたり、不具合が起きたりする可能性を下げるために制限されます。
Android 9(API 28)以降から制限されるようになっており、制限には以下の種類があるようです。
コードタグ | 説明 |
---|---|
blocked / blacklist | クラッシュまたは無視される |
max-target-x / greylist-max-x | API レベルごとにエラーや例外がスローされる |
unsupported / greylist | 今は制限されておらず、今後される可能性あり |
非SDKインタフェースを使用しているかの確認
公式でもいくつか方法が挙げられていますが、私は以下の方法を試しました。
1. ログを確認する
デバック状態でアプリを動かし、Logcatでログを確認しました。
画面の遷移やアクションなど、すべての動作を網羅するようにアプリを動かします。
その際、非SDKインタフェースを使用していた場合は以下のようなログが出力されます。
W Accessing hidden method Landroid/view/ViewGroup;->makeOptionalFitsSystemWindows()V (greylist, reflection, allowed)
Accessing hidden methodの他に、Accessing hidden field、Accessing hidden constructor、Accessing hidden classなどもあります。
2. veridexで確認する
veridexはapkファイルの静的解析ツールです。
JNI を介した呼び出しは検出できないなど一部制約はありますが、調査の1つとして取り入れても良いと思います。
手順は以下のとおりです。
- ここからveridexツールをダウンロード
- .tar.gzファイルがダウンロードされるので、ダブルクリックで解凍
- 手順2で解凍したフォルダの中にあるveridex-mac.zipを解凍
- ターミナルでveridex-macのフォルダに移動して、以下コマンドを実行
$ ./appcompat.sh --dex-file=apkファイルのルートパス
以下はデスクトップにapp-debug.apkという名前のapkファイルがある例です。
$ ./appcompat.sh --dex-file=/Users/自身のユーザー名/Desktop/app-debug.apk
“veridex”が開けないなどのエラーダイアログが表示される場合は、macのシステム設定 > プライバシーとセキュリティ > セキュリティの項目で「AppStore」にチェックをした状態であれば、「このまま許可」というボタンが表示されます。
コマンド実行がうまくいくと、以下のようなものが出力されます。
veridex-mac % ./appcompat.sh --dex-file=/Users/自身のユーザー名/Desktop/app-debug.apk
NOTE: appcompat.sh is still under development. It can report
API uses that do not execute at runtime, and reflection uses
that do not exist. It can also miss on reflection uses.
#1: Linking blocked Landroid/icu/number/FormattedNumber;->getOutputUnit()Landroid/icu/util/MeasureUnit; use(s):
Landroidx/core/text/util/LocalePreferences$Api33Impl;->getResolvedTemperatureUnit(Ljava/util/Locale;)Ljava/lang/String;
#2: Linking blocked Landroid/icu/text/DateFormat$HourCycle;->values()[Landroid/icu/text/DateFormat$HourCycle; use(s):
Landroidx/core/text/util/LocalePreferences$1;-><clinit>()V
~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~
#83: Reflection unsupported Lsun/misc/Unsafe;->allocateInstance use(s):
Lcom/google/gson/internal/UnsafeAllocator;->create()Lcom/google/gson/internal/UnsafeAllocator;
#84: Reflection unsupported Lsun/misc/Unsafe;->theUnsafe use(s):
Lcom/google/gson/internal/UnsafeAllocator;->create()Lcom/google/gson/internal/UnsafeAllocator;
84 hidden API(s) used: 26 linked against, 58 through reflection
56 in unsupported
10 in blocked
6 in max-target-o
10 in max-target-p
2 in max-target-q
0 in max-target-r
To run an analysis that can give more reflection accesses,
but could include false positives, pass the --imprecise flag.
あとがき
警告に対する対処法はまた別途まとめようと思います。
夜に殴り書きしたので、時間がある時に少しずつメンテします。
参考:https://developer.android.com/guide/app-compatibility/restrictions-non-sdk-interfaces?hl=ja