วิธีหลีกเลี่ยงบัญชีดำ API ที่ซ่อนอยู่ใน Android 9+

Google แนะนำข้อจำกัดใน Android 9 ซึ่งนักพัฒนาสามารถเข้าถึง API ได้ ต่อไปนี้เป็นวิธีหลีกเลี่ยงข้อจำกัด API ที่ซ่อนอยู่

ย้อนกลับไปในปี 2018 Google ได้เปิดตัว Android Pie ท่ามกลางการเปลี่ยนแปลง UI และคุณสมบัติใหม่ มีการเปลี่ยนแปลงด้านนักพัฒนาด้วย การเปลี่ยนแปลงเหล่านั้นรวมถึง API ใหม่ การแก้ไขข้อบกพร่องสำหรับ API ที่มีอยู่ และยังรวมถึง ข้อ จำกัด ในการเข้าถึง API ที่ซ่อนอยู่.

โชคดีที่มีวิธีแก้ไขข้อจำกัดเหล่านั้น ก่อนที่ฉันจะอธิบายวิธีหลีกเลี่ยงข้อจำกัดนี้ ฉันควรอธิบายเล็กน้อยเกี่ยวกับ API ที่ซ่อนอยู่ว่าคืออะไร เหตุใดจึงถูกจำกัดตั้งแต่แรก และเหตุใดคุณจึงต้องการเข้าถึง API เหล่านั้น

API ที่ซ่อนอยู่คือ API ใน Android ที่นักพัฒนาแอปปกติไม่สามารถมองเห็นได้ หากคุณดูโค้ดของ AOSP คุณจะเห็นคลาส ตัวแปร และเมธอดมากมายที่มี @hide คำอธิบายประกอบภายในบล็อกความคิดเห็นด้านบน

คำอธิบายประกอบนี้จะสั่งให้เครื่องมือใดก็ตามที่ Google ใช้ในการรวบรวม SDK ให้ยกเว้นรายการที่อยู่ในนั้น SDK นั้นจะถูกแจกจ่ายให้กับนักพัฒนาภายใน SDK ที่ดาวน์โหลดผ่าน Android Studio Android Studio จะคิดว่ารายการที่ซ่อนอยู่เหล่านั้นไม่มีอยู่เว้นแต่ว่าคุณใช้ SDK ที่ได้รับการแก้ไข หากคุณพยายามใช้โดยตรง มันจะแสดงเป็นสีแดงและปฏิเสธที่จะคอมไพล์

มีสาเหตุหลายประการว่าทำไม API อาจถูกซ่อนไว้ บางสิ่งมีไว้สำหรับใช้งานโดยแอปภายในหรือระบบเท่านั้น และจะไม่ทำงานหากใช้โดยแอปของบุคคลที่สาม ส่วนรายการอื่นๆ อยู่ในช่วงทดลองหรือไม่เสถียร และอาจถูกลบหรือเปลี่ยนแปลงในอนาคต บางตัวเป็นเพียง API ที่ Google ไม่ต้องการใช้วงจรการเลิกใช้งานตามปกติหากพวกมันถูกลบออกไป

ในขณะที่ Android SDK มาตรฐานมี มาก ในนั้นบางครั้งก็ไม่เพียงพอ บางครั้งมีบางอย่างที่คุณต้องการทำซึ่งมีอยู่แล้วใน Android แต่ก็ไม่ได้เปิดเผยต่อสาธารณะ

ตัวอย่างเช่น แอปมากมายที่ฉันทำ รวมทั้งด้วย จูนเนอร์ SystemUI และ วิดเจ็ตล็อคหน้าจอใช้ประโยชน์จาก API ที่ซ่อนอยู่มากมาย SystemUI Tuner จำเป็นต้องเข้าถึงบางส่วนเพื่อติดตาม เปลี่ยนแปลง และรีเซ็ตตัวเลือกได้อย่างถูกต้อง วิดเจ็ตหน้าจอล็อคใช้บางส่วนเพื่อแสดงวอลเปเปอร์ข้างใต้วิดเจ็ต เหนือสิ่งอื่นใด

นักพัฒนาส่วนใหญ่ไม่จำเป็นต้องเข้าถึง API ที่ซ่อนอยู่ แต่บางครั้งมันก็มีประโยชน์ทีเดียว

ด้วยการเปิดตัว Android 9 (Pie) Google ได้เปิดตัวบัญชีดำ API ที่ซ่อนอยู่ ไม่ใช่ทุก API ที่ซ่อนอยู่ และรายการก็มีระดับที่แตกต่างกัน ทุกคนสามารถเข้าถึง API ที่ซ่อนอยู่ในรายการที่อนุญาตได้ API ที่ซ่อนอยู่ในรายการสีเทาอ่อนสามารถเข้าถึงได้โดยแอปใดๆ แต่อาจไม่สามารถเข้าถึงได้ใน Android เวอร์ชันต่อๆ ไป ทุกสิ่งที่อยู่ในรายการสีเทาเข้มสามารถเข้าถึงได้โดยแอปที่กำหนดเป้าหมายระดับ API ก่อน Pie เท่านั้น (เช่น ก่อนระดับ API 28) แอพที่กำหนดเป้าหมายเป็น Pie และหลังจากนั้นจะถูกปฏิเสธการเข้าถึง ในที่สุด API ที่ซ่อนอยู่ในบัญชีดำไม่สามารถเข้าถึงได้โดยแอปที่ไม่ใช่ระบบ (หรือไม่ใช่รายการที่อนุญาตพิเศษ) ไม่ว่าจะเป็น API เป้าหมายก็ตาม

Android 10 เปลี่ยนวิธีการจัดระเบียบรายการ และทำให้รายการง่ายขึ้นเล็กน้อย แต่แนวคิดยังคงเหมือนเดิม แอพสามารถเข้าถึง API ที่ซ่อนอยู่บางส่วนได้ ในขณะที่บางตัวถูกบล็อก แอนดรอยด์ 11 เพิ่มความเข้มแข็งในการตรวจจับการเข้าถึง ถึง ปิดกั้นทางเบี่ยง ใช้สำหรับพายและ 10

ใน Android เวอร์ชันทั้งหมด เมื่อใดก็ตามที่แอปของบุคคลที่สามพยายามเข้าถึง API ที่ซ่อนไว้ในบัญชีดำ Android จะแสดงข้อผิดพลาด "ไม่พบ" ที่เหมาะสม

จริงๆ แล้วมีหลายวิธีในการผ่านบัญชีดำของ API ที่ซ่อนอยู่ คุณสามารถเลือกอันที่ใช้งานได้กับ Android ทุกรุ่น, อันที่ใช้งานได้กับ Android 9 และ 10 เท่านั้น, อันที่ใช้โค้ด Native C++ และอันที่ใช้ Java อย่างสมบูรณ์ ทั้งนี้ขึ้นอยู่กับความต้องการของคุณ มีวิธีแก้ไขปัญหาเฉพาะด้านการพัฒนาโดยใช้ ADB

วิธีแก้ปัญหาของ ADB

หากอุปกรณ์ของคุณใช้ Android Pie ให้รันคำสั่ง 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

หากต้องการเปลี่ยนกลับเป็นพฤติกรรมเริ่มต้น เพียงแทนที่ put กับ delete และลบ 1.

แน่นอนว่าคำสั่งเหล่านี้ไม่มีประโยชน์สำหรับแอปที่ใช้งานจริงเลย ฉันสามารถบอกคุณได้โดยตรงว่าการสอนผู้ใช้อย่างถูกต้องเกี่ยวกับวิธีใช้ ADB นั้นเป็นเรื่องยากอย่างไม่น่าเชื่อ แต่จะมีประโยชน์หากคุณต้องการอัปเดตแอปเก่าเพื่อให้เป็นไปตามข้อจำกัดใหม่

วิธีแก้ปัญหาดั้งเดิม/JNI

มีสองวิธีที่คุณสามารถข้ามบัญชีดำ API ที่ซ่อนอยู่ได้โดยใช้ JNI ในแอป Android ของคุณ อันหนึ่งใช้ได้กับ Android 9 และ 10 และอีกอันใช้ได้กับ Android 9 ขึ้นไป

แอนดรอยด์ 9 และ 10

หากคุณมีส่วนดั้งเดิมของแอปอยู่แล้ว สิ่งนี้จะง่ายต่อการนำไปใช้ เพียงแค่ใช้ JNI_OnLoad() การทำงาน.

ศิลปะแบบคงที่:: Runtime * 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 เวอร์ชันใดก็ตาม คุณมีไลบรารีให้เลือกสองไลบรารีเพื่อหลีกเลี่ยงข้อจำกัดของ API ที่ซ่อนอยู่: FreeReflection และ RestrictionBypass

ทั้งสองง่ายต่อการใช้งานและใช้งาน

เพื่อใช้งาน FreeReflectionเพิ่มการพึ่งพาให้กับ build.gradle ระดับโมดูลของคุณ

implementation 'me.weishu: free_reflection: 3.0.1'

จากนั้นแทนที่ attachBaseContext() ในคลาสแอปพลิเคชันของคุณ

@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'

และนั่นมัน ไลบรารีนี้จะลบข้อจำกัดของบัญชีดำโดยอัตโนมัติ

วิธีแก้ปัญหาจาวา

แม้ว่าโซลูชัน JNI จะมีประสิทธิภาพ แต่ก็มีบางครั้งที่คุณอาจไม่ต้องการใช้โค้ดแบบเนทีฟ หากคุณยังไม่ได้ทำสิ่งต่าง ๆ ด้วย C++ อาจเพิ่มขนาดที่ไม่จำเป็นพร้อมกับข้อจำกัดของแพลตฟอร์มให้กับแอปของคุณได้ โชคดีที่มีวิธีเลี่ยงผ่านบัญชีดำ API ที่ซ่อนอยู่โดยใช้ Java เท่านั้น

แอนดรอยด์ 9 และ 10

ใน Android 9 และ 10 คุณสามารถใช้สิ่งที่เรียกว่า double-reflection หรือ meta-reflection เพื่อเลี่ยงผ่านบัญชีดำ API ที่ซ่อนอยู่ เนื่องจากระบบจะตรวจสอบเฉพาะแอปของบุคคลที่สามที่กำลังเรียกอยู่ การสะท้อนซ้ำสองครั้งจึงหลอกให้คิดว่าระบบกำลังทำการเรียก API ที่ซ่อนอยู่

เคล็ดลับนี้สามารถใช้เพื่อเรียกวิธีการเพื่อให้แอปของคุณได้รับการยกเว้น API ที่ซ่อนอยู่ซึ่งมีชื่อเหมาะสม setHiddenApiExemptions(). เพียงเพิ่มโค้ดต่อไปนี้ในช่วงต้นของวงจรการใช้งานแอปของคุณ (เช่น Application's 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 และใหม่กว่า

หากต้องการข้ามบัญชีดำ API ที่ซ่อนอยู่ใน Android 9 และเวอร์ชันที่ใหม่กว่า คุณสามารถใช้ไลบรารีของ LSPosed ไลบรารีนี้ใช้ Unsafe API ของ Java ดังนั้นจึงไม่น่าจะเสียหาย

หากต้องการใช้งาน เพียงเพิ่มการพึ่งพาให้กับ build.gradle ระดับโมดูลของคุณ

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

จากนั้นใช้มันเพื่อหลีกเลี่ยงบัญชีดำ

HiddenApiBypass.addHiddenApiExemptions("L");

หากแอปของคุณเข้ากันได้กับ Android เวอร์ชันต่ำกว่า 9 อย่าลืมรวมสิ่งนี้ไว้ในการตรวจสอบเวอร์ชัน

บทสรุปและข้อมูลเพิ่มเติม

มีตัวเลือกมากมายในการข้ามบัญชีดำ API ที่ซ่อนอยู่บน Android ไม่ว่าคุณจะกำหนดเป้าหมายหรือใช้เวอร์ชันแพลตฟอร์มใดก็ตาม หากคุณต้องการเรียนรู้เพิ่มเติมเกี่ยวกับวิธีการทำงานและไลบรารีเหล่านี้ โปรดตรวจสอบลิงก์ต่อไปนี้

  • ถามตอบเกี่ยวกับ Stack Overflow ของฉัน.
  • ไลบรารี Bypass API ที่ซ่อนอยู่ของ LSposed บน GitHub.
  • ห้องสมุด RestrictionBypass ของ ChickenHook บน GitHub.
  • ไลบรารี FreeReflection ของ tiann บน GitHub.
  • เอกสารของ Google เกี่ยวกับบัญชีดำ API ที่ซ่อนอยู่.