zoukankan      html  css  js  c++  java
  • Unity和Android、iOS原生交互

    Unity 调用 Android Java 原生方法可以通过 C# 反射去调用 Java 的方法

    // 获取类,主要用于获取静态字段或调用静态方法,常用来获取 UnityPlayer
    AndroidJavaClass jc = new AndroidJavaClass("com.unity.game.UnityPlayerActivity");
    // 获取静态字段,只有泛型版本
    AndroidJavaObject jo = jc.GetStatic<AndroidJavaObject>("currentActivity");
    // 调用对象方法:使用 AndroidJavaObject 类的 Call 调用Java方法。
    jo.Call(javaFuncName, args);

    Android 回调 Unity

    Android 主动调用 Unity 可以通过 Sendmessage 方法

    // objectName: Unity 对象的名称
    // methodName: Unity 对象绑定的脚本方法名
    // message: 自定义消息
    UnityPlayer.UnitySendMessage(String objectName, String methodName, String message);

    该方法有一个弊端,就是发送消息的方法对应的类,必须要挂载在一个 game object 上。

    该方法有一点需要注意,就是在原生触发回调接口的时候,可能跟 Unity 的主线程并不是一个线程,此时需要通知 Unity 主线程执行回调。

    Unity 调用 IOS OC方法

    // DllImport这个方法相当于是告诉Unity,有一个CallObjCFunc函数在外部会实现。
    // 使用这个方法必须要导入System.Runtime.InteropServices;
    [DllImport("__Internal")]
    private static extern void CallObjCFunc(string funcName);
    public static void CallNativeFunction(string funcName, params object[] args)
    {
        CallObjCFunc(funcName);
    }

    对应的CallObjCFunc在oc层

    extern "C" {
        void CallObjCFunc(const char* methodName)
        {
            SEL selector = NSSelectorFromString([NSString stringWithUTF8String:methodName]);
        
            if ([Plugin respondsToSelector:selector]) {
                [Plugin performSelector:selector];
            }
        }
    }

    IOS 回调 Unity

    iOS 主动调用 Unity 可以通过 Sendmessage 方法

    NSString *data = @"";//需要传递的参数
    UnitySendMessage("Game", "CallFromNative", [data UTF8String]);

    整合后的代码

    SDKInterface.cs

     1 using UnityEngine;
     2 using System.Collections;
     3 using LitJson;
     4 
     5 #if UNITY_IOS && !UNITY_EDITOR
     6 using System.Runtime.InteropServices;
     7 #endif
     8 
     9 public class SDKInterface : MonoBehaviour
    10 {
    11     private static SDKInterface m_instance;
    12     public static SDKInterface Instance
    13     {
    14         get
    15         {
    16             if (m_instance == null)
    17             {
    18                 if (Game.game)
    19                 {
    20                     m_instance = Game.game.gameObject.AddComponent<SDKInterface>();
    21                     Debug.Log("SDKInterface initialized");
    22                 }
    23             }
    24             return m_instance;
    25         }
    26     }
    27 
    28 
    29 #if UNITY_ANDROID && !UNITY_EDITOR
    30     private const string JAVA_CLASS_NAME = "com.unity.game.UnityPlayerActivity";
    31     private static void CallJavaFunc(string javaFuncName, params object[] args)
    32     {
    33         try
    34         {
    35             using (AndroidJavaClass jc = new AndroidJavaClass(JAVA_CLASS_NAME))
    36             {
    37                 //获取Activity
    38                 using (AndroidJavaObject jo = jc.GetStatic<AndroidJavaObject>("currentActivity"))
    39                 {
    40                     //调用Java方法
    41                     if (args == null)
    42                     {
    43                         jo.Call(javaFuncName);
    44                     }
    45                     else
    46                     {
    47                         jo.Call(javaFuncName, args);
    48                     }
    49                 }
    50             }
    51         }
    52         catch (System.Exception ex)
    53         {
    54             Debug.LogError("callSdk error: " + ex.Message);
    55         }
    56     }
    57 #endif
    58 
    59 #if UNITY_IOS && !UNITY_EDITOR
    60     // DllImport这个方法相当于是告诉Unity,有一个CallObjCFunc函数在外部会实现。
    61     // 使用这个方法必须要导入System.Runtime.InteropServices;
    62     [DllImport("__Internal")]
    63     private static extern void CallObjCFunc(string funcName);
    64 #endif
    65 
    66     public static void CallNativeFunction(string funcName, params object[] args)
    67     {
    68         if (Instance == null)
    69         {
    70             return;
    71         }
    72 
    73         Debug.Log("call native function: " + funcName);
    74 #if UNITY_EDITOR
    75 #else
    76 #if UNITY_ANDROID
    77         CallJavaFunc(funcName, args);
    78 #elif UNITY_IOS
    79         CallObjCFunc(funcName);
    80 #endif
    81 #endif
    82     }
    83 
    84     //从java层或者oc层调用
    85     public void CallFromNative(string data)
    86     {
    87         Debug.Log("call from native: " + data);
    88 
    89         JsonData json = JsonMapper.ToObject(data);
    90         string funcname = (string)json["FuncName"];
    91 
    92         Game.game.luaManager.CallFunction(funcname, data);
    93     }
    94 }
    UnityPlayerActivity.cs
    ..
    public class UnityPlayerActivity extends Activity
    {
        ..
        public void getStartupData()
        {
            String data = "";
            UnityPlayer.UnitySendMessage("Game", "CallFromNative", data);
        }
        ..
    }

    Plugin.m

     1 #import "Plugin.h"
     2 
     3 @implementation Plugin
     4 
     5 +(void)getStartupData
     6 {
     7     NSString *data = @"";
     8     
     9     UnitySendMessage("Game", "CallFromNative", [data UTF8String]);
    10 }
    11 
    12 @end
    13 
    14 extern "C" {
    15     void CallObjCFunc(const char* methodName)
    16     {
    17         SEL selector = NSSelectorFromString([NSString stringWithUTF8String:methodName]);
    18     
    19         if ([Plugin respondsToSelector:selector]) {
    20             [Plugin performSelector:selector];
    21         }
    22     }
    23 }
  • 相关阅读:
    《ArcGIS Runtime SDK for Android开发笔记》——问题集:Error:Error: File path too long on Windows, keep below 240 characters
    《ArcGIS Runtime SDK for Android开发笔记》——(12)、自定义方式加载Bundle格式缓存数据
    《ArcGIS Runtime SDK for Android开发笔记》——(11)、ArcGIS Runtime SDK常见空间数据加载
    《ArcGIS Runtime SDK for Android开发笔记》——问题集:如何解决ArcGIS Runtime SDK for Android中文标注无法显示的问题(转载)
    《ArcGIS Runtime SDK for Android开发笔记》——数据制作篇:紧凑型切片制作(Server缓存切片)
    《ArcGIS Runtime SDK for Android开发笔记》——(10)、ArcGIS Runtime SDK支持的空间数据类型
    《ArcGIS Runtime SDK for Android开发笔记》——(9)、空间数据的容器-地图MapView
    《ArcGIS Runtime SDK for Android开发笔记》——(8)、关于ArcGIS Android开发的未来(“Quartz”版Beta)
    legend3---9、项目的日志以及调试信息数据量非常大
    laravel如何从mysql数据库中随机抽取n条数据
  • 原文地址:https://www.cnblogs.com/ring1992/p/15612630.html
Copyright © 2011-2022 走看看