Android蓝牙通信聊天实现发送和接受功能
程序员文章站
2024-03-05 08:25:12
很不错的蓝牙通信demo实现发送和接受功能,就用了两个类就实现了,具体内容如下
说下思路把 主要有两个类 主界面类 和 蓝牙聊天服务类 。 首先创建线程 实际上...
很不错的蓝牙通信demo实现发送和接受功能,就用了两个类就实现了,具体内容如下
说下思路把 主要有两个类 主界面类 和 蓝牙聊天服务类 。 首先创建线程 实际上就是创建bluetoothchatservice() (蓝牙聊天服务类) 这个时候把handler 传过去 这样就可以操作ui 界面了,在线程中不断轮询读取蓝牙消息,当主界面点击发送按钮时 调用bluetoothchatservice 的发送方法write 方法,这里的write 方法 使用了handler 发送消息,在主界面显示,另一个 客户端 不断读取蓝牙消息 类似的有个read 方法 同样显示到界面上去,这样就完成了通信了。
import java.util.arraylist; import java.util.set; import android.app.activity; import android.app.alertdialog; import android.bluetooth.bluetoothadapter; import android.bluetooth.bluetoothdevice; import android.content.broadcastreceiver; import android.content.context; import android.content.dialoginterface; import android.content.intent; import android.content.intentfilter; import android.os.bundle; import android.os.handler; import android.os.message; import android.util.log; import android.view.menu; import android.view.menuitem; import android.view.view; import android.view.view.onclicklistener; import android.view.window; import android.widget.button; import android.widget.edittext; import android.widget.textview; import android.widget.toast; public class bluetoothchat extends activity { // message types sent from the bluetoothchatservice handler public static final int message_state_change = 1; public static final int message_read = 2; public static final int message_write = 3; public static final int message_device_name = 4; public static final int message_toast = 5; // key names received from the bluetoothchatservice handler public static final string device_name = "device_name"; public static final string toast = "toast"; // intent request codes private static final int request_connect_device = 1; private static final int request_enable_bt = 2; private textview mtitle; private edittext text_chat; private edittext text_input; private button but_on_off; private button but_search; // ------> 在菜单中可以搜索 private button but_create; // ------> 在菜单中设置"可被发现" private button msendbutton; // 连接到的蓝牙设备的名称 private string mconnecteddevicename; // string buffer for outgoing messages private stringbuffer moutstringbuffer; // local bluetooth adapter private bluetoothadapter mbluetoothadapter = null; // member object for the chat services private bluetoothchatservice mchatservice = null; private arraylist<string> mpaireddeviceslist = new arraylist<string>(); private arraylist<string> mnewdeviceslist = new arraylist<string>(); private string[] strname; private string address; @override public void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); requestwindowfeature(window.feature_custom_title); setcontentview(r.layout.main); mtitle = (textview) this.findviewbyid(r.id.text_title); text_chat = (edittext) this.findviewbyid(r.id.text_chat); text_input = (edittext) this.findviewbyid(r.id.text_input); but_on_off = (button) this.findviewbyid(r.id.but_off_on); but_search = (button) this.findviewbyid(r.id.but_search_div); but_create = (button) this.findviewbyid(r.id.but_cjlj); msendbutton = (button) this.findviewbyid(r.id.but_fsxx); // 获得本地的蓝牙适配器 mbluetoothadapter = bluetoothadapter.getdefaultadapter(); // 如果为null,说明没有蓝牙设备 if (mbluetoothadapter == null) { toast.maketext(this, "没有蓝牙设备", toast.length_long).show(); finish(); return; } if (mbluetoothadapter.isenabled()) { but_on_off.settext("关闭蓝牙"); } else { but_on_off.settext("开启蓝牙"); } but_on_off.setonclicklistener(new onclicklistener() { @override public void onclick(view v) { if (!mbluetoothadapter.isenabled()) { mbluetoothadapter.enable(); toast.maketext(bluetoothchat.this, "蓝牙已开启", toast.length_short).show(); but_on_off.settext("关闭蓝牙"); } else { mbluetoothadapter.disable(); toast.maketext(bluetoothchat.this, "蓝牙已关闭", toast.length_short).show(); but_on_off.settext("开启蓝牙"); } } }); but_search.setonclicklistener(new onclicklistener() { @override public void onclick(view v) { searchdevice(); } }); but_create.setonclicklistener(new onclicklistener() { @override public void onclick(view v) { final edittext et = new edittext(bluetoothchat.this); et.setsingleline(); et.settext(mbluetoothadapter.getname()); new alertdialog.builder(bluetoothchat.this) .settitle("请输入房间名:") .setview(et) .setpositivebutton("确定", new dialoginterface.onclicklistener() { @override public void onclick(dialoginterface dialog, int which) { string name = et.gettext().tostring() .trim(); if (name.equals("")) { toast.maketext(bluetoothchat.this, "请输入房间名", toast.length_short).show(); return; } // 设置房间名 mbluetoothadapter.setname(name); } }) .setnegativebutton("取消", new dialoginterface.onclicklistener() { @override public void onclick(dialoginterface dialog, int which) { } }).create().show(); // 创建连接,也就是设备本地蓝牙设备可被其他用户的蓝牙搜到 ensurediscoverable(); } }); // 获得一个已经配对的蓝牙设备的set集合 set<bluetoothdevice> paireddevices = mbluetoothadapter .getbondeddevices(); if (paireddevices.size() > 0) { for (bluetoothdevice device : paireddevices) { mpaireddeviceslist.add("已配对:" + device.getname() + "\n" + device.getaddress()); } } else { toast.maketext(this, "没有已配对的设备", toast.length_short).show(); } // 当发现一个新的蓝牙设备时注册广播 intentfilter filter = new intentfilter(bluetoothdevice.action_found); this.registerreceiver(mreceiver, filter); // 当搜索完毕后注册广播 filter = new intentfilter(bluetoothadapter.action_discovery_finished); this.registerreceiver(mreceiver, filter); } @override public void onstart() { super.onstart(); // if bt is not on, request that it be enabled. // setupchat() will then be called during onactivityresult if (!mbluetoothadapter.isenabled()) { intent enableintent = new intent( bluetoothadapter.action_request_enable); startactivityforresult(enableintent, request_enable_bt); // otherwise, setup the chat session } else { if (mchatservice == null) setupchat(); } } @override public synchronized void onresume() { super.onresume(); // performing this check in onresume() covers the case in which bt was // not enabled during onstart(), so we were paused to enable it... // onresume() will be called when action_request_enable activity // returns. if (mchatservice != null) { // only if the state is state_none, do we know that we haven't // started already if (mchatservice.getstate() == bluetoothchatservice.state_none) { // start the bluetooth chat services mchatservice.start(); } } } private void setupchat() { msendbutton.setonclicklistener(new onclicklistener() { public void onclick(view v) { // send a message using content of the edit text widget string message = text_input.gettext().tostring(); sendmessage(message); } }); // initialize the bluetoothchatservice to perform bluetooth connections mchatservice = new bluetoothchatservice(this, mhandler); // initialize the buffer for outgoing messages moutstringbuffer = new stringbuffer(""); } @override public void ondestroy() { super.ondestroy(); // stop the bluetooth chat services if (mchatservice != null) mchatservice.stop(); // make sure we're not doing discovery anymore if (mbluetoothadapter != null) { mbluetoothadapter.canceldiscovery(); } // unregister broadcast listeners this.unregisterreceiver(mreceiver); } /** 使本地的蓝牙设备可被发现 */ private void ensurediscoverable() { if (mbluetoothadapter.getscanmode() != bluetoothadapter.scan_mode_connectable_discoverable) { intent discoverableintent = new intent( bluetoothadapter.action_request_discoverable); discoverableintent.putextra( bluetoothadapter.extra_discoverable_duration, 300); startactivity(discoverableintent); } } /** * sends a message. * * @param message * a string of text to send. */ private void sendmessage(string message) { // check that we're actually connected before trying anything if (mchatservice.getstate() != bluetoothchatservice.state_connected) { toast.maketext(this, "没有连接上", toast.length_short).show(); return; } // check that there's actually something to send if (message.length() > 0) { // get the message bytes and tell the bluetoothchatservice to write byte[] send = message.getbytes(); mchatservice.write(send); // reset out string buffer to zero and clear the edit text field moutstringbuffer.setlength(0); text_input.settext(moutstringbuffer); } } // the handler that gets information back from the bluetoothchatservice private final handler mhandler = new handler() { @override public void handlemessage(message msg) { switch (msg.what) { case message_state_change: switch (msg.arg1) { case bluetoothchatservice.state_connected: mtitle.settext("已经连接"); mtitle.append(mconnecteddevicename); // mconversationarrayadapter.clear(); break; case bluetoothchatservice.state_connecting: mtitle.settext("正在连接中..."); break; case bluetoothchatservice.state_listen: case bluetoothchatservice.state_none: mtitle.settext("未连接上"); break; } break; case message_write: byte[] writebuf = (byte[]) msg.obj; // construct a string from the buffer string writemessage = new string(writebuf); // mconversationarrayadapter.add("me: " + writemessage); text_chat.append("我:" + writemessage + "\n"); break; case message_read: byte[] readbuf = (byte[]) msg.obj; // construct a string from the valid bytes in the buffer string readmessage = new string(readbuf, 0, msg.arg1); // mconversationarrayadapter.add(mconnecteddevicename+": " + // readmessage); text_chat.append(mconnecteddevicename + ":" + readmessage + "\n"); break; case message_device_name: // save the connected device's name mconnecteddevicename = msg.getdata().getstring(device_name); toast.maketext(getapplicationcontext(), "连接到 " + mconnecteddevicename, toast.length_short) .show(); break; case message_toast: toast.maketext(getapplicationcontext(), msg.getdata().getstring(toast), toast.length_short) .show(); break; } } }; // 连接蓝牙设备 private void linkdevice() { if (mbluetoothadapter.isdiscovering()) { mbluetoothadapter.canceldiscovery(); } int cou = mpaireddeviceslist.size() + mnewdeviceslist.size(); if (cou == 0) { toast.maketext(bluetoothchat.this, "没有搜索到可用的蓝牙设备", toast.length_short).show(); return; } // 把已经配对的蓝牙设备和新发现的蓝牙设备的名称都放入数组中,以便在对话框列表中显示 strname = new string[cou]; for (int i = 0; i < mpaireddeviceslist.size(); i++) { strname[i] = mpaireddeviceslist.get(i); } for (int i = mpaireddeviceslist.size(); i < strname.length; i++) { strname[i] = mnewdeviceslist.get(i - mpaireddeviceslist.size()); } address = strname[0].substring(strname[0].length() - 17); new alertdialog.builder(bluetoothchat.this) .settitle("搜索到的蓝牙设备:") .setsinglechoiceitems(strname, 0, new dialoginterface.onclicklistener() { @override public void onclick(dialoginterface dialog, int which) { // 当用户点击选中的蓝牙设备时,取出选中的蓝牙设备的mac地址 address = strname[which].split("\\n")[1].trim(); } }) .setpositivebutton("连接", new dialoginterface.onclicklistener() { @override public void onclick(dialoginterface dialog, int which) { if (address == null) { toast.maketext(bluetoothchat.this, "请先连接外部蓝牙设备", toast.length_short).show(); return; } log.i("sxd", "address:" + address); // get the bluetoothdevice object bluetoothdevice device = mbluetoothadapter .getremotedevice(address); // attempt to connect to the device mchatservice.connect(device); } }) .setnegativebutton("取消", new dialoginterface.onclicklistener() { @override public void onclick(dialoginterface dialog, int which) { } }).create().show(); } // 搜索蓝牙设备蓝牙设备 private void searchdevice() { mtitle.settext("正在努力搜索中..."); setprogressbarindeterminatevisibility(true); if (mbluetoothadapter.isdiscovering()) { mbluetoothadapter.canceldiscovery(); } mnewdeviceslist.clear(); mbluetoothadapter.startdiscovery(); } @override public boolean oncreateoptionsmenu(menu menu) { menu.add(0, 1, 0, "搜索设备"); menu.add(0, 2, 0, "可被发现"); return true; } 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 it's already paired, skip it, because it's been listed // already if (device.getbondstate() != bluetoothdevice.bond_bonded) { string s = "未配对: " + device.getname() + "\n" + device.getaddress(); if (!mnewdeviceslist.contains(s)) mnewdeviceslist.add(s); } // when discovery is finished, change the activity title } else if (bluetoothadapter.action_discovery_finished .equals(action)) { setprogressbarindeterminatevisibility(false); if (mnewdeviceslist.size() == 0) { toast.maketext(bluetoothchat.this, "没有发现新设备", toast.length_short).show(); } mtitle.settext("未连接"); linkdevice(); } } }; @override public boolean onoptionsitemselected(menuitem item) { switch (item.getitemid()) { case 1: searchdevice(); return true; case 2: // ensure this device is discoverable by others ensurediscoverable(); return true; } return false; } }
package com.it2388.bluetooth; /* * copyright (c) 2009 the android open source project * * licensed under the apache license, version 2.0 (the "license"); * you may not use this file except in compliance with the license. * you may obtain a copy of the license at * * http://www.apache.org/licenses/license-2.0 * * unless required by applicable law or agreed to in writing, software * distributed under the license is distributed on an "as is" basis, * without warranties or conditions of any kind, either express or implied. * see the license for the specific language governing permissions and * limitations under the license. */ import java.io.ioexception; import java.io.inputstream; import java.io.outputstream; import java.util.uuid; import android.bluetooth.bluetoothadapter; import android.bluetooth.bluetoothdevice; import android.bluetooth.bluetoothserversocket; import android.bluetooth.bluetoothsocket; import android.content.context; import android.os.bundle; import android.os.handler; import android.os.message; import android.util.log; /** * this class does all the work for setting up and managing bluetooth * connections with other devices. it has a thread that listens for incoming * connections, a thread for connecting with a device, and a thread for * performing data transmissions when connected. * * *这个类做所有的工作,建立和管理蓝牙 与其他设备的连接。它有一个线程监听 传入的连接,一个用于连接一个设备的线程,和一个 当连接时执行数据传输的线程。 */ public class bluetoothchatservice { // debugging private static final string tag = "bluetoothchatservice"; private static final boolean d = true; // name for the sdp record when creating server socket 对于sdp记录名称创建服务器套接字时 private static final string name = "bluetoothchat"; // unique uuid for this application private static final uuid my_uuid = uuid .fromstring("fa87c0d0-afac-11de-8a39-0800200c9a66"); // member fields private final bluetoothadapter madapter; private final handler mhandler; private acceptthread macceptthread; private connectthread mconnectthread; private connectedthread mconnectedthread; private int mstate; // constants that indicate the current connection state public static final int state_none = 0; // we're doing nothing 我们什么都不做 public static final int state_listen = 1; // now listening for incoming 现在监听 // connections public static final int state_connecting = 2; // now initiating an outgoing // 启动一个外向 // connection public static final int state_connected = 3; // now connected to a remote // 连接到一个远程 // device /** * constructor. prepares a new bluetoothchat session. * * @param context * the ui activity context * @param handler * a handler to send messages back to the ui activity */ public bluetoothchatservice(context context, handler handler) { madapter = bluetoothadapter.getdefaultadapter(); mstate = state_none; mhandler = handler; } /** * set the current state of the chat connection * * @param state * an integer defining the current connection state */ private synchronized void setstate(int state) { if (d) log.d(tag, "setstate() " + mstate + " -> " + state); mstate = state; // give the new state to the handler so the ui activity can update mhandler.obtainmessage(bluetoothchat.message_state_change, state, -1) .sendtotarget(); } /** * return the current connection state. */ public synchronized int getstate() { return mstate; } /** * start the chat service. specifically start acceptthread to begin a * session in listening (server) mode. called by the activity onresume() */ public synchronized void start() { if (d) log.d(tag, "start"); // cancel any thread attempting to make a connection if (mconnectthread != null) { mconnectthread.cancel(); mconnectthread = null; } // cancel any thread currently running a connection if (mconnectedthread != null) { mconnectedthread.cancel(); mconnectedthread = null; } // start the thread to listen on a bluetoothserversocket if (macceptthread == null) { macceptthread = new acceptthread(); macceptthread.start(); } setstate(state_listen); } /** * start the connectthread to initiate a connection to a remote device. * * @param device * the bluetoothdevice to connect */ public synchronized void connect(bluetoothdevice device) { if (d) log.d(tag, "connect to: " + device); // cancel any thread attempting to make a connection if (mstate == state_connecting) { if (mconnectthread != null) { mconnectthread.cancel(); mconnectthread = null; } } // cancel any thread currently running a connection if (mconnectedthread != null) { mconnectedthread.cancel(); mconnectedthread = null; } // start the thread to connect with the given device mconnectthread = new connectthread(device); mconnectthread.start(); setstate(state_connecting); } /** * start the connectedthread to begin managing a bluetooth connection * * @param socket * the bluetoothsocket on which the connection was made * @param device * the bluetoothdevice that has been connected */ public synchronized void connected(bluetoothsocket socket, bluetoothdevice device) { if (d) log.d(tag, "connected"); // cancel the thread that completed the connection if (mconnectthread != null) { mconnectthread.cancel(); mconnectthread = null; } // cancel any thread currently running a connection if (mconnectedthread != null) { mconnectedthread.cancel(); mconnectedthread = null; } // cancel the accept thread because we only want to connect to one // device if (macceptthread != null) { macceptthread.cancel(); macceptthread = null; } // start the thread to manage the connection and perform transmissions mconnectedthread = new connectedthread(socket); mconnectedthread.start(); // send the name of the connected device back to the ui activity message msg = mhandler.obtainmessage(bluetoothchat.message_device_name); bundle bundle = new bundle(); bundle.putstring(bluetoothchat.device_name, device.getname()); msg.setdata(bundle); mhandler.sendmessage(msg); setstate(state_connected); } /** * stop all threads */ public synchronized void stop() { if (d) log.d(tag, "stop"); if (mconnectthread != null) { mconnectthread.cancel(); mconnectthread = null; } if (mconnectedthread != null) { mconnectedthread.cancel(); mconnectedthread = null; } if (macceptthread != null) { macceptthread.cancel(); macceptthread = null; } setstate(state_none); } /** * write to the connectedthread in an unsynchronized manner * * @param out * the bytes to write * @see connectedthread#write(byte[]) */ public void write(byte[] out) { // create temporary object connectedthread r; // synchronize a copy of the connectedthread synchronized (this) { if (mstate != state_connected) return; r = mconnectedthread; } // perform the write unsynchronized r.write(out); } /** * indicate that the connection attempt failed and notify the ui activity. */ private void connectionfailed() { setstate(state_listen); // send a failure message back to the activity message msg = mhandler.obtainmessage(bluetoothchat.message_toast); bundle bundle = new bundle(); bundle.putstring(bluetoothchat.toast, "不能连接到设备"); msg.setdata(bundle); mhandler.sendmessage(msg); } /** * indicate that the connection was lost and notify the ui activity. */ private void connectionlost() { setstate(state_listen); // send a failure message back to the activity message msg = mhandler.obtainmessage(bluetoothchat.message_toast); bundle bundle = new bundle(); bundle.putstring(bluetoothchat.toast, "设备连接中断"); msg.setdata(bundle); mhandler.sendmessage(msg); } /** * this thread runs while listening for incoming connections. it behaves * like a server-side client. it runs until a connection is accepted (or * until cancelled). */ private class acceptthread extends thread { // the local server socket private final bluetoothserversocket mmserversocket; public acceptthread() { bluetoothserversocket tmp = null; // create a new listening server socket try { tmp = madapter .listenusingrfcommwithservicerecord(name, my_uuid); } catch (ioexception e) { log.e("sxd", " ======== ufcomm exception =======", e); } mmserversocket = tmp; } public void run() { if (d) log.d(tag, "begin macceptthread" + this); setname("acceptthread"); bluetoothsocket socket = null; // listen to the server socket if we're not connected while (mstate != state_connected) { try { // this is a blocking call and will only return on a // successful connection or an exception socket = mmserversocket.accept(); } catch (ioexception e) { log.e("sxd", "---> accept socket failed <---", e); break; } // if a connection was accepted if (socket != null) { synchronized (bluetoothchatservice.this) { switch (mstate) { case state_listen: case state_connecting: // situation normal. start the connected thread. connected(socket, socket.getremotedevice()); break; case state_none: case state_connected: // either not ready or already connected. terminate // new socket. try { socket.close(); } catch (ioexception e) { log.e(tag, "could not close unwanted socket", e); } break; } } } } if (d) log.i(tag, "end macceptthread"); } public void cancel() { if (d) log.d(tag, "cancel " + this); try { mmserversocket.close(); } catch (ioexception e) { log.e(tag, "close() of server failed", e); } } } /** * this thread runs while attempting to make an outgoing connection with a * device. it runs straight through; the connection either succeeds or * fails. */ private class connectthread extends thread { private final bluetoothsocket mmsocket; private final bluetoothdevice mmdevice; public connectthread(bluetoothdevice device) { mmdevice = device; bluetoothsocket tmp = null; // get a bluetoothsocket for a connection with the // given bluetoothdevice try { tmp = device.createrfcommsockettoservicerecord(my_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 madapter.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) { log.e("sxd", "链接发生了异常", e); connectionfailed(); // close the socket try { mmsocket.close(); } catch (ioexception e2) { log.e(tag, "unable to close() socket during connection failure", e2); } // start the service over to restart listening mode bluetoothchatservice.this.start(); return; } // reset the connectthread because we're done synchronized (bluetoothchatservice.this) { mconnectthread = null; } // start the connected thread connected(mmsocket, mmdevice); } 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. * * 和已经建立连接的设置进行数据的传输 */ 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[1024]; int bytes; // keep listening to the inputstream while connected while (true) { try { // read from the inputstream bytes = mminstream.read(buffer); // send the obtained bytes to the ui activity mhandler.obtainmessage(bluetoothchat.message_read, bytes, -1, buffer).sendtotarget(); } catch (ioexception e) { log.e(tag, "disconnected", e); connectionlost(); break; } } } /** * write to the connected outstream. * * @param buffer * the bytes to write */ public void write(byte[] buffer) { try { mmoutstream.write(buffer); // share the sent message back to the ui activity mhandler.obtainmessage(bluetoothchat.message_write, -1, -1, buffer).sendtotarget(); } 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); } } } }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
上一篇: java选择框、单选框和单选按钮
下一篇: Java线程调度之线程休眠用法分析