इस गाइड में Android API लाइब्रेरी रैपर को इस्तेमाल करने का तरीका बताया गया है. लाइब्रेरी रैपर कमांड-लाइन टूल, Java Android के लिए C-भाषा का रैपर कोड जनरेट करता है एपीआई की मदद से, Java लाइब्रेरी को नेटिव C/C++ Android ऐप्लिकेशन के साथ इंटिग्रेट किया जा सकता है. लाइब्रेरी रैपर के बारे में ज़्यादा जानकारी के लिए, इसे देखें Android APIs के लिए लाइब्रेरी रैपर.
इस सिलसिलेवार निर्देश में बताया गया है कि कैसे रैपर टूल का इस्तेमाल करके
Java लाइब्रेरी को खास Android ऐप्लिकेशन में जोड़ें. उदाहरण के लिए, इस गाइड में
androidx.core.app
पैकेज की सूचना लाइब्रेरी को इंटिग्रेट करना.
इस लाइब्रेरी के बारे में ज़्यादा जानने के लिए, सूचना बनाएं देखें.
ज़रूरी शर्तें
इस गाइड में यह माना गया है कि आपके पास पहले से एक नेटिव Android प्रोजेक्ट है. यह भी Gradle बिल्ड सिस्टम का इस्तेमाल करता है. अगर आपके पास कोई मौजूदा प्रोजेक्ट नहीं है, तो Android Studio में नेटिव C++ टेंप्लेट का इस्तेमाल करके नया प्रोजेक्ट बनाएं.
इस गाइड में उदाहरण के तौर पर दिया गया कोड, डायरेक्ट्री रूट my_project/
का इस्तेमाल करता है. नेटिव लेआउट
कोड my_project/app/src/main/cpp/
में मौजूद है, जो इसकी डिफ़ॉल्ट डायरेक्ट्री है
Android Studio प्रोजेक्ट.
अगर आपके पास पहले से लाइब्रेरी रैपर टूल नहीं है, तो फ़ाइल को डाउनलोड करें और अनज़िप करें अपनी पसंद की डायरेक्ट्री में जोड़ें. इस सीएलआई टूल के लिए Java रनटाइम की ज़रूरत है एनवायरमेंट (जेआरई).
नेटिव कोड जनरेट करें
Java लाइब्रेरी को इंटिग्रेट करते समय, रैपर टूल का इस्तेमाल करके कोई नेटिव कोड रैपर जनरेट करें. सबसे पहला चरण है रैपर कॉन्फ़िगर करना.
रैपर कॉन्फ़िगरेशन बनाएं
लाइब्रेरी रैपर कॉन्फ़िगरेशन फ़ाइलें बनाई जा सकती हैं, ताकि नेटिव कोड जनरेटर का आउटपुट. इस फ़ाइल की एक सुविधा से, आपको यह तय करने की सुविधा मिलती है कि रैपर कोड जनरेट करने की क्लास और तरीके.
चूंकि नोटिफ़िकेशन लाइब्रेरी को रैप करने के ज़्यादा तरीके नहीं हैं, इसलिए आप
इन्हें सीधे 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)"
]
}
]
}
पिछले सैंपल में, आपने सीधे तौर पर उन Java क्लास और तरीकों के बारे में बताया है जो को नेटिव रैपर कोड की ज़रूरत है.
लाइब्रेरी रैपर चलाएं
आपकी रैपर कॉन्फ़िगरेशन फ़ाइल तय होने के बाद, अब आप टूल का इस्तेमाल करके नेटिव रैपर कोड शामिल करें. वहां से एक टर्मिनल खोलें जहां से आपने लाइब्रेरी रैपर निकाला था और इन कमांड को चलाएं:
java -jar lw.jar \
-o "my_project/app/src/main/cpp/native_wrappers" \
-c "my_project/library_wrapper/config.json"
पिछले सैंपल में, रैपर तय करने के लिए -c
पैरामीटर का इस्तेमाल किया जाता है
कॉन्फ़िगरेशन लोकेशन और -o
पैरामीटर की मदद से, जनरेट की गई कोड डायरेक्ट्री को शामिल किया जा सकता है.
टूल चलाने के बाद, अब आपके पास
आपके खास ऐप्लिकेशन का Java-आधारित नोटिफ़िकेशन API.
नेटिव सूचनाएं लागू करें
इस सेक्शन में, Android की सूचना लाइब्रेरी को
नेटिव ऐप्लिकेशन के लिए तैयार किया गया है. सबसे पहले अपनी साइट का
प्रोजेक्ट के ऐप्लिकेशन-लेवल का gradle.build
संसाधन (my_project/app/gradle.build
).
gradle.build
को अपडेट करें
GNI एक सहायता लाइब्रेरी है, जो जनरेट किए गए रैपर कोड के लिए ज़रूरी है. सभी प्रोजेक्ट तो जनरेट किए गए कोड का उपयोग करने से इस लाइब्रेरी का संदर्भ होना चाहिए. इस लाइब्रेरी का संदर्भ देने के लिए,
build.gradle
केdependencies
सेक्शन में यह लाइन जोड़ें:implementation 'com.google.android.gms:play-services-gni-native-c:1.0.0-beta2'
प्रीफ़ैब सहायता चालू करने के लिए,
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
में बदलाव करें
अपने प्रोजेक्ट के
CMakeLists.txt
में GNI लाइब्रेरी जोड़ें (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()
को कॉल करने वाले कोड को कंपाइल करें और चलाएं. आसान
सूचना, आपके टेस्ट डिवाइस की स्क्रीन पर सबसे ऊपर दिखनी चाहिए.
JAR से रैपर जनरेट करें
पिछले उदाहरण में, आपने मैन्युअल रूप से Java की क्लास तय की है और किसी रैपर कॉन्फ़िगरेशन फ़ाइल में नेटिव कोड की ज़रूरत के लिए तरीके. ऐसी स्थितियों के लिए जहां आपको को एपीआई के बड़े सेक्शन ऐक्सेस करने की ज़रूरत होती है, ताकि रैपर टूल में ज़्यादा लाइब्रेरी JAR जोड़ें. इसके बाद रैपर, में मिलने वाले सभी सार्वजनिक चिह्नों का इस्तेमाल करें.
नीचे दिए गए उदाहरण में एक लाइब्रेरी देकर, पूरे Notifications API को शामिल किया गया है जापान.
ज़रूरी JAR पाएं
सूचना एपीआई, androidx.core
पैकेज का हिस्सा है. यह यहां उपलब्ध है
Google Maven रिपॉज़िटरी. लाइब्रेरी aar फ़ाइल डाउनलोड करें और उसे अनपैक करें
अपनी पसंद की डायरेक्ट्री पर क्लिक करें. classes.jar
फ़ाइल ढूंढें.
classes.jar
फ़ाइल में हमारी ज़रूरी सूचनाओं के अलावा, और भी कई क्लास हैं
लाइब्रेरी. अगर आप सिर्फ़ classes.jar
में लाइब्रेरी रैपर देते हैं, तो यह टूल
JAR में हर क्लास के लिए नेटिव कोड जनरेट करता है, जो कि
हमारे प्रोजेक्ट के लिए गैर-ज़रूरी है. इसे हल करने के लिए,
रैपर कॉन्फ़िगरेशन, जो JAR की सूचना में कोड जनरेट करने से रोकता है
क्लास.
अनुमति वाला फ़िल्टर तय करें
फ़िल्टर फ़ाइलें सादे टेक्स्ट वाली ऐसी फ़ाइलें होती हैं जो आपकी लाइब्रेरी के रैपर में दी जाती हैं कॉन्फ़िगरेशन. इनकी मदद से, यह तय किया जा सकता है कि किन क्लास को शामिल करना है या कौनसा नहीं .
अपने प्रोजेक्ट में, allowed-symbols.txt
टाइटल वाली फ़ाइल बनाएं और उसमें
नीचे दी गई लाइन:
androidx.core.app.NotificationCompat*
अनुमति वाले फ़िल्टर के तौर पर इस्तेमाल करने पर, ऊपर दिया गया कोड बताता है कि सिर्फ़ सिंबल
जिनका नाम androidx.core.app.NotificationCompat
से शुरू होता है, उसे रैप किया गया है.
लाइब्रेरी रैपर चलाएं
JAR डायरेक्ट्री के लिए कोई टर्मिनल खोलें और यह कमांड चलाएं:
java -jar lw.jar \
-i classes.jar \
-o "./generated-jar" \
-c "./config.json" \
-fa allowed-symbols.txt \
--skip_deprecated_symbols
पिछला सैंपल कमांड, आपकी फ़िल्टर की गई क्लास के लिए रैपर कोड जनरेट करता है
generated-jar/
डायरेक्ट्री में.
सहायता
अगर आपको लाइब्रेरी रैपर में कोई समस्या मिलती है, तो कृपया हमें बताएं.
गड़बड़ियां ब्राउज़ करें | गड़बड़ी की शिकायत करें |
---|---|
इंजीनियरिंग | bug_report |
दस्तावेज़ | bug_report |