Android 9 以降で非表示の API ブラックリストをバイパスする方法

Google は Android 9 で、開発者が API にアクセスできる制限を導入しました。 これらの隠れた API 制限を回避する方法は次のとおりです。

遡ること2018年、GoogleはAndroid Pieをリリースしました。 UIの変更と新機能の中には、開発者側の変更もいくつかありました。 これらの変更には、新しい API、既存の API のバグ修正が含まれます。 非表示の API へのアクセス制限.

ただし幸いなことに、これらの制限を回避する方法があります。 制限を回避する方法を説明する前に、隠し API とは何か、そもそもなぜ制限されているのか、そしてなぜそれらにアクセスする必要があるのか​​について少し説明する必要があります。

隠し API は、アプリ開発者が通常見ることができない Android の API です。 AOSP のコードを見ると、次のようなクラス、変数、メソッドが大量にあることがわかります。 @hide その上のコメント ブロック内の注釈。

このアノテーションは、Google が SDK をコンパイルするときに使用するツールに対して、その下の項目を除外するように指示します。 その SDK は、Android Studio を通じてダウンロードされた SDK 内の開発者に配布されます。 修正された SDK を使用しない限り、Android Studio はこれらの非表示の項目は存在しないものとみなします。 直接使用しようとすると、赤色で表示され、コンパイルが拒否されます。

API が非表示になる理由はたくさんあります。 一部のものは、内部アプリまたはシステム アプリでのみ使用されることを目的としており、サードパーティ アプリで使用すると機能しません。 その他は実験的または不安定であり、将来削除または変更される可能性があります。 一部の API は、削除されたとしても Google が通常の非推奨サイクルを適用したくないだけです。

標準の Android SDK には 多く それで十分ではないこともあります。 場合によっては、Android にすでに存在していても、一般に公開されていないだけで、やりたいことが存在することがあります。

たとえば、私が作ったアプリの多くは、 システムUIチューナー そして ロック画面ウィジェット、さまざまな隠し API を利用します。 SystemUI Tuner は、オプションを適切に追跡、変更、リセットするためにいくつかにアクセスする必要があります。 ロック画面ウィジェットは、その下に壁紙を表示するためにいくつかを使用します。

ほとんどの開発者は隠し API にアクセスする必要はありませんが、場合によっては非常に便利です。

Android 9 (Pie) のリリースに伴い、Google は非表示の API ブラックリストを導入しました。 すべての隠し API が含まれているわけではなく、さまざまなレベルのリストがありました。 ホワイトリストにある非表示の API には誰でもアクセスできます。 ライトグレーのリストにある非表示の API はどのアプリでもアクセスできますが、Android の将来のバージョンではアクセスできなくなる可能性があります。 ダークグレーリストにあるものは、Pie より前の API レベル (つまり、API レベル 28 より前) をターゲットとするアプリによってのみアクセスできます。 Pie 以降をターゲットとするアプリはアクセスを拒否されます。 最後に、ブラックリストにある非表示の API は、ターゲット API に関係なく、システム以外の (またはホワイトリストに登録されていない) アプリからはアクセスできませんでした。

Android 10 ではリストの構成方法が変更され、若干簡素化されましたが、アイデアは同じままです。 特定の非表示 API はアプリからアクセスできる一方で、他の API はブロックされる可能性がありました。 アンドロイド11 アクセス検知を強化しましたバイパスを遮断する Pieと10に使用されます。

すべての Android バージョンで、サードパーティ アプリがブラックリストに登録された隠し API にアクセスしようとすると、Android は適切な「見つからない」エラーをスローします。

実際には、非表示の API ブラックリストを回避する方法はかなりたくさんあります。 ニーズに応じて、すべての Android バージョンで動作するもの、Android 9 と 10 でのみ動作するもの、ネイティブ C++ コードを使用するもの、完全に Java ベースのものを選択できます。 ADB を使用した開発専用の回避策もあります。

ADB の回避策

デバイスが Android Pie を実行している場合は、次の 2 つの ADB コマンドを実行して、非表示の API アクセスを有効にします。

adb shell settings put global hidden_api_policy_pre_p_apps 1
adb shell settings put global hidden_api_policy_p_apps 1

デバイスが Android 10 以降を実行している場合は、次の ADB コマンドを実行して、非表示の API アクセスを有効にします。

adb shell settings put global hidden_api_policy 1

デフォルトの動作に戻すには、次のように置き換えます。 putdelete そして、を削除します 1.

明らかに、これらのコマンドは実稼働アプリにはまったく役に立ちません。 ADB の使用方法をユーザーに適切に指導するのは、非常に難しいことだと直接言えます。 ただし、新しい制限に準拠するために古いアプリを更新する必要がある場合には便利です。

ネイティブ/JNI の回避策

Android アプリで JNI を使用して非表示の API ブラックリストをバイパスする方法は 2 つあります。 1 つは Android 9 および 10 で動作し、もう 1 つは Android 9 以降で動作します。

アンドロイド9と10

アプリのネイティブ部分がすでにある場合、これは簡単に実装できます。 ただ使用してください JNI_OnLoad() 関数。

静的アート:: ランタイム* runtime = nullptr;

extern "C"jint JNI_OnLoad(JavaVM *vm, void *reserved){
...
runtime = reinterpret_cast<: javavmext>(vm)->GetRuntime();
runtime->SetHiddenApiEnforcementPolicy(art:: hiddenapi:: EnforcementPolicy:: kNoChecks);
...
}

この方法は Android 9 と 10 でのみ機能することに注意してください。

Android 9以降

Android のどのバージョンでも、FreeReflection と RestrictionBypass という隠れた API 制限をバイパスする 2 つのライブラリから選択できます。

どちらも実装と使用が簡単です。

FreeReflection を実装するには、依存関係をモジュールレベルの build.gradle に追加します。

implementation 'me.weishu: free_reflection: 3.0.1'

次にオーバーライドします attachBaseContext() Application クラスで。

@Override
protectedvoidattachBaseContext(Context base){
super.attachBaseContext(base);
Reflection.unseal(base);
}

Application クラスがない場合は、非常に簡単に追加できます。 拡張した新しいクラスを作成する Application そして、AndroidManifest.xml でそれをポイントします。

例:

publicclassAppextendsApplication{
...
@Override
protectedvoidattachBaseContext(Context base){
super.attachBaseContext(base);

Reflection.unseal(base);
}
}

<manifest>
...
...
name=".App">
...
application>
manifest>

RestrictionBypass を実装するには、JitPack リポジトリをプロジェクト レベルの build.gradle に追加します。

allprojects {
repositories {
...
maven { url "https://jitpack.io" }
}
}

次に、依存関係をモジュールレベルの build.gradle に追加します。

implementation 'com.github.ChickenHook: RestrictionBypass: 2.2'

以上です。 このライブラリは、ブラックリストの制限を自動的に削除します。

Java の回避策

JNI ソリューションは効果的ですが、ネイティブ コードを使用したくない場合もあります。 まだ C++ で作業を行っていない場合は、プラットフォームの制限とともに不要なサイズがアプリに追加される可能性があります。 幸いなことに、Java のみを使用して非表示の API ブラックリストを回避する方法があります。

アンドロイド9と10

Android 9 および 10 では、二重反射またはメタ反射と呼ばれるものを使用して、非表示の API ブラックリストをバイパスできます。 システムはサードパーティ アプリが何を呼び出しているかをチェックするだけであるため、二重反射によりシステムが隠れた API 呼び出しを行っていると思わせます。

このトリックを使用すると、アプリに非表示の API 免除を与えるメソッドを呼び出すことができます。 setHiddenApiExemptions(). アプリのライフサイクルの早い段階 (アプリケーションの onCreate() メソッド)、ブラックリストのバイパスを処理します。

Method forName = Class.class.getDeclaredMethod("forName", String.class);
Method getDeclaredMethod = Class.class.getDeclaredMethod("getDeclaredMethod", String.class, Class[].class);

Class vmRuntimeClass = (Class) forName.invoke(null, "dalvik.system.VMRuntime");
Method getRuntime = (Method) getDeclaredMethod.invoke(vmRuntimeClass, "getRuntime", null);
Method setHiddenApiExemptions = (Method) getDeclaredMethod.invoke(vmRuntimeClass, "setHiddenApiExemptions", newClass[] { String[].class} );

Object vmRuntime = getRuntime.invoke(null);
setHiddenApiExemptions.invoke(vmRuntime, newString[][] { newString[] { "L" } });

アプリが Android 9 より前のバージョンと互換性がある場合は、これをバージョン チェックでラップすることを忘れないでください。

Android 9以降

Android 9 以降のバージョンで非表示の API ブラックリストをバイパスするには、LSPosed のライブラリを使用できます。 このライブラリは Java の Unsafe API を使用しているため、壊れる可能性はほとんどありません。

これを実装するには、モジュールレベルの build.gradle に依存関係を追加するだけです。

implementation 'org.lsposed.hiddenapibypass: hiddenapibypass: 2.0'

次に、それを使用してブラックリストをバイパスします。

HiddenApiBypass.addHiddenApiExemptions("L");

アプリが Android 9 より前のバージョンと互換性がある場合は、これをバージョン チェックでラップすることを忘れないでください。

結論と詳細情報

ターゲットまたは使用するプラットフォームのバージョンに関係なく、Android では非表示の API ブラックリストをバイパスするためのオプションが多数あります。 これらのメソッドとライブラリがどのように機能するかについて詳しく知りたい場合は、次のリンクを必ずチェックしてください。

  • 私のスタック オーバーフローに関する Q&A.
  • GitHub 上の LSposed の Hidden API Bypass ライブラリ.
  • GitHub 上の ChickenHook の RestrictionBypass ライブラリ.
  • GitHub 上の tiann の FreeReflection ライブラリ.
  • 非表示の API ブラックリストに関する Google のドキュメント.