classic bluetooth chat 三

来源:互联网 发布:动态网站源码 编辑:程序博客网 时间:2024/05/17 22:27

第3节 获取要连接的设备

这一节我们开始设计蓝牙聊天应用的界面。根据之前的规划,连接管理将放在单独的ConnectionManager模块当中,所以每当要使用连接功能的时候,我们就暂时把它空着,等到ConnectionManager开发完成之后再加进来。

这里我们将完成下面的界面设计,

3.1 主界面

主界面是一个独立的ActivityChatActivity,它要实现三个主要功能,

  1. 当蓝牙没有开启或者设备不能被发现的时候,请求用户打开对应的功能;
  2. 下方有输入框输入要发送的文字内容,点击按钮后能实现文字的发送;输入框上方的大部分区域用来显示聊天的内容;
  3. 菜单栏根据当前蓝牙连接的状态,显示不同的菜单项。例如,没有连接时启动蓝牙设备选择界面;

3.1.1 打开蓝牙功能

ChatActivity创建的时候,查询当前蓝牙设备是否满足运行的要求,

  1. 提示开启蓝牙功能,

    @Overrideprotected void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    setContentView(R.layout.activity_chat);    //如果蓝牙功能没有打开,请用户开启蓝牙功能    BluetoothAdapter BTAdapter = BluetoothAdapter.getDefaultAdapter();    if (!BTAdapter.isEnabled()) {        Intent i = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);        startActivity(i);        finish();        return;    }}
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
  2. 提示开启被其它蓝牙设备发现的功能,

    @Overrideprotected void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    setContentView(R.layout.activity_chat);    ......    //如果被其它蓝牙设备发现的功能没有打开,请用户开启    if(BTAdapter.getScanMode() != BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE) {        Intent i = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);        //设置为一直开启        i.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 0);        startActivity(i);    }}
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

3.1.2 界面布局

界面布局比较简单,使用垂直的线性布局LinearLayout将界面分成两个区域,上面的大区域显示聊天的内容,用ListView的显示;下面文字输入和发送用TextEditorImageButton组合起来。

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical" >    <!--聊天内容显示区域-->    <ListView        android:id="@+id/message_list"        android:layout_width="match_parent"        android:layout_height="match_parent"        android:layout_weight="1"        android:divider="#0000" ---数据项之间的分割行,设置成透明的,我们将用别的方式来区分每条数据项        android:stackFromBottom="true"        android:transcriptMode="alwaysScroll" />    <!--为了美观,增加一条分割线-->    <View        android:layout_width="match_parent"        android:layout_height="2dp"        android:background="#000"/>    <!--编辑文字及发送按钮区域-->    <LinearLayout        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:orientation="horizontal" >        <EditText            android:id="@+id/msg_editor"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_gravity="bottom"            android:layout_weight="1"            android:imeOptions="actionSend"/>        <ImageButton            android:id="@+id/send_btn"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:background="@mipmap/ic_content_add_circle" />    </LinearLayout></LinearLayout>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43

在代码中,获取将来要操作的控件,

private ImageButton mSendBtn;private ListView mMessageListView;private EditText mMessageEditor;@Overrideprotected void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    setContentView(R.layout.activity_chat);    ......    mMessageEditor = (EditText) findViewById(R.id.msg_editor);    mSendBtn = (ImageButton) findViewById(R.id.send_btn);    mMessageListView = (ListView) findViewById(R.id.message_list);    ......}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

3.1.3 菜单项显示

菜单栏根据当前蓝牙连接的状态,显示不同的菜单项,

  1. 没有连接时,显示启动连接。点击该菜单,将启动显示可连接设备的ActivityDeviceListActivity

  2. 正在连接时,显示取消。点击该菜单,将取消正在进行的连接;

  3. 已经连接时,显示断开连接。点击该菜单,将断开与其它设备已经建立好的连接;

由于这里要根据蓝牙设备连接的状况设计不同的逻辑,所以接下来设计的ConnectionManager要为其它模块提供获取当前连接状态的接口。

目前,我们就暂时将它设计成满足条件1的状况,

  1. 定义一个菜单main_menu.xml

    <menu xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:apps="http://schemas.android.com/apk/res-auto">    <!--一直显示的菜单项,将根据连接的状态变化显示的标题-->    <item android:id="@+id/connect_menu"        android:title="@string/connect"        apps:showAsAction="always"/>    <!--启动关于界面的菜单项-->    <item android:id="@+id/about_menu"        android:title="@string/about"        apps:showAsAction="never"/></menu>
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
  2. 将菜单添加到菜单栏中,

    private MenuItem mConnectionMenuItem;@Overridepublic boolean onCreateOptionsMenu(Menu menu) {    super.onCreateOptionsMenu(menu);    getMenuInflater().inflate(R.menu.main_menu, menu);    mConnectionMenuItem = menu.findItem(R.id.connect_menu);    return true;}
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
  3. 响应菜单栏,启动DeviceListActivity获取可以连接到设备名称

    @Overridepublic boolean onOptionsItemSelected(MenuItem item) {    switch (item.getItemId())    {        case R.id.connect_menu: {            //根据当前连接到状态,判断对应的响应方式,            //目前,我们就暂时将它设计成满足条件1的状况,            //启动DeviceListActivity获取可以连接到设备名称        }        return true;        case R.id.about_menu: {            //启动关于界面        }        return true;        default:            return false;    }}
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    我们从ChatActivity启动DeviceListActivity,目的是要获取DeviceListActivity返回的内容-蓝牙设备的连接地址。所以不能简单的使用startActivity()方法了。

    1. 两个Activity之间传递数据,可以使用startActivityForResult()方法,这里面要设置一个ResultCode,用来主返回结果的时候使用辨别结果对应的是哪个请求,

      private final int RESULT_CODE_BTDEVICE = 0;@Overridepublic boolean onOptionsItemSelected(MenuItem item) {    switch (item.getItemId())    {        case R.id.connect_menu: {            //根据当前连接到状态,判断对应的响应方式,            //目前,我们就暂时将它设计成满足条件1的状况,            //启动DeviceListActivity获取可以连接到设备名称            Intent i = new Intent(ChatActivity.this, DeviceListActivity.class);            startActivityForResult(i, RESULT_CODE_BTDEVICE);        }        return true;        ......    }}
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
    2. 返回的结果将在onActivityResult()函数中被通知到。这里参数的requestCode就是我们在startActivityForResult()中填入的那个数值;而resultCode代表另一个Activity是否如我们所愿返回了结果,

      @Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) {    super.onActivityResult(requestCode, resultCode, data);    if(requestCode == RESULT_CODE_BTDEVICE && resultCode == RESULT_OK) {        //取出传回来的地址        String deviceAddr = data.getStringExtra("DEVICE_ADDR");        //得到蓝牙设备的地址后,就可以通过ConnectionManager模块去连接设备了。    }}
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10

      得到蓝牙设备的地址后,就可以通过ConnectionManager模块去连接设备了。

在蓝牙设备连接之前,是不需要编辑文字和发送内容的。所以,可以使用ViewsetEnabled()函数,将TextEditorImageButton给禁用掉(点击它们不会有任何响应)。等到设备连接上之后,在把它们开启。

mMessageEditor.setEnabled(false);mSendBtn.setEnabled(false);
  • 1
  • 2
  • 1
  • 2

3.2 设备列表界面开发

为设备列表界面创建一个DeviceListActivity

3.2.1 主界面布局

  1. 界面布局很简单,就是一个ListView

    <ListView xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    tools:context="com.anddle.anddlechat.MainActivity"    android:id="@+id/device_list"></ListView>
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    在代码中,设置上返回按钮,并获取这个ListView,以备将来使用,

    private ListView mBTDeviceListView;@Overrideprotected void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    setContentView(R.layout.device_list_activity);    //设置返回按钮    getSupportActionBar().setDisplayHomeAsUpEnabled(true);    mBTDeviceListView = (ListView) findViewById(R.id.device_list);    ...... }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
  2. 为了展示可连接的蓝牙设备,我们会把收集到的可连接设备保存起来,通过ListView进行显示。

    这里将自定义一个AdapterDeviceItemAdapter,让它显示设备的名字和地址,

    1. 数据项的界面布局,

      <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:orientation="horizontal" android:layout_width="match_parent"    android:layout_height="wrap_content"    android:minHeight="58dp"    android:padding="5dp">    <TextView        android:layout_width="wrap_content"        android:layout_height="match_parent"        android:id="@+id/device_name"        android:gravity="center_vertical"        android:drawableLeft="@mipmap/ic_device_bluetooth"/>    <TextView        android:layout_width="match_parent"        android:layout_height="match_parent"        android:id="@+id/device_info"        android:gravity="center_vertical|right"/></LinearLayout>
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
    2. 自定义的DeviceItemAdapter将继承自ArrayAdapter

      public class DeviceItemAdapter extends ArrayAdapter<BluetoothDevice> {    private final LayoutInflater mInflater;    private int mResource;    public DeviceItemAdapter(Context context, int resource) {        super(context, resource);        mInflater = LayoutInflater.from(context);        mResource = resource;    }    @Override    public View getView(int position, View convertView, ViewGroup parent) {        if (convertView == null) {            convertView = mInflater.inflate(mResource, parent, false);        }        TextView name = (TextView) convertView.findViewById(R.id.device_name);        TextView info = (TextView) convertView.findViewById(R.id.device_info);        BluetoothDevice device = getItem(position);        name.setText(device.getName());        info.setText(device.getAddress());        return convertView;    }}
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
    3. 使用ListView

      @Overrideprotected void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    setContentView(R.layout.device_list_activity);    ......            DeviceItemAdapter adapter = new DeviceItemAdapter(this, R.layout.device_list_item);    mBTDeviceListView = (ListView) findViewById(R.id.device_list);    mBTDeviceListView.setAdapter(adapter);    ...... }
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12

3.2.2 展现可连接的设备

可连接的设备包括两种,

  1. 曾经连接过的,已经被系统记录在案,连接这种设备时,系统不会提示用户有设备需要配对;
  2. 完全新发现的设备,连接这种设备时,系统会提示用户有设备需要配对。

3.2.2.1 获取已绑定过的设备

获取第一种设备很简单,使用BluetoothAdaptergetBondedDevices()方法就可以了。找到后,添加到ListView中显示,

@Overrideprotected void onCreate(Bundle savedInstanceState) {   super.onCreate(savedInstanceState);   setContentView(R.layout.device_list_activity);    ......    mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();    //获取已经配对过的设备    Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();    DeviceItemAdapter adapter = (DeviceItemAdapter) mBTDeviceListView.getAdapter();    //将其添加到设备列表中    if (pairedDevices.size() > 0) {        for (BluetoothDevice device : pairedDevices) {            adapter.add(device);        }    }   ......}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

3.2.2.2 获取新发现的设备

获取第二种设备,就采用技术验证时使用的mBluetoothAdapter.startDiscovery()方法;

  1. 首先要注册一个BroadcastReceiver,然后startDiscovery(),之后系统会发出BluetoothAdapter.ACTION_DISCOVERY_STARTED的广播,告知搜索开始;发出BluetoothAdapter.ACTION_DISCOVERY_FINISHED的广播,告知搜索结束,

    @Overrideprotected void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    setContentView(R.layout.device_list_activity);    ......    //注册广播    IntentFilter filter = new IntentFilter();    filter.addAction(BluetoothDevice.ACTION_FOUND);    filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);    filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);    registerReceiver(mReceiver, filter);    //开始搜索    mBluetoothAdapter.startDiscovery();    ......}
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
  2. 根据收到的广播,更新显示列表。假如搜索到的设备是曾经绑定过的,说明之前已经加到设备列表里面了,这里不需要重复添加,

    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {    @Override    public void onReceive(Context context, Intent intent) {        String action = intent.getAction();        //找到设备        if (BluetoothDevice.ACTION_FOUND.equals(action)) {            BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);            //避免重复添加已经绑定过的设备            if (device.getBondState() != BluetoothDevice.BOND_BONDED) {                DeviceItemAdapter adapter = (DeviceItemAdapter) mBTDeviceListView.getAdapter();                adapter.add(device);                adapter.notifyDataSetChanged();            }        }     }};
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    注意,这里能够在BroadcastReceiveronReceive()方法中直接修改界面元素,是因为onReceive()是运行在UI线程-主线程当中的。

  3. DeviceListActivity销毁的时候,注销BroadcastReceiver,同时也别忘了取消可能正在进行的搜索,

    @Overrideprotected void onDestroy() {   super.onDestroy();   //取消搜索   if (mBluetoothAdapter.isDiscovering()) {       mBluetoothAdapter.cancelDiscovery();   }   //注销BroadcastReceiver,防止资源泄露   unregisterReceiver(mReceiver);}
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

至此,DeviceListActivity已经可以列出可被发现和连接到设备了。

3.2.3 设置菜单栏

设置菜单栏的菜单项device_menu.xml,让菜单项一直显示,

<menu xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:apps="http://schemas.android.com/apk/res-auto">    <item android:id="@+id/search_menu"        android:title="@string/search"        apps:showAsAction="always"/></menu>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

我们将根据搜索设备的状态更改该菜单项的名称。所以,这里要定义当前搜索的状态,

  1. 当正在搜索的时候,显示取消,此时状态是BT_SEARCH_STATE_SEARCHING 
  2. 当没有搜索的时候,显示搜索,此时对应的状态是BT_SEARCH_STATE_IDLE 

这两种状态,都要记录下来,

private final int BT_SEARCH_STATE_IDLE = 0;private final int BT_SEARCH_STATE_SEARCHING = 1;private int mBTSearchingState = BT_SEARCH_STATE_IDLE;
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

在代码中添加菜单项,

private MenuItem mSearchMenuItem;@Overridepublic boolean onCreateOptionsMenu(Menu menu) {    getMenuInflater().inflate(R.menu.device_menu, menu);    mSearchMenuItem = menu.findItem(R.id.search_menu);    updateUI();    return true;}//更新菜单项的显示内容private void updateUI() {    switch (mBTSearchingState)    {        //将菜单项显示成搜索        case BT_SEARCH_STATE_IDLE: {            if(mSearchMenuItem != null) {                mSearchMenuItem.setTitle(R.string.search);            }        }        break;        //将菜单项显示成取消        case BT_SEARCH_STATE_SEARCHING: {            if(mSearchMenuItem != null) {                mSearchMenuItem.setTitle(R.string.cancel);            }        }        break;    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35

响应菜单项,

@Overridepublic boolean onOptionsItemSelected(MenuItem item) {    switch(item.getItemId())    {        case R.id.search_menu:        {            if(mBTSearchingState == BT_SEARCH_STATE_IDLE) {                //开始搜索可连接的设备                if (mBluetoothAdapter.isDiscovering()) {                    mBluetoothAdapter.cancelDiscovery();                }                //重新清空列表内容,重新获取已绑定到设备,重新发现新的可连接的设备                updateDeviceList();            }            else if(mBTSearchingState == BT_SEARCH_STATE_SEARCHING) {                //停止搜素可连接的设备                if (mBluetoothAdapter.isDiscovering()) {                    mBluetoothAdapter.cancelDiscovery();                }            }        }        break;        case android.R.id.home:            this.finish();        break;    }    return true;}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33

为了更新菜单项,还需要BroadcastReceiver的配合,

@Overridepublic void onReceive(Context context, Intent intent) {    String action = intent.getAction();    if (BluetoothDevice.ACTION_FOUND.equals(action)) {        ......    } else if (BluetoothAdapter.ACTION_DISCOVERY_STARTED.equals(action)) {        //收到搜索开始的通知,更改状态并更新菜单栏的显示内容        mBTSearchingState = BT_SEARCH_STATE_SEARCHING;        updateUI();    } else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {        //收到搜索结束的通知,更改状态并更新菜单栏的显示内容        mBTSearchingState = BT_SEARCH_STATE_IDLE;        updateUI();    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

3.3 得到要连接的设备

当用户点击要连接的设备后,将把该设备的地址返回给ChatActivity,由ChatActivity去连接设备。

  1. 为设备列表设置点击响应;
  2. 假如点击的时候还在进行搜索,取消搜索;
  3. 获取设备的地址,将它存储到Intent当中,最后通过setResult()方法,将结果传递给启动DeviceListActivityActivityChatActivity
@Overrideprotected void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    setContentView(R.layout.device_list_activity);    ......    //设置数据项的点击监听    mBTDeviceListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {        @Override        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {            //取消可能正在进行的搜索            if (mBluetoothAdapter.isDiscovering()) {                mBluetoothAdapter.cancelDiscovery();            }            ArrayAdapter adapter = (ArrayAdapter) mBTDeviceListView.getAdapter();            BluetoothDevice device = (BluetoothDevice) adapter.getItem(position);            Intent i = new Intent();            //将设备地址存储到Intent当中            i.putExtra("DEVICE_ADDR", device.getAddress());            //将数据结果返回给ChatActivity,并关闭当前的Activity界面            setResult(RESULT_OK, i);            finish();        }    });    ......}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

点击之后,选中的设备地址会传递到ChatActivityonActivityResult()方法中,

@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) {  super.onActivityResult(requestCode, resultCode, data);  if(requestCode == RESULT_CODE_BTDEVICE && resultCode == RESULT_OK) {      //取出传回来的地址      String deviceAddr = data.getStringExtra("DEVICE_ADDR");      //得到蓝牙设备的地址后,就可以通过ConnectionManager模块去连接设备了。  }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

0 0