求知 文章 文库 Lib 视频 iPerson 课程 认证 咨询 工具 讲座 Modeler   Code  
会员   
 
  
 
 
     
   
分享到
Unity3D研究之Android实现本地数据共享
 
火龙果软件    发布于 2013-9-13
 

开始本篇文章之前我先为大家简单的介绍一下Android NDK编程的原理, 我们知道Android开发使用JAVA语言来编程它的运行效率要比C/C++低很多,为了让JAVA语言可以调用 C/C++ 这时候NDK就出现了,使用DNK可以很方便的实现 JAVA 与 C/C++之间的互相调用。NDK的工作原理是使用谷歌提供的NDK工具将C/C++的代码编译成 .so文件,最后使用JAVA代码与.so文件之间相互调用。

下面我先说一下在Unity中结合Android NDK实现本地数据的共享的原理,如下图所示 ,Unity工程加入NDK后工程大致可分为三个部分 Android(JAVA) 、 C/C++(.so)、Unity(C#)它们之间是可以相互调用的,在之前的文章中我向大家介绍了 Android与Unity之间相互调用的原理,Unity3D研究院之打开Activity与调用JAVA代码传递参数(十八)。这种方式只能相互传递String字符串,少量数据传递时可以使用这种方式。如果是大量数据这样就有点限制了,其实我们可以把C/C++的代码做为一个中转站,实现两边的数据引用与共享。

首先在官网中下载NDK最新的安装包,安装包分为三个版本这里我下载使用的是MAC OS版本,最新版本已经到了R8。

下载地址:http://developer.android.com/sdk/ndk/index.html

OK,我们在Eclipse中创建一个Android工程,在res与src平级文件夹目录下创建一个jni的文件夹。接着在文件夹中创建两个代码文件,分别是C与C++还有一个配置文件Android.mk。

c.c代码一共分为两个方法,先说说方法Java_com_xys_UnityTestActivity_TestAddInt 这个方法是漏给Java代码调用的,jint表示此方法的返回值为整形,数据类型还可以是jlong 、jfloat、jdouble、 jobject、jboolean、jbyte、jchar、jshort,搞程序的一看就应该明白了吧?我就不一一解释了。 方法名中java开头是标准用法,com_xys表示当前程序的包名,UnityTestActivity表示当前类,TestAddInt表示方法名,在Android中就是调用这个方法的,这个方法实现了一个简单的整形相加的操作。在说说第二个方法int addInt(),这个方法是留给Unity中C#语言调用的,它的结构与上面不一样不能在Java代码中调用,同样它也就是实现整形相加的操作。

先是C的文件 c.c

[代码]c#/cpp/oc代码:

01	#include
02 #include
03
04 //Android中java代码调用此方法
05 jint
06 Java_com_xys_UnityTestActivity_TestAddInt( JNIEnv* env, jobject thiz ,jint a,jint b)
07 {
08 return addInt(a,b);
09 }
10
11 //Unity中C#代码调用此方法
12 int addInt(int a, int b)
13 {
14 return a + b;
15 }

在看看C++文件,它和C文件的调用原理差不多,不过值得注意的是C++中一定要把需要调用的方法写在extern “C”{ } 中,否则无法调用。

cplus.cpp

[代码]c#/cpp/oc代码:

01	#include
02 #include
03
04 //声明一个类
05 class MyClass
06 {
07 public:
08 static float add(float a, float b)
09 {
10 return a + b;
11 }
12
13 };
14
15 //外部调用的方法需要写在这里
16 extern "C"
17 {
18
19 jfloat
20 Java_com_xys_UnityTestActivity_TestAddFloat( JNIEnv* env, jobject thiz ,jfloat a,jfloat b)
21 {
22 return MyClass::add(a,b);
23 }
24
25 float addFloat(float a,float b)
26 {
27 return MyClass::add(a,b);
28 }
29
30 }

再看看第三个配置文件,文件中比较重要的两个变量 LOCAL_MODULE表示生成出的.so的名称 LOCAL_SRC_FILES 表示需要编译的文件,如果是多个C/C++文件中间需要使用 \ 隔开。

Android.mk

[代码]c#/cpp/oc代码:

01	LOCAL_PATH := $(call my-dir)
02
03 include $(CLEAR_VARS)
04
05 LOCAL_MODULE := xuanyusong
06 LOCAL_SRC_FILES := \
07 c.c \
08 cplus.cpp
09
10 include $(BUILD_SHARED_LIBRARY)

OK ,此时C/C++代码的准备工作就做完了,下面我们学习如何把c.c 与 cplus.cpp 一个C文件与一个C++文件一同打包进.so文件中。首先打开终端,cd到刚刚创建的jni目录下,然后执行一开始下载的DNK开发包中的ndk- build命令,你可以直接在android-ndk-r8中找到ndk-build然后拖拽到终端中即可,如果代码没有错误如图所示表示.so文件编译成功。

再看看当前Android工程的目录结构,libs -> armeabi -> libxuanyusong.so 就是刚刚编译生成的.so文件,xuanyusong.so前面的lib是系统默认添加的,大家不必惊慌。

下面我们编写Java代码,学习如何在java代码中调用C/C++,代码比较简单在OnCreat()方法中分别调用C与C++的方法,并且弹出一个Toast显示在界面中。

UnityTestActivity.java

[代码]java代码:

01	package com.xys;
02
03 import android.os.Bundle;
04 import android.widget.Toast;
05
06 import com.unity3d.player.UnityPlayerActivity;
07
08 public class UnityTestActivity extends UnityPlayerActivity
09 {
10
11 @Override
12 public void onCreate(Bundle savedInstanceState)
13 {
14 super.onCreate(savedInstanceState);
15
16 //在这里调用.so中的两个方法,并且显示在屏幕中
17 Toast.makeText(getApplicationContext(), "整形 = " + TestAddInt(1,2)+" 浮点型 = " + TestAddFloat(1.5f, 1.1f),
18 Toast.LENGTH_LONG).show();
19
20 }
21
22 //声明c.c中的TestAddInt方法
23 public native int TestAddInt(int a, int b);
24
25 //声明cplus.cpp中的TestAddFloat方法
26 public native float TestAddFloat(float a, float b);
27
28 static
29 {
30 //加载.so文件
31 System.loadLibrary("xuanyusong");
32 }
33
34 }

好的,我们终于把Android的工程建立完毕。接着我们需要把工程拷贝至Unity的Android插件中, 插件的制作还有谁不会?? 不会的朋友请看之前的文章,这里就不赘述。如下图所示,Android插件已经制作完毕放在Unity中。目录结构如下所示。

编写test.cs脚本,实现通过C#脚本直接访问libxuanyusong.so文件,直接把test.cs挂在摄像机上。使用 [DllImport ("xuanyusong")]来引入.so 的方法, 这里注意的是 一定要把.so文件名的lib 与后缀.so去掉, 最后将数据通过GUI显示在屏幕中。

test.cs

[代码]c#/cpp/oc代码:

01	using UnityEngine;
02 using System.Collections;
03 using System.Runtime.InteropServices;
04 public class test : MonoBehaviour {
05
06 int i = 0 ;
07 float f = 0.0f;
08
09 //引用C 、C++中的方法
10 [DllImport ("xuanyusong")]
11 private static extern int addInt(int a,int b);
12 [DllImport ("xuanyusong")]
13 private static extern float addFloat(float a,float b);
14
15 void Start ()
16 {
17 //调用方法中相加函数
18 i = addInt (1,2);
19 f = addFloat (1.0f,2.2f);
20
21 }
22
23 void OnGUI()
24 {
25
26 //将相加后的信息显示在屏幕中
27 if(i !=0)
28 GUILayout.Label(" use c =" + i );
29
30 if(f !=0.0f)
31 GUILayout.Label(" use cplus =" + f );
32 }
33 }

所有的工作已经做完,我们打包编译上真机,首先是在Android中调用.so时 弹出结果的Toast 。

然后是在Unity中调用.so后通过GUI绘制在屏幕中的结果。

 
相关文章

手机软件测试用例设计实践
手机客户端UI测试分析
iPhone消息推送机制实现与探讨
Android手机开发(一)
 
相关文档

Android_UI官方设计教程
手机开发平台介绍
android拍照及上传功能
Android讲义智能手机开发
相关课程

Android高级移动应用程序
Android系统开发
Android应用开发
手机软件测试
 
分享到
 
 


android人机界面指南
Android手机开发(一)
Android手机开发(二)
Android手机开发(三)
Android手机开发(四)
iPhone消息推送机制实现探讨
手机软件测试用例设计实践
手机客户端UI测试分析
手机软件自动化测试研究报告
更多...   


Android高级移动应用程序
Android应用开发
Android系统开发
手机软件测试
嵌入式软件测试
Android软、硬、云整合


领先IT公司 android开发平台最佳实践
北京 Android开发技术进阶
某新能源领域企业 Android开发技术
某航天公司 Android、IOS应用软件开发
阿尔卡特 Linux内核驱动
艾默生 嵌入式软件架构设计
西门子 嵌入式架构设计
更多...