其實這個方法,不管是要開啟藍芽還是振動之類需要有權限的要求,都可以達成。
使用Android Studio可以看這篇Unity 使用Android Bluetooth (Android Studio)
建議可以先看過這篇文章(Unity使用Android的Toast),作法上有很多類似的地方。
而藍芽部分可以看這篇文章
開啟個新的專案
之後請到Unity的安裝路徑:Unity\Editor\Data\PlaybackEngines\androidplayer\development\bin
複製這個檔案到剛剛創建的Eclipse專案的libs資料夾內
之後再對該專案按下F5重新整理,即可看到如下圖所示:
再來開啟src資料夾內的MainActivity.java,編寫以下程式碼,在這個範例中是假設手機上有藍芽設備、且為不通知使用者強制開啟藍芽。
package com.example.androidbluetooth;
import android.bluetooth.BluetoothAdapter;
import com.unity3d.player.UnityPlayer;
public class MainActivity
{
public static void openBluetooth()
{
UnityPlayer.currentActivity.runOnUiThread(new Runnable()
{
@Override
public void run()
{
BluetoothAdapter bluetoothAdapter;
bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (bluetoothAdapter.isEnabled() == false)
{
bluetoothAdapter.enable();
}
}
});
}
}
都好後Ctrl+S存檔,再對專案點右鍵 → Export,選擇JAR file
然後按照下面這張圖的方式勾選完畢後,按下Finish
之後開啟Unity,新建一個專案,命名為useBluetooth,並產生如下的資料夾
並將剛剛Eclipse產生的jar放到libs資料夾內
再來就是最重要的一步!
到Unity的安裝路徑:Unity\Editor\Data\PlaybackEngines\androidplayer
複製到Android資料夾內
再來就是打開這個xml檔案...
將
改為剛剛在Eclipse上建立的的 AndroidBluetooth → AndroidManifest.xml 的 package 名稱(也就是改成下面藍底的那行)
以及將這行也加入
和藍芽權限
完成後的檔案就長這樣(更動到的地方已經用綠框框住)
以上步驟都做好後,就新增三個C#腳本,分別命名為:AndroidBehaviour 、 Bluetooth 、Test
AndroidBehaviour腳本同開頭我提到的「Unity使用Android的Toast」那篇AndroidBehaviour腳本相同,所以就不再重複了
而Bluetooth腳本程式碼如下:
using UnityEngine;
using System.Collections;
public class Bluetooth : AndroidBehaviour<Bluetooth>
{
protected override string javaClassName
{
//要呼叫的class所在的Package名稱.要呼叫的java class名稱
get { return "com.example.androidbluetooth.MainActivity"; }
}
public static void openBT()
{
instance.CallStatic("openBluetooth");
}
}
Test腳本程式碼如下
using UnityEngine;
using System.Collections;
public class Test : MonoBehaviour
{
private void Start()
{
Bluetooth.openBT();
}
}
都好之後將Test和Bluetooth放到同個物件上!
(在此範例我放到Camera上)
之後在 Player Setting 內的 Bundle Identifier 要和 AndroidBluetooth 的 package 名稱一樣,且minSdk也要相同
最後就Build成apk,丟到手機上安裝執行了!(其實也可以直接Build And Run)
藍芽開啟了!(紅圈處)
完整檔案在此(包含 Eclipse 的 AndroidBluetooth 和 Unity 的 useBluetooth )

感謝大大 無私分享……這個文章真棒。 解決了 不少對於以unity 開發 android權限問題。
你好~謝謝你的分享,受益良多! 目前有個問題就是,我想使用android的藍芽搜尋裝置功能 發現需將你的.activity,該class extend Activity後才能使用廣播(registerReceiver) ,也就是public class MainActivity 改為public class MainActivity extend Activity, 但如此包成jar給unity後,於手機執行該unity程式時呼叫jar內的函式則沒有動靜甚至卡住..去掉"extend Activity"則正常,不知道版主有解決的方法嗎? 謝謝!
您好,原因可能是當 Unity3D 呼叫 Android 的函式時, 會因為 UI Thread 安全性關系,所以不能彈出 AlertDialog,所以您如果要達成廣播功能可能要搭配上Handler
你好~謝謝你的回答~不過我並沒有用alertdialog等ui部分 我發現的問題是~我把宣告廣播的部分拿掉(例如找到藍芽裝置的廣播: IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND); registerReceiver(discoveryFinishReceiver, filter); ) 但只要我將MainActivity 做extend Activity ( 或extend UnityPlayerActivity <=我也還不太清楚這個有何用處,網路上查的) 則會發生當call該MainActivity裡的方法式時就會卡住,而沒有extend Activity 時就正常。 真是奇怪XD還要再研究看看><
我的意思是,使用AlertDialog的功能來模擬部分的功能。 先偵測使用者是否有有藍芽且未開啟,若是符合條件則跳出AlertDialog的是非選項,選是則直接開啟,選否則不進行任何動作。 只是若用這個方法則必須在程式碼內直接綁定要連接的藍芽就是了...... 如果是要和搜尋藍芽狀態改變、搜索周圍藍芽之類的功能,那就要在試試看其他方式了...
請問版主我開起藍芽後我該怎發送指令給arduino藍芽板子 我對這塊還不太了解 可以為我解惑嗎 拜託版主
不好意思,我沒使用過Arduino,所以沒辦法幫你解釋..(連接板子的藍芽我是使用外面販售的藍芽元件直接連接)
那麼我有辦法輸出資料的方法 或者接收資料的方法可以告訴我嗎 還是他跟 "www" 這個方法一樣的
傳輸和接收資料的方法就要寫在Android端
今天我要輸入 A 寫法怎麼附加進去 該怎麼附加進去 (arduino的基礎我還能應付 只是unity我真的不知道該怎麼寫 )
資料傳輸處理都是寫在Eclipse那邊,而Unity只是"負責呼叫Method"而已...
懇求版主寫一個Eclipse端搭配unity藍芽資料傳輸的簡單範例 我試了好幾次,有的是Eclipse端為了包覆unity而程式無法執行 不然就是終於封包成jar給unity卻呼叫不出來 小弟能力不足努力了兩個禮拜了 到處找也找不到android連接unity藍芽傳輸的範本 真心請求版主教學
好的,不過要晚點才能給你,目前我還在上課...
謝謝你了!!!
恩...只有一台手機,無法測試.....((倒 如同這樣的做法(只要看UnityTestActivity.java和TestActivity.java的UnityPlayer.UnitySendMessage)http://www.xuanyusong.com/archives/676 從Unity傳遞資料給Eclipse,然後在Eclipse上編寫兩台手機間的藍芽訊息傳遞
感謝你!! 我試試看
不好意思,剛剛我只是把網頁下方的材質包打開來想說試試看 結果能執行,但是當我按下commit按鈕時卻跑出下方這個錯誤 Exception: JNI: Init'd AndroidJavaClass with null ptr! 上網查了一下可能是class不一樣,但也就那一個而已不是嗎?
網頁下方材質包= =?? 你是說我這個網頁?
你好,我又出現了... 我有寫出來了... 但開啟藍芽跟掃描藍芽裝置都可執行 但是加入資料傳輸後就當掉了== 能不能請你幫我檢查一下程式哪裡出錯
阿...抱歉 你剛剛的回覆(#12),我手殘按到廣告,留言直接消失了....... 能麻煩您再重新留言一次嗎>"<
*****
*****
這是我android端的程式碼,能幫我看一下到底是哪裡出問題嗎? 我後來有在網路上看到其他範例了,晚點再試試看。 package com.bluetoothtest; import android.widget.Toast; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothServerSocket; import android.bluetooth.BluetoothSocket; import java.io.InputStream; import java.io.OutputStream; import java.util.Set; import java.util.UUID; import java.io.IOException; import android.os.Handler; import com.unity3d.player.UnityPlayer; public class bluetoothtest { public static BluetoothAdapter bluetoothAdapter; public static UUID MY_UUID_SECURE = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"); public static BluetoothSocket socket = null; public static BluetoothDevice mmdevice; public static BluetoothSocket mmSocket; public static Handler mHandler = null; public static InputStream mmInStream; public static OutputStream mmOutStream; //Method必須為static public static void showToast(final String content, final boolean isLong)//傳入的參入必須為final,才可讓Runnable()內部使用 { UnityPlayer.currentActivity.runOnUiThread(new Runnable() { @Override public void run() { //若使用者傳入的boolean為true,則Toast顯示3.5秒;否則為2秒 Toast.makeText(UnityPlayer.currentActivity, content, isLong ? Toast.LENGTH_LONG : Toast.LENGTH_SHORT).show(); } }); } public static void findBT() { UnityPlayer.currentActivity.runOnUiThread(new Runnable() { @Override public void run() { bluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); if (bluetoothAdapter.isEnabled() == false) { Toast.makeText(UnityPlayer.currentActivity, "TURN ON BLUETOOTH AND RESTART", Toast.LENGTH_LONG).show(); }else { /* String address = bluetoothAdapter.getAddress(); String name = bluetoothAdapter.getName(); Toast.makeText(UnityPlayer.currentActivity, address + name, Toast.LENGTH_LONG).show();*/ Toast.makeText(UnityPlayer.currentActivity, "Welcome", Toast.LENGTH_LONG).show(); } Set pairedDevices = bluetoothAdapter.getBondedDevices();
if(pairedDevices.size() > 0)
{
for(BluetoothDevice device : pairedDevices)
{
if(device.getName().equals("BT-001"))
{
Toast.makeText(UnityPlayer.currentActivity,
device.getName() +" "+ device.getAddress(), Toast.LENGTH_LONG).show();
mmdevice=device;
}
}
}
}
});
}
public static void AcceptThread ()
{
UnityPlayer.currentActivity.runOnUiThread(new Runnable()
{
@Override
public void run()
{
BluetoothServerSocket mmServerSocket;
BluetoothServerSocket tmp = null;
try {
// MY_UUID is the app's UUID string, also used by the client code
tmp = bluetoothAdapter.listenUsingRfcommWithServiceRecord("BT-001",MY_UUID_SECURE);
} catch (IOException e) { }
mmServerSocket = tmp;
// Keep listening until exception occurs or a socket is returned
while (true) {
try {
socket = mmServerSocket.accept();
Toast.makeText(UnityPlayer.currentActivity,
"AcceptThread1", Toast.LENGTH_LONG).show();
} catch (IOException e) {
break;
}
// If a connection was accepted
if (socket != null) {
/* // Do work to manage the connection (in a separate thread)
ConnectedSocket(socket);
try {
mmServerSocket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}*/
Toast.makeText(UnityPlayer.currentActivity,
"AcceptThread2", Toast.LENGTH_LONG).show();
break;
}
}
}
});
}
public static void ConnectThread ()//傳入的參入必須為final,才可讓Runnable()內部使用
{
UnityPlayer.currentActivity.runOnUiThread(new Runnable()
{
@Override
public void run()
{
//final BluetoothDevice mmDevice;
// Use a temporary object that is later assigned to mmSocket,
// because mmSocket is final
BluetoothSocket tmp = null;
// mmDevice = device;
// Get a BluetoothSocket to connect with the given BluetoothDevice
try {
// MY_UUID is the app's UUID string, also used by the server code
tmp = mmdevice.createRfcommSocketToServiceRecord(MY_UUID_SECURE);
Toast.makeText(UnityPlayer.currentActivity,
"ConnectThread_UUID", Toast.LENGTH_LONG).show();
} catch (IOException e) { }
mmSocket = tmp;
// Cancel discovery because it will slow down the connection
bluetoothAdapter.cancelDiscovery();
try {
// Connect the device through the socket. This will block
// until it succeeds or throws an exception
mmSocket.connect();
Toast.makeText(UnityPlayer.currentActivity,
"ConnectThread_connect", Toast.LENGTH_LONG).show();
} catch (IOException connectException) {
// Unable to connect; close the socket and get out
try {
mmSocket.close();
} catch (IOException closeException) { }
return;
}
// Do work to manage the connection (in a separate thread)
// manageConnectedSocket(mmSocket);
}
});
}
public static void ConnectedThread ()
{
UnityPlayer.currentActivity.runOnUiThread(new Runnable()
{
@Override
public void run()
{
mmSocket = socket;
InputStream tmpIn = null;
OutputStream tmpOut = null;
// Get the input and output streams, using temp objects because
// member streams are final
try {
tmpIn = socket.getInputStream();
tmpOut = socket.getOutputStream();
Toast.makeText(UnityPlayer.currentActivity,
"ConnectedThread_getOutputStream", Toast.LENGTH_LONG).show();
} catch (IOException e) { }
mmInStream = tmpIn;
mmOutStream = tmpOut;
byte[] buffer = new byte[1024]; // buffer store for the stream
int bytes; // bytes returned from read()
// Keep listening to the InputStream until an exception occurs
while (true) {
try {
// Read from the InputStream
bytes = mmInStream.read(buffer);
int MESSAGE_READ = 0;
// Send the obtained bytes to the UI activity
mHandler.obtainMessage(MESSAGE_READ, bytes, -1, buffer).sendToTarget();
Toast.makeText(UnityPlayer.currentActivity,
"ConnectedThread_mHandler", Toast.LENGTH_LONG).show();
} catch (IOException e) {
break;
}
}
}
});
}
public static void write(final byte[] bytes)
{
UnityPlayer.currentActivity.runOnUiThread(new Runnable()
{
@Override
public void run()
{
try {
mmOutStream.write(bytes);
} catch (IOException e) { }
}
});
}
/* Call this from the main activity to send data to the remote device */
/* Call this from the main activity to shutdown the connection */
}
我剛剛重新編寫了一個,明天我去找同學借手機測試一下,如果成功會再通知您。 不過一傳資料就閃退...推測可能是沒有完全連結上 or Thread的問題... 詳細情況我明天才能和您說
好喔 那我在測試看看 謝謝你
OH YA~成功了!!! 謝謝你!!!! 你真是太厲害了!!
所以問題是出在沒有連線完成就傳資料嗎? (((才剛放學回到家
應該可以這麼說XD 因為我之後直接把連接和傳送的程式碼參考這個網址的做就成功了 https://www.javaworld.com.tw/jute/post/view?bid=26&id=275260 因為我只是需要透過藍芽傳輸資料給arduino而已~
請問 藍芽連線這段 我現在不懂在socket 已經是connect的狀況 但在 int bytes ; ( mmInStream =socket.getInputStream() ) bytes = mmInStream.read(buffer); 在read時,整個app就停住了 使用Thread 的方法也是到read的地方就不會再繼續下去執行 請問這是什麼原因 要怎麼解決?
本來就會停在那邊,直到成功連接藍芽裝置後才會繼續往下執行。 或是另外新增一個script,繼承Thread,將連線的程式碼寫在裡面,然後從另個script呼叫
我是unity5.2.4
試了兩天 終於成功用文章的內容開啟藍芽!! 現在要做藍芽連線遊戲 透過藍芽傳輸資料 android程式碼我用了13樓的資料 (如有侵權我會刪掉抱歉><) 但不知道unity端怎麼呼叫 是test.cs檔要改嗎 程式新手只會網路上找資料不會自己寫 真的翻遍網路還是找不到 請版主救救我
只要修改Bluetooth.cs就好,至於要怎麼修改我程式碼都有中文註解說了,照著註解修改即可。
您好,我想做一個可以讓兩台手機傳訊的遊戲 一端用Android Studio 另一端用Unity 由AS傳陀螺儀的三軸座標給Unity做接收 因為必須即時傳送即時判斷所以打算用藍芽 但是Google了兩天完全找不到AS傳給Unity的範例 請問大大有更好的解決方案或是範例或關鍵字供參考嗎 小弟感激不盡
您好,我另外寫了一篇使用Android Studio來達成的文章,可以看一下。(和這篇文章同樣的作法,只是從Eclipse換成Android Studio) http://oblivious9.pixnet.net/blog/post/204640543-Unity%20%E4%BD%BF%E7%94%A8Android%20Bluetooth%20(Android%20Studio)
把完整檔案在此下載下來,之後要放進哪一個資料夾裡面
AndroidBluetooth:這整個就是Eclipse的專案資料夾了 useBluetooth:這就是Unity的專案資料夾了 看你要放哪裡都可以,只是他們只接受英文和數字的路徑
請問一下有 Bluetooth 、Test 的完整檔案嗎
文章最下面有給載點
請問一下, 參考13樓的寫法, 一傳輸資料就會閃退的原因是什麼阿? 是了很久還是一樣??
在java和C#都用try-catch抓一下錯誤訊息,看看錯誤原因是什麼
請問一下, 最後傳值的部分,如果Unity要當接收端, 應該要開一個Thread去執行Connected吧?! 這樣的想法是對的嗎?
YES 但是接收到的訊息要去控制Unity的物件的話,就不能用Thread了。
不好意思,在補問一個 如果Unity開一個Thread去執行一個jar的function 而這個function是無窮迴圈,這樣會掛掉嗎?
是的! 因為Unity結束時,不會自動停下非Unity自行產生的Thread。 詳情和解決方法請看我這篇:http://oblivious9.pixnet.net/blog/post/204439375-unity-c%23-thread-%E6%B3%A8%E6%84%8F%E4%BA%8B%E9%A0%85
不好意思,我又來了~ 這是我Unity端C#的程式: Receive = new Thread(new ThreadStart( Bluetooth.Receive_data)); Receive.IsBackground = true; Receive.Start(); public static void Receive_data() { instance.CallStatic("ConnectedThread"); } Android 端的function: public static void ConnectedThread () { UnityPlayer.currentActivity.runOnUiThread(new Runnable() { @Override public void run() { //socket = mmSocket; //mmSocket = socket; Toast.makeText(UnityPlayer.currentActivity, "Start Receive1...", Toast.LENGTH_LONG).show(); } }); } 我是先簡單測試,能不能用Unity的Thread去執行jar的function 但這樣,程式就閃退了 因為同樣的android程式碼,如果直接call,可以Toast出來,用Thread去call就閃退 目前猜測,是因為android端UnityPlayer.currentActivity.runOnUiThread(new Runnable() 這個沒辦法用Unity的Thread去執行嗎? 像這樣要怎麼解決阿? 麻煩您了!! 謝謝
推測是UnityPlayer.currentActivity.runOnUiThread(new Runnable())屬於Unity的Thread,所以無法給C# Thread去執行 用這幾篇的方法試試看: http://ppt.cc/bbVhi http://ppt.cc/iqi0V http://ppt.cc/yYmp9
真的太感謝你了~ 現在以經可以成功傳值了 謝謝您!!!!!
不知大大有沒有能夠達成unity藍芽連線的程式碼 可不可以分享一下 我在unity呼叫android的function時間遇到不少問題
可以參考一下上面幾個人的問題,應該能找到你想要的解答 或者是把錯誤原因貼上來 我已經很久沒去碰藍芽這塊,原始碼都刪掉了
大大你好 有一些unity 的問題 方便請教嗎?
你好 不好意思 有一些unity問題想請教 請問方便提問嗎?