• Android JNI调用


    JNI(Java Native InterfaceJava本地接口),是用于实现Java与Native代码相互调用的编程框架。

    Native调用Java

    void ObjFunc_int_voidret(JNIEnv *env, jobject obj, const char *funcname, jint param)
    {
      jclass cls = (*env)->GetObjectClass(env, obj);
      jmethodID mid = (*env)->GetMethodID(env, cls, funcname, "(I)V");
      if (mid != 0)
      {
          (*env)->CallVoidMethod(env, obj, mid, param); // 调用obj对象的成员函数:void funcname(int param)
      }
    }
    
    void StaticFunc_string_string_voidret(JNIEnv *env, const char *classname, const char *funcname, jstring s1, jstring s2)
    {
      jclass cls = env->FindClass(classname);
      if (cls != 0)
      {
          jmethodID mid = (*env)->GetStaticMethodID(cls, funcname, "(Ljava/lang/String;Ljava/lang/String;)V");
          if (mid != 0)
          {
              (*env)->CallStaticVoidMethod(env, mid, s1, s2); // 调用classname类的静态成员函数:void funcname(string s1, string s2)
          }
      }
    }

    字符串格式为(arg-type;arg-type) ret-type。arg-type之间通过分号分割。

    JNI字段描述符(JavaNative Interface FieldDescriptors)  参考:JNI Types and Data Structures 

    Java类型 JNI类型 符号 备注
    void void V  
    boolean jboolean Z

    #define JNI_FALSE 0 
    #define JNI_TRUE 1

    byte jbyte B  
    char jchar C  
    short jshort S  
    int jint I typedef jint jsize; 
    long jlong J  
    float jfloat F  
    double jdouble D  
    boolean[] jbooleanArray [Z  
    byte[] jbyteArray [B  
    char[] jcharArray [C  
    short[] jshortArray [S  
    int[] jintArray [I

    JNIEnv *env;

    jintArray iarr = env->NewIntArray(5);

    jint tmp[5];
    for(int i = 0; i < 5; i++) {
       tmp[i] = i;
    }
    env->SetIntArrayRegion(iarr, 0, 5, tmp);

    long[] jlongArray [J  
    float[] jfloatArray [F  
    double[] jdoubleArray [D  
    byte[][]   [[B  
    int[][][]   [[[I  
    String   Ljava/lang/String;  
    String[]   [Ljava/lang/String;

    JNIEnv *env;

    char *data[5]= {"A", "B", "C", "D", "E"};
    jobjectArray sa= (jobjectArray)env->NewObjectArray(5,env->FindClass("java/lang/String"),env->NewStringUTF(""));
    for(int i=0;i<5;i++) {
        env->SetObjectArrayElement(sa,i,env->NewStringUTF(data[i]));
    }

    Class jclass Ljava/lang/Class; typedef jobject jclass;
    Object jobject Ljava/lang/Object;

    typedef _jobject *jobject; 
    typedef _jclass *jclass;

    Object[] jobjectArray [Ljava/lang/Object;  
    FileStatus   Landroid/os/FileUtils;  
    FileStatus为FileUtils的嵌套类   Landroid/os/FileUtils$FileStatus;  

    Java调用Native

    AndroidJavasrccomepicgamesue4GameActivity.java.template

    public class GameActivity extends NativeActivity implements SurfaceHolder.Callback2,
                                                                GoogleApiClient.ConnectionCallbacks,
                                                                GoogleApiClient.OnConnectionFailedListener,
                                                                SensorEventListener,
                                                                Logger.ILoggerCallback,
                                                                ComponentCallbacks2
    {
        // ... ...
        public native void nativeConsoleCommand(String commandString);
        
        public void cmdTest()
        {
            nativeConsoleCommand("god");
        }
    }

    LaunchAndroid.cpp

    //This function is declared in the Java-defined class, GameActivity.java: "public native void nativeConsoleCommand(String commandString);"
    JNI_METHOD void Java_com_epicgames_ue4_GameActivity_nativeConsoleCommand(JNIEnv* jenv, jobject thiz, jstring commandString)
    {
        FString Command = FJavaHelper::FStringFromParam(jenv, commandString);
        if (GEngine != NULL)
        {
            // Run on game thread to avoid race condition with DeferredCommands
            AsyncTask(ENamedThreads::GameThread, [Command]()
            {
                GEngine->DeferredCommands.Add(Command);
            });
        }
        else
        {
            FPlatformMisc::LowLevelOutputDebugStringf(TEXT("Ignoring console command (too early): %s"), *Command);
        }
    }

    注:#define JNI_METHOD __attribute__ ((visibility ("default"))) extern "C"

    UE4从Java传入命令行参数

    GameActivity.java.template

    public String AndroidThunkJava_GetExtraCommandLineArg()
    { 
        String extraArg = "";
        try 
        { 
            if (_extrasBundle != null)
            {
                extraArg = _extrasBundle.getString("extraArg");
            } 
        } 
        catch (Exception e) 
        {
            Log.debug("[JAVA] - AndroidThunkJava_GetExtraCommandLineArg exception " + e.toString());
        } 
    
                     
        //Log.debug("AndroidThunkJava_GetExtraCommandLineArg returning " + extraArg);
        return extraArg;
    }

    AndroidJNI.h

    class FJavaWrapper
    {
    public:
    
        // ... ...
        
        static jmethodID AndroidThunkJava_GetExtraCommandLineArg;
    
        // ... ...
    };

    AndroidJNI.cpp

    void FJavaWrapper::FindClassesAndMethods(JNIEnv* Env)
    {
        // ... ...
        AndroidThunkJava_GetExtraCommandLineArg = FindMethod(Env, GameActivityClassID, "AndroidThunkJava_GetExtraCommandLineArg", "()Ljava/lang/String;", bIsOptional);
        // ... ...
    }
    
    jmethodID FJavaWrapper::AndroidThunkJava_GetExtraCommandLineArg;
    
    FString AndroidThunkCpp_GetExtraCommandLineArg()
    {
        FString ExtraArg;
        if (JNIEnv* Env = FAndroidApplication::GetJavaEnv())
        {
            jstring extraArg = (jstring)FJavaWrapper::CallObjectMethod(Env, FJavaWrapper::GameActivityThis, FJavaWrapper::AndroidThunkJava_GetExtraCommandLineArg);
            if (!Env->IsSameObject(extraArg, NULL))
            {
                const char *nativeandroidextraArgString = Env->GetStringUTFChars(extraArg, 0);
                ExtraArg = FString(nativeandroidextraArgString);
                Env->ReleaseStringUTFChars(extraArg, nativeandroidextraArgString);
                Env->DeleteLocalRef(extraArg);
            }
        }
        return ExtraArg;
    }

    LaunchAndroid.cpp

    static void InitCommandLine()
    {
        // ... ...
    #if !UE_BUILD_SHIPPING
        {
            extern FString AndroidThunkCpp_GetExtraCommandLineArg();
    
    
            FString ExtraArg = AndroidThunkCpp_GetExtraCommandLineArg();
            if (!ExtraArg.IsEmpty())
            {
                FCommandLine::Append(TEXT(" "));
                FCommandLine::Append(*ExtraArg);
                FPlatformMisc::LowLevelOutputDebugStringf(TEXT("Extra Command Line Arg: %s"), *ExtraArg);
                UE_LOG(LogAndroid, Log, TEXT("Extra Command Line Arg: %"), *ExtraArg);
            } 
    }
    #endif
        // ... ...
    }

    带命令行参数来启动游戏

    adb.exe shell am start -e extraArg '-NoVerifyGC' -n com.tencent.mf.test1/com.epicgames.ue4.GameActivity

    adb.exe shell am start -e extraArg '-messaging -TcpMessagingConnect=10.168.0.95:7777 -SessionOwner=nicochen -SessionName=test1' -n com.tencent.mf.test1/com.epicgames.ue4.GameActivity

    扩展阅读:

    Java Programming Tutorial:Java Native Interface (JNI)

    JNI Functions

    JNIEnv Class 

    Java Native Interface Specification 

    https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/jniTOC.html

    https://docs.oracle.com/javase/8/docs/api/java/net/NetworkInterface.html

    https://docs.oracle.com/javase/9/docs/specs/jni/index.html 

    https://developer.android.com/reference/classes

    JNI 提示

    Android JNI原理分析

    java_net_NetworkInterface.cpp

    ndk-samples(github)

    libandroidjni(github)

    Android NDK学习--jni访问java层方法

    Android Stuido Ndk-Jni 开发(五):Jni回调java静态方法和非静态方法

    如何操作jni-String 

    Android NDK JNI 入门笔记-day03-引用数据类型

    Android NDK开发之JNI基础

    JNI的某些数组和字符串类型转换

    Developer Perspective: UE4 Logging and Console Commands for Mobile VR

    UE:UPL 与 JNI 调用的最佳实践 

  • 相关阅读:
    flash使用lua
    如何写出兼容大部分浏览器的CSS 代码
    typeof 详解
    人月神话阅读笔记(三)
    人月神话阅读笔记(二)
    仓库物资管理
    动手动脑(四)
    人月神话阅读笔记(一)
    动手动脑(六 文件操作)及课后作业
    java异常处理
  • 原文地址:https://www.cnblogs.com/kekec/p/12595607.html
Copyright © 2020-2023  润新知