1. 程式人生 > >Androidble4.0藍芽開發相容2.0藍芽應用(針對arduino藍芽控制小車開發應用HC-08,06藍芽模組的連線)

Androidble4.0藍芽開發相容2.0藍芽應用(針對arduino藍芽控制小車開發應用HC-08,06藍芽模組的連線)

1.嗯有段時間沒更新部落格啦,給廣大CSDN友上點幹活

2.android藍芽即智慧穿戴裝置火起來之後藍芽的普及也是有點猛,今天我們部落格的主題就是圍繞arduino開發藍芽控制小車寫的測試demo,連線的藍芽模組是HC-08,06型號,所以出廠的硬體UUID是廠商提供的,增對該demo用的範圍也是有限的,當前藍芽的開發功能和庫的使用基本都是一樣的,不一樣的只是硬體藍芽模組的UUID,假如想做智慧手環什麼的換成手環的藍芽UUID就可以用,嗯,就是這麼簡單

3.下面先上個gif圖爽爽看看效果先,本人基本都是先看效果再決定是否下載該demo


由於我的網路不是很好用的遠端投屏至電腦才錄製的gif所以看起來搜尋藍芽有點卡,實際效果是不卡的,中間出現的警告框是樓主的手機後臺記憶體只有600+M所以有一個實時監測手機記憶體的,防止記憶體不足demo崩了,嗯,個人感覺還是不錯的

4.下面上主要程式碼截圖:MainActivity

package com.example.androidbluetooch;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import com.baoyz.swipemenulistview.SwipeMenu;
import com.baoyz.swipemenulistview.SwipeMenuCreator;
import com.baoyz.swipemenulistview.SwipeMenuItem;
import com.baoyz.swipemenulistview.SwipeMenuListView;
import com.baoyz.swipemenulistview.SwipeMenuListView.OnMenuItemClickListener;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.Dialog;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattDescriptor;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothSocket;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.content.pm.PackageManager;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.util.Log;
import android.util.TypedValue;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnTouchListener;
import android.view.inputmethod.InputMethodManager;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.AdapterView.OnItemClickListener;

public class MainActivity extends Activity implements OnClickListener, OnItemClickListener {

	protected static final String TAG = "MainActivity";
	// 掃描、斷開、傳送藍芽button
	private Button btn_scan_device, btn_disconnect, btn_send;
	// 未配對藍芽的listview
	private ListView lv_disconnect, listview_msgxianshi;
	// 已配對藍芽的listview,自定義的listview帶滑動刪除
	private SwipeMenuListView lv_connect;
	// 輸入資料的edittext
	private EditText ed_inout;

	private int REQUEST_ENABLE_BT = 1;
	private List<String> list = new ArrayList<String>();
	private ConnectThread mConnectThread;
	public ConnectedThread mConnectedThread;

	private Dialog progressDialog;
	private TextView msg;
	// 藍芽介面卡
	private BluetoothAdapter mBluetoothAdapter;
	// 已經配對的藍芽ArrayList
	private ArrayList<BluetoothDevice> data_connect = new ArrayList<BluetoothDevice>();
	// 未配對的藍芽ArrayList
	private ArrayList<BluetoothDevice> data_disconnect = new ArrayList<BluetoothDevice>();
	// 自定義的adapater,已經配對的藍芽,未配對的藍芽
	private LeDeviceListAdapter connectListAdapter, disconnectListAdapter;
	// HC-08藍芽連線狀態
	private boolean mConnected = false;
	// HC-06藍芽連線狀態
	private boolean mhc06Connected = false;
	// 連線成功的藍芽名字
	private String connect_string;
	// 未配對的HC-06,08點選的標記位
	private int data_onitemclick, datahc06_onitemclick;
	// HC-06:判斷是已經配對的藍芽還是未配對的藍芽,斷開連線的檢視更新
	private boolean disconnect_flag = false;
	// HC-08藍芽地址
	private String mDeviceAddress;
	// 藍芽裝置
	private BluetoothDevice dataconnectBean;
	// 藍芽service,負責後臺的藍芽服務
	private static BluetoothLeService mBluetoothLeService;
	// 藍芽的連線狀態
	private String status = "disconnected";
	// 藍芽特徵值
	private static BluetoothGattCharacteristic target_chara = null;
	private ArrayList<ArrayList<BluetoothGattCharacteristic>> mGattCharacteristics = new ArrayList<ArrayList<BluetoothGattCharacteristic>>();
	// 藍芽4.0的UUID,其中0000ffe1-0000-1000-8000-00805f9b34fb是廣州匯承資訊科技有限公司08藍芽模組的UUID
	public static String HEART_RATE_MEASUREMENT = "0000ffe1-0000-1000-8000-00805f9b34fb";
	// HC-06藍芽UUID
	private static final String SPP_UUID = "00001101-0000-1000-8000-00805F9B34FB";
	private List<Integer> mBuffer = new ArrayList<Integer>();

	private List<ChatMsgEntity> mDataArrays = new ArrayList<ChatMsgEntity>();
	private ChatMsgViewAdapter mAdapter;
	private SelfDialog selfDialog;
	private Handler mhandler = new Handler();
	private Handler myHandler = new Handler() {
		// 2.重寫訊息處理函式
		public void handleMessage(Message msg) {
			switch (msg.what) {
			// 判斷髮送的訊息
			case 1: {
				// 更新View
				if (mConnected == true) {
					String state = msg.getData().getString("connect_state");
					setTitle(connect_string + ":" + state);
				} else {
					String state = msg.getData().getString("connect_state");
					setTitle(state);
				}

				break;
			}
			case 2: {
				// 更新View
				if (mhc06Connected == true) {
					String state = msg.getData().getString("connect_state");
					setTitle(connect_string + ":" + state);

					data_connect.add(data_disconnect.get(datahc06_onitemclick));

					data_disconnect.remove(datahc06_onitemclick);
					disconnectListAdapter = new LeDeviceListAdapter(MainActivity.this, data_disconnect);
					// 為listview指定介面卡
					lv_disconnect.setAdapter(disconnectListAdapter);
					disconnectListAdapter.notifyDataSetChanged();

					connectListAdapter = new LeDeviceListAdapter(MainActivity.this, data_connect);
					// 為listview指定介面卡
					lv_connect.setAdapter(connectListAdapter);
					connectListAdapter.notifyDataSetChanged();
				} else {
					String state = msg.getData().getString("connect_state");
					setTitle(state);
				}

				break;
			}
			case 3: {
				// 更新View
				if (mhc06Connected == true) {
					String state = msg.getData().getString("connect_state");
					setTitle(connect_string + ":" + state);
				} else {
					String state = msg.getData().getString("connect_state");
					setTitle(state);
				}

				break;
			}
			case 4: {
				String state = msg.getData().getString("updata_msg");
				listview_msg_stringReceiver(new String(state));
				break;
			}
			}
			super.handleMessage(msg);
		}

	};

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		btn_scan_device = (Button) findViewById(R.id.btn_scandevice);
		btn_disconnect = (Button) findViewById(R.id.btn_disconnectdevice);
		ed_inout = (EditText) findViewById(R.id.ed_inout);
		btn_send = (Button) findViewById(R.id.btn_send);
		lv_connect = (SwipeMenuListView) findViewById(R.id.lv_connect);
		lv_disconnect = (ListView) findViewById(R.id.lv_disconnect);
		listview_msgxianshi = (ListView) findViewById(R.id.listView1);
		btn_scan_device.setOnClickListener(this);
		btn_disconnect.setOnClickListener(this);
		btn_send.setOnClickListener(this);
		lv_disconnect.setOnItemClickListener(this);
		lv_connect.setOnItemClickListener(this);

		// mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
		final BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
		mBluetoothAdapter = bluetoothManager.getAdapter();
		// 開啟藍芽許可權
		if (mBluetoothAdapter == null || !mBluetoothAdapter.isEnabled()) {
			Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
			startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
		}
		Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();
		if (pairedDevices.size() > 0) {
			for (BluetoothDevice device : pairedDevices) {
				// DeviceBean bean = new DeviceBean();
				// bean.setAddress(device.getAddress());
				// bean.setName(device.getName());
				data_connect.add(device);
				// unpairDevice(device);
			}
		} else {
			Toast.makeText(MainActivity.this, "沒有已配對的裝置", Toast.LENGTH_SHORT).show();
		}

		IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
		this.registerReceiver(mReceiver, filter);

		// Register for broadcasts when discovery has finished
		filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
		this.registerReceiver(mReceiver, filter);

		if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
			msgDialog("您的手機系統低於4.3,不支援ble4.0藍芽");
		} else {
			msgDialog("您的手機系統高於4.3,支援ble4.0藍芽");
		}
		connectListAdapter = new LeDeviceListAdapter(MainActivity.this, data_connect);
		// 為listview指定介面卡
		lv_connect.setAdapter(connectListAdapter);
		disconnectListAdapter = new LeDeviceListAdapter(MainActivity.this, data_disconnect);
		// 為listview指定介面卡
		lv_disconnect.setAdapter(disconnectListAdapter);

		/* 啟動藍芽service */
		Intent gattServiceIntent = new Intent(this, BluetoothLeService.class);
		bindService(gattServiceIntent, mServiceConnection, BIND_AUTO_CREATE);

		// 繫結廣播接收器
		registerReceiver(mGattUpdateReceiver, makeGattUpdateIntentFilter());

		progressDialog = new Dialog(MainActivity.this, R.style.progress_dialog);
		progressDialog.setContentView(R.layout.dialog);
		progressDialog.setCancelable(true);
		progressDialog.getWindow().setBackgroundDrawableResource(android.R.color.transparent);
		msg = (TextView) progressDialog.findViewById(R.id.id_tv_loadingmsg);
		progressDialog.setCanceledOnTouchOutside(false);

		SwipeMenuCreator creator = new SwipeMenuCreator() {

			@Override
			public void create(SwipeMenu menu) {
				// create "open" item
				SwipeMenuItem openItem = new SwipeMenuItem(getApplicationContext());
				// set item background
				openItem.setBackground(new ColorDrawable(Color.rgb(0xC9, 0xC9, 0xCE)));
				// set item width
				openItem.setWidth(dp2px(90));
				// set item title
				openItem.setTitle("取消配對");
				// set item title fontsize
				openItem.setTitleSize(14);
				// set item title font color
				openItem.setTitleColor(Color.WHITE);
				// add to menu
				menu.addMenuItem(openItem);
			}
		};
		// set creator
		lv_connect.setMenuCreator(creator);

		// step 2. listener item click event
		lv_connect.setOnMenuItemClickListener(new OnMenuItemClickListener() {
			@Override
			public void onMenuItemClick(int position, SwipeMenu menu, int index) {
				if (data_connect.get(position).getName().equals("HC-06")) {
					if_or_notPair();
					unpairDevice(data_connect.get(position));
					data_connect.remove(position);
					connectListAdapter.notifyDataSetChanged();
				} else {
					Toast.makeText(MainActivity.this, "HC-06支援取消配對,別的藍芽裝置無法消配對", Toast.LENGTH_SHORT).show();
				}
			}
		});

		mAdapter = new ChatMsgViewAdapter(getApplicationContext(), mDataArrays);
		listview_msgxianshi.setAdapter(mAdapter);
		listview_msgxianshi.setOnTouchListener(new OnTouchListener() {

			@Override
			public boolean onTouch(View v, MotionEvent event) {
				((InputMethodManager) getSystemService(INPUT_METHOD_SERVICE)).hideSoftInputFromWindow(
						getCurrentFocus().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
				return false;
			}
		});
	}

	// 取消已經配對的藍芽(HC-06)
	private void unpairDevice(BluetoothDevice device) {
		try {
			Method m = device.getClass().getMethod("removeBond", (Class[]) null);
			m.invoke(device, (Object[]) null);
		} catch (Exception e) {
			Log.e(TAG, e.getMessage());
		}
	}

	private void msgDialog(String string) {
		selfDialog = new SelfDialog(MainActivity.this);
		selfDialog.setTitle("提示");
		selfDialog.setMessage(string);
		selfDialog.setYesOnclickListener("確定", new SelfDialog.onYesOnclickListener() {
			@Override
			public void onYesClick() {
				// Toast.makeText(MainActivity.this,"點選了--確定--按鈕",Toast.LENGTH_LONG).show();
				selfDialog.dismiss();
			}
		});
		selfDialog.setNoOnclickListener("取消", new SelfDialog.onNoOnclickListener() {
			@Override
			public void onNoClick() {
				// Toast.makeText(MainActivity.this,"點選了--取消--按鈕",Toast.LENGTH_LONG).show();
				selfDialog.dismiss();
			}
		});
		selfDialog.show();
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		int id = item.getItemId();
		if (id == R.id.action_settings) {
			return true;
		}
		return super.onOptionsItemSelected(item);
	}

	@Override
	public void onClick(View v) {
		switch (v.getId()) {
		case R.id.btn_scandevice:
			btn_scan_device.setEnabled(false);
			msg.setText("賣力載入中");
			progressDialog.show();
			doDiscovery();
			break;
		case R.id.btn_disconnectdevice:
			if (mConnected == true) {
				mBluetoothLeService.disconnect();
				for (int i = 0; i < data_connect.size(); i++) {
					if (data_connect.get(i).equals(dataconnectBean)) {

						data_disconnect.add(data_connect.get(i));
						data_connect.remove(i);
					}
				}
				connectListAdapter = new LeDeviceListAdapter(MainActivity.this, data_connect);
				// 為listview指定介面卡
				lv_connect.setAdapter(connectListAdapter);
				connectListAdapter.notifyDataSetChanged();

				disconnectListAdapter = new LeDeviceListAdapter(MainActivity.this, data_disconnect);
				// 為listview指定介面卡
				lv_disconnect.setAdapter(disconnectListAdapter);
				disconnectListAdapter.notifyDataSetChanged();
			}

			if_or_notPair();
			break;
		case R.id.btn_send:

			if (mConnected == false) {
				
			} else {
				if (ed_inout.getText().toString().equals("")) {
					Log.d(TAG, "111111");

				} else {
					
					
					if(isServiceRunning(getApplicationContext(), "com.example.androidbluetooch.BluetoothLeService")==true){
//						Toast.makeText(getApplicationContext(), "存在", Toast.LENGTH_SHORT).show();
						if(target_chara==null){
							
						}else{
							Log.d(TAG, "222222");
							target_chara.setValue(ed_inout.getText().toString());
							// 呼叫藍芽服務的寫特徵值方法實現傳送資料
							mBluetoothLeService.writeCharacteristic(target_chara);
							listview_msg_stringSend();
						}
					}else{
						msgDialog("運行當前所需的服務沒有起來,請至應用管理釋放點記憶體,以保證當前APP所需的執行記憶體");
					}
				}
			}
			if (mhc06Connected == true) {
				if (ed_inout != null && !"".equals(ed_inout)) {
					try {
						mConnectedThread.write(ed_inout.getText().toString().getBytes());
						listview_msg_stringSend();
					} catch (Exception e) {
					}
				}

			}
			if(mConnected==false||mhc06Connected==false){
				listview_msg_stringSend();
			}
			ed_inout.setText("");
			break;
		default:
			break;
		}
	}

	private String getDate() {
		Calendar c = Calendar.getInstance();

		String year = String.valueOf(c.get(Calendar.YEAR));
		String month = String.valueOf(c.get(Calendar.MONTH)+ 1);
		String day = String.valueOf(c.get(Calendar.DAY_OF_MONTH));
		String hour = String.valueOf(c.get(Calendar.HOUR_OF_DAY));
		String mins = String.valueOf(c.get(Calendar.MINUTE));

		StringBuffer sbBuffer = new StringBuffer();
		sbBuffer.append(year + "-" + month + "-" + day + " " + hour + ":" + mins);

		return sbBuffer.toString();
	}

	private void listview_msg_stringSend() {
		/**
		 * 傳送訊息跟新View
		 */
		ChatMsgEntity entity = new ChatMsgEntity();
		entity.setDate(getDate());
		entity.setName("user");
		entity.setMsgType(false);
		entity.setText(ed_inout.getText().toString());
		mDataArrays.add(entity);
		mAdapter.notifyDataSetChanged();
		ed_inout.setText("");
		listview_msgxianshi.setSelection(listview_msgxianshi.getCount() - 1);
	}

	private void listview_msg_stringReceiver(String string) {
		/**
		 * 接收訊息跟新View
		 */
		ChatMsgEntity entity = new ChatMsgEntity();
		entity.setDate(getDate());
		entity.setName("裝置");
		entity.setMsgType(true);
		entity.setText(string);
		mDataArrays.add(entity);
		mAdapter.notifyDataSetChanged();
		listview_msgxianshi.setSelection(listview_msgxianshi.getCount() - 1);
	}

	private void if_or_notPair() {
		if (disconnect_flag == true) {
			if (mhc06Connected == true) {
				if (mConnectThread != null) {
					mConnectThread.cancel();
					mConnectThread = null;
				}
				if (mConnectedThread != null) {
					mConnectedThread.cancel();
					mConnectedThread = null;
				}
				mhc06Connected = false;
				status = "disconnected";
				// 更新連線狀態
				Message msg1 = new Message();
				msg1.what = 3;
				Bundle b = new Bundle();
				b.putString("connect_state", status);
				msg1.setData(b);
				// 將連線狀態更新的UI的textview上
				myHandler.sendMessage(msg1);

			}
		} else {
			if (mhc06Connected == true) {
				if (mConnectThread != null) {
					mConnectThread.cancel();
					mConnectThread = null;
				}
				if (mConnectedThread != null) {
					mConnectedThread.cancel();
					mConnectedThread = null;
				}
				mhc06Connected = false;
				status = "disconnected";
				// 更新連線狀態
				Message msg2 = new Message();
				msg2.what = 2;
				Bundle b = new Bundle();
				b.putString("connect_state", status);
				msg2.setData(b);
				// 將連線狀態更新的UI的textview上
				myHandler.sendMessage(msg2);

			}
		}
	}

	// 搜尋藍芽
	private void doDiscovery() {
		setTitle(R.string.scanning);
		if (mBluetoothAdapter.isDiscovering()) {
			mBluetoothAdapter.cancelDiscovery();
		}
		mBluetoothAdapter.startDiscovery();
	}

	// 搜尋藍芽的廣播
	private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
		@Override
		public void onReceive(Context context, Intent intent) {
			String action = intent.getAction();

			// When discovery finds a device
			if (BluetoothDevice.ACTION_FOUND.equals(action)) {
				// Get the BluetoothDevice object from the Intent
				BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
				// If it's already paired, skip it, because it's been listed
				// already
				if (device.getBondState() != BluetoothDevice.BOND_BONDED) {
					// mNewDevicesArrayAdapter.add(device.getName() + "\n" +
					// device.getAddress());

					if (list.indexOf(device.getAddress().toString()) == -1) {
						Map<String, Object> listem = new HashMap<String, Object>();

						listem.put("dName", device.getName());
						listem.put("dAddress", device.getAddress().toString());
						Log.d("searchBtDevices==", list.toString());
						list.add(device.getAddress());
						Log.d("searchBtDevices==", list.toString());
						Log.d("Devices==", device.getAddress());
						Log.d("==", "not");

						// DeviceBean bean = new DeviceBean();
						// bean.setAddress(device.getAddress());
						// bean.setName(device.getName());

						data_disconnect.add(device);

						disconnectListAdapter = new LeDeviceListAdapter(MainActivity.this, data_disconnect);
						// 為listview指定介面卡
						lv_disconnect.setAdapter(disconnectListAdapter);
						disconnectListAdapter.notifyDataSetChanged();
					} else {
						Log.d("==", "have");
					}
				}
			} else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
				btn_scan_device.setEnabled(true);
				progressDialog.dismiss();
				setTitle(R.string.select_device);
			}
		}
	};

	/* BluetoothLeService繫結的回撥函式 */
	private final ServiceConnection mServiceConnection = new ServiceConnection() {

		@Override
		public void onServiceConnected(ComponentName componentName, IBinder service) {
			mBluetoothLeService = ((BluetoothLeService.LocalBinder) service).getService();
			if (!mBluetoothLeService.initialize()) {
				Log.e("MainActivity.this", "Unable to initialize Bluetooth");
				finish();
			}
			// Automatically connects to the device upon successful start-up
			// initialization.
			// 根據藍芽地址,連線裝置
			// 每次連線之前關閉上一次連線,這樣在第二次連線藍芽的時候速度快
			// 部落格參考http://bbs.eeworld.com.cn/thread-438571-1-1.html
			mBluetoothLeService.close();
			mBluetoothLeService.connect(mDeviceAddress);

		}

		@Override
		public void onServiceDisconnected(ComponentName componentName) {
			mBluetoothLeService = null;
		}

	};
	/**
	 * 廣播接收器,負責接收BluetoothLeService類傳送的資料
	 */
	private final BroadcastReceiver mGattUpdateReceiver = new BroadcastReceiver() {
		@Override
		public void onReceive(Context context, Intent intent) {
			final String action = intent.getAction();
			if (BluetoothLeService.ACTION_GATT_CONNECTED.equals(action))// Gatt連線成功
			{
				progressDialog.dismiss();
				mConnected = true;
				status = "connected";
				// 更新連線狀態
				updateConnectionState(status);
				System.out.println("BroadcastReceiver :" + "device connected");

				data_connect.add(data_disconnect.get(data_onitemclick));

				data_disconnect.remove(data_onitemclick);
				disconnectListAdapter = new LeDeviceListAdapter(MainActivity.this, data_disconnect);
				// 為listview指定介面卡
				lv_disconnect.setAdapter(disconnectListAdapter);
				disconnectListAdapter.notifyDataSetChanged();

				connectListAdapter = new LeDeviceListAdapter(MainActivity.this, data_connect);
				// 為listview指定介面卡
				lv_connect.setAdapter(connectListAdapter);
				connectListAdapter.notifyDataSetChanged();

			} else if (BluetoothLeService.ACTION_GATT_DISCONNECTED// Gatt連線失敗
					.equals(action)) {
				progressDialog.dismiss();
				mConnected = false;
				status = "disconnected";
				// 更新連線狀態
				updateConnectionState(status);
				System.out.println("BroadcastReceiver :" + "device disconnected");

				for (int i = 0; i < data_connect.size(); i++) {
					if (data_connect.get(i).equals(dataconnectBean)) {

						data_disconnect.add(data_connect.get(i));
						data_connect.remove(i);
					}
				}
				connectListAdapter = new LeDeviceListAdapter(MainActivity.this, data_connect);
				// 為listview指定介面卡
				lv_connect.setAdapter(connectListAdapter);
				connectListAdapter.notifyDataSetChanged();

				disconnectListAdapter = new LeDeviceListAdapter(MainActivity.this, data_disconnect);
				// 為listview指定介面卡
				lv_disconnect.setAdapter(disconnectListAdapter);
				disconnectListAdapter.notifyDataSetChanged();

			} else if (BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED// 發現GATT伺服器
					.equals(action)) {
				// Show all the supported services and characteristics on the
				// user interface.
				// 獲取裝置的所有藍芽服務
				displayGattServices(mBluetoothLeService.getSupportedGattServices());
				System.out.println("BroadcastReceiver :" + "device SERVICES_DISCOVERED");
			} else if (BluetoothLeService.ACTION_DATA_AVAILABLE.equals(action)) {// 有效資料
				// 處理髮送過來的資料
				Log.d(TAG, intent.getStringExtra(BluetoothLeService.EXTRA_DATA));
				listview_msg_stringReceiver(intent.getStringExtra(BluetoothLeService.EXTRA_DATA));
			}
		}
	};

	/* 更新連線狀態 */
	private void updateConnectionState(String status) {
		Message msg = new Message();
		msg.what = 1;
		Bundle b = new Bundle();
		b.putString("connect_state", status);
		msg.setData(b);
		// 將連線狀態更新的UI的textview上
		myHandler.sendMessage(msg);
		System.out.println("connect_state:" + status);

	}

	/**
	 * @Title: displayGattServices @Description: TODO(處理藍芽服務) @param 無 @return
	 *         void @throws
	 */
	private void displayGattServices(List<BluetoothGattService> gattServices) {

		if (gattServices == null)
			return;
		String uuid = null;
		// 服務資料,可擴充套件下拉列表的第一級資料
		ArrayList<HashMap<String, String>> gattServiceData = new ArrayList<HashMap<String, String>>();

		// 特徵資料(隸屬於某一級服務下面的特徵值集合)
		ArrayList<ArrayList<HashMap<String, String>>> gattCharacteristicData = new ArrayList<ArrayList<HashMap<String, String>>>();

		// 部分層次,所有特徵值集合
		mGattCharacteristics = new ArrayList<ArrayList<BluetoothGattCharacteristic>>();

		// Loops through available GATT Services.
		for (BluetoothGattService gattService : gattServices) {

			// 獲取服務列表
			HashMap<String, String> currentServiceData = new HashMap<String, String>();
			uuid = gattService.getUuid().toString();

			// 查表,根據該uuid獲取對應的服務名稱。SampleGattAttributes這個表需要自定義。

			gattServiceData.add(currentServiceData);

			System.out.println("Service uuid:" + uuid);

			ArrayList<HashMap<String, String>> gattCharacteristicGroupData = new ArrayList<HashMap<String, String>>();

			// 從當前迴圈所指向的服務中讀取特徵值列表
			List<BluetoothGattCharacteristic> gattCharacteristics = gattService.getCharacteristics();

			ArrayList<BluetoothGattCharacteristic> charas = new ArrayList<BluetoothGattCharacteristic>();

			// Loops through available Characteristics.
			// 對於當前迴圈所指向的服務中的每一個特徵值
			for (final BluetoothGattCharacteristic gattCharacteristic : gattCharacteristics) {
				charas.add(gattCharacteristic);
				HashMap<String, String> currentCharaData = new HashMap<String, String>();
				uuid = gattCharacteristic.getUuid().toString();

				if (gattCharacteristic.getUuid().toString().equals(HEART_RATE_MEASUREMENT)) {
					// 測試讀取當前Characteristic資料,會觸發mOnDataAvailable.onCharacteristicRead()
					mhandler.postDelayed(new Runnable() {

						@Override
						public void run() {
							mBluetoothLeService.readCharacteristic(gattCharacteristic);
						}
					}, 200);

					// 接受Characteristic被寫的通知,收到藍芽模組的資料後會觸發mOnDataAvailable.onCharacteristicWrite()
					mBluetoothLeService.setCharacteristicNotification(gattCharacteristic, true);
					target_chara = gattCharacteristic;
					// 設定資料內容
					// 往藍芽模組寫入資料
					// mBluetoothLeService.writeCharacteristic(gattCharacteristic);
				}
				List<BluetoothGattDescriptor> descriptors = gattCharacteristic.getDescriptors();
				for (BluetoothGattDescriptor descriptor : descriptors) {
					System.out.println("---descriptor UUID:" + descriptor.getUuid());
					// 獲取特徵值的描述
					mBluetoothLeService.getCharacteristicDescriptor(descriptor);
					// mBluetoothLeService.setCharacteristicNotification(gattCharacteristic,
					// true);
				}

				gattCharacteristicGroupData.add(currentCharaData);
			}
			// 按先後順序,分層次放入特徵值集合中,只有特徵值
			mGattCharacteristics.add(charas);
			// 構件第二級擴充套件列表(服務下面的特徵值)
			gattCharacteristicData.add(gattCharacteristicGroupData);

		}

	}

	/* 意圖過濾器 */
	private static IntentFilter makeGattUpdateIntentFilter() {
		final IntentFilter intentFilter = new IntentFilter();
		intentFilter.addAction(BluetoothLeService.ACTION_GATT_CONNECTED);
		intentFilter.addAction(BluetoothLeService.ACTION_GATT_DISCONNECTED);
		intentFilter.addAction(BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED);
		intentFilter.addAction(BluetoothLeService.ACTION_DATA_AVAILABLE);
		return intentFilter;
	}

	// HC-06藍芽的連線方法
	public void connect(BluetoothDevice device) {
		Log.d(TAG, "connect to: " + device);
		// Start the thread to connect with the given device
		mConnectThread = new ConnectThread(device);
		mConnectThread.start();
	}

	/**
	 * This thread runs while attempting to make an outgoing connection with a
	 * device. It runs straight through; the connection either succeeds or
	 * fails.
	 */
	// HC-06藍芽的連線方法
	private class ConnectThread extends Thread {
		private final BluetoothSocket mmSocket;

		public ConnectThread(BluetoothDevice device) {
			BluetoothSocket tmp = null;

			// Get a BluetoothSocket for a connection with the
			// given BluetoothDevice
			try {
				tmp = device.createRfcommSocketToServiceRecord(UUID.fromString(SPP_UUID));
			} catch (IOException e) {
				Log.e(TAG, "create() failed", e);
			}
			mmSocket = tmp;
		}

		public void run() {
			Log.i(TAG, "BEGIN mConnectThread");
			setName("ConnectThread");

			// Always cancel discovery because it will slow down a connection
			mBluetoothAdapter.cancelDiscovery();

			// Make a connection to the BluetoothSocket
			try {
				// This is a blocking call and will only return on a
				// successful connection or an exception
				mmSocket.connect();
			} catch (IOException e) {
				progressDialog.dismiss();
				Log.e(TAG, "unable to connect() socket", e);
				// Close the socket
				try {
					mmSocket.close();
				} catch (IOException e2) {
					Log.e(TAG, "unable to close() socket during connection failure", e2);
				}
				return;
			}

			mConnectThread = null;
			progressDialog.dismiss();
			if (disconnect_flag == true) {
				mhc06Connected = true;
				status = "connected";
				// 更新連線狀態
				Message msg = new Message();
				msg.what = 3;
				Bundle b = new Bundle();
				b.putString("connect_state", status);
				msg.setData(b);
				// 將連線狀態更新的UI的textview上
				myHandler.sendMessage(msg);
			} else {
				mhc06Connected = true;
				status = "connected";
				// 更新連線狀態
				Message msg = new Message();
				msg.what = 2;
				Bundle b = new Bundle();
				b.putString("connect_state", status);
				msg.setData(b);
				// 將連線狀態更新的UI的textview上
				myHandler.sendMessage(msg);
			}
			// Start the connected thread
			// Start the thread to manage the connection and perform
			// transmissions
			mConnectedThread = new ConnectedThread(mmSocket);
			mConnectedThread.start();

		}

		public void cancel() {
			try {
				mmSocket.close();
			} catch (IOException e) {
				Log.e(TAG, "close() of connect socket failed", e);
			}
		}
	}

	/**
	 * This thread runs during a connection with a remote device. It handles all
	 * incoming and outgoing transmissions.
	 */
	// HC-06藍芽的連線方法
	private class ConnectedThread extends Thread {
		private final BluetoothSocket mmSocket;
		private final InputStream mmInStream;
		private final OutputStream mmOutStream;

		public ConnectedThread(BluetoothSocket socket) {
			Log.d(TAG, "create ConnectedThread");
			mmSocket = socket;
			InputStream tmpIn = null;
			OutputStream tmpOut = null;

			// Get the BluetoothSocket input and output streams
			try {
				tmpIn = socket.getInputStream();
				tmpOut = socket.getOutputStream();
			} catch (IOException e) {
				Log.e(TAG, "temp sockets not created", e);
			}

			mmInStream = tmpIn;
			mmOutStream = tmpOut;
		}

		public void run() {
			Log.i(TAG, "BEGIN mConnectedThread");
			byte[] buffer = new byte[256];
			int bytes;

			// Keep listening to the InputStream while connected
			while (true) {
				try {
					// //HC-06藍芽的讀資料方法
					bytes = mmInStream.read(buffer);
					Log.d(TAG, "" + new String(buffer));

					Message msg1 = new Message();
					msg1.what = 4;
					Bundle b = new Bundle();
					b.putString("updata_msg", new String(buffer));
					msg1.setData(b);
					// 將連線狀態更新的UI的textview上
					myHandler.sendMessage(msg1);

					synchronized (mBuffer) {
						for (int i = 0; i < bytes; i++) {
							mBuffer.add(buffer[i] & 0xFF);
						}
					}
					// mHandler.sendEmptyMessage(MSG_NEW_DATA);
				} catch (IOException e) {
					Log.e(TAG, "disconnected", e);
					break;
				}
			}
		}

		/**
		 * Write to the connected OutStream.
		 * 
		 * @param buffer
		 *            The bytes to write
		 */
		// HC-06藍芽的寫資料方法
		public void write(byte[] buffer) {
			try {
				mmOutStream.write(buffer);
			} catch (IOException e) {
				Log.e(TAG, "Exception during write", e);
			}
		}

		public void cancel() {
			try {
				mmSocket.close();
			} catch (IOException e) {
				Log.e(TAG, "close() of connect socket failed", e);
			}
		}
	}

	private int dp2px(int dp) {
		return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, getResources().getDisplayMetrics());
	}

	@Override
	public void onItemClick(AdapterView<?> arg0, View arg1, int position, long arg3) {
		switch (arg0.getId()) {
		// 已經配對的藍芽點選事件
		case R.id.lv_connect:
			if (mConnected == true || mhc06Connected == true) {
				Toast.makeText(MainActivity.this, "請先斷開當前連線", Toast.LENGTH_SHORT).show();
			} else {
				if (data_connect.get(position).getName().equals("HC-06")) {
					msg.setText("連線藍芽中");
					progressDialog.show();
					BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(data_connect.get(position).getAddress());
					// Attempt to connect to the device
					connect(device);
					connect_string = data_connect.get(position).getName();
					datahc06_onitemclick = position;
					disconnect_flag = true;
				} else {
					Toast.makeText(getApplicationContext(), "該功能只支援連線HC-06,08藍芽模組", Toast.LENGTH_SHORT).show();
				}
			}
			break;
		// 未配對的藍芽點選事件
		case R.id.lv_disconnect:
			if (mConnected == true || mhc06Connected == true) {
				Toast.makeText(MainActivity.this, "請先斷開當前連線", Toast.LENGTH_SHORT).show();
			} else {
				if (data_disconnect.get(position).getName().equals("HC-08")) {
					msg.setText("連線藍芽中");
					progressDialog.show();
					data_onitemclick = position;
					dataconnectBean = data_disconnect.get(position);
					mDeviceAddress = data_disconnect.get(position).getAddress();
					Log.d(TAG, "111" + data_disconnect.get(position).getAddress());
					if (mBluetoothLeService != null) {
						// 每次連線之前關閉上一次連線,這樣在第二次連線藍芽的時候速度快
						// 部落格參考http://bbs.eeworld.com.cn/thread-438571-1-1.html
						mBluetoothLeService.close();
						final boolean result = mBluetoothLeService.connect(mDeviceAddress);
						connect_string = data_disconnect.get(position).getName();
						Log.d(TAG, "Connect request result=" + result);
					}

				} else if (data_disconnect.get(position).getName().equals("HC-06")) {
					msg.setText("連線藍芽中");
					progressDialog.show();
					BluetoothDevice device = mBluetoothAdapter
							.getRemoteDevice(data_disconnect.get(position).getAddress());
					// Attempt to connect to the device
					connect(device);
					connect_string = data_disconnect.get(position).getName();
					datahc06_onitemclick = position;
				} else {
					Toast.makeText(getApplicationContext(), "該功能只支援連線HC-06,08藍芽模組", Toast.LENGTH_SHORT).show();
				}
			}
			break;
		default:
			break;
		}
	}
	//判斷com.hf.tabhost.BluetoothLeService是否被系統殺死
	public static boolean isServiceRunning(Context mContext, String className) {
		boolean isRunning = false;
		ActivityManager activityManager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
		List<ActivityManager.RunningServiceInfo> serviceList = activityManager.getRunningServices(30);
		if (!(serviceList.size() > 0)) {
			return false;
		}
		for (int i = 0; i < serviceList.size(); i++) {
			if (serviceList.get(i).service.getClassName().equals(className) == true) {
				isRunning = true;
				break;
			}
		}
		return isRunning;
	}
	@Override
	protected void onDestroy() {
		super.onDestroy();

		// Make sure we're not doing discovery anymore
		if (mBluetoothAdapter != null) {
			mBluetoothAdapter.cancelDiscovery();
		}

		// Unregister broadcast listeners
		this.unregisterReceiver(mReceiver);

		// 解除廣播接收器
		unregisterReceiver(mGattUpdateReceiver);
		mBluetoothLeService = null;
	}
}

5.程式碼下載地址:CSDN:http://download.csdn.net/download/qq_31546677/10151400

CSDN上傳下載分不能為0了所以我選擇了最少的2分,資源分不多的可以去我github下載,喜歡的可以點個star哦,謝謝了!

6.還有一個樓主寫了一個專門用於arduino控制藍芽小車的APP喜歡的和需要的可以去應用寶下載下來爽爽哦,個人感覺比SPP功能強太多哦,歡迎下載,搜尋HFEasyControl

6.插播幾張APP的截圖給大家爽爽