创建Android插件 Building Plugins for Android

This page describes Native Code Plugins for android.

本页描述了为Android平台创建本地代码插件

Building a Plugin for Android 
为Andrid创建插件

To build a plugin for Android, you should first obtain the Android NDK and familiarize yourself with the steps involved in building a shared library.

为Android创建一个插件,你应该首先获得Android NDK然后按照自己熟悉的步骤建立一个共享库。

If you are using C++ (.cpp) to implement the plugin you must ensure the functions are declared with C linkage to avoid name mangling issues.

如果你正在使用C++(.cpp) 或者Objective-C(.mm)来实现一个插件,那么你必须要确保你创建的功能使用C linkage方式进行声明,以避免出现名称重整问题
[AppleScript]  纯文本查看  复制代码
?
1
2
3
extern "C" {
   float FooPluginFunction ( ) ;
}

Using Your Plugin from C#使用C#创建插件
Once built, the shared library should be copied to the Assets->Plugins->Android folder.  unity  will then find it by name when you define a function like the following in the C# script:-
插件创建好后,将插件放置在Unity工程文件中的Assets->Plugins->Android文件夹中。如果你在C#脚本中仿照以下的方式定义一个函数,Unity将根据你定义的名字找到对应的插件。
[AppleScript]  纯文本查看  复制代码
?
1
2
[DllImport ( "PluginName" ) ]
private static extern float FooPluginFunction ( ) ;
Please note that PluginName should not include the prefix ('lib') nor the extension ('.so') of the filename. It is advisable to wrap all native code methods with an additional C# code layer. This code should check Application.platform and call native methods only when the app is running on the actual device; dummy values can be returned from the C# code when running in the Editor. You can also use platform defines to control platform dependent code compilation.
请注意"PluginName"不应该包括lib前缀以及.so的后缀。。最好是将所有的本地代码的方法都包含在一个C#代码层中。这个代码层需要检查Application.platform并且仅在应用程序运行在真机上时才会调用本地代码方法;但在编辑器中运行时将返回一个虚拟值。您还可以使用平台定义来控制依赖于平台的代码编译。
Deployment 部署
For cross platform deployment, your project should include plugins for each supported platform (ie, libPlugin.so for Android, Plugin.bundle for Mac and Plugin.dll for Windows). Unity automatically picks the right plugin for the target platform and includes it with the player.
对于跨平台的部署,你的项目针对每个平台都有一个可支持的插件(ie,Android下libPlugin.so,Mac下Plugin.bundle,Windows下Plugin.dll)。Unity将根据平台自动匹配插件并将其导入到播放器中。
Using Java Plugins使用Java插件
The Android plugin mechanism also allows Java to be used to enable interaction with the Android OS.
Android插件机制允许使用Java与Android系统进行交互。
Building a Java Plugin for Android为Android创建Java插件
There are several ways to create a Java plugin but the result in each case is that you end up with a .jar file containing the .class files for your plugin. One approach is to download the JDK, then compile your .java files from the command line with javac. This will create .class files which you can then package into a .jar with the jar command line tool. Another option is to use the Eclipse IDE together with the ADT.
创建一个Java插件的方法有很多种,但最后的结果都是你的插件是一个包含了.class文件的.jar文件。一种方法是下载JDK然后使用javac命令行来编译你的.java文件。这样将生成一个由jar命令行打包好的包括了.class文件的.jar文件。另外一种方法是使用包含了ADT的的Eclipse IDE。
Using Your Java Plugin from Native Code从本机代码使用Java插件
Once you have built your Java plugin (.jar) you should copy it to the Assets->Plugins->Android folder in the Unity project. Unity will package your .class files together with the rest of the Java code and then access the code using the Java Native Interface (JNI). JNI is used both when calling native code from Java and when interacting with Java (or the JavaVM) from native code.
一旦你创建好了你的Java插件(.jar)你需要将插件拷贝到项目中的Assets-->Plugings-->Android文件夹中。Unity将你的.class文件与其Java代码的其余部分打包在一起,然后使用Java本地接口(JNI)访问本地代码。JNI用于Java调用本地代码以及本地代码与Java(或者是Java虚拟机)之间交互。
To find your Java code from the native side you need access to the Java VM. Fortunately, that access can be obtained easily by adding a function like this to your C/C++ code:
从本地端查找您的Java代码你需要访问Java虚拟机。幸运的是,将下面的功能加入到你的C/C++代码中可以轻松的访问:
[AppleScript]  纯文本查看  复制代码
?
1
2
3
4
jint JNI_OnLoad ( JavaVM * vm , void * reserved ) {
   JNIEnv * jni_env = 0 ;
   vm - > AttachCurrentThread ( & jni_env , 0 ) ;
}
This is all that is needed to start using Java from C/C++. It is beyond the scope of this document to explain JNI completely. However, using it usually involves finding the class definition, resolving the constructor (<init>) method and creating a new object instance, as shown in this example:-
这是所有通过C/C++开始Java使用的通用方法。它超出了本文关于JNI的解释范围。然而,使用它通常涉及到寻找类的定义、解决构造方法并创建一个新的对象实例,如下例所示:
[AppleScript]  纯文本查看  复制代码
?
1
2
3
4
5
6
jobject createJavaObject ( JNIEnv * jni_env ) {
   jclass cls_JavaClass = jni_env - > FindClass ( "com/your/java/Class" ) ;          / / find class definition
   jmethodID mid_JavaClass = jni_env - > GetMethodID ( cls_JavaClass , "<init>" ,  "()V" ) ;        / / find constructor method
   jobject obj_JavaClass = jni_env - > NewObject ( cls_JavaClass , mid_JavaClass ) ;      / / create object instance
   return jni_env - > NewGlobalRef ( obj_JavaClass ) ;                       / / return object with a global reference
}
Using Your Java Plugin with helper classes使用helper类的Java插件
AndroidJNIHelper and AndroidJNI can be used to ease some of the pain with raw JNI.
使用AndroidJNIHelper和AndroidJNI能够减少使用原生JNI的痛苦。
AndroidJavaObject and AndroidJavaClass automate a lot of tasks and also use cacheing to make calls to Java faster. The combination of AndroidJavaObject and AndroidJavaClass builds on top of AndroidJNI and AndroidJNIHelper, but also has a lot of logic in its own right (to handle the automation). These classes also come in a 'static' version to access static members of Java classes.
AndroidJavaObject和AndroidJavaClass能够自动化的完成很多任务也可以使用即时缓存以获得更快的Java访问。AndroidJavaObject和AndroidJavaClass的组合建立在AndroidJNI和AndroidJNIHelper的基础上,但有很多自己的逻辑(处理自动化)。这些类也有在"静态"版本中访问Java类的静态成员。
You can choose whichever approach you prefer, be it raw JNI through AndroidJNI class methods, or AndroidJNIHelper together with AndroidJNI and eventually AndroidJavaObject/AndroidJavaClass for maximum automation and convenience.
你可以选择任何你喜欢的方法,无论是通过AndroidJNI类的方法使用原生JNI,亦或是与AndroidJNI结合的AndroidJNIHelper用以达到最大的自动化和便利。
UnityEngine.AndroidJNI is a wrapper for the JNI calls available in C (as described above). All methods in this class are static and have a 1:1 mapping to the Java Native Interface. UnityEngine.AndroidJNIHelper provides helper functionality used by the next level, but is exposed as public methods because they may be useful for some special cases.
UnityEngine.AndroidJNI是一个提供给JNI访问C的封装(如上所述)。这个类所有的方法都是静态的并且与Java本地接口有1:1的映射关系。UnityEngine.AndroidJNI由下一级使用提供了辅助功能,但是他是作为一个公共方法暴露出来,因为他可能在某些特殊情况下非常有用。
Instances of UnityEngine.AndroidJavaObject and UnityEngine.AndroidJavaClass have a 1:1 mapping to an instance of java.lang.Object and java.lang.Class (or subclasses thereof) on the Java side, respectively. They essentially provide 3 types of interaction with the Java side:
UnityEngine.AndroidJavaObject 和 UnityEngine.AndroidJavaClass的实例,1:1分别映射到java的java.lang.Object 和 java.lang.Class的实例(或其子类),他们基本上提供了与Java端3种类型的互动:
Call a method 调用方法Get the value of a field 获取字段的值Set the value of a field 设置字段的值The Call is separated into two categories: Call to a 'void' method, and Call to a method with non-void return type. A generic type is used to represent the return type of those methods which return a non-void type. The Get and Set always take a generic type representing the field type.
该调用被分为两类:调用void的方法和调用non-void返回类型的方法。泛型类型用来表示这些方法的返回类型,返回non-void类型。Get和Set总是采用一个泛型类型来表示字段类型。
Example 1 示例1
[AppleScript]  纯文本查看  复制代码
?
1
2
3
4
5
6
7
8
9
/ / The comments describe what you would need to do if you were using raw JNI
  AndroidJavaObject jo = new AndroidJavaObject ( "java.lang.String" , "some_string" ) ;
  / / jni.FindClass ( "java.lang.String" ) ;
  / / jni.GetMethodID ( classID , "<init>" , "(Ljava/lang/String;)V" ) ;
  / / jni.NewStringUTF ( "some_string" ) ;
  / / jni.NewObject ( classID , methodID , javaString ) ;
  int hash = jo.Call < int > ( "hashCode" ) ;
  / / jni.GetMethodID ( classID , "hashCode" , "()I" ) ;
  / / jni.CallIntMethod ( objectID , methodID ) ;
Here, we're creating an instance of java.lang.String, initialized with a string of our choice and retrieving the hash value for that string.
这里,我们创建一个java.lang.String的实例,初始化我们选择的字符串并获取该字符串的哈希值。
The AndroidJavaObject constructor takes at least one parameter, the name of class for which we want to construct an instance. Any parameters after the class name are for the constructor call on the object, in this case the string "some_string". The subsequent Call to hashCode() returns an 'int' which is why we use that as the generic type parameter to the Call method.
AndroidJavaObject构造器需要至少一个参数,我们要构建一个实例的类名。类名之后的任何参数,用于对象构造函数的调用,在本例是“some_string”。随后调用hashCode()返回“int”,这就是为什么我们用作泛型类型参数的调用方法。
Note: You cannot instantiate a nested Java class using dotted notation. Inner classes must use the $ separator, and it should work in both dotted and slashed format. So android.view.ViewGroup$LayoutParams or android/view/ViewGroup$LayoutParams can be used, where a LayoutParams class is nested in a ViewGroup class.
注意:你不能使用句点来嵌套Java类。内部类必须使用$分隔符,并能工作于句点和斜线格式。所以android.view.ViewGroup$LayoutParams 或 android/view/ViewGroup$LayoutParams可以被使用,其中LayoutParams类是被嵌套在ViewGroup类中。
Example 2 示例2
One of the plugin samples above shows how to get the cache directory for the current application. This is how you would do the same thing from C# without any plugins:-
上述插件的例子,演示如何获取当前应用程序的缓存目录。这是在么以任何插件的情况下用C#做怎样做同样的事情:
[AppleScript]  纯文本查看  复制代码
?
01
02
03
04
05
06
07
08
09
10
11
12
13
14
AndroidJavaClass jc = new AndroidJavaClass ( "com.unity3d.player.UnityPlayer" ) ;
/ / jni.FindClass ( "com.unity3d.player.UnityPlayer" ) ;
AndroidJavaObject jo = jc.GetStatic < AndroidJavaObject > ( "currentActivity" ) ;
/ / jni.GetStaticFieldID ( classID , "Ljava/lang/Object;" ) ;
/ / jni.GetStaticObjectField ( classID , fieldID ) ;
/ / jni.FindClass ( "java.lang.Object" ) ;
 
Debug.Log ( jo.Call < AndroidJavaObject > ( "getCacheDir" ) .Call < string > ( "getCanonicalPath" ) ) ;
/ / jni.GetMethodID ( classID , "getCacheDir" , "()Ljava/io/File;" ) ; / / or any baseclass thereof!
/ / jni.CallObjectMethod ( objectID , methodID ) ;
/ / jni.FindClass ( "java.io.File" ) ;
/ / jni.GetMethodID ( classID , "getCanonicalPath" , "()Ljava/lang/String;" ) ;
/ / jni.CallObjectMethod ( objectID , methodID ) ;
/ / jni.GetStringUTFChars ( javaString ) ;
In this case, we start with AndroidJavaClass instead of AndroidJavaObject because we want to access a static member of com.unity3d.player.UnityPlayer rather than create a new object (an instance is created automatically by the Android UnityPlayer). Then we access the static field "currentActivity" but this time we use AndroidJavaObject as the generic parameter. This is because the actual field type (android.app.Activity) is a subclass of java.lang.Object, and any non-primitive type must be accessed as AndroidJavaObject. The exceptions to this rule are strings, which can be accessed directly even though they don't represent a primitive type in Java.
本例,我们开始用AndroidJavaClass取代AndroidJavaObject因为我们想访问静态com.unity3d.player.UnityPla成员而不是创建新的对象(通过Android UnityPlayer实例被自动创建)。然后我们访问静态字段currentActivity,但这时我们使用AndroidJavaObject作为泛型参数。这是因为实际字段类型(android.app.Activity)是java.lang.Object的子类,以及任何non-primitive type必须必须作为AndroidJavaObject访问。此规则的例外是字符串,它可以直接访问,即使即使他们并不代表Java的原始类型。
After that it is just a matter of traversing the Activity through getCacheDir() to get the File object representing the cache directory, and then calling getCanonicalPath() to get a string representation.
之后,它仅仅是一个遍历的问题,Activity通过getCacheDir()类获得表示缓存目录的File对象,然后调用getCanonicalPath()得到的字符串表示。
Of course, nowadays you don't need to do that to get the cache directory since Unity provides access to the application's cache and file directory with Application.temporaryCachePath and Application.persistentDataPath.
当然,现在你并不需要做,要获得缓存目录,Untiy提供了Application.temporaryCachePath 和 Application.persistentDataPath来访问应用程序的缓存和文件目录。
Example 3 示例3
Finally, here is a trick for passing data from Java to script code using UnitySendMessage.
最后,这里是一个从Java脚本代码使用UnitySendMessage传递数据的技巧。
[AppleScript]  纯文本查看  复制代码
?
01
02
03
04
05
06
07
08
09
10
11
12
13
14
using UnityEngine;
public class NewBehaviourScript : MonoBehaviour {
 
     void Start ( ) {
         JNIHelper.debug = true ;
         using ( JavaClass jc = new JavaClass ( "com.unity3d.player.UnityPlayer" ) ) {
             jc.CallStatic ( "UnitySendMessage" , "Main Camera" , "JavaMessage" , "whoowhoo" ) ;
         }
     }
 
     void JavaMessage ( string message ) {
         Debug.Log ( "message from java: " + message ) ;
     }
}
The Java class com.unity3d.player.UnityPlayer now has a static method UnitySendMessage, equivalent to the iOS UnitySendMessage on the native side. It can be used in Java to pass data to script code.
Java类com.unity3d.player.UnityPlayer现在有静态方法UnitySendMessage,相当于iOS本地端的UnitySendMessage。可用来在Java将数据传递到脚本代码。
Here though, we call it directly from script code, which essentially relays the message on the Java side. This then calls back to the native/Unity code to deliver the message to the object named "Main Camera". This object has a script attached which contains a method called "JavaMessage".
虽然这里,我们直接从脚本代码调用,其基本上在Java端中继该消息。然后回调到本地/Unity代码传递消息给名为“Main Camera”对象。这个对象附加了包含叫作“JavaMessage”方法的脚本。
Best practice when using Java plugins with Unity在Unity使用Java插件是最好的方法
As this section is mainly aimed at people who don't have comprehensive JNI, Java and Android experience, we assume that the AndroidJavaObject/AndroidJavaClass approach has been used for interacting with Java code from Unity.
本节主要针对那些没有全面了解JNI、Java和Android经验的人,我们假设AndroidJavaObject/ AndroidJavaClass方法从Unity已经使用与Java代码交互。
The first thing to note is that any operation you perform on an AndroidJavaObject or AndroidJavaClass is computationally expensive (as is the raw JNI approach). It is highly advisable to keep the number of transitions between managed and native/Java code to a minimum, for the sake of performance and also code clarity.
首先要注意的是在AndroidJavaObject 或 AndroidJavaClass上执行任何操作的运算是昂贵的(原始的JNI方法)。非常明智的是保持到最低限度的托管和本地/Java代码之间的转换,为了性能也为了代码简洁。
You could have a Java method to do all the actual work and then use AndroidJavaObject / AndroidJavaClass to communicate with that method and get the result. However, it is worth bearing in mind that the JNI helper classes try to cache as much data as possible to improve performance.
你应该有一个Java方法做所有的实际工作,然后使用AndroidJavaObject / AndroidJavaClass带有该方法进行通信,获得结果。然而值得铭记,JNI helper类尝试缓存尽可能多的数据来提高性能。
[AppleScript]  纯文本查看  复制代码
?
1
2
3
4
/ / The first time you call a Java function like
AndroidJavaObject jo = new AndroidJavaObject ( "java.lang.String" , "some_string" ) / / somewhat expensive
int hash = jo.Call < int > ( "hashCode" ) / / first time - expensive
int hash = jo.Call < int > ( "hashCode" ) / / second time - not as expensive as we already know the java method and can call it directly
The Mono garbage collector should release all created instances of AndroidJavaObject and AndroidJavaClass after use, but it is advisable to keep them in a using(){} statement to ensure they are deleted as soon as possible. Without this, you cannot be sure when they will be destroyed. If you set AndroidJNIHelper.debug to true, you will see a record of the garbage collector's activity in the debug output.
Mono垃圾收集器应该释放所有AndroidJavaObject 和 AndroidJavaClass使用后创建的实例,但仍然建议在using(){}语句保留他们,以确保他们尽快删除。没有这点,不能确保它们将被销毁。如果设置AndroidJNIHelper.debug为true,你将看到垃圾收集器的活动在调试输出的纪录。
[AppleScript]  纯文本查看  复制代码
?
1
2
3
4
5
6
7
8
9
/ / Getting the system language with the safe approach
void Start ( ) {
     using ( AndroidJavaClass cls = new AndroidJavaClass ( "java.util.Locale" ) ) {
         using ( AndroidJavaObject locale = cls.CallStatic < AndroidJavaObject > ( "getDefault" ) ) {
             Debug.Log ( "current lang = " + locale.Call < string > ( "getDisplayLanguage" ) ) ;
 
         }
     }
}
You can also call the .Dispose() method directly to ensure there are no Java objects lingering. The actual C# object might live a bit longer, but will be garbage collected by mono eventually.
你也可以调用.Dispose()方法直接确保没有Java对象代码。实际C#对象可以活得时间长一点,单最终由Mono垃圾回收。
Extending the UnityPlayerActivity Java Code扩展UnityPlayerActivity Java代码
With  unity android  it is possible to extend the standard UnityPlayerActivity class (the primary Java class for the Unity Player on Android, similar to AppController.mm on Unity iOS).
Unity Andriod可以扩展标准的UnityPlayerActivity类(在Android主Java类用于Unity播放器,在Unity iOS 类似于AppController.mm)。
An application can override any and all of the basic interaction between Android OS and Unity Android. You can enable this by creating a new Activity which derives from UnityPlayerActivity (UnityPlayerActivity.java can be found at /Applications/Unity/Unity.app/Contents/PlaybackEngines/AndroidPlayer/src/com/unity3d/player on Mac and usually at C:\Program Files\Unity\Editor\Data\PlaybackEngines\AndroidPlayer\src\com\unity3d\player on Windows).
应用程序可以覆盖任何和所有的Android操作系统和Unity Android之间的基本交互。你可以通过创新的从UnityPlayerActivity派生的活动,来启用这个。(在Mac系统UnityPlayerActivity.java 可以在/Applications/Unity/Unity.app/Contents/PlaybackEngines/AndroidPlayer/src/com/unity3d/player 找到,Windows系统通常在 C:\Program Files\Unity\Editor\Data\PlaybackEngines\AndroidPlayer\src\com\unity3d\player ).
To do this, first locate the classes.jar shipped with Unity Android. It is found in the installation folder (usually C:\Program Files\Unity\Editor\Data (on Windows) or /Applications/Unity (on Mac)) in a sub-folder called PlaybackEngines/AndroidPlayer/bin. Then add classes.jar to the classpath used to compile the new Activity. The resulting .class file(s) should be compressed into a .jar file and placed in the Assets->Plugins->Android folder. Since the manifest dictates which activity to launch it is also necessary to create a new AndroidManifest.xml. The AndroidManifest.xml file should also be placed in the Assets->Plugins->Android folder.
要做到这点,首先找到Unity Android附带的classes.jar。在安装文件夹的 (在Windows通常是在 C:\Program Files\Unity\Editor\Data,在Mac是在 /Applications/Unity)PlaybackEngines/AndroidPlayer/bin只文件夹中找到。然后添加classes.jar到类路径用于编译新的活动。由此产生的.class文件应该被压缩到一个.jar文件中和并放置在Assets->Plugins->Android文件夹。由于清单决定要启动哪个活动,还需要建立一个新的AndroidManifest.xml。AndroidManifest.xml文件也放置在Assets->Plugins->Android文件夹。
The new activity could look like the following example, OverrideExample.java:
新的活动,看起来像下面的例子,OverrideExample.java:
[AppleScript]  纯文本查看  复制代码
?
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package com. company .product;
 
import com.unity 3 d.player.UnityPlayerActivity;
 
import android.os.Bundle;
import android.util.Log;
 
public class OverrideExample extends UnityPlayerActivity {
 
   protected void onCreate ( Bundle savedInstanceState ) {
 
     / / call UnityPlayerActivity.onCreate ( )
     super.onCreate ( savedInstanceState ) ;
 
     / / print debug message to logcat
     Log.d ( "OverrideActivity" , "onCreate called!" ) ;
   }
 
   public void onBackPressed ( )
   {
     / / instead of calling UnityPlayerActivity.onBackPressed ( ) we just ignore the back button event
     / / super.onBackPressed ( ) ;
   }
}
And this is what the corresponding AndroidManifest.xml would look like:
并添加相应的AndroidManifest.xml,像这样:
[AppleScript]  纯文本查看  复制代码
?
01
02
03
04
05
06
07
08
09
10
11
12
13
< ?xml version = "1.0" encoding = "utf-8" ? >
< manifest xmlns : android = "http://schemas.android.com/apk/res/android" package = "com.company.product" >
   < application android : icon = "@drawable/app_icon" android : label = "@string/app_name" >
     < activity android : name = ".OverrideExample"
               android : label = "@string/app_name"
               android : configChanges = "fontScale|keyboard|keyboardHidden|locale|mnc|mcc|navigation|orientation|screenLayout|screenSize|smallestScreenSize|uiMode|touchscreen" >
         < intent - filter >
             < action android : name = "android.intent.action.MAIN" / >
             < category android : name = "android.intent.category.LAUNCHER" / >
         < / intent - filter >
     < / activity >
   < / application >
< / manifest >
UnitPlayerNativeActivity
It is also possible to extend the UnityPlayerNativeActivity to reduce input latency. But be aware that NativeActivity was introduced in Gingerbread and does not work with older devices. Since touch/motion events are processed in native code java views would normally not see those events. There is however a forwarding mechanism in unity which allows events to be propagated to the DalvikVM. You need to set unityplayer.ForwardNativeEventsToDalvik to true to turn this feature on.
也可以扩展UnityPlayerNativeActivity来减少输入延迟。但要注意,NativeActivity在Gingerbread被引入,但在老设备并不工作。因为touch/motion事件在本地代码被处理,Java视图通常不会看到这些事件。然而,Unity有一个的转发机制,允许事件传递到DalvikVM。你需要设置unityplayer.ForwardNativeEventsToDalvik为true,来开启此功能。
[AppleScript]  纯文本查看  复制代码
?
1
2
3
4
5
6
7
< ?xml version = "1.0" encoding = "utf-8" ? >
< activity android : name = "com.unity3d.player.UnityPlayerNativeActivity"
           android : label = "@string/app_name"
           android : configChanges = "fontScale|keyboard|keyboardHidden|locale|mnc|mcc|navigation|orientation|screenLayout|screenSize|smallestScreenSize|uiMode|touchscreen" >
   < meta - data android : name = "android.app.lib_name" android : value = "unity" / >
   < meta - data android : name = "unityplayer.ForwardNativeEventsToDalvik" android : value = "false" / >
< / activity >

Examples 示例

Native Plugin Sample 
本地插件示例

A simple example of the use of a native code plugin can be found here

可以在这里找到一个简单的使用一个本地代码插件例子。

This sample demonstrates how C code can be invoked from a Unity Android application. The package includes a scene which displays the sum of two values as calculated by the native plugin. Please note that you will need the Android NDK to compile the plugin.

此示例演示C代码如果从Unity Android应用程序调用。该包包括一个场景,显示通过本地插件计算两个值的总和。请注意,您需要Android NDK来编译插件。

Java Plugin Sample
Java插件示例

An example of the use of Java code can be found here

在这里找到使用使用Java代码的一个例子。

This sample demonstrates how Java code can be used to interact with the Android OS and how C++ creates a bridge between C# and Java. The scene in the package displays a button which when clicked fetches the application cache directory, as defined by the Android OS. Please note that you will need both the JDK and the Android NDK to compile the plugins.

此示例演示Java代码与Android系统如何交互以及C++如何创建C#和Java之间的桥梁。包中的场景显示一个按钮,当点击它读取应用程序的缓存目录,由Android操作系统定义。请注意,你将需要JDK和Android NDK来编译此插件。

Here is a similar example but based on a prebuilt JNI library to wrap the native code into C#.

这里是一个类似的例子,但基于prebuilt JNI库来打包本地代码到C#。
  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值