Android蓝牙开发经验总结(三)

前两篇已经写了主要的东西了,已经可以实现请求连接和接受连接的操作了,但是主控制界面的代码还没有贴上,其实Android官方自带的那个界面还是挺不错的,就是一个聊天的界面,但是我们项目需求的话用不到那样的,只是需要用到一个数据传输,而不是那种聊天式的界面。所以我改了一下。

public class BluetoothControl extends Activity {
    private String address;
    private String Devicename;
    private String TAG = "BluetoothControl";
    private boolean D = true;
    private BluetoothAdapter mBluetoothAdapter;
    private Button scan, discoverable;
    private TextView mTitle;
    private AcceptThread mAcceptThread;
    private ConnectThread mConnectThread;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_CUSTOM_TITLE);
        setContentView(R.layout.activity_bluetoothcontrol);
        getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE, R.layout.title);
        init();
    }

    @Override
    protected void onResume() {
        // TODO Auto-generated method stub
        super.onResume();
    }

    // 对需要使用到的资源进行初始化
    private void init() {
        mTitle = (TextView) this.findViewById(R.id.title_left_text);
        mTitle.setText("未连接");
        // 获得系统默认蓝牙适配器
        mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        if (mBluetoothAdapter == null) {
            Toast.makeText(getApplicationContext(),
                    getResources().getString(R.string.none_bluetooth),
                    Toast.LENGTH_LONG).show();
            finish();
        } else {
            openBluetooth();
        }
        scan = (Button) this.findViewById(R.id.scan);
        discoverable = (Button) this.findViewById(R.id.discoverable);
        scan.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View arg0) {
                // TODO Auto-generated method stub
                // 跳转到DeviceList类
                Intent intent = new Intent(BluetoothControl.this,
                        DeviceList.class);
                startActivityForResult(intent, Constant.REQUEST_CONNECT_DEVICE);
                scan.setEnabled(false);
                discoverable.setEnabled(false);
            }
        });

        discoverable.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View arg0) {
                // TODO Auto-generated method stub
                Intent discoverableIntent = new Intent(
                        BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
                discoverableIntent.putExtra(
                        BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 120);
                startActivity(discoverableIntent);
                mTitle.setText("正在等待连接");
                mAcceptThread = Constant.getAcceptThread();
                if (mAcceptThread == null) {
                    mAcceptThread = new AcceptThread(mHandler);
                    mAcceptThread.start();
                    Constant.setAcceptThread(mAcceptThread);
                } else if (mAcceptThread != null) {
                    mAcceptThread = null;
                    mAcceptThread = new AcceptThread(mHandler);
                    mAcceptThread.start();
                    Constant.setAcceptThread(mAcceptThread);
                }
            }
        });

    }

    private void openBluetooth() {// 打开蓝牙的方法
        if (!mBluetoothAdapter.isEnabled()) {
            Intent enableIntent = new Intent(
                    BluetoothAdapter.ACTION_REQUEST_ENABLE);
            startActivityForResult(enableIntent, 2);
        }
    }

    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (D)
            Log.d(TAG, "onActivityResult " + resultCode);
        switch (requestCode) {
        case Constant.REQUEST_CONNECT_DEVICE:
            if (resultCode == Activity.RESULT_OK) {
                address = data.getExtras().getString(
                        DeviceList.EXTRA_DEVICE_ADDRESS);
                Log.i(TAG, address);
                BluetoothDevice device = mBluetoothAdapter
                        .getRemoteDevice(address);
                mConnectThread = Constant.getConnectThread();
                mConnectThread = new ConnectThread(mHandler, device);
                mConnectThread.start();
                Constant.setConnectThread(mConnectThread);
                mTitle.setText("正在连接" + device.getName());

            }
            break;
        case Constant.REQUEST_ENABLE_BT:
            if (resultCode == Activity.RESULT_OK) {
                openBluetooth();
            } else {
                Log.d(TAG, "BT not enabled");
                Toast.makeText(this, "蓝牙不可用", Toast.LENGTH_SHORT).show();
                finish();
            }
        }
    }

    private final Handler mHandler = new Handler() {
        public void handleMessage(Message msg) {
            switch (msg.what) {
            case Constant.MESSAGE_STATE_CHANGE:
                if (D)
                    Log.i(TAG, "MESSAGE_STATE_CHANGE: " + msg.arg1);
                // 显示现在处在的状态

                // switch (msg.arg1) {
                // case BluetoothControlService.STATE_CONNECTED:
                // mTitle.setText(R.string.title_connected_to);
                // mTitle.append(Devicename);
                // break;
                // case BluetoothControlService.STATE_CONNECTING:
                // mTitle.setText(R.string.title_connecting);
                // break;
                // case BluetoothControlService.STATE_LISTEN:
                // mTitle.setText(R.string.title_not_connected);
                // break;
                // case BluetoothControlService.STATE_NONE:
                // mTitle.setText(R.string.title_not_connected);
                // break;
                // }
                // break;
            case Constant.MESSAGE_READ:
                // 读取获得的信息
                byte[] readBuf = (byte[]) msg.obj;
                String readMessage = new String(readBuf, 0, msg.arg1);
                System.out.println("readMessage" + readMessage);
                // UnityPlayer.UnitySendMessage(readMessage.substring(0,
                // readMessage.indexOf(",")), readMessage.substring(
                // readMessage.indexOf(",") + 1,
                // readMessage.lastIndexOf(",")), readMessage
                // .substring(readMessage.lastIndexOf(",") + 1));
                break;
            case Constant.MESSAGE_DEVICE_NAME:
                // 获得连接到的设备名字,显示
                Devicename = msg.getData().getString(Constant.DEVICE_NAME);
                Toast.makeText(getApplicationContext(), "连接到:" + Devicename,
                        Toast.LENGTH_SHORT).show();
                mTitle.setText("已连接到:" + Devicename);
                // UnityPlayer.UnitySendMessage("BluetoothObjects",
                // "BluetoothConnected", "");
                finish();
                break;
            case Constant.MESSAGE_TOAST:
                Toast.makeText(getApplicationContext(),
                        msg.getData().getString(Constant.TOAST),
                        Toast.LENGTH_SHORT).show();
                mTitle.setText("未连接");
                scan.setEnabled(true);
                discoverable.setEnabled(true);
                // UnityPlayer.UnitySendMessage("BluetoothObjects",
                // "BluetoothDisconnected", "");
                break;
            }
        }
    };
}

由于我们的项目需要用到到的是Unity3D,所以有调用U3D的接口,但是这需求是很特别的,一般来说是用不到这些的,所以我把它注释掉了,但是也算是为了防止以后有可能再次用到,就先把它放这上面了。

这个类里面定义了一个Handler对象,用来进行进程之间数据的传递,上一篇里用到的handler就是从这里面传递过去的,定义AcceptThread和ConnectThread线程的时候都将Handler对象作为构造函数的参数传递了过去,这样在子线程中发生了什么就可以通过Handler向主线程发送提示,比如连接突然断开,就可以通过Handler发送消息告知主线程,主线程这时可以弹出一个Toast来告知用户连接已经断开。

另外需要注意的是

 requestWindowFeature(Window.FEATURE_CUSTOM_TITLE);

这个方法是官方demo里的,我对这类主题窗口类的方法还不是很了解,所以我就在网上查了一下,这个类是用来显示自定义的Title的,我们Android系统的主题里面给我们定义了一些Title,但这些Title的功能往往不适合我们的项目,所以我们需要自定义一个Title,这个方法就是用来告知系统我要用自己定义的一个Title了,就直接取代了系统的Title了。至于Title的样式则需要在XML文件中自己来定义啦。

最后再讲一下蓝牙的断开,蓝牙连接是可以了,但是要是想在程序里断开,官方demo里是没有这个功能的,于是我就想着怎么能给用户提供一个断开的方法呢,总不能总是让用户一直连着,或者需要用户关闭程序或者关闭蓝牙才能实现这样的需求吧。
后来还真是找到了办法,思路就是断开Socket,在ConnectedThread里面,我们可以看到连接之后传过来的Socket对象,就是它,蓝牙之间通信就是像网络通信一样用的是Socket。所以,我们只要断开了Socket,两个蓝牙设备之间的通信就会断开,于是,就可以用以下代码了。

    Button off = (Button) findViewById(R.id.off);
        off.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View arg0) {
                // TODO Auto-generated method stub
                mConnectedThread = Constant.getConnectedThread();
                if (mConnectedThread != null) {
                    mConnectedThread.cancel();
                    mConnectedThread = null;
                    Constant.setConnectedThread(mConnectedThread);
                }
                finish();
            }
        });

因为前面的线程里,我已经把ConnectedThread的对象存入到了Constant中,现在只需要通过getConnectedThread()这个方法就能获得,获得之后判断是否为空,如果不为空的话,就调用mConnectedThread对象里的cancle方法,在这个方法里会执行关闭Socket的操作,这样就算是断开了,断开之后将mConnceted设为空即可。
蓝牙的部分基本上就是这些了!有什么问题可以找我共同探讨沟通^_^

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值