化石原创文章,转载请注明来源并保留原文链接


写了个蓝牙的server,可以直接编译成aar,供unity使用。技术上利用了service和java反射,因此无需在Unity中注入和改动任何东西。

代码在github,这里

编译出的aar直接放Unity工程的Assets目录下的任何地方即可开始使用。

Unity代码开启和关闭蓝牙服务器:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class NewBehaviourScript : MonoBehaviour {

	AndroidJavaClass blueToothServer;

	void Awake() {
		AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
		AndroidJavaObject currentActivity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity");
		AndroidJavaObject unityContext = currentActivity.Call<AndroidJavaObject>("getApplicationContext");

		blueToothServer = new AndroidJavaClass ("com.huashi.bluetuth.BlueTuthServer");
		blueToothServer.CallStatic ("init", unityContext);
	}

	void Start () {
		GameObject.Find ("Canvas/Start").GetComponent<Button> ().onClick.AddListener (onStartClick);
		GameObject.Find ("Canvas/Stop").GetComponent<Button> ().onClick.AddListener (onStopClick);
	}

	void onStartClick() {
		blueToothServer.CallStatic ("startServer");				
	}
	
	void onStopClick () {
		blueToothServer.CallStatic ("stopServer");				
	}
}

Unity代码接收服务器消息:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Text;

public class JavaMessageReceiver : MonoBehaviour {

	public void ReceiveJavaMessage(string msg) {
		Debug.Log ("Receive msg.");

		byte[] bytes = Encoding.ASCII.GetBytes (msg);

		if (bytes.Length != 0) {
			switch (bytes [0]) {
			case 1:
				Debug.Log ("CLIENT_CONNECTED");
				string real = msg.Substring (1);
				Debug.Log ("Content is: " + real);
				break;
			case 2:
				Debug.Log ("RECEIVE_CLIENT_DATA");
				for (int i = 1; i < bytes.Length; ++i) {
					Debug.Log ("index = " + i + ":" + bytes[i]);
				}
				break;
			case 3:
				Debug.Log ("REMOTE_SHUTDOWN");
				string realll = msg.Substring (1);
				Debug.Log ("Content is: " + realll);
				break;
			default:
				Debug.Log ("Received from java, tag = " + bytes[0]);
				break;
			}
		}
	}
}

上面的这个代码必须挂在一个名字为JavaMessageReceiver的GameObject上。


化石原创文章,转载请注明来源并保留原文链接



化石原创文章,转载请注明来源并保留原文链接


Unity侧:

AAR文件可以放在assets目录的任何地方

AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer");     

AndroidJavaObject currentActivity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity");     

AndroidJavaObject unityContext = currentActivity.Call<AndroidJavaObject>("getApplicationContext");

这三步能拿到大多数aar需要的context,activity

AndroidJavaClass.CallStatic(methodName, parameter0, parameter1, pameter2);

使用最上面的方法得到Android Class后,内部的static方法,用这个方法调用。多个参数依次排列在方法名字后面即可(官方文档没有例子,使用了数组形式,没测过)

AndroidJavaClass.Call(methodName, parameter0, parameter1, pameter2);

调用实例的方法。

Java侧:

com.unity3d.player包中,有类

UnityPlayer,提供方法UnitySendMessage(GameObjectName, MethodName, parameter)

该类的反编译结果可以在这里看到。截取方法的定义如下:

public static native void UnitySendMessage(String var0, String var1, String var2); 

写插件的过程中,如果不想让java侧代码一定跟Unity3d绑定,那么可以使用java的反射来取得上面的方法。

Class playerClass = Class.forName("com.unity3d.player.UnityPlayer");

Log.d("MyTag", playerClass.toString());

Method sendMessageMethod = playerClass.getMethod("UnitySendMessage", String.class, String.class, String.class);

Log.d("MyTag", sendMessageMethod.getName() + ", " + sendMessageMethod.toString());


化石原创文章,转载请注明来源并保留原文链接