android5.0 进行蓝牙广播(BLE Peripheral)

具有低功耗蓝牙模块的设备可以扮演2个角色,中心,周边。周边是数据提供者,中心是数据接收/处理者。自Android 4.3的系统就规定了BLE的API,但是仅限于中心,至于周边一直没有API的支持。直到Android 5.0的出现,才带来了周边API的支持(BluetoothLeAdvertiser)。

public class Main4Activity extends AppCompatActivity implements View.OnClickListener {


public final static UUID CLIENT_CHARACTERISTIC_CONFIG = UUID.fromString("00002902-0000-1000-8000-00805f9b34fb");
public final static UUID UUID_LOST_SERVICE = UUID.fromString("0000fff0-0000-1000-8000-00805f9b34fb");
public final static UUID UUID_LOST_WRITE = UUID.fromString("0000fff1-0000-1000-8000-00805f9b34fb");
public final static UUID UUID_LOST_ENABLE = UUID.fromString("0000fff2-0000-1000-8000-00805f9b34fb");

private static final String TAG = "yushu";
private TextView txtDevice;
private Button btnStart;
private Button btnNotify;
private Button btnStop;

private BluetoothManager mBluetoothManager;
private BluetoothLeAdvertiser mBluetoothLeAdvertiser;

private BluetoothGattServer gattServer;
private BluetoothGattCharacteristic characterNotify;
private BluetoothDevice bluetoothDevice;


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main4);
    initView();
    initBLE();
    setServer();
}

private void initView() {
    txtDevice = (TextView) findViewById(R.id.txt_device);
    btnStart = (Button) findViewById(R.id.btn_start);
    btnNotify = (Button) findViewById(R.id.btn_notify);
    btnStop = (Button) findViewById(R.id.btn_stop);
    btnNotify.setOnClickListener(this);
    btnStart.setOnClickListener(this);
    btnStop.setOnClickListener(this);
}


/**
 * 初始化蓝牙
 */
private void initBLE() {
    if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
        Toast.makeText(this, "不支持BLE", Toast.LENGTH_LONG).show();
        finish();
    }
    mBluetoothManager = (BluetoothManager) getSystemService(BLUETOOTH_SERVICE);
    BluetoothAdapter mBluetoothAdapter = mBluetoothManager.getAdapter();
    if (mBluetoothAdapter == null) {
        Toast.makeText(this, "蓝牙不支持", Toast.LENGTH_LONG).show();
        finish();
    }
    assert mBluetoothAdapter != null;
    mBluetoothLeAdvertiser = mBluetoothAdapter.getBluetoothLeAdvertiser();
    if (mBluetoothLeAdvertiser == null) {
        Toast.makeText(this, "the device not support peripheral", Toast.LENGTH_SHORT).show();
        finish();
    }
}


/**
 * 添加服务,特征
 */
private void setServer() {
    //读写特征
    BluetoothGattCharacteristic characterWrite = new BluetoothGattCharacteristic(
            UUID_LOST_WRITE, BluetoothGattCharacteristic.PROPERTY_READ | BluetoothGattCharacteristic.PROPERTY_WRITE,
            BluetoothGattCharacteristic.PERMISSION_READ | BluetoothGattCharacteristic.PERMISSION_WRITE);
    //使能特征
    characterNotify = new BluetoothGattCharacteristic(UUID_LOST_ENABLE,
            BluetoothGattCharacteristic.PROPERTY_NOTIFY, BluetoothGattCharacteristic.PERMISSION_READ);
    characterNotify.addDescriptor(new BluetoothGattDescriptor(CLIENT_CHARACTERISTIC_CONFIG, BluetoothGattDescriptor.PERMISSION_WRITE | BluetoothGattCharacteristic.PERMISSION_READ));
    //服务
    BluetoothGattService gattService = new BluetoothGattService(UUID_LOST_SERVICE,
            BluetoothGattService.SERVICE_TYPE_PRIMARY);
    //为服务添加特征
    gattService.addCharacteristic(characterWrite);
    gattService.addCharacteristic(characterNotify);
    //管理服务,连接和数据交互回调
    gattServer = mBluetoothManager.openGattServer(this,
            new BluetoothGattServerCallback() {

                @Override
                public void onConnectionStateChange(final BluetoothDevice device,
                                                    final int status, final int newState) {
                    super.onConnectionStateChange(device, status, newState);
                    bluetoothDevice = device;
                    Log.d("Chris", "onConnectionStateChange:" + device + "    " + status + "   " + newState);
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            txtDevice.setText(device.getAddress() + "   " + device.getName() + "   " + status + "  " + newState);
                        }
                    });
                }

                @Override
                public void onServiceAdded(int status,
                                           BluetoothGattService service) {
                    super.onServiceAdded(status, service);
                    Log.d("Chris", "service added");
                }

                @Override
                public void onCharacteristicReadRequest(
                        BluetoothDevice device, int requestId, int offset,
                        BluetoothGattCharacteristic characteristic) {
                    super.onCharacteristicReadRequest(device, requestId,
                            offset, characteristic);
                    gattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, offset, characteristic.getValue());
                    Log.d("Chris", "onCharacteristicReadRequest");
                }

                @Override
                public void onCharacteristicWriteRequest(
                        BluetoothDevice device, int requestId,
                        BluetoothGattCharacteristic characteristic,
                        boolean preparedWrite, boolean responseNeeded,
                        int offset, final byte[] value) {
                    super.onCharacteristicWriteRequest(device, requestId,
                            characteristic, preparedWrite, responseNeeded,
                            offset, value);
                    gattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, offset, null);
                    Log.d("Chris", "onCharacteristicWriteRequest" + value[0]);
                    runOnUiThread(new Runnable() {
                        @SuppressLint("SetTextI18n")
                        @Override
                        public void run() {
                            txtDevice.setText(value[0] + "");
                        }
                    });
                }

                @Override
                public void onNotificationSent(BluetoothDevice device, int status) {
                    super.onNotificationSent(device, status);
                    Log.i(TAG, "onNotificationSent: ");
                }

                @Override
                public void onMtuChanged(BluetoothDevice device, int mtu) {
                    super.onMtuChanged(device, mtu);
                }

                @Override
                public void onDescriptorReadRequest(BluetoothDevice device,
                                                    int requestId, int offset,
                                                    BluetoothGattDescriptor descriptor) {
                    super.onDescriptorReadRequest(device, requestId,
                            offset, descriptor);
                    gattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, offset, characterNotify.getValue());
                    Log.d("Chris", "onDescriptorReadRequest");
                }

                @Override
                public void onDescriptorWriteRequest(BluetoothDevice device, int requestId,
                                                     BluetoothGattDescriptor descriptor, boolean preparedWrite, boolean responseNeeded,
                                                     int offset, byte[] value) {
                    super.onDescriptorWriteRequest(device, requestId, descriptor, preparedWrite, responseNeeded,
                            offset, value);
                    gattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, offset, value);
//                        characterNotify.setValue("HIHHHHH");
//                        gattServer.notifyCharacteristicChanged(bluetoothDevice, characterNotify, false);
                    Log.d("Chris", "onDescriptorWriteRequest");
                }

                @Override
                public void onExecuteWrite(BluetoothDevice device,
                                           int requestId, boolean execute) {
                    super.onExecuteWrite(device, requestId, execute);
                    Log.d("Chris", "onExecuteWrite");
                }
            });
    gattServer.addService(gattService);
}

/**
  *广播的一些基本设置
  **/
public AdvertiseSettings createAdvSettings(boolean connectAble, int timeoutMillis) {
    AdvertiseSettings.Builder builder = new AdvertiseSettings.Builder();
    builder.setAdvertiseMode(AdvertiseSettings.ADVERTISE_MODE_BALANCED);
    builder.setConnectable(connectAble);
    builder.setTimeout(timeoutMillis);
    builder.setTxPowerLevel(AdvertiseSettings.ADVERTISE_TX_POWER_HIGH);
    AdvertiseSettings mAdvertiseSettings = builder.build();
    if (mAdvertiseSettings == null) {
        Toast.makeText(this, "mAdvertiseSettings == null", Toast.LENGTH_LONG).show();
        Log.e(TAG, "mAdvertiseSettings == null");
    }
    return mAdvertiseSettings;
}


@Override
public void onClick(View v) {
    if (v == btnNotify) {
        characterNotify.setValue("HIHHHHH");
        gattServer.notifyCharacteristicChanged(bluetoothDevice, characterNotify, false);
    } else if (v == btnStart) {
        mBluetoothLeAdvertiser.startAdvertising(createAdvSettings(true, 0), createAdvertiseData(), mAdvertiseCallback);
    } else if (v == btnStop) {
        stopAdvertise();
    }
}


private void stopAdvertise() {
    if (mBluetoothLeAdvertiser != null) {
        mBluetoothLeAdvertiser.stopAdvertising(mAdvertiseCallback);
    }
}


//广播数据
public AdvertiseData createAdvertiseData() {
    AdvertiseData.Builder mDataBuilder = new AdvertiseData.Builder();
    mDataBuilder.setIncludeDeviceName(true); //广播名称也需要字节长度
    mDataBuilder.setIncludeTxPowerLevel(true);
    mDataBuilder.addServiceData(ParcelUuid.fromString("0000fff0-0000-1000-8000-00805f9b34fb"),new byte[]{1,2});
    AdvertiseData mAdvertiseData = mDataBuilder.build();
    if (mAdvertiseData == null) {
        Toast.makeText(Main4Activity.this, "mAdvertiseSettings == null", Toast.LENGTH_LONG).show();
        Log.e(TAG, "mAdvertiseSettings == null");
    }
    return mAdvertiseData;
}


private AdvertiseCallback mAdvertiseCallback = new AdvertiseCallback() {
    @Override
    public void onStartSuccess(AdvertiseSettings settingsInEffect) {
        super.onStartSuccess(settingsInEffect);
        if (settingsInEffect != null) {
            Log.d(TAG, "onStartSuccess TxPowerLv=" + settingsInEffect.getTxPowerLevel() + " mode=" + settingsInEffect.getMode()
                    + " timeout=" + settingsInEffect.getTimeout());
        } else {
            Log.e(TAG, "onStartSuccess, settingInEffect is null");
        }
        Log.e(TAG, "onStartSuccess settingsInEffect" + settingsInEffect);

    }

    @Override
    public void onStartFailure(int errorCode) {
        super.onStartFailure(errorCode);
        Log.e(TAG, "onStartFailure errorCode" + errorCode);

        if (errorCode == ADVERTISE_FAILED_DATA_TOO_LARGE) {
            Toast.makeText(Main4Activity.this, "R.string.advertise_failed_data_too_large", Toast.LENGTH_LONG).show();
            Log.e(TAG, "Failed to start advertising as the advertise data to be broadcasted is larger than 31 bytes.");
        } else if (errorCode == ADVERTISE_FAILED_TOO_MANY_ADVERTISERS) {
            Toast.makeText(Main4Activity.this, "R.string.advertise_failed_too_many_advertises", Toast.LENGTH_LONG).show();
            Log.e(TAG, "Failed to start advertising because no advertising instance is available.");
        } else if (errorCode == ADVERTISE_FAILED_ALREADY_STARTED) {
            Toast.makeText(Main4Activity.this, "R.string.advertise_failed_already_started", Toast.LENGTH_LONG).show();
            Log.e(TAG, "Failed to start advertising as the advertising is already started");
        } else if (errorCode == ADVERTISE_FAILED_INTERNAL_ERROR) {
            Toast.makeText(Main4Activity.this, "R.string.advertise_failed_internal_error", Toast.LENGTH_LONG).show();
            Log.e(TAG, "Operation failed due to an internal error");
        } else if (errorCode == ADVERTISE_FAILED_FEATURE_UNSUPPORTED) {
            Toast.makeText(Main4Activity.this, "R.string.advertise_failed_feature_unsupported", Toast.LENGTH_LONG).show();
            Log.e(TAG, "This feature is not supported on this platform");
        }
    }
};
}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,826评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,968评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,234评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,562评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,611评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,482评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,271评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,166评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,608评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,814评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,926评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,644评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,249评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,866评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,991评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,063评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,871评论 2 354

推荐阅读更多精彩内容