gluonfx 在 graalvm 和 android 之间附加服务

gluonfx attach service between graalvm and android

这是我的胶子附加服务(在文件夹 native/android/dalvik/ 下)

package com.gluonhq.helloandroid;

import android.app.Activity;
import android.util.Log;

public class DalvikSmsService {
    private final Activity activity;

    public DalvikSmsService(Activity activity) {
        this.activity = activity;
    }

    public static void receiveSms(String phone, String sms) {
        processReceivedSms(phone, sms);
    }
    
    private native static void processReceivedSms(String key, String value);
}

对应的 JNI sms.c(在 native/android/c/ 下)文件如下

#include "util.h"

// ... other handle declarations ...

JNIEXPORT jint JNICALL 
JNI_OnLoad_sms(JavaVM *vm, void *reserved)
{
    ATTACH_LOG_INFO("JNI_OnLoad_sms called");
#ifdef JNI_VERSION_1_8
    JNIEnv* graalEnv;
    if ((*vm)->GetEnv(vm, (void **)&graalEnv, JNI_VERSION_1_8) != JNI_OK) {
        ATTACH_LOG_WARNING("sms error initializing native Sms from OnLoad");
        return JNI_FALSE;
    }
    ATTACH_LOG_FINE("[sms service] Initializing native Sms from OnLoad started");
    initializeGraalHandles(graalEnv);
    initializeDalvikHandles();
    ATTACH_LOG_FINE("[sms service] Initializing native Sms from OnLoad done");
    return JNI_VERSION_1_8;
#else
    #error Error: Java 8+ SDK is required to compile Attach
#endif
}

JNIEXPORT void JNICALL Java_com_gluonhq_helloandroid_DalvikSmsService_processReceivedSms 
(JNIEnv *env, jclass service, jstring jkey, jstring jvalue) 
{
 // ... additonal code not show ...
}

当我加载 apk 和 运行 应用程序时,短信服务被加载,但是 当我尝试调用 DalvikSmsService.receiveSms('', 'sample sms'); 方法被调用但出现以下错误 ...

AndroidRuntime: java.lang.UnsatisfiedLinkError: No implementation found for void com.gluonhq.helloandroid.DalvikSmsService.processReceivedSms(java.lang.String, java.lang.String) (tried Java_com_gluonhq_helloandroid_DalvikSmsService_processReceivedSms and Java_com_gluonhq_helloandroid_DalvikSmsService_processReceivedSms__Ljava_lang_String_2Ljava_lang_String_2)

构建输出结构...

来自 JNI (sms.c) 的调用:

static void initializeGraalHandles(JNIEnv* env) {
    ...
    jGraalReceiceSmsMethod = (*env)->GetStaticMethodID(env, jGraalSmsClass, "receiveSms", "(Ljava/lang/String;Ljava/lang/String;)V");
}

JNIEXPORT void JNICALL Java_com_gluonhq_helloandroid_DalvikSmsService_processReceivedSms
(JNIEnv *env, jclass service, jstring jkey, jstring jvalue)
{
    ...
    ATTACH_LOG_FINE("[sms service] call dalvik->native layer all got sms, key: %s, value: %s", keyChars, valueChars);
    ...
    (*graalEnv)->CallStaticVoidMethod(graalEnv, jGraalSmsClass, jGraalReceiceSmsMethod, jKeyChars, jValueChars);
    ...
}

至 Java (AndroidSmsService.java):

public static void receiveSms(String phone, String sms) {
    Platform.runLater(() -> messages.add(new Message(phone, sms)));
}

实际使用了反射。

目前调用该方法时,有一个SIGSEGV:

08-12 16:51:22.346 29215 29246 D GluonAttach: [sms service] Initializing native Sms from OnLoad started
08-12 16:51:22.346 29215 29246 D GraalGluon: ATTACH_DALVIK, tid = 29246, existed? 1, dalvikEnv at 0x7845064540
08-12 16:51:22.346 29215 29246 D GluonAttach: Util :: Load className com/gluonhq/helloandroid/DalvikSmsService
08-12 16:51:22.347 29215 29246 D GraalGluon: ATTACH_DALVIK, tid = 29246, existed? 1, dalvikEnv at 0x7845064540
08-12 16:51:22.351 29215 29246 I DalvikSmsService: sms receiced, phone: 123, sms: 456
08-12 16:51:22.351 29215 29246 D GluonAttach: [sms service] native layer got sms, key: 123, value: 456
08-12 16:51:22.351 29215 29246 D GraalGluon: ATTACH_GRAAL, tid = 29246, existed? 1, graalEnv at 0x7845064400
08-12 16:51:22.351 29215 29246 D GluonAttach: [sms service] call dalvik->native layer all got sms, key: 123, value: 456
--------- beginning of crash
08-12 16:51:22.352 29215 29246 F libc    : Fatal signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x20 in tid 29246 (Thread-3), pid 29215 (ples.hellogluon)
08-12 16:51:22.463 29410 29410 I crash_dump64: obtaining output fd from tombstoned, type: kDebuggerdTombstone
08-12 16:51:22.468   835   835 I /system/bin/tombstoned: received crash request for pid 29246
08-12 16:51:22.469 29410 29410 I crash_dump64: performing dump of process 29215 (target tid = 29246)
08-12 16:51:22.480 29410 29410 F DEBUG   : *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
08-12 16:51:22.480 29410 29410 F DEBUG   : Build fingerprint: 'google/marlin/marlin:10/QP1A.191005.007.A3/5972272:user/release-keys'
08-12 16:51:22.480 29410 29410 F DEBUG   : Revision: '0'
08-12 16:51:22.480 29410 29410 F DEBUG   : ABI: 'arm64'

为了防止崩溃,您只需要在 src/main/resources/META-INF/substrate/config/jniconfig-aarch64-android.json 下的 jniconfig-aarch64-android.json 文件中包含方法 receiveSms:

[
    {
        "name" : "org.jpereda.attach.sms.impl.AndroidSmsService",
        "methods":[
            {"name":"receiveSms","parameterTypes":["java.lang.String","java.lang.String"] }
        ]
    }
]

这对我适用于 GluonFX 1.0.4 和 Gluon 的 GraalVM 21.2.0。