I'm trying to call the function through the environment variableenv, namelyenv->FindClass("android/os/BatteryManager"), but eventually the error
F/libc (27883): Fatal signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x0 in tid 27883 (meerkat.rukkola), pid 27883 (meerkat.rukkola)*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***Build fingerprint: 'google/sdk_gphone64_x86_64/emu64xa:15/AE3A.240806.005/12228598:user/release-keys'Revision: '0'ABI: 'x86_64'Timestamp: 2025-08-08 12:01:41.442403800+0000Process uptime: 11sCmdline: com.nelset.meerkat.rukkolapid: 27883, tid: 27883, name: meerkat.rukkola >>> com.nelset.meerkat.rukkola <<<uid: 10254signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x0000000000000000Cause: null pointer dereference rax 0000000000000000 rbx 00007e848cb2efa0 rcx 00007e830a51c189 rdx 00007e848cb2efa0 r8 0000000000000400 r9 0000000000400010 r10 00007e848d206f90 r11 0000000000000000 r12 00007e848cdbbbdc r13 00007e8300008081 r14 00007e855d49b3f0 r15 00007e830a711721 rdi 00007ffe279b2c10 rsi 00007e848cb2e905 rbp 00007ffe279b30e0 rsp 00007ffe279b30c8 rip 00000000000000005 total framesbacktrace: #00 pc 0000000000000000 <unknown> #01 pc 0000000000000cf0 /data/app/~~a1Xqb36CA6Sv_f1JdZKm8Q==/com.nelset.meerkat.rukkola-l9SGe0rQMJa1u9lgl8wPFQ==/lib/x86_64/libbattery_info_ffi.so (_JNIEnv::FindClass(char const*)+32) (BuildId: d00d0ba3ecc382809f198710bd41789e3cfc5db1) #02 pc 0000000000000c2f /data/app/~~a1Xqb36CA6Sv_f1JdZKm8Q==/com.nelset.meerkat.rukkola-l9SGe0rQMJa1u9lgl8wPFQ==/lib/x86_64/libbattery_info_ffi.so (Java_com_example_battery_info_ffi_BatteryInfoFfiPlugin_getBatteryLevel+31) (BuildId: d00d0ba3ecc382809f198710bd41789e3cfc5db1) #03 pc 0000000000000fc0 /data/app/~~a1Xqb36CA6Sv_f1JdZKm8Q==/com.nelset.meerkat.rukkola-l9SGe0rQMJa1u9lgl8wPFQ==/lib/x86_64/libbattery_info_ffi.so (get_battery_level+32) (BuildId: d00d0ba3ecc382809f198710bd41789e3cfc5db1) #04 pc 0000000000006fea [anon:dart-code]Lost connection to device.comes out when processing the method.Code frombattery_info_android.cpp:
#include <jni.h>extern "C" JNIEXPORT jint JNICALLJava_com_example_battery_info_ffi_BatteryInfoFfiPlugin_getBatteryLevel(JNIEnv *env, jobject thiz){ // Получаем уровень заряда батареи через Android NDK jclass batteryManagerClass = env->FindClass("android/os/BatteryManager"); jmethodID getSystemService = env->GetStaticMethodID(batteryManagerClass, "getSystemService", "(Ljava/lang/String;)Ljava/lang/Object;"); jstring serviceName = env->NewStringUTF("batterymanager"); jobject batteryManager = env->CallStaticObjectMethod(batteryManagerClass, getSystemService, serviceName); jmethodID getIntMethod = env->GetMethodID(batteryManagerClass, "getIntProperty", "(I)I"); jint batteryLevel = env->CallIntMethod(batteryManager, getIntMethod, 4); // 4 = BATTERY_PROPERTY_CAPACITY return batteryLevel;}extern "C" JNIEXPORT jboolean JNICALLJava_com_example_battery_info_ffi_BatteryInfoFfiPlugin_isCharging(JNIEnv *env, jobject thiz){ // Проверяем, заряжается ли устройство return JNI_FALSE;}// Функции для Dart FFIextern "C" JNIEXPORT jint JNICALLget_battery_level(JNIEnv *env, jobject thiz, jobject context){ return Java_com_example_battery_info_ffi_BatteryInfoFfiPlugin_getBatteryLevel(env, thiz);}extern "C" JNIEXPORT jboolean JNICALLis_charging(JNIEnv *env, jobject thiz, jobject context){ return Java_com_example_battery_info_ffi_BatteryInfoFfiPlugin_isCharging(env, thiz);}Code fromBatteryInfoFfiPlugin.java:
package com.example.battery_info_ffi;import androidx.annotation.NonNull;import io.flutter.embedding.engine.plugins.FlutterPlugin;import io.flutter.plugin.common.MethodCall;import io.flutter.plugin.common.MethodChannel;import android.content.Context;import android.os.Looper;public class BatteryInfoFfiPlugin implements FlutterPlugin, MethodChannel.MethodCallHandler { private MethodChannel channel; private Context context; static { System.loadLibrary("battery_info_ffi"); } @Override public void onAttachedToEngine(@NonNull FlutterPluginBinding binding) { context = binding.getApplicationContext(); channel = new MethodChannel(binding.getBinaryMessenger(), "battery_info_ffi"); channel.setMethodCallHandler(this); } @Override public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) { channel.setMethodCallHandler(null); } @Override public void onMethodCall(@NonNull MethodCall call, @NonNull MethodChannel.Result result) { if (Looper.myLooper() == null) { Looper.prepare(); } try{ if (call.method.equals("getBatteryLevel")) { result.success(getBatteryLevel()); } if (call.method.equals("isCharging")) { result.success(isCharging()); } else { result.notImplemented(); } }catch(Exception e){ result.error("NATIVE_ERROR", e.getMessage(), null); } } public native int getBatteryLevel(); public native boolean isCharging();}Full project:battery_info
I tried to do this throughandroid.content.Context, passing it to native methods, but the result was no different, and similar errors were given. I also tried testing on other devices, with a different one, but the result is the same.
- 2
envis not an environment variable. There are nogetSystemServicemethod inandroid/os/BatteryManagerclass. ¿Perhaps you meant to useandroid.content.Context? Each JNI call requires appropriate error checking that this code lacks.user7860670– user78606702025-08-09 13:31:24 +00:00CommentedAug 9 at 13:31 - I've been working on this problem for a long time, but it has brought me a comprehensive understanding of how native programming works. If you call native methods via
_library.lookupFunction, the java file is bypassed and functions from c++ are called directly, while incorrect parameters are passed. I've redone it so that now the methods are called viaMethodChannel, and then the calls are intercepted in the Java file. With this approach, I pass all the parameters correctly, but I will need to learn how to intercept calls in ios and other platforms. All the changes are on gitgub.Dmitry– Dmitry2025-08-09 15:12:47 +00:00CommentedAug 9 at 15:12 - In addition your code misses error handling. E.g.
findClasscan returnNULLand I assumeGetStaticMethodIDwill returnNULL, too if the method does not exist.Robert– Robert2025-08-09 16:40:28 +00:00CommentedAug 9 at 16:40 - "If you call native methods via _library.lookupFunction, the java file is bypassed and functions from c++ are called directly, while incorrect parameters are passed. " That makes no sense and is not how JNI works. Especially since nothing in the Flutter package exists in JNI, it absolutely can't be how it works. MethodChannel may have something to do with communication with Flutter, but it does not with Java calling C or C++Gabe Sechan– Gabe Sechan2025-08-10 02:12:44 +00:00CommentedAug 10 at 2:12
- I would also suggest, if you're calling this via flutter to Java to C, to post the flutter end as wellGabe Sechan– Gabe Sechan2025-08-10 02:22:49 +00:00CommentedAug 10 at 2:22
Related questions
Related questions
