前面两篇讲的是布局,连接设备,这一节我们来说一说如何通过蓝牙来发送接收数据吧、
大概步骤就是,我们先定义两个线程,分别是客户端的接收线程,还有服务端接收线程,这两个线程我们主要来接收数据,那个发送数据,我们定义了一个send()方法,分别在oncread(),onItemClick()两个方法中调用(第一个是用给服务端发送数据,第二个是用来给客户端发送数据)。
首先,我们涉及到聊天界面,肯定要用到消息处理,类似微信的聊天界面,我们在程序中就得自定义一下聊天界面。
①:新建消息类Msg,功能是将发送的消息显示在右边,接收的消息放在左边。
public class Msg {
public static final int TYPE_RECEIVED = 0;
public static final int TYPE_SENT = 1;
private String content;
private int type;
public Msg(String content, int type){
this.content = content;
this.type = type;
}
public String getContent(){
return content;
}
public int getType(){
return type;
}
}
②:新建MyAdapter适配器
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.TextView;
import java.util.List;
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder>{
private List<Msg> mMsgList;
static class ViewHolder extends RecyclerView.ViewHolder{
LinearLayout leftLayout;
LinearLayout rightLayout;
TextView leftMsg;
TextView rightMsg;
public ViewHolder(View view){
super(view);
leftLayout = (LinearLayout) view.findViewById(R.id.left_layout);
rightLayout = (LinearLayout) view.findViewById(R.id.right_layout);
leftMsg = view.findViewById(R.id.left_msg);
rightMsg = view.findViewById(R.id.right_msg);
}
}
public MyAdapter(List<Msg> msgList){
this.mMsgList = msgList;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.msg_item,parent,false);
ViewHolder holder = new ViewHolder(view);
return holder;
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
Msg msg = mMsgList.get(position);
if(msg.getType()==Msg.TYPE_RECEIVED){
//如果收到消息,则在左边显示,右边隐藏
holder.leftLayout.setVisibility(View.VISIBLE);
holder.rightLayout.setVisibility(View.GONE);
holder.leftMsg.setText(msg.getContent());
}else if(msg.getType() == Msg.TYPE_SENT){
holder.rightLayout.setVisibility(View.VISIBLE);
holder.leftLayout.setVisibility(View.GONE);
holder.rightMsg.setText(msg.getContent());
}
}
@Override
public int getItemCount() {
return mMsgList.size();
}
}
③:回到我们的MainActivity,先定义线程,分别有服务端和客户端的,用来时刻接收数据。
private RecyclerView msgRecyclerView; private List<Msg> msgList = new ArrayList<>(); private IntentFilter filter; private OutputStream os; private InputStream in; private SeverAcceptThread thread; private AcceptThread Thread1; private String content1;
/**************************************客户端IO线程**********************************************/
private class AcceptThread extends Thread{
public void run() {
try {
os = bluetoothSocket.getOutputStream();
in = bluetoothSocket.getInputStream();
while (true) {
// 创建一个128字节的缓冲
byte[] buffer = new byte[128];
// 每次读取128字节,并保存其读取的角标
int count = in.read(buffer);
// 创建Message类,向handler发送数据
Message msg = new Message();
// 发送一个String的数据,让他向上转型为obj类型
msg.obj = new String(buffer, 0, count);
// 发送数据
handler.sendMessage(msg);
}
} catch (IOException e) {
Log.d("CZK","线程有问题");
}
}
}
/*************************************服务端IO线程**********************************/
private class SeverAcceptThread extends Thread{
private BluetoothServerSocket serverSocket;// 获取服务端接口
private BluetoothSocket socket;// 获取到客户端的接口
private InputStream is;// 获取到输入流
private SeverAcceptThread(){
try {
// 通过UUID监听请求,然后获取到对应的服务端接口
serverSocket = bluetoothAdapter
.listenUsingRfcommWithServiceRecord(NAME, MY_UUID);
} catch (Exception e) {
// TODO: handle exception
}
}
public void run(){
try {
Log.d("CZK","thread start");
// 接收其客户端的接口
socket = serverSocket.accept();
// 获取到输入流
is = socket.getInputStream();
// 获取到输出流
os = socket.getOutputStream();
// 无线循环来接收数据
while (true) {
// 创建一个128字节的缓冲
byte[] buffer = new byte[128];
// 每次读取128字节,并保存其读取的角标
int count = is.read(buffer);
// 创建Message类,向handler发送数据
Message msg = new Message();
// 发送一个String的数据,让他向上转型为obj类型
msg.obj = new String(buffer, 0, count);
// 发送数据
handler.sendMessage(msg);
}
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
}
④:定义send()方法,主要来发送数据
/*****************************************send*****************************************/
private void send(){
msgRecyclerView = findViewById(R.id.recycler_view);
editText = findViewById(R.id.input_text);
send = findViewById(R.id.send1);
LinearLayoutManager LayoutManager = new LinearLayoutManager(this);
msgRecyclerView.setLayoutManager(LayoutManager);
Myadapter = new MyAdapter(msgList);
msgRecyclerView.setAdapter(Myadapter);
send.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Log.d("CZK","click");
content1 = editText.getText().toString();
if(!"".equals(content1)) {
Msg msg1 = new Msg(content1, Msg.TYPE_SENT);
msgList.add(msg1);
Myadapter.notifyItemInserted(msgList.size()); //刷新
msgRecyclerView.scrollToPosition(msgList.size() - 1); //定位
try {
os.write(content1.getBytes());
Log.d("CZK","向客户端发送消息成功");
} catch (IOException e) {
e.printStackTrace();
}
editText.setText("");
}
}
});
}
⑤:在之前的OnitemClick()中添加客户端线程并加入send()方法。
//启动线程
// 实例接收客户端传过来的数据线程
Thread1 = new AcceptThread();
// 线程开始
Thread1.start();
setContentView(R.layout.activity_main);
setTitle("与"+ bluetoothDevice.getName()+"连接中");
send();
⑥:重定义Handle类,用来处理接收的数据。
/****************************************Handler****************************/
@SuppressLint("HandlerLeak")
Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
Msg msg2 = new Msg(msg.obj.toString(),Msg.TYPE_RECEIVED);
msgList.add(msg2);
Myadapter.notifyItemInserted(msgList.size()); //刷新
msgRecyclerView.scrollToPosition(msgList.size()-1); //定位
}
};
⑦:onCreat()
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setTitle("蓝牙助手");
bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
// 用Set集合保持已绑定的设备
Set<BluetoothDevice> devices = bluetoothAdapter.getBondedDevices();
if (devices.size() > 0) {
for (BluetoothDevice bluetoothDevice : devices) {
// 保存到arrayList集合中
list.add(bluetoothDevice.getName() + ":"
+ bluetoothDevice.getAddress() + "\n");
adapter = new ArrayAdapter<>(MainActivity.this,android.R.layout.simple_list_item_1,android.R.id.text1,list);
listView.setAdapter(adapter);
adapter.notifyDataSetChanged();
}
}
send();
thread = new SeverAcceptThread();
// 线程开始
thread.start();
}