代码改变世界

Android蓝牙3.0和4.0开发记录

2016-04-01 10:25  一切尽在掌握  阅读(880)  评论(0编辑  收藏  举报

至于3.0和4.0的区别后续再补。

1、3.0

 

先获取默认的蓝牙适配器

    /* 取得默认的蓝牙适配器 */
    private BluetoothAdapter _bluetooth = BluetoothAdapter.getDefaultAdapter();

 

再判断有没有打开蓝牙

        /* 如果蓝牙适配器没有打开,则结果 */
        if (!_bluetooth.isEnabled()) {

            finish();
            return;
        }

 

注册找到设备和扫描结束的监听

        /* 注册接收器 */
        IntentFilter discoveryFilter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
        registerReceiver(_discoveryReceiver, discoveryFilter);
        
        IntentFilter foundFilter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
        registerReceiver(_foundReceiver, foundFilter);

 监听到扫描到设备则取出

	private BroadcastReceiver _foundReceiver = new BroadcastReceiver() {
		public void onReceive(Context context, Intent intent) {
			/* 从intent中取得搜索结果数据 */
			BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
			/* 将结果添加到列表中 */
			_devices.add(device);
			/* 显示列表 */
			showDevices();
		}
	};

 定义一个list用来存储扫描到的蓝牙设备

	/* 用来存储搜索到的蓝牙设备 */
	private List<BluetoothDevice> _devices = new ArrayList<BluetoothDevice>();

 监听到扫描结束的广播则卸载监听并置位

	private BroadcastReceiver _discoveryReceiver = new BroadcastReceiver() {

		@Override
		public void onReceive(Context context, Intent intent) {
			/* 卸载注册的接收器 */
			unregisterReceiver(_foundReceiver);
			unregisterReceiver(this);
			_discoveryFinished = true;
		}
	};

 然后准备个Runnable,至于为什么需要Runnable,有什么用?系统不是会自己发扫描结束的广播吗?测试了下并非一定要用Runnable,系统会在12秒后自动结束扫描

	private Runnable _discoveryWorkder = new Runnable() {
		public void run() {
			/* 开始搜索 */
			_bluetooth.startDiscovery();
			for (;;) {
				if (_discoveryFinished) {
					break;
				}
				try {
					Thread.sleep(100);
				} catch (InterruptedException e) {
				}
			}
		}
	};

12秒后结束扫描,源码上的体现:

    /**
     * Start the remote device discovery process.
     * <p>The discovery process usually involves an inquiry scan of about 12
     * seconds, followed by a page scan of each new device to retrieve its
     * Bluetooth name.
     * <p>This is an asynchronous call, it will return immediately. Register
     * for {@link #ACTION_DISCOVERY_STARTED} and {@link
     * #ACTION_DISCOVERY_FINISHED} intents to determine exactly when the
     * discovery starts and completes. Register for {@link
     * BluetoothDevice#ACTION_FOUND} to be notified as remote Bluetooth devices
     * are found.
     * <p>Device discovery is a heavyweight procedure. New connections to
     * remote Bluetooth devices should not be attempted while discovery is in
     * progress, and existing connections will experience limited bandwidth
     * and high latency. Use {@link #cancelDiscovery()} to cancel an ongoing
     * discovery. Discovery is not managed by the Activity,
     * but is run as a system service, so an application should always call
     * {@link BluetoothAdapter#cancelDiscovery()} even if it
     * did not directly request a discovery, just to be sure.
     * <p>Device discovery will only find remote devices that are currently
     * <i>discoverable</i> (inquiry scan enabled). Many Bluetooth devices are
     * not discoverable by default, and need to be entered into a special mode.
     * <p>If Bluetooth state is not {@link #STATE_ON}, this API
     * will return false. After turning on Bluetooth,
     * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON}
     * to get the updated value.
     * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}.
     *
     * @return true on success, false on error
     */
    public boolean startDiscovery() {
        if (getState() != STATE_ON) return false;
        try {
            synchronized(mManagerCallback) {
                if (mService != null) return mService.startDiscovery();
            }
        } catch (RemoteException e) {Log.e(TAG, "", e);}
        return false;
    }

 

创建个正在扫描的对话框:

		/* 显示一个对话框,正在搜索蓝牙设备 */
		SamplesUtils.indeterminate(DiscoveryActivity.this, _handler, "Scanning...", _discoveryWorkder, new OnDismissListener() {
			public void onDismiss(DialogInterface dialog) {

				for (; _bluetooth.isDiscovering();) {

					_bluetooth.cancelDiscovery();
				}

				_discoveryFinished = true;
			}
		}, true);

 

	private static void indeterminateInternal(Context context, final Handler handler, String message, final Runnable runnable, OnDismissListener dismissListener, boolean cancelable) {

		final ProgressDialog dialog = createProgressDialog(context, message);
		dialog.setCancelable(cancelable);

		if (dismissListener != null) {

			dialog.setOnDismissListener(dismissListener);
		}

		dialog.show();

		new Thread() {

			@Override
			public void run() {
				runnable.run();

				handler.post(new Runnable() {

					public void run() {

						try {

							dialog.dismiss();
						} catch (Exception e) {
						}
					}
				});
			};
		}.start();
	}

 

	private static ProgressDialog createProgressDialog(Context context, String message) {

		ProgressDialog dialog = new ProgressDialog(context);
		dialog.setIndeterminate(false);
		dialog.setMessage(message);

		return dialog;
	}

 OK  就这样了

分析下蓝牙ble

首先检查是否支持蓝牙BLE

		// 检查当前手机是否支持ble 蓝牙,如果不支持退出程序
		if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
			Toast.makeText(this, R.string.ble_not_supported, Toast.LENGTH_SHORT).show();
			finish();
		}

		// 初始化 Bluetooth adapter, 通过蓝牙管理器得到一个参考蓝牙适配器(API必须在以上android4.3或以上和版本)
		final BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
		mBluetoothAdapter = bluetoothManager.getAdapter();

		// 检查设备上是否支持蓝牙
		if (mBluetoothAdapter == null) {
			Toast.makeText(this, R.string.error_bluetooth_not_supported, Toast.LENGTH_SHORT).show();
			finish();
			return;
		}

 开启扫描,需要自己设置结束的时间

	private void scanLeDevice(final boolean enable) {
		if (enable) {
			// Stops scanning after a pre-defined scan period.
			mHandler.postDelayed(new Runnable() {
				@Override
				public void run() {
					mScanning = false;
					mBluetoothAdapter.stopLeScan(mLeScanCallback);
				}
			}, SCAN_PERIOD);//BLE会不停的进行扫描

			mScanning = true;
			mBluetoothAdapter.startLeScan(mLeScanCallback);
		} else {
			mScanning = false;
			mBluetoothAdapter.stopLeScan(mLeScanCallback);
		}
	}

 开启扫描和结束扫描都要传LeScanCallback callback

	private BluetoothAdapter.LeScanCallback mLeScanCallback = new BluetoothAdapter.LeScanCallback() {

		@Override
		public void onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord) {
			runOnUiThread(new Runnable() {
				@Override
				public void run() {
					mLeDeviceListAdapter.addDevice(device);//TODO 扫描完之后在这里添加
					mLeDeviceListAdapter.notifyDataSetChanged();
				}
			});
		}
		
	};