Bu kılavuzda, Android API kitaplığı sarmalayıcının nasıl kullanılacağı açıklanmaktadır. Kitaplık sarmalayıcı komut satırı aracı, Java Android API'leri için C dili sarmalayıcı kodu oluşturarak Java kitaplıklarını yerel C/C++ Android uygulamalarına entegre etmenizi sağlar. Kitaplık sarmalayıcı hakkında daha fazla bilgi için Android API'leri için kitaplık sarmalayıcı bölümüne bakın.
Bu adım adım açıklamalı kılavuzda, Java kitaplığını yerel bir Android uygulamasına entegre etmek için sarmalayıcı aracının nasıl kullanılacağı gösterilmektedir. Örneğin, bu kılavuzda androidx.core.app
paketinin bildirim kitaplığının entegre edilmesi ele alınmaktadır.
Bu kitaplık hakkında daha fazla bilgi edinmek için Bildirim Oluşturma başlıklı makaleye bakın.
Ön koşullar
Bu kılavuzda, mevcut bir yerel Android projenizin olduğu varsayılmaktadır. Ayrıca Gradle derleme sistemini de kullanır. Mevcut bir projeniz yoksa Yerel C++ şablonunu kullanarak Android Studio'da yeni bir proje oluşturun.
Bu kılavuzdaki örnek kod my_project/
dizin kökünü kullanır. Yerel kod, Android Studio projeleri için varsayılan dizin olan my_project/app/src/main/cpp/
konumunda bulunur.
Kitaplık sarmalayıcı aracına sahip değilseniz paketi indirin ve istediğiniz dizine giden sıkıştırmasını açın. Bu CLI aracı için Java Runtime Ortamı (JRE) gerekir.
Yerel kod oluşturun
Java kitaplığı entegre ederken yerel kod sarmalayıcı oluşturmak için sarmalayıcı aracını kullanın. İlk adım, sarmalayıcıyı yapılandırmaktır.
Sarmalayıcı yapılandırmasını oluşturma
Yerel kod oluşturma aracının çıkışını kontrol etmek için kitaplık sarmalayıcı yapılandırma dosyaları oluşturursunuz. Bu dosyanın bir özelliği, sarmalayıcı kodu oluşturmak için sınıfları ve yöntemleri belirtmenize olanak tanır.
Bildirim kitaplığı için sarmalama yapılacak çok fazla yöntem olmadığından, bunları doğrudan custom_classes
bölümünde tanımlayabilirsiniz. Yöntemleri tanımlamak için projenizin herhangi bir yerinde yeni bir config.json
kaynağı oluşturun. Örneğin, my_project/library_wrapper/config.json
oluşturup aşağıdaki örnek yapılandırmayı yapıştırabilirsiniz:
{
"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)"
]
}
]
}
Önceki örnekte, yerel sarmalayıcı kodu gerektiren Java sınıflarını ve yöntemlerini doğrudan bildiriyorsunuz.
Kitaplık sarmalayıcıyı çalıştırma
Sarmalayıcı yapılandırma dosyanız tanımlanmışsa, yerel sarmalayıcı kodu oluşturmak için aracı kullanmaya hazırsınız demektir. Kitaplık sarmalayıcıyı çıkardığınız bir terminal penceresi açın ve aşağıdaki komutu çalıştırın:
java -jar lw.jar \
-o "my_project/app/src/main/cpp/native_wrappers" \
-c "my_project/library_wrapper/config.json"
Önceki örnekte, sarmalayıcı yapılandırma konumunuzu belirtmek için -c
parametresini ve oluşturulan kod dizinini tanımlamak için -o
parametresini kullanırsınız.
Aracı çalıştırdıktan sonra, yerel uygulamanızdan Java tabanlı Notifications API'yi çağırmak için gereken kodu elde etmiş olmanız gerekir.
Yerel bildirimleri uygulayın
Bu bölümde, oluşturulan sarmalayıcı kodunuzu kullanarak Android bildirim kitaplığını yerel uygulamanıza entegre edeceksiniz. İlk adım, projenizin uygulama düzeyindeki gradle.build
kaynağını (my_project/app/gradle.build
) güncellemektir.
gradle.build
uygulamasını güncelle
GNI, oluşturulan sarmalayıcı kodunun gerektirdiği bir destek kitaplığıdır. Oluşturulan kod kullanan tüm projeler bu kitaplığa başvurmalıdır. Bu kitaplığa referans vermek için aşağıdaki satırı
build.gradle
öğesinindependencies
bölümüne ekleyin:implementation 'com.google.android.gms:play-services-gni-native-c:1.0.0-beta2'
Prefab desteğini etkinleştirmek için aşağıdaki kodu
android
bölümüne ekleyin:buildFeatures { prefab true }
cmake
hizmetini yapılandırmak içinandroid/defaultConfig
bölümünde aşağıdakicmake
yapılandırmasını kullanın:externalNativeBuild { cmake { arguments '-DANDROID_STL=c++_shared' } }
Tamamlanmış build.gradle
yapılandırmanız aşağıdakine benzer şekilde görünmelidir:
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
öğesini değiştir
Dosyanın en üst seviyesine aşağıdaki satırı ekleyerek GNI kitaplığını projenizin
CMakeLists.txt
(my_project/app/src/main/cpp/CMakeLists.txt
) bölümüne ekleyin:find_package(com.google.android.gms.gni.c REQUIRED CONFIG)
Aşağıdaki satırı
target_link_libraries
bölümüne ekleyin:PUBLIC com.google.android.gms.gni.c::gni_shared
Aşağıdaki satırı dosyanın üst düzeyine ekleyerek oluşturulan koda bir referans ekleyin:
file(GLOB_RECURSE native_wrappers CONFIGURE_DEPENDS "native_wrappers/*.cpp" "native_wrappers/*.cc")
Dosyanın sonuna şu satırları ekleyin:
include_directories(./native_wrappers/c) include_directories(./native_wrappers/cpp)
Güncellenen CMakeLists.txt
kaynağınız şu örneğe benzeyecektir:
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)
Bildirim mantığını uygulayın
Bildirim özelliklerini uygulamak istediğiniz kaynak dosyayı açın veya oluşturun. Bu dosyaya
gni.h
başlık dosyasını ekleyin ve yeni birShowNativeNotification()
işlevi tanımlayın:#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); }
Bildirime özgü sabit değerleri ve bildirim işleyici işlevleri olan
CharSequenceFromCString()
veCreateNotification()
tanımlayın: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; }
Bildirim kitaplığının bazı işlevleri,
String
yerineCharSequence
öğesini kullanır.CharSequenceFromCString()
işlevi, bu nesneler arasında dönüştürme işlemi sağlar.CreateNotification()
işlevi, bildirim oluşturmak için Java'nınNotificationCompat.Builder
sarmalanmış sürümünü kullanır.Aşağıdaki işleve (
CreateNotificationChannel()
) yapıştırarak bildirim kanalı oluşturma mantığını ekleyin: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); }
Daha önce oluşturduğunuz
ShowNativeNotification()
işleviniCreateNotificationChannel()
çağırmak için güncelleyin.ShowNativeNotification()
öğesinin sonuna aşağıdaki kodu ekleyin: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); }
Mantığınız tanımlandıktan sonra, projenizde uygun bir konuma
ShowNativeNotification()
çağrısı yaparak bir bildirimi tetikleyin.
Uygulamayı çalıştırma
ShowNativeNotification()
kodunu çağıran kodu derleyip çalıştırın. Test cihazınızın ekranının üst kısmında basit bir bildirim görünür.
JAR'lerden sarmalayıcı oluşturma
Önceki örnekte, sarmalayıcı yapılandırma dosyasında yerel kod gerektiren Java sınıflarını ve yöntemlerini manuel olarak tanımlamıştınız. Bir API'nin büyük bölümlerine erişiminizin gerektiği senaryolarda sarmalayıcı aracına bir veya daha fazla kitaplık JAR'si sağlamak daha etkilidir. Sarmalayıcı daha sonra JAR'de bulduğu tüm genel semboller için sarmalayıcılar oluşturur.
Aşağıdaki örnekte, bir kitaplık JAR sağlayarak Notifications API'nin tamamı sarmalanmıştır.
Gerekli JAR'leri alın
Notification API, Google Maven deposunda bulunan androidx.core
paketinin bir parçasıdır. Kitaplık aar dosyasını indirin ve paketinden istediğiniz bir dizine açın. classes.jar
dosyasını bulun.
classes.jar
dosyası, gerekli bildirim kitaplığımızın dışında birçok sınıf içerir. Kitaplık sarmalayıcıya yalnızca classes.jar
sağlarsanız araç, JAR'deki her sınıf için yerel kod oluşturur. Bu, projemiz için verimsiz ve gereksizdir. Bu sorunu çözmek için, kod oluşturmayı JAR'ın bildirim sınıflarıyla kısıtlamak üzere sarmalayıcı yapılandırmasına bir filtre dosyası sağlayın.
İzin verme filtresi tanımlama
Filtre dosyaları, kitaplık sarmalayıcı yapılandırmanıza sağladığınız düz metin dosyalarıdır. Bunlar, kitaplık sarmalayıcıya sağlanan JAR dosyalarına dahil edilecek (veya hariç tutulacak) sınıfları tanımlamanıza olanak tanır.
Projenizde allowed-symbols.txt
adlı bir dosya oluşturun ve aşağıdaki satıra yapıştırın:
androidx.core.app.NotificationCompat*
İzin verme filtresi olarak kullanıldığında, önceki kod yalnızca adı androidx.core.app.NotificationCompat
ile başlayan simgelerin sarmalandığını belirtir.
Kitaplık sarmalayıcıyı çalıştırma
JAR dizinine giden bir terminal penceresi açın ve aşağıdaki komutu çalıştırın:
java -jar lw.jar \
-i classes.jar \
-o "./generated-jar" \
-c "./config.json" \
-fa allowed-symbols.txt \
--skip_deprecated_symbols
Yukarıdaki örnek komut, filtrelenen sınıflarınız için generated-jar/
dizininde sarmalayıcı kodu oluşturur.
Destek
Kitaplık sarmalayıcıyla ilgili bir sorun tespit ederseniz lütfen bize bildirin.
Hatalara göz at | Hata bildir |
---|---|
Mühendislik | bug_report |
Dokümanlar | bug_report |