BlueTooth 通信 小实例

来源:互联网 发布:域名推广 编辑:程序博客网 时间:2024/04/29 19:16


添加权限  注册Activity  区分label

<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android"    package="com.moliying.bluetooth">   <span style="color:#FF0000;"> <uses-permission android:name="android.permission.BLUETOOTH" />    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" /></span>    <application        android:allowBackup="true"        android:icon="@mipmap/ic_launcher"        android:label="@string/app_name"        android:supportsRtl="true"        android:theme="@style/AppTheme">        <activity android:name=".MainActivity">            <intent-filter>                <action android:name="android.intent.action.MAIN" />                <category android:name="android.intent.category.LAUNCHER" />            </intent-filter>        </activity>        <span style="font-size:14px;color:#FF0000;"><activity android:name=".ServerActivity" android:label="server" android:configChanges="keyboard|keyboardHidden|screenSize|orientation"/>      <activity android:name=".ClientActivity" android:label="client" android:configChanges="keyboard|keyboardHidden|screenSize|orientation"/></span>    </application></manifest>

四个布局文件

activity_main.xml

bluetooth_item.xml

activity_server.xml

activity_client.xml




activity_main.xml

<?xml version="1.0" encoding="utf-8"?><RelativeLayout    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"    android:paddingLeft="@dimen/activity_horizontal_margin"    android:paddingRight="@dimen/activity_horizontal_margin"    android:paddingTop="@dimen/activity_vertical_margin"    android:paddingBottom="@dimen/activity_vertical_margin"    tools:context="com.moliying.bluetooth.MainActivity">    <Button        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:onClick="openClick"        android:text="查找蓝牙"        android:id="@+id/openBlueTooth"        android:layout_toStartOf="@+id/button_start_server" />    <ListView        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:id="@+id/listView_blueTooth"        android:layout_below="@+id/openBlueTooth"        android:layout_alignParentStart="true" />    <Button        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:text="启动服务"        android:onClick="startServerClick"        android:id="@+id/button_start_server"        android:layout_alignTop="@+id/openBlueTooth"        android:layout_alignParentEnd="true" /></RelativeLayout>



bluetooth_item.xml

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:orientation="vertical" android:layout_width="match_parent"    android:layout_height="match_parent"    android:padding="@dimen/activity_horizontal_margin">    <TextView        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:text="name"        android:id="@+id/textView_name" />    <TextView        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:text="address"        android:id="@+id/textView2_address" />    <TextView        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:text="配对状态"        android:id="@+id/textView_bond" /></LinearLayout>





activity_server.xml


<?xml version="1.0" encoding="utf-8"?><RelativeLayout 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"    android:paddingBottom="@dimen/activity_vertical_margin"    android:paddingLeft="@dimen/activity_horizontal_margin"    android:paddingRight="@dimen/activity_horizontal_margin"    android:paddingTop="@dimen/activity_vertical_margin"    tools:context="com.moliying.bluetooth.ServerActivity">    <Button        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:text="发送"        android:onClick="sendClick"        android:id="@+id/button_send"        android:layout_alignParentBottom="true"        android:layout_alignParentStart="true"        android:layout_alignParentEnd="true" />    <EditText        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:id="@+id/editText_info"        android:layout_above="@+id/button_send"        android:layout_alignParentStart="true"        android:layout_alignEnd="@+id/button_send" />    <TextView        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:text=""        android:id="@+id/textView_info"        android:gravity="top"        android:textSize="16sp"        android:layout_alignParentTop="true"        android:layout_alignParentStart="true"        android:layout_alignParentEnd="true"        android:layout_above="@+id/editText_info" /></RelativeLayout>


activity_client.xml     布局与 activity_server.xml 相同

<?xml version="1.0" encoding="utf-8"?><RelativeLayout 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"    android:paddingBottom="@dimen/activity_vertical_margin"    android:paddingLeft="@dimen/activity_horizontal_margin"    android:paddingRight="@dimen/activity_horizontal_margin"    android:paddingTop="@dimen/activity_vertical_margin"    tools:context="com.moliying.bluetooth.ServerActivity">    <Button        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:text="发送"        android:onClick="sendClick"        android:id="@+id/button_send"        android:layout_alignParentBottom="true"        android:layout_alignParentStart="true"        android:layout_alignParentEnd="true" />    <EditText        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:id="@+id/editText_info"        android:layout_above="@+id/button_send"        android:layout_alignParentStart="true"        android:layout_alignEnd="@+id/button_send" />    <TextView        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:text=""        android:id="@+id/textView_info"        android:gravity="top"        android:textSize="16sp"        android:layout_alignParentTop="true"        android:layout_alignParentStart="true"        android:layout_alignParentEnd="true"        android:layout_above="@+id/editText_info" /></RelativeLayout>



三个Activity

MainActivity.java

ServerActivity.java

ClientActivity.java



MainActivity.java

package com.moliying.bluetooth;import android.bluetooth.BluetoothAdapter;import android.bluetooth.BluetoothDevice;import android.content.BroadcastReceiver;import android.content.Context;import android.content.Intent;import android.content.IntentFilter;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.util.Log;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.AdapterView;import android.widget.BaseAdapter;import android.widget.ListView;import android.widget.TextView;import java.lang.reflect.Method;import java.util.ArrayList;import java.util.List;public class MainActivity extends AppCompatActivity implements AdapterView.OnItemClickListener {    private static final int REQUEST_ENABLE = 0x1;    private ListView listView_bluetooth;    private MyAdapter myAdapter;    private List<BluetoothDevice> deviceList = new ArrayList<>();    BluetoothAdapter bluetoothAdapter;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        listView_bluetooth = (ListView) findViewById(R.id.listView_blueTooth);        myAdapter = new MyAdapter(this,deviceList);        listView_bluetooth.setAdapter(myAdapter);        listView_bluetooth.setOnItemClickListener(this);    }    public void openClick(View v){        deviceList.clear();        //提示用户是否打开蓝牙//        Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);//        startActivityForResult(intent,REQUEST_ENABLE);        //直接打开蓝牙        bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();        bluetoothAdapter.enable();        if(bluetoothAdapter.isEnabled()){            bluetoothAdapter.startDiscovery(); //开始扫描设备        }    }    //启动为蓝牙服务器    public void startServerClick(View view){        Intent intent = new Intent(this,ServerActivity.class);        startActivity(intent);    }    private BlueToothReceiver receiver = new BlueToothReceiver();    @Override    protected void onStart() {        super.onStart();        //注册广播接收器        IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);        registerReceiver(receiver,filter);    }    @Override    protected void onStop() {        //取消注册        unregisterReceiver(receiver);        super.onStop();    }    @Override    protected void onDestroy() {        bluetoothAdapter.cancelDiscovery();        myAdapter = null;        deviceList = null;        super.onDestroy();    }    @Override    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {        bluetoothAdapter.cancelDiscovery();//取消查找        BluetoothDevice device = deviceList.get(position);        int state = device.getBondState();        switch (state){            case BluetoothDevice.BOND_NONE:                //发现了没有配对的设备//                    device.createBond(); //该方法在API19后可以使用                try {                    //API19以下版本可便用反射来调用配对的方法                    Method createBondMethod = BluetoothDevice.class.getMethod("createBond");                    createBondMethod.invoke(device);                } catch (Exception e) {                    e.printStackTrace();                }                break;            case BluetoothDevice.BOND_BONDED:                Intent intent = new Intent(this,ClientActivity.class);                intent.putExtra("device",device);                startActivity(intent);                break;        }    }    private static class MyAdapter extends BaseAdapter{        private Context context;        private List<BluetoothDevice> list;        public MyAdapter(Context context, List<BluetoothDevice> list) {            this.context = context;            this.list = list;        }        @Override        public int getCount() {            return list.size();        }        @Override        public Object getItem(int position) {            return list.get(position);        }        @Override        public long getItemId(int position) {            return position;        }        @Override        public View getView(int position, View convertView, ViewGroup parent) {            ViewHolder vh = null;            if(convertView==null){                convertView = LayoutInflater.from(context).inflate(R.layout.bluetooth_item,null);                vh = new ViewHolder();                vh.textView_name = (TextView) convertView.findViewById(R.id.textView_name);                vh.textView_address = (TextView) convertView.findViewById(R.id.textView2_address);                vh.textView_bond = (TextView) convertView.findViewById(R.id.textView_bond);                convertView.setTag(vh);            }else{                vh = (ViewHolder) convertView.getTag();            }            BluetoothDevice bd = list.get(position);            vh.textView_name.setText(bd.getName());            vh.textView_address.setText(bd.getAddress());            String bond = "";            switch (bd.getBondState()){                case BluetoothDevice.BOND_NONE:                    bond = "未配对";                    break;                case BluetoothDevice.BOND_BONDED:                    bond = "已配对";                    break;                default:                    bond = "未知";            }            vh.textView_bond.setText(bond);            return convertView;        }        static class ViewHolder{            TextView textView_name;            TextView textView_address;            TextView textView_bond;        }    }    //发现蓝牙设备后用于接收设备    class BlueToothReceiver extends BroadcastReceiver{        @Override        public void onReceive(Context context, Intent intent) {            BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);            Log.i("BlueToothReceiver", "onReceive: "+device.getName()+"-"+device.getAddress());            deviceList.add(device);            myAdapter.notifyDataSetChanged();        }    }}

ServerActivity.java

package com.moliying.bluetooth;import android.bluetooth.BluetoothAdapter;import android.bluetooth.BluetoothServerSocket;import android.bluetooth.BluetoothSocket;import android.os.Handler;import android.os.Message;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.text.TextUtils;import android.view.View;import android.widget.Button;import android.widget.EditText;import android.widget.TextView;import android.widget.Toast;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.io.PrintStream;import java.util.UUID;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;public class ServerActivity extends AppCompatActivity {    private static final int START_SERVER = 0x1;    private static final int CLIENT_CONNECT = 0X2;    private static final int HANDLER_INFO = 0x3;    private static final int CLEAN_INFO = 0x4;    private TextView textView_info;    private EditText editText_info;    private Button button_send;    private BluetoothServerSocket serverSocket;    private BluetoothSocket socket;    private ExecutorService es = Executors.newFixedThreadPool(3);    private PrintStream ps;    private BufferedReader in;    private String name;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_server);        textView_info = (TextView) findViewById(R.id.textView_info);        editText_info = (EditText) findViewById(R.id.editText_info);        button_send = (Button) findViewById(R.id.button_send);        startServer();    }    //启动服务    private void startServer() {        handler.sendEmptyMessage(START_SERVER);        final BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();        final UUID uuid = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");        es.execute(new Runnable() {            @Override            public void run() {                try {                    serverSocket = adapter.listenUsingRfcommWithServiceRecord("server",uuid);                    //等待连接,会阻塞                    socket = serverSocket.accept();                    ps = new PrintStream(socket.getOutputStream());                    in = new BufferedReader(new InputStreamReader(socket.getInputStream()));                    name = socket.getRemoteDevice().getName();                    handler.sendEmptyMessage(CLIENT_CONNECT);                } catch (IOException e) {                    e.printStackTrace();                }            }        });    }    private boolean isReceive = false;    //接收消息的线程    class ReceiverThread implements Runnable{        public ReceiverThread() {            isReceive = true;        }        @Override        public void run() {            while (isReceive){                try {                    String info = in.readLine();//阻塞                    Message msg = handler.obtainMessage(HANDLER_INFO,info);                    handler.sendMessage(msg);                } catch (IOException e) {                    e.printStackTrace();                    isReceive = false;                }            }        }    }    //发送消息的事件    public void sendClick(View view){        final String info = editText_info.getText().toString();        if (TextUtils.isEmpty(info)){            Toast.makeText(ServerActivity.this, "不能发送空消息", Toast.LENGTH_SHORT).show();        }        es.execute(new Runnable() {            @Override            public void run() {                ps.println(info);                ps.flush();                handler.sendEmptyMessage(CLEAN_INFO);            }        });    }    //统一处理消息,更新UI    private Handler handler = new Handler(){        @Override        public void handleMessage(Message msg) {            switch (msg.what){                case HANDLER_INFO:                    textView_info.append("【"+name+"】对我说:"+msg.obj.toString()+"\n");                    break;                case CLEAN_INFO:                    textView_info.append("我对【"+name+"】说:"+editText_info.getText().toString());                    editText_info.setText("");                    break;                case START_SERVER:                    textView_info.append("服务器端已启动,正在等待连接...\n");                    break;                case CLIENT_CONNECT:                    textView_info.append("【"+name+"】连接成功\n");                    es.execute(new ReceiverThread());//启动接收消息的线程                    break;            }        }    };    @Override    protected void onDestroy() {        isReceive = false;        es.shutdown();        try {            socket.close();        } catch (IOException e) {            e.printStackTrace();        }        super.onDestroy();    }}



ClientActivity.java

package com.moliying.bluetooth;import android.bluetooth.BluetoothDevice;import android.bluetooth.BluetoothSocket;import android.os.Handler;import android.os.Message;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.text.TextUtils;import android.view.View;import android.widget.Button;import android.widget.EditText;import android.widget.TextView;import android.widget.Toast;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.io.PrintStream;import java.util.UUID;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;public class ClientActivity extends AppCompatActivity {    private static final int CONN_SUCCESS = 0x1;    private static final int HANDLER_INFO = 0x2;    private static final int CLEAN_INFO = 0x3;    private TextView textView_info;    private EditText editText_info;    private Button button_send;    private BluetoothDevice device;    private BluetoothSocket socket;    private ExecutorService es = Executors.newFixedThreadPool(3);    private PrintStream ps;    private BufferedReader in;    private String name;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_client);        textView_info = (TextView) findViewById(R.id.textView_info);        editText_info = (EditText) findViewById(R.id.editText_info);        button_send = (Button) findViewById(R.id.button_send);        connect();    }    //连接指定的设备    private void connect() {        device = getIntent().getParcelableExtra("device");        if(device!=null){            es.execute(new Runnable() {                @Override                public void run() {                    UUID uuid = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");                    try {                        socket = device.createRfcommSocketToServiceRecord(uuid);                        if(socket!=null) {                            socket.connect();                            ps = new PrintStream(socket.getOutputStream());                            in = new BufferedReader(new InputStreamReader(socket.getInputStream()));                            name = socket.getRemoteDevice().getName();                            handler.sendEmptyMessage(CONN_SUCCESS);                        }                    } catch (IOException e) {                        e.printStackTrace();                    }                }            });        }    }    private boolean isReceive = false;    //接收消息的线程    class ReceiverThread implements Runnable{        public ReceiverThread() {            isReceive = true;        }        @Override        public void run() {            while (isReceive){                try {                    String info = in.readLine();//阻塞                    Message msg = handler.obtainMessage(HANDLER_INFO,info);                    handler.sendMessage(msg);                } catch (IOException e) {                    e.printStackTrace();                    isReceive = false;                }            }        }    }    //发送消息的事件    public void sendClick(View view){        final String info = editText_info.getText().toString();        if (TextUtils.isEmpty(info)){            Toast.makeText(ClientActivity.this, "不能发送空消息", Toast.LENGTH_SHORT).show();        }        es.execute(new Runnable() {            @Override            public void run() {                ps.println(info);                ps.flush();                handler.sendEmptyMessage(CLEAN_INFO);            }        });    }    //更新UI的处理器    private Handler handler = new Handler(){        @Override        public void handleMessage(Message msg) {            switch (msg.what){                case HANDLER_INFO:                    textView_info.append("【"+name+"】对我说:"+msg.obj.toString()+"\n");                    break;                case CLEAN_INFO:                    textView_info.append("我对【"+name+"】说:"+editText_info.getText().toString()+"\n");                    editText_info.setText("");                    break;                case CONN_SUCCESS:                    String name = device.getName();                    textView_info.append("成功与【"+name+"】连接\n");                    es.execute(new ReceiverThread());                    break;            }        }    };    @Override    protected void onDestroy() {        isReceive = false;        es.shutdown();        try {            socket.close();        } catch (IOException e) {            e.printStackTrace();        }        super.onDestroy();    }}




0 0