คำแนะนำนี้จะอธิบายวิธีใช้ Wrapper ของไลบรารี Android API ห้องสมุด เครื่องมือบรรทัดคำสั่ง Wrapper จะสร้างโค้ด Wrapper ภาษา C สำหรับ Java Android API ที่ช่วยให้คุณผสานรวมไลบรารี Java เข้ากับแอป Android สำหรับ C/C++ ที่มาพร้อมเครื่อง ดูรายละเอียดเพิ่มเติมเกี่ยวกับ Wrapper ของไลบรารีได้ที่ Wrapper ของไลบรารีสำหรับ API ของ Android
คำแนะนำทีละขั้นตอนนี้จะสาธิตวิธีใช้เครื่องมือ Wrapper เพื่อผสานรวม
ไลบรารี Java ลงในแอป Android ที่มาพร้อมเครื่อง คู่มือนี้มีตัวอย่างเพื่อวัตถุประสงค์ดังนี้
การผสานรวมไลบรารีการแจ้งเตือนของแพ็กเกจ androidx.core.app
โปรดดูที่สร้างการแจ้งเตือนเพื่อเรียนรู้เพิ่มเติมเกี่ยวกับไลบรารีนี้
สิ่งที่ต้องมีก่อน
คู่มือนี้จะถือว่าคุณมีโปรเจ็กต์ Android ที่มาพร้อมเครื่องอยู่แล้ว และ ใช้ระบบบิลด์ Gradle หากยังไม่มี ให้สร้างโปรเจ็กต์ เวอร์ชันใหม่ใน Android Studio โดยใช้เทมเพลต C++ ดั้งเดิม
โค้ดตัวอย่างในคู่มือนี้ใช้รูทไดเรกทอรี my_project/
เนทีฟ
รหัสอยู่ใน my_project/app/src/main/cpp/
ซึ่งเป็นไดเรกทอรีเริ่มต้นสำหรับ
โปรเจ็กต์ Android Studio
หากคุณยังไม่มีเครื่องมือ Wrapper ของไลบรารี ให้ดาวน์โหลดและแตกไฟล์ ลงในไดเรกทอรีที่คุณเลือก เครื่องมือ CLI นี้ต้องใช้รันไทม์ของ Java Environment (JRE)
สร้างโค้ดเนทีฟ
เมื่อผสานรวมไลบรารี Java ให้ใช้เครื่องมือ Wrapper เพื่อ สร้าง Wrapper โค้ดแบบเนทีฟ ขั้นตอนแรกคือกำหนดค่า Wrapper
สร้างการกำหนดค่า Wrapper
คุณสามารถสร้างไฟล์การกำหนดค่า Wrapper ของไลบรารีเพื่อควบคุม เอาต์พุตของโปรแกรมสร้างโค้ดแบบเนทีฟ ฟีเจอร์หนึ่งของไฟล์นี้ช่วยให้คุณระบุ คลาสและวิธีสร้างโค้ด Wrapper
เนื่องจากการรวมสำหรับไลบรารีการแจ้งเตือนมีหลายวิธีด้วยกัน คุณสามารถ
ให้ระบุในส่วน custom_classes
โดยตรง สร้างใหม่
config.json
ที่ใดก็ได้ในโปรเจ็กต์เพื่อกำหนดเมธอด ตัวอย่างเช่น
คุณสามารถสร้าง my_project/library_wrapper/config.json
และวางข้อมูลต่อไปนี้
ตัวอย่างการกำหนดค่า:
{
"custom_classes": [
{
"class_name": "class java.lang.CharSequence"
},
{
"class_name": "class java.lang.Object",
"methods": [
"java.lang.String toString()"
]
},
{
"class_name": "class java.lang.String"
},
{
"class_name": "class android.content.Context",
"methods": [
"java.lang.Object getSystemService(java.lang.String name)"
]
},
{
"class_name": "class android.app.Notification"
},
{
"class_name": "class android.app.NotificationManager",
"methods": [
"void createNotificationChannel(android.app.NotificationChannel channel)"
]
},
{
"class_name": "class android.app.NotificationChannel",
"methods": [
"NotificationChannel(java.lang.String id, java.lang.CharSequence name, int importance)",
"void setDescription(java.lang.String description)"
]
},
{
"class_name": "class androidx.core.app.NotificationCompat"
},
{
"class_name": "class androidx.core.app.NotificationCompat$Builder",
"methods": [
"Builder(android.content.Context context, java.lang.String channelId)",
"androidx.core.app.NotificationCompat$Builder setContentText(java.lang.CharSequence text)",
"androidx.core.app.NotificationCompat$Builder setContentTitle(java.lang.CharSequence title)",
"androidx.core.app.NotificationCompat$Builder setSmallIcon(int icon)",
"androidx.core.app.NotificationCompat$Builder setPriority(int pri)",
"android.app.Notification build()"
]
},
{
"class_name": "class androidx.core.app.NotificationManagerCompat",
"methods": [
"static androidx.core.app.NotificationManagerCompat from(android.content.Context context)",
"void notify(int id, android.app.Notification notification)"
]
}
]
}
ในตัวอย่างก่อนหน้านี้ คุณจะประกาศคลาสและ Method ของ Java โดยตรงที่ ซึ่งต้องการรหัส Wrapper เนทีฟ
เรียกใช้ Wrapper ของไลบรารี
หลังจากกำหนดไฟล์การกำหนดค่า Wrapper คุณก็พร้อมที่จะใช้เครื่องมือเพื่อสร้าง ด้วยโค้ด Wrapper เนทีฟ เปิดเทอร์มินัลไปยังตำแหน่งที่คุณแตก Wrapper ของไลบรารี และเรียกใช้คำสั่งต่อไปนี้
java -jar lw.jar \
-o "my_project/app/src/main/cpp/native_wrappers" \
-c "my_project/library_wrapper/config.json"
ในตัวอย่างก่อนหน้านี้คุณใช้พารามิเตอร์ -c
เพื่อระบุ Wrapper
ตำแหน่งการกำหนดค่า และพารามิเตอร์ -o
เพื่อกำหนดไดเรกทอรีโค้ดที่สร้างขึ้น
หลังจากเรียกใช้เครื่องมือ ตอนนี้คุณควรมีโค้ดที่สร้างขึ้นซึ่งจำเป็นต้องใช้เพื่อเรียกใช้
API การแจ้งเตือนแบบ Java จากแอปที่มาพร้อมเครื่อง
ใช้การแจ้งเตือนดั้งเดิม
ในส่วนนี้ คุณได้ผสานรวมไลบรารีการแจ้งเตือนของ Android ไว้ใน
แอปที่มาพร้อมเครื่อง โดยใช้โค้ด Wrapper ที่คุณสร้างขึ้น ขั้นตอนแรกให้อัปเดต
ทรัพยากร gradle.build
ระดับแอปของโปรเจ็กต์ (my_project/app/gradle.build
)
อัปเดต gradle.build
GNI คือไลบรารีการสนับสนุนที่จำเป็นสำหรับโค้ด Wrapper ที่สร้างขึ้น โปรเจ็กต์ทั้งหมด ที่ใช้โค้ดที่สร้างขึ้นควรอ้างอิงไลบรารีนี้ หากต้องการอ้างอิงไลบรารีนี้ เพิ่มบรรทัดต่อไปนี้ในส่วน
dependencies
ของbuild.gradle
:implementation 'com.google.android.gms:play-services-gni-native-c:1.0.0-beta2'
ในการเปิดใช้การสนับสนุน prefab ให้เพิ่มรหัสต่อไปนี้ในส่วน
android
:buildFeatures { prefab true }
หากต้องการกำหนดค่า
cmake
ให้ใช้การกำหนดค่าcmake
ต่อไปนี้ใน ส่วนandroid/defaultConfig
:externalNativeBuild { cmake { arguments '-DANDROID_STL=c++_shared' } }
การกำหนดค่า build.gradle
ที่เสร็จสมบูรณ์แล้วควรมีลักษณะต่อไปนี้
android {
...
buildFeatures {
prefab true
}
defaultConfig {
...
externalNativeBuild {
cmake {
arguments '-DANDROID_STL=c++_shared'
}
}
}
}
dependencies {
...
implementation 'com.google.android.gms:play-services-gni-native-c:1.0.0-beta2'
...
}
แก้ไข CMakeLists
เพิ่มไลบรารี GNI ลงใน
CMakeLists.txt
ของโปรเจ็กต์ (my_project/app/src/main/cpp/CMakeLists.txt
) ด้วยการเพิ่มบรรทัดต่อไปนี้ที่ ระดับบนสุดของไฟล์:find_package(com.google.android.gms.gni.c REQUIRED CONFIG)
เพิ่มบรรทัดต่อไปนี้ในส่วน
target_link_libraries
PUBLIC com.google.android.gms.gni.c::gni_shared
เพิ่มการอ้างอิงไปยังโค้ดที่สร้างขึ้นโดยการเพิ่มบรรทัดต่อไปนี้ที่ ระดับสูงสุดของไฟล์:
file(GLOB_RECURSE native_wrappers CONFIGURE_DEPENDS "native_wrappers/*.cpp" "native_wrappers/*.cc")
เพิ่มบรรทัดต่อไปนี้ใกล้กับส่วนท้ายของไฟล์
include_directories(./native_wrappers/c) include_directories(./native_wrappers/cpp)
ทรัพยากร CMakeLists.txt
ที่อัปเดตแล้วควรมีลักษณะคล้ายกับตัวอย่างต่อไปนี้
cmake_minimum_required(VERSION 3.18.1)
project("my_project")
file(GLOB_RECURSE native_wrappers CONFIGURE_DEPENDS "native_wrappers/*.cpp" "native_wrappers/*.cc")
add_library(
my_project
SHARED
native-lib.cpp
${native_wrappers}
)
find_library(
log-lib
log)
find_package(com.google.android.gms.gni.c REQUIRED CONFIG)
target_link_libraries(
my_project
PUBLIC com.google.android.gms.gni.c::gni_shared
${log-lib})
include_directories(./native_wrappers/c)
include_directories(./native_wrappers/cpp)
ใช้ตรรกะการแจ้งเตือน
เปิดหรือสร้างไฟล์ต้นฉบับที่คุณต้องการนำการแจ้งเตือนไปใช้ ความสามารถ ในไฟล์นี้ ให้รวมไฟล์ส่วนหัว
gni.h
และกำหนด ฟังก์ชันShowNativeNotification()
ใหม่:#include "gni/gni.h" void ShowNativeNotification(JNIEnv *env, jobject main_activity, int icon_id) { // Get the JavaVM from the JNIEnv. JavaVM *java_vm; env->GetJavaVM(&java_vm); // Initialize the GNI runtime. This function needs to be called before any // call to the generated code. GniCore_init(java_vm, main_activity); }
กำหนดค่าคงที่ของการแจ้งเตือน ตัวแฮนเดิลฟังก์ชัน
CharSequenceFromCString()
และCreateNotification()
:C
const int32_t IMPORTANCE_HIGH = 4; // NotificationManager.IMPORTANCE_HIGH const int32_t PRIORITY_MAX = 2; // NotificationCompat.PRIORITY_MAX const int32_t NOTIFICATION_ID = 123; // User defined notification id. // Convert a C string into CharSequence. CharSequence *CharSequenceFromCString(const char *text) { String *string = String_fromCString(text); // Cast String to CharSequence. In Java, a String implements CharSequence. CharSequence *result = GNI_CAST(CharSequence, String, string); // Casting creates a new object, so it needs to be destroyed as normal. String_destroy(string); return result; } // Create a notification. Notification * CreateNotification(Context *context, String *channel_id, const char *title, const char *content, int32_t icon_id) { // Convert C strings to CharSequence. CharSequence *title_chars = CharSequenceFromCString(title); CharSequence *content_chars = CharSequenceFromCString(content); // Create a NotificationCompat.Builder and set all required properties. NotificationCompat_Builder *notification_builder = NotificationCompat_Builder_construct(context, channel_id); NotificationCompat_Builder_setContentTitle(notification_builder, title_chars); NotificationCompat_Builder_setContentText(notification_builder, content_chars); NotificationCompat_Builder_setSmallIcon(notification_builder, icon_id); NotificationCompat_Builder_setPriority(notification_builder, PRIORITY_MAX); // Build a notification. Notification *notification = NotificationCompat_Builder_build(notification_builder); // Clean up allocated objects. NotificationCompat_Builder_destroy(notification_builder); CharSequence_destroy(title_chars); CharSequence_destroy(content_chars); return notification; }
C++
const int32_t IMPORTANCE_HIGH = 4; // NotificationManager.IMPORTANCE_HIGH const int32_t PRIORITY_MAX = 2; // NotificationCompat.PRIORITY_MAX const int32_t NOTIFICATION_ID = 123; // User defined notification id. // Convert a C string into CharSequence. CharSequence *CharSequenceFromCString(const char *text) { String *string = String_fromCString(text); // Cast String to CharSequence. In Java, a String implements CharSequence. CharSequence *result = new CharSequence(string->GetImpl()); // Casting creates a new object, so it needs to be destroyed as normal. String::destroy(string); return result; } // Create a notification. Notification& CreateNotification(Context *context, String *channel_id, const char *title, const char *content, int32_t icon_id) { // Convert C strings to CharSequence. CharSequence *title_chars = CharSequenceFromCString(title); CharSequence *content_chars = CharSequenceFromCString(content); // Create a NotificationCompat.Builder and set all required properties. NotificationCompat::Builder *notification_builder = new NotificationCompat::Builder(*context, *channel_id); notification_builder->setContentTitle(*title_chars); notification_builder->setContentText(*content_chars); notification_builder->setSmallIcon(icon_id); notification_builder->setPriority(PRIORITY_MAX); // Build a notification. Notification& notification = notification_builder->build(); // Clean up allocated objects. NotificationCompat::Builder::destroy(notification_builder); CharSequence::destroy(title_chars); CharSequence::destroy(content_chars); return notification; }
ฟังก์ชันบางอย่างของไลบรารีการแจ้งเตือนจะใช้
CharSequence
แทนString
ฟังก์ชันCharSequenceFromCString()
ช่วยให้แปลงค่าระหว่าง วัตถุเหล่านี้ ฟังก์ชันCreateNotification()
จะใช้เวอร์ชันสรุปของ JavaNotificationCompat.Builder
เพื่อสร้างการแจ้งเตือนเพิ่มตรรกะเพื่อสร้างช่องทางการแจ้งเตือนโดยวางข้อมูลต่อไปนี้ ฟังก์ชัน
CreateNotificationChannel()
:C
void CreateNotificationChannel(Context *context, String *channel_id) { CharSequence *channel_name = CharSequenceFromCString("channel name"); String *channel_description = String_fromCString("channel description"); String *system_service_name = String_fromCString("notification"); NotificationChannel *channel = NotificationChannel_construct(channel_id, channel_name, IMPORTANCE_HIGH); NotificationChannel_setDescription(channel, channel_description); Object *notification_manager_as_object = Context_getSystemService(context, system_service_name); NotificationManager *notification_manager = GNI_CAST(NotificationManager, Object, notification_manager_as_object); NotificationManager_createNotificationChannel(notification_manager, channel); CharSequence_destroy(channel_name); String_destroy(channel_description); String_destroy(system_service_name); NotificationChannel_destroy(channel); Object_destroy(notification_manager_as_object); NotificationManager_destroy(notification_manager); }
C++
void CreateNotificationChannel(Context *context, String *channel_id) { CharSequence *channel_name = CharSequenceFromCString("channel name"); String *channel_description = String_fromCString("channel description"); String *system_service_name = String_fromCString("notification"); NotificationChannel *channel = new NotificationChannel(*channel_id, *channel_name, IMPORTANCE_HIGH); channel->setDescription(*channel_description); Object& notification_manager_as_object = context->getSystemService(*system_service_name); NotificationManager *notification_manager = new NotificationManager(notification_manager_as_object.GetImpl()); notification_manager->createNotificationChannel(*channel); CharSequence::destroy(channel_name); String::destroy(channel_description); String::destroy(system_service_name); NotificationChannel::destroy(channel); Object::destroy(¬ification_manager_as_object); NotificationManager::destroy(notification_manager); }
อัปเดตฟังก์ชัน
ShowNativeNotification()
ที่คุณสร้างไว้ก่อนหน้านี้เป็น โทรหาCreateNotificationChannel()
เพิ่มโค้ดต่อไปนี้ต่อท้ายShowNativeNotification()
:C
void ShowNativeNotification(JNIEnv *env, jobject main_activity, int icon_id) { // ... // Create a Context object by wrapping an existing JNI reference. Context *context = Context_wrapJniReference(main_activity); // Create a String object. String *channel_id = String_fromCString("new_messages"); // Create a notification channel. CreateNotificationChannel(context, channel_id); // Create a notification with a given title, content, and icon. Notification *notification = CreateNotification(context, channel_id, "My Native Notification", "Hello!", icon_id); // Create a notification manager and use it to show the notification. NotificationManagerCompat *notification_manager = NotificationManagerCompat_from(context); NotificationManagerCompat_notify(notification_manager, NOTIFICATION_ID, notification); // Destroy all objects. Context_destroy(context); String_destroy(channel_id); Notification_destroy(notification); NotificationManagerCompat_destroy(notification_manager); }
C++
void ShowNativeNotification(JNIEnv *env, jobject main_activity, int icon_id) { // Get the JavaVM from the JNIEnv. JavaVM *java_vm; env->GetJavaVM(&java_vm); // Initialize the GNI runtime. This function needs to be called before any // call to the generated code. GniCore::Init(java_vm, main_activity); // Create a Context object by wrapping an existing JNI reference. Context *context = new Context(main_activity); // Create a String object. String *channel_id = String_fromCString("new_messages"); // Create a notification channel. CreateNotificationChannel(context, channel_id); // Create a notification with a given title, content, and icon. Notification& notification = CreateNotification(context, channel_id, "My Native Notification", "Hello!", icon_id); // Create a notification manager and use it to show the notification. NotificationManagerCompat& notification_manager = NotificationManagerCompat::from(*context); notification_manager.notify(NOTIFICATION_ID, notification); // Destroy all objects. Context::destroy(context); String::destroy(channel_id); Notification::destroy(¬ification); NotificationManagerCompat::destroy(¬ification_manager); }
ทริกเกอร์การแจ้งเตือนด้วยการโทรตามตรรกะที่กำหนดแล้ว
ShowNativeNotification()
ที่ตำแหน่งที่เหมาะสมในโปรเจ็กต์ของคุณ
เรียกใช้แอป
คอมไพล์และเรียกใช้โค้ดที่เรียกใช้ ShowNativeNotification()
องค์ประกอบ
การแจ้งเตือนจะปรากฏที่ด้านบนของหน้าจออุปกรณ์ทดสอบ
สร้าง Wrapper จาก JAR
ในตัวอย่างก่อนหน้านี้ คุณได้กำหนดคลาส Java ด้วยตนเองและ เมธอดที่ต้องใช้โค้ดแบบเนทีฟในไฟล์การกำหนดค่า Wrapper สำหรับสถานการณ์ที่คุณ ต้องการเข้าถึงส่วนต่างๆ ของ API ขนาดใหญ่ จะมีประสิทธิภาพมากกว่าในการมอบ JAR ของไลบรารีเพิ่มเติมไปยังเครื่องมือ Wrapper จากนั้น Wrapper จะสร้าง Wrapper สำหรับ สัญลักษณ์สาธารณะทั้งหมดที่พบใน JAR
ตัวอย่างต่อไปนี้รวม Notifications API ทั้งหมดด้วยการระบุไลบรารี JAR
รับ JAR ที่จำเป็น
Notification API เป็นส่วนหนึ่งของแพ็กเกจ androidx.core
ซึ่งมีให้บริการจาก
ที่เก็บ Google Maven ดาวน์โหลดไฟล์ไลบรารี aar และแตกไฟล์ไปยัง
ไดเรกทอรีที่คุณเลือก ค้นหาไฟล์ classes.jar
ไฟล์ classes.jar
มีชั้นเรียนจำนวนมากนอกเหนือจากการแจ้งเตือนที่เรากำหนดไว้
ไลบรารี หากคุณให้ Wrapper ของไลบรารีเพียง classes.jar
เครื่องมือ
สร้างโค้ดแบบเนทีฟสำหรับทุกคลาสใน JAR ซึ่งไม่มีประสิทธิภาพ
สำหรับโปรเจ็กต์ของเรา หากต้องการแก้ไขปัญหานี้ ให้ระบุไฟล์ตัวกรองไปยัง
การกำหนดค่า Wrapper เพื่อจำกัดการสร้างโค้ดไว้เฉพาะการแจ้งเตือนของ JAR
ใหม่
กำหนดตัวกรองการอนุญาต
กรองไฟล์เป็นไฟล์ข้อความธรรมดาที่คุณส่งไปยัง Wrapper ไลบรารี การกำหนดค่า เทมเพลตเหล่านี้ให้คุณกำหนดชั้นเรียนที่จะรวม (หรือยกเว้น) ได้ จากไฟล์ JAR ที่ให้ไว้ใน Wrapper ของไลบรารี
สร้างโปรเจ็กต์ ให้สร้างไฟล์ชื่อ allowed-symbols.txt
แล้ววางลงในไฟล์
บรรทัดต่อไปนี้:
androidx.core.app.NotificationCompat*
เมื่อใช้เป็นตัวกรองการอนุญาต โค้ดที่อยู่ก่อนหน้าจะระบุเฉพาะสัญลักษณ์
ที่ชื่อขึ้นต้นด้วย androidx.core.app.NotificationCompat
ระบบจะรวมชื่อดังกล่าว
เรียกใช้ Wrapper ของไลบรารี
เปิดเทอร์มินัลไปยังไดเรกทอรี JAR และเรียกใช้คำสั่งต่อไปนี้
java -jar lw.jar \
-i classes.jar \
-o "./generated-jar" \
-c "./config.json" \
-fa allowed-symbols.txt \
--skip_deprecated_symbols
คำสั่งตัวอย่างก่อนหน้านี้จะสร้างโค้ด Wrapper สำหรับคลาสที่กรอง
ไปที่ไดเรกทอรี generated-jar/
การสนับสนุน
หากคุณพบปัญหาเกี่ยวกับ Wrapper ของไลบรารี โปรดแจ้งให้เราทราบ
เรียกดูข้อบกพร่อง | รายงานข้อบกพร่อง |
---|---|
วิศวกรรม | bug_report |
เอกสารประกอบ | bug_report |