首页 > 代码库 > Unity3d Android SDK接入解析(二)Unity3d Android SDK的设计与两种接入方式

Unity3d Android SDK接入解析(二)Unity3d Android SDK的设计与两种接入方式

一、前言


上篇说清楚了Unity和Android调用的方式,但很多实际接入的部分没有讲的很详细,因为重头在这篇,会详细讲述具体接入Android SDK的方式,和怎么去做一个方便Unity接入的SDK。

传送门:
前篇:Unity3d 与 Android之间的互相调用
http://blog.csdn.net/yang8456211/article/details/51331358
后篇:Unity3d Android SDK接入解析(三)接入Android Library的理解
http://blog.csdn.net/yang8456211/article/details/51435465

二、中篇:Unity3d Android SDK的设计与两种接入方式


(Android SDK的接入一般分为两种)

1)一种是把Unity的工程导出google project的形式进行接入
2)另一种是通过把Android的工程做成Plugins的形式进行接入

对比:

类别(形式) google project U3d Plugins
优点 容易理解、方便接入原生SDK、几乎所有SDK都可以接入 接入方便、容易在Unity中进行扩展与管理
缺点 接入比较繁琐,对U3d项目不友好 不是所有SDK都提供U3d Plugins形式
apk导出 Android IDE导出 Unity 导出

建议:

如果做一个sdk,还是推荐分开Android形式的SDK(可以是Library),与Unity3d形式的SDK(Plugins),因为一般项目会有自己的SDK架构,而让他们打破这个架构,导出Google project的形式进行接入,这无疑是很难被接受的。

下面我们就来说一下具体的操作:

首先我们会自己写一个SDK,并说明白其中的注意点,然后会用两种方式接入这个SDK。

2.1 一个简单Android SDK

这个SDK实现几个小功能,实现四个方法:

  • init方法,用来传入上下文
  • 传入两个数返回他们的和
  • 传入msg,弹出一个Toast提示
  • 弹出一个提示窗口,窗口需要的文字信息从strings.xml里面获取,点击确认关闭

先回答一个可能困惑大家问题:

1)实现SDK时一定要存在一个中间件Activity继承UnityPlayerActivity吗?

网上几乎所有教程都是这样教的,新建一个MyActivity,然后继承UnityPlayerActivity,在MyActivity里面写接口,然而根本没有讲清楚为什么要这样做。。

有关于这种方式的一些研究请看前篇:
http://blog.csdn.net/yang8456211/article/details/51331358。

2)让我们抛弃MyActivity吧

对于1)的问题,答案是NO,简单说一下我的理解,只有当需要在Activity的生命周期中执行一些操作时,我们才需要一个中间Activity去完成这些与生命周期相关的操作,而其他情况下,一个Class足以。那就让我们开始吧:

  • 新建一个Android Project callAndroid

    技术分享

  • 删除其中MainActivity和activity_main.xml
    技术分享

  • 新建一个Java class 取名CallMethod,写好上述四个方法。(可以自己先写写,然后看跟我写的有什么不一样)

public class CallMethod {
    private static Context unityContext;
    private static Activity unityActivity;
    private static AlertDialog.Builder alert;

    //init方法,用来传入上下文    
    public static void init(Context paramContext){
        unityContext = paramContext.getApplicationContext();
        unityActivity = (Activity) paramContext;
    }

    //传入两个数返回他们的和
    public static int add(int arg0, int arg1){
        return arg0 + arg1;
    }

    //传入msg,弹出一个Toast提示
    public static void showMessage(final String msg){

        unityActivity.runOnUiThread(new Runnable()
        {    
            public void run()    
            {    
                Toast.makeText(unityContext,msg, Toast.LENGTH_LONG).show();
            }
        });

    }

    //弹出一个提示窗口,窗口需要的文字信息从strings.xml里面获取,点击确认关闭
    public static void showAlertView(){

        alert = new AlertDialog.Builder(unityActivity).setTitle("弹出窗口").setMessage(unityContext.getResources().getIdentifier("msgAlert", "string", unityContext.getPackageName())).setPositiveButton("确认", new DialogInterface.OnClickListener() {

            @Override
            public void onClick(DialogInterface arg0, int arg1) {
                // TODO Auto-generated method stub
                unityActivity.finish();
            }
        });


        unityActivity.runOnUiThread(new Runnable()    
        {    
            public void run()    
            {    
                alert.show();
            }
        });
    }
}

这一小段代码,含金量可不小,能解决绝大部分你所遇到的问题~

1. 不使用Activity,那Activity上下文怎么来?

使用init的方法让Unity传当前上下文进来,我们就能拿到当前的Activity和应用上下文。(至于Unity怎么拿上下文,前篇我没有明确指出,但是我是有提的~请保持思考!)

2. 怎么弹出窗口?怎么对界面进行操作?

Unity调用Android方法默认不是在UI主线程上执行的,所以如果你想要对UI界面进行操作,那就要使用runOnUiThread才行。

3. 使用Plugins接入的时候,怎么才能读到R的资源?

这个问题困扰了我挺久的,因为直接把libs放入到Plugins中会导致读取不到资源,最后是通过反编译各种第三方SDK,才找到方法。此处是通过unityContext.getResources().getIdentifier(“msgAlert”, “string”, unityContext.getPackageName())这种java反射机制获取。(这里是获取了一个string,类比其他)

4. 只能使用静态方法吗?

当然不是,也可以使用实例方法,只是静态方法更容易调用,想要使用实例方法,我们可以创建一个单例,然后使用这个单例去调用实例方法。

    private static CallMethod invokeSingleTon = null;

    public static CallMethod getInvokeClass(){
        if (invokeSingleTon == null){
            invokeSingleTon = new CallMethod();
        }
        return invokeSingleTon;
    }

    public void sayhello(){
        //方法内容
    }

3)怎么发布我们的SDK呢?

此时我们就已经写好了我们的SDK,这个SDK比较健壮,怎么发布都行,可以勾上isLibrary以Android的库文件的形式进行发布;也可以分离出jar和res,以代码和资源的方式进行发布。

2.2 一个简单Unity工程

在写完AndroidSDK之后,我们简单的写一个Unity的工程,用来调用Android设置的接口。

  • 首先建立一个空的Unity工程,命名为UnityCall
  • 选中摄像机MainCamera,新建一个CS脚本callAnd
    技术分享

  • 绑定到Main Camera
    选中Main Camera,在add component的地方,选择刚才写的callAnd脚本

    技术分享

cs脚本的代码:

    AndroidJavaClass unityPlayer;
    AndroidJavaObject currentActivity;
    AndroidJavaClass androidCall;

    void Start () {
        //获取context
        unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
        currentActivity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity");
        androidCall = new AndroidJavaClass("com.atany.callandroid.CallMethod");
        androidCall.CallStatic("init",currentActivity);
    }

    void Update () {
    }

    void OnGUI()  
    {  
        GUI.skin.textArea.fontSize = 50;
        GUI.skin.button.fontSize = 50;

        // add
        if(GUI.Button(new Rect(100,300,450,300),"add"))  
        {  
            int sum = androidCall.CallStatic<int>("add",1,2);
            print ("sum is "+ sum);
        } 

        // showMessage
        if(GUI.Button(new Rect(600,300,450,300),"showMessage"))
        {
            androidCall.CallStatic("showMessage","显示这一段的文字");           
        }

        // showAlertView
        if(GUI.Button(new Rect(100,700,450,300),"showAlertView"))
        {
            androidCall.CallStatic("showAlertView");            
        }
    }

画了三个button,用于调用我们设置好的Android三个不同的功能。

2.3 导出Android工程进行接入

首先呢,我们就先试一试导出Android工程的接入形式,把我们的Unity工程导出,然后接入我们的Android SDK。

  • 导出Android 工程(快捷键 Shift+Ctrl+b调出Build Settings)

    技术分享

  • 导入到IDE 这里使用eclipse,当然Idea也是一样的
    技术分享

注意:这里一定要选Existing Android Code Into Workspace,不要选Existing projects into Workspace

  • 我们把Android SDK打成jar+res(就一个stringnew.xml)的形式发布,加入到Unity导出的工程中。
    技术分享

-可以看到,我们就加入了两个东西,一个jar和一个xml,让我们跑起来看看效果

add:
点击add成功收到Unity3d打印的返回值。
技术分享

showMessage:
点击showMessage,成功在当前界面显示了toast。
技术分享

showAlertView:
点击showAlertView,成功在界面弹出了对话框
技术分享

OK,到这里我使用导出google project的方法实现的android sdk的接入!也说明我们的资源读取的方式是正确的(取到stringnew里面的字符串资源),能够弹出对话框和Toast就意味着你能够实现各种可视化的界面操作。接着,我们看看怎么使用Unity插件的形式进行接入。

2.4 使用Unity插件形式进行接入

这种形式更加简单,简而言之就是以U3d要求的一种形式放好你的资源和jar包,然后就能够运行了~

  • 构建Plugins的形式
    我们还是用之前新建的U3d的工程,记得开始的时候我们只添加了一个脚本,现在我们要在assets下面建立如下的结构:

    技术分享

    Plugins:assets 下的根目录(下面可能有Android或者IOS)
    Android:主目录
    bin:放中间件的工程(我们没有建立MyActivity的中间件,如果有的话放在这里)
    libs:放所有jar包
    res:放所需要的资源
    
  • 放入我们刚导出的Android SDK的libs和res
    技术分享

注意:
1.callAndroid的jar是放在libs里面的,stringnew这个xml是放在values里面的,我是通过多选让大家看看我添加的所有文件
2.如果bin里面有加入中间件MyActivity,或者有需要添加的权限以及Android的组件,需要放入AndroidManifest到Android目录下。

  • 运行效果和导出google project的效果是一样的,我就不重新贴图贴一次了。

总结:

如果你跟着我做完了,你应该理解到的内容:
1. 正确的完成一个方便Unity接入的SDK
2. 使用导出工程的模式完成SDK的接入
3. 使用Unity插件的形式进行Android的接入

后篇我会讲讲具体的例子,怎么接入一个具体的Android的Library工程。

三、demo地址

Android接入demo分为三个工程:

  1. UnityCall:Plugins形式的Unity3d的工程
  2. EclipseProj:Android的两个工程
    UnityPlayerNativeActivity:Unity3d导出式的工程
    callAndroid:Android的sdk工程

下载地址:

http://download.csdn.net/detail/yang8456211/9517718

杨光(atany)原创,转载请注明博主与博文链接,未经博主允许,禁止任何商业用途。
博文地址:http://download.csdn.net/detail/yang8456211/9517718
博客地址:http://blog.csdn.net/yang8456211
本文遵循“署名-非商业用途-保持一致”创作公用协议

<script type="text/javascript"> $(function () { $(‘pre.prettyprint code‘).each(function () { var lines = $(this).text().split(‘\n‘).length; var $numbering = $(‘
    ‘).addClass(‘pre-numbering‘).hide(); $(this).addClass(‘has-numbering‘).parent().append($numbering); for (i = 1; i <= lines; i++) { $numbering.append($(‘
  • ‘).text(i)); }; $numbering.fadeIn(1700); }); }); </script>

    Unity3d Android SDK接入解析(二)Unity3d Android SDK的设计与两种接入方式