轉載請注明出處,謝謝http://blog.csdn.net/metalseed/article/details/7988945
Android藍牙操作:與藍牙串口模塊通信,或其他藍牙設備通信。
初涉android的藍牙操作,按照固定MAC地址連接獲取Device時,程序始終是異常終止,查了好多天代碼都沒查出原因。今天改了一下API版本,突然就成功連接了。總結之后發現果然是個坑爹之極的錯誤。
為了這種錯誤拼命查原因浪費大把時間是非常不值得的,但是問題不解決更是揪心。可惜我百度了那么多,都沒有給出確切原因。今天特此mark,希望后來者遇到這個問題的時候能輕松解決。
下面是我的連接過程,中間崩潰原因及解決辦法。
1:用AT指令獲得藍牙串口的MAC地址,地址是簡寫的,按照常理猜測可得標准格式。
2:開一個String adress= "************" //MAC地址, String MY_UUID= "************"//UUID根據通信而定,網上都有。
3:取得本地Adapter用getDefaultAdapter(); 遠程的則用getRemoteDevice(adress); 之后便可用UUID開socket進行通信。
如果中途各種在getRemoteDevice處崩潰,大家可以查看一下當前的API版本,如果是2.1或以下版本的話,便能確定是API版本問題,只要換成2.2或者以上就都可以正常運行了~ 這么坑爹的錯誤的確很為難初學者。 唉·········· 為這種小trick浪費很多時間真是難過。
(另外有個重要地方,別忘了給manifest里面加以下兩個藍牙操作權限哦~)
<uses-permission android:name="android.permission.BLUETOOTH"></uses-permission> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"></uses-permission>
下面附上Android藍牙操作中用固定MAC地址傳輸信息的模板,通用搜索模式日后再補刪模板:
private BluetoothAdapter mBluetoothAdapter = null; private BluetoothSocket btSocket = null; private OutputStream outStream = null; private InputStream inStream = null; private static final UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"); //這條是藍牙串口通用的UUID,不要更改 private static String address = "00:12:02:22:06:61"; // <==要連接的藍牙設備MAC地址 /*獲得通信線路過程*/ /*1:獲取本地BlueToothAdapter*/ mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); if(mBluetoothAdapter == null) { Toast.makeText(this, "Bluetooth is not available.", Toast.LENGTH_LONG).show(); finish(); return; } if(!mBluetoothAdapter.isEnabled()) { Toast.makeText(this, "Please enable your Bluetooth and re-run this program.", Toast.LENGTH_LONG).show(); finish(); return; } /*2:獲取遠程BlueToothDevice*/ BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address); if(mBluetoothAdapter == null) { Toast.makeText(this, "Can't get remote device.", Toast.LENGTH_LONG).show(); finish(); return; } /*3:獲得Socket*/ try { btSocket = device.createRfcommSocketToServiceRecord(MY_UUID); } catch (IOException e) { Log.e(TAG, "ON RESUME: Socket creation failed.", e); } /*4:取消discovered節省資源*/ mBluetoothAdapter.cancelDiscovery(); /*5:連接*/ try { btSocket.connect(); Log.e(TAG, "ON RESUME: BT connection established, data transfer link open."); } catch (IOException e) { try { btSocket.close(); } catch (IOException e2) { Log .e(TAG,"ON RESUME: Unable to close socket during connection failure", e2); } } /*此時可以通信了,放在任意函數中*/ /* try { outStream = btSocket.getOutputStream(); inStream = btSocket.getInputStream(); //可在TextView里顯示 } catch (IOException e) { Log.e(TAG, "ON RESUME: Output stream creation failed.", e); } String message = "1"; byte[] msgBuffer = message.getBytes(); try { outStream.write(msgBuffer); } catch (IOException e) { Log.e(TAG, "ON RESUME: Exception during write.", e); } */
通用搜索模式代碼模板:
簡潔簡潔方式1 demo
作用: 用VerticalSeekBar控制一個 LED屏幕的亮暗。
直接上碼咯~
package com.example.seed2; import android.app.Activity; import android.app.AlertDialog; import android.app.Dialog; import android.os.Bundle; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.UUID; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothSocket; import android.content.DialogInterface; import android.util.Log; import android.view.KeyEvent; import android.widget.Toast; public class MetalSeed extends Activity { private static final String TAG = "BluetoothTest"; private BluetoothAdapter mBluetoothAdapter = null; private BluetoothSocket btSocket = null; private OutputStream outStream = null; private InputStream inStream = null; private VerticalSeekBar vskb = null; private static final UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"); //這條是藍牙串口通用的UUID,不要更改 private static String address = "00:12:02:22:06:61"; // <==要連接的藍牙設備MAC地址 /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); this.vskb = (VerticalSeekBar)super.findViewById(R.id.mskb); this.vskb.setOnSeekBarChangeListener(new OnSeekBarChangeListenerX()); mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); if(mBluetoothAdapter == null) { Toast.makeText(this, "Bluetooth is not available.", Toast.LENGTH_LONG).show(); finish(); return; } if(!mBluetoothAdapter.isEnabled()) { Toast.makeText(this, "Please enable your Bluetooth and re-run this program.", Toast.LENGTH_LONG).show(); finish(); return; } } private class OnSeekBarChangeListenerX implements VerticalSeekBar.OnSeekBarChangeListener { public void onProgressChanged(VerticalSeekBar seekBar, int progress, boolean fromUser) { //Main.this.clue.setText(seekBar.getProgress()); /* String message; byte [] msgBuffer; try { outStream = btSocket.getOutputStream(); } catch (IOException e) { Log.e(TAG,"ON RESUME : Output Stream creation failed.", e); } message =Integer.toString( seekBar.getProgress() ); msgBuffer = message.getBytes(); try{ outStream.write(msgBuffer); } catch (IOException e) { Log.e (TAG, "ON RESUME : Exception during write.", e); } */ } public void onStartTrackingTouch(VerticalSeekBar seekBar) { String message; byte [] msgBuffer; try { outStream = btSocket.getOutputStream(); } catch (IOException e) { Log.e(TAG,"ON RESUME : Output Stream creation failed.", e); } message =Integer.toString( seekBar.getProgress() ); msgBuffer = message.getBytes(); try{ outStream.write(msgBuffer); } catch (IOException e) { Log.e (TAG, "ON RESUME : Exception during write.", e); } } public void onStopTrackingTouch(VerticalSeekBar seekBar) { String message; byte [] msgBuffer; try { outStream = btSocket.getOutputStream(); } catch (IOException e) { Log.e(TAG,"ON RESUME : Output Stream creation failed.", e); } message =Integer.toString( seekBar.getProgress() ); msgBuffer = message.getBytes(); try{ outStream.write(msgBuffer); } catch (IOException e) { Log.e (TAG, "ON RESUME : Exception during write.", e); } } } @Override public void onStart() { super.onStart(); } @Override public void onResume() { super.onResume(); BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address); try { btSocket = device.createRfcommSocketToServiceRecord(MY_UUID); } catch (IOException e) { Log.e(TAG, "ON RESUME: Socket creation failed.", e); } mBluetoothAdapter.cancelDiscovery(); try { btSocket.connect(); Log.e(TAG, "ON RESUME: BT connection established, data transfer link open."); } catch (IOException e) { try { btSocket.close(); } catch (IOException e2) { Log .e(TAG,"ON RESUME: Unable to close socket during connection failure", e2); } } // Create a data stream so we can talk to server. /* try { outStream = btSocket.getOutputStream(); inStream = btSocket.getInputStream(); } catch (IOException e) { Log.e(TAG, "ON RESUME: Output stream creation failed.", e); } String message = "read"; byte[] msgBuffer = message.getBytes(); try { outStream.write(msgBuffer); } catch (IOException e) { Log.e(TAG, "ON RESUME: Exception during write.", e); } int ret = -1; while( ret != -1) { try { ret = inStream.read(); } catch (IOException e) { e.printStackTrace(); } } */ } @Override public void onPause() { super.onPause(); if (outStream != null) { try { outStream.flush(); } catch (IOException e) { Log.e(TAG, "ON PAUSE: Couldn't flush output stream.", e); } } try { btSocket.close(); } catch (IOException e2) { Log.e(TAG, "ON PAUSE: Unable to close socket.", e2); } } @Override public void onStop() { super.onStop(); } @Override public void onDestroy() { super.onDestroy(); } @Override public boolean onKeyDown(int keyCode, KeyEvent event){ if(keyCode == KeyEvent.KEYCODE_BACK){ this.exitDialog(); } return false; } private void exitDialog(){ Dialog dialog = new AlertDialog.Builder(MetalSeed.this) .setTitle("退出程序?") .setMessage("您確定要退出本程序嗎?") .setPositiveButton("確定", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int whichButton) { MetalSeed.this.finish(); } }).setNegativeButton("取消", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int whichButton) { } }).create(); dialog.show(); } }
此為上述demo的layout
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@drawable/bcf" > <TextView android:id="@+id/myt" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:layout_centerHorizontal="true" android:layout_marginTop="48dp" android:text="MetalSeed" android:textSize="40dip" /> <com.example.seed2.VerticalSeekBar android:id="@+id/mskb" android:layout_width="105dp" android:layout_height="219dp" android:layout_below="@+id/myt" android:layout_centerHorizontal="true" android:layout_marginTop="85dp" android:maxHeight="95dip" android:minHeight="95dip" android:minWidth="95dip" android:thumbOffset="0dip" /> </RelativeLayout>