赞
踩
目录
2. 在文件res/values/strings.xml里,添加程序运行过程中的状态描述文本及配色代码等
5.建立选择蓝牙设备的布局文件 device_list.xml
6.新建Activity组件DeviceList,实现选取与之会话的蓝牙设备
- <!--下面2个是普通权限,只需要在清单文件里注册,不需要在程序里动态申请-->
- <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
- <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
-
- <!--搜索WiFi,需要定位权限,它是危险权限,在此声明外,还需要在程序里动态申请-->
- <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
- <resources>
- <string name="app_name">BlueTooth_Chat</string>
- <string name="top_name">蓝牙聊天</string>
- <string name="bottom_image">底部图标</string>
- <string name="bottom_name1">微信</string>
- <string name="bottom_name2">朋友</string>
- <string name="bottom_name3">通讯录</string>
- <string name="bottom_name4">设置</string>
-
- <string name="send">发送</string>
- <string name="not_connected">你没有链接一个设备</string>
- <string name="bt_not_enabled_leaving">蓝牙不可用,离开聊天室</string>
- <string name="title_connecting">链接中...</string>
- <string name="title_connected_to">连接到:</string>
- <string name="title_not_connected">无链接</string>
- <string name="scanning">蓝牙设备搜索中...</string>
- <string name="select_device">选择一个好友链接</string>
- <string name="none_paired">没有配对好友</string>
- <string name="none_found">附近没有发现好友</string>
- <string name="title_paired_devices">已配对好友</string>
- <string name="title_other_devices">其它可连接好友</string>
- <string name="button_scan">搜索好友</string>
- <string name="connect">我的好友</string>
- <string name="discoverable">设置在线</string>
- <string name="back">退出</string>
- <string name="startVideo">开始聊天</string>
- <string name="stopVideo">结束聊天</string>
-
- <!-- TODO: Remove or change this placeholder text -->
- <string name="hello_blank_fragment">Hello blank fragment</string>
- </resources>
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/device_name"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:background="@color/bg01"
- android:orientation="vertical">
-
- <!--新版Android支持的Toolbar,对标题栏布局-->
- <!-- <android.support.v7.widget.Toolbar-->
- <androidx.appcompat.widget.Toolbar
- android:id="@+id/toolbar"
- android:layout_width="match_parent"
- android:layout_height="34dp">
-
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="horizontal">
-
- <TextView
- android:id="@+id/title_left_text"
- style="?android:attr/windowTitleStyle"
- android:layout_width="0dp"
- android:layout_height="match_parent"
- android:layout_alignParentLeft="true"
- android:layout_weight="1"
- android:ellipsize="end"
- android:gravity="left"
- android:singleLine="true" />
-
- <TextView
- android:id="@+id/title_right_text"
- android:layout_width="0dp"
- android:layout_height="match_parent"
- android:layout_alignParentRight="true"
- android:layout_weight="1"
- android:ellipsize="end"
- android:gravity="right"
- android:singleLine="true"
- android:textColor="#fff" />
- </LinearLayout>
- </androidx.appcompat.widget.Toolbar>
- <!-- </android.support.v7.widget.Toolbar>-->
-
- <ListView
- android:id="@+id/in"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_weight="1"
- android:stackFromBottom="true"
- android:transcriptMode="alwaysScroll" />
-
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal">
-
- <EditText
- android:id="@+id/edit_text_out"
- android:layout_width="0dp"
- android:layout_height="wrap_content"
- android:layout_gravity="bottom"
- android:layout_weight="1" />
-
- <Button
- android:id="@+id/button_send"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/send" />
- </LinearLayout>
- </LinearLayout>
- package com.e.bluetooth_chat;
-
- 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 java.io.IOException;
- import java.io.InputStream;
- import java.io.OutputStream;
- import java.util.UUID;
-
- public class ChatService {
- //本应用的主Activity组件名称
- private static final String NAME = "BlueToothChat";
- // UUID:通用唯一识别码,是一个128位长的数字,一般用十六进制表示
- //算法的核心思想是结合机器的网卡、当地时间、一个随机数来生成
- //在创建蓝牙连接
- private static final UUID MY_UUID = UUID.fromString("fa87c0d0-afac-11de-8a39-0800200c9a66");
- private final BluetoothAdapter mAdapter;
- private final Handler mHandler;
- private AcceptThread mAcceptThread;
- private ConnectThread mConnectThread;
- private ConnectedThread mConnectedThread;
- private int mState;
- public static final int STATE_NONE = 0;
- public static final int STATE_LISTEN = 1;
- public static final int STATE_CONNECTING = 2;
- public static final int STATE_CONNECTED = 3;
-
- //构造方法,接收UI主线程传递的对象
- public ChatService(Context context,Handler handler){
- //构造方法完成蓝牙对象的创建
- mAdapter = BluetoothAdapter.getDefaultAdapter();
- mState = STATE_NONE;
- mHandler = handler;
- }
-
- private synchronized void setState(int state){
- mState = state;
- mHandler.obtainMessage(weixinFragment.MESSAGE_STATE_CHANGE, state, -1).sendToTarget();
- }
-
- public synchronized int getState(){
- return mState;
- }
-
- public synchronized void start(){
- if (mConnectThread != null) {
- mConnectThread.cancel();
- mConnectThread = null;
- }
- if (mConnectedThread != null) {
- mConnectedThread.cancel();
- mConnectedThread = null;
- }
- if (mAcceptThread == null) {
- mAcceptThread = new AcceptThread();
- mAcceptThread.start();
- }
- setState(STATE_LISTEN);
- }
-
- //取消 CONNECTING 和 CONNECTED 状态下的相关线程,然后运行新的 mConnectThread 线程
- public synchronized void connect(BluetoothDevice device) {
- if (mState == STATE_CONNECTING) {
- if (mConnectThread != null) {
- mConnectThread.cancel();
- mConnectThread = null;
- }
- }
- if (mConnectedThread != null) {
- mConnectedThread.cancel();
- mConnectedThread = null;
- }
- mConnectThread = new ConnectThread(device);
- mConnectThread.start();
- setState(STATE_CONNECTING);
- }
-
- /*
- 开启一个 ConnectedThread 来管理对应的当前连接。之前先取消任意现存的 mConnectThread 、
- mConnectedThread 、 mAcceptThread 线程,然后开启新 mConnectedThread ,传入当前刚刚接受的
- socket 连接。最后通过 Handler来通知UI连接
- */
- public synchronized void connected(BluetoothSocket socket, BluetoothDevice device) {
- if (mConnectThread != null) {
- mConnectThread.cancel();
- mConnectThread = null;
- }
- if (mConnectedThread != null) {
- mConnectedThread.cancel();
- mConnectedThread = null;
- }
- if (mAcceptThread != null) {
- mAcceptThread.cancel();
- mAcceptThread = null;
- }
- mConnectedThread = new ConnectedThread(socket);
- mConnectedThread.start();
- Message msg = mHandler.obtainMessage(weixinFragment.MESSAGE_DEVICE_NAME);
- Bundle bundle = new Bundle();
- bundle.putString(weixinFragment.DEVICE_NAME, device.getName());
- msg.setData(bundle);
- mHandler.sendMessage(msg);
- setState(STATE_CONNECTED);
- }
-
- // 停止所有相关线程,设当前状态为 NONE
- public synchronized void 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);
- }
-
- // 在 STATE_CONNECTED 状态下,调用 mConnectedThread 里的 write 方法,写入 byte
- public void write(byte[] out) {
- ConnectedThread r;
- synchronized (this) {
- if (mState != STATE_CONNECTED)
- return;
- r = mConnectedThread;
- }
- r.write(out);
- }
-
- // 连接失败的时候处理,通知 ui ,并设为 STATE_LISTEN 状态
- public void connectionFailed() {
- setState(STATE_LISTEN);
- Message msg = mHandler.obtainMessage(weixinFragment.MESSAGE_TOAST);
- Bundle bundle = new Bundle();
- bundle.putString(weixinFragment.TOAST, "链接不到设备");
- msg.setData(bundle);
- mHandler.sendMessage(msg);
- }
-
- // 当连接失去的时候,设为 STATE_LISTEN 状态并通知 ui
- public void connectionLost() {
- setState(STATE_LISTEN);
- Message msg = mHandler.obtainMessage(weixinFragment.MESSAGE_TOAST);
- Bundle bundle = new Bundle();
- bundle.putString(weixinFragment.TOAST, "设备链接中断");
- msg.setData(bundle);
- mHandler.sendMessage(msg);
- }
-
-
- private class AcceptThread extends Thread {
- private final BluetoothServerSocket mmServerSocket;
-
- public AcceptThread() {
- BluetoothServerSocket tmp = null;
- try {
- //使用射频端口(RF comm)监听
- tmp = mAdapter.listenUsingRfcommWithServiceRecord(NAME, MY_UUID);
- } catch (IOException e) {
- }
- mmServerSocket = tmp;
- }
-
- @Override
- public void run() {
- setName("AcceptThread");
- BluetoothSocket socket = null;
- while (mState != STATE_CONNECTED) {
- try {
- socket = mmServerSocket.accept();
- } catch (IOException e) {
- e.printStackTrace();
- break;
- }
- if (socket != null) {
- synchronized (ChatService.this) {
- switch (mState) {
- case STATE_LISTEN:
- case STATE_CONNECTING:
- connected(socket, socket.getRemoteDevice());
- break;
- case STATE_NONE:
- case STATE_CONNECTED:
- try {
- socket.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- break;
- }
- }
- }
- }
- }
-
-
- public void cancel() {
- try {
- mmServerSocket.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
-
- /*
- 连接线程,专门用来对外发出连接对方蓝牙的请求和处理流程。
- 构造函数里通过 BluetoothDevice.createRfcommSocketToServiceRecord() ,
- 从待连接的 device 产生 BluetoothSocket. 然后在 run 方法中 connect ,
- 成功后调用 BluetoothChatSevice 的 connected() 方法。定义 cancel() 在关闭线程时能够关闭相关socket 。
- */
- private class ConnectThread extends Thread{
- private final BluetoothSocket mmSocket;
- private final BluetoothDevice mmDevice;
-
- public ConnectThread(BluetoothDevice device) {
- mmDevice = device;
- BluetoothSocket tmp = null;
- try {
- tmp = device.createRfcommSocketToServiceRecord(MY_UUID);
- } catch (IOException e) {
- e.printStackTrace();
- }
- mmSocket = tmp;
- }
-
- @Override
- public void run() {
- setName("ConnectThread");
- mAdapter.cancelDiscovery();
- try {
- mmSocket.connect();
- } catch (IOException e) {
- connectionFailed();
- try {
- mmSocket.close();
- } catch (IOException e2) {
- e.printStackTrace();
- }
- ChatService.this.start();
- return;
- }
- synchronized (ChatService.this) {
- mConnectThread = null;
- }
- connected(mmSocket, mmDevice);
- }
-
- public void cancel() {
- try {
- mmSocket.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
-
- /*
- 双方蓝牙连接后一直运行的线程;构造函数中设置输入输出流。
- run()方法中使用阻塞模式的 InputStream.read()循环读取输入流,然后发送到 UI 线程中更新聊天消息。
- 本线程也提供了 write() 将聊天消息写入输出流传输至对方,传输成功后回写入 UI 线程。最后使用cancel()关闭连接的 socket
- */
- private class ConnectedThread extends Thread{
- private final BluetoothSocket mmSocket;
- private final InputStream mmInStream;
- private final OutputStream mmOutStream;
-
- public ConnectedThread(BluetoothSocket socket) {
- mmSocket = socket;
- InputStream tmpIn = null;
- OutputStream tmpOut = null;
- try {
- tmpIn = socket.getInputStream();
- tmpOut = socket.getOutputStream();
- } catch (IOException e) {
- e.printStackTrace();
- }
- mmInStream = tmpIn;
- mmOutStream = tmpOut;
- }
-
- @Override
- public void run() {
- byte[] buffer = new byte[1024];
- int bytes;
- while (true) {
- try {
- bytes = mmInStream.read(buffer);
- mHandler.obtainMessage(weixinFragment.MESSAGE_READ, bytes, -1, buffer).sendToTarget();
- } catch (IOException e) {
- connectionLost();
- break;
- }
- }
- }
-
- public void write(byte[] buffer) {
- try {
- mmOutStream.write(buffer);
- mHandler.obtainMessage(weixinFragment.MESSAGE_WRITE, -1, -1, buffer).sendToTarget();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
-
- public void cancel() {
- try {
- mmSocket.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
- }
- <?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">
- <TextView android:id="@+id/title_paired_devices"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:text="@string/title_paired_devices"
- android:visibility="gone"
- android:background="#666"
- android:textColor="#fff"
- android:paddingLeft="5dp"
- android:paddingStart="5dp" />
- <ListView android:id="@+id/paired_devices"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_weight="1" />
- <TextView android:id="@+id/title_new_devices"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:text="@string/title_other_devices"
- android:visibility="gone"
- android:background="#666"
- android:textColor="#fff"
- android:paddingLeft="5dp"
- android:paddingStart="5dp" />
- <!--android:visibility="gone"表示不占空间的隐藏,invisible是占空间-->
- <ListView android:id="@+id/new_devices"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_weight="2" />
- <Button android:id="@+id/button_scan"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:text="@string/button_scan" />
- </LinearLayout>
- package com.e.bluetooth_chat;
-
- import android.app.Activity;
- 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.os.Bundle;
- import android.provider.Settings;
- import android.view.View;
- import android.widget.AdapterView;
- import android.widget.ArrayAdapter;
- import android.widget.Button;
- import android.widget.ListView;
- import android.widget.TextView;
- import android.widget.Toast;
-
- import androidx.annotation.Nullable;
- import androidx.appcompat.app.AppCompatActivity;
-
- import java.util.Set;
-
- /*
- 本程序供菜单项主界面的选项菜单“我的友好”调用,用于:
- (1)显示已配对的好友列表;
- (2)搜索可配对的好友进行配对
- (3)新选择并配对的蓝牙设备将刷新好友列表
- 注意:发现新的蓝牙设备并请求配对时,需要对应接受
- 关键技术:动态注册一个广播接收者,处理蓝牙设备扫描的结果
- */
- public class DeviceList extends AppCompatActivity {
- private BluetoothAdapter mBtAdapter;
- private ArrayAdapter<String> mPairedDevicesArrayAdapter;
- private ArrayAdapter<String> mNewDevicesArrayAdapter;
- public static String EXTRA_DEVICE_ADDRESS = "device_address"; //Mac地址
- //定义广播接收者,用于处理扫描蓝牙设备后的结果
- 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){
- mNewDevicesArrayAdapter.add(device.getName()+"\n"+device.getAddress());
- }
- }else if(BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)){
- if(mNewDevicesArrayAdapter.getCount() == 0){
- String noDevices = getResources().getText(R.string.none_found).toString();
- mNewDevicesArrayAdapter.add(noDevices);
- }
- }
- }
- };
-
- @Override
- protected void onCreate(@Nullable Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.device_list);
- //在被调用活动里,设置返回结果码
- setResult(Activity.RESULT_CANCELED);
- init(); //活动界面
- }
-
- private void init() {
- Button scanButton = findViewById(R.id.button_scan);
- scanButton.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- Toast.makeText(DeviceList.this,R.string.scanning,Toast.LENGTH_LONG).show();
- doDiscovery(); //搜索蓝牙设备
- }
- });
- mPairedDevicesArrayAdapter = new ArrayAdapter<String>(this,R.layout.device_name);
- mNewDevicesArrayAdapter = new ArrayAdapter<String>(this, R.layout.device_name);
- // mPairedDevicesArrayAdapter = new ArrayAdapter<String>(this,R.layout.device_name);
- // mNewDevicesArrayAdapter = new ArrayAdapter<String>(this, R.layout.device_name);
- //已配对蓝牙设备列表
- ListView pairedListView =findViewById(R.id.paired_devices);
- pairedListView.setAdapter(mPairedDevicesArrayAdapter);
- pairedListView.setOnItemClickListener(mPaireDeviceClickListener);
- //未配对蓝牙设备列表
- ListView newDevicesListView = findViewById(R.id.new_devices);
- newDevicesListView.setAdapter(mNewDevicesArrayAdapter);
- newDevicesListView.setOnItemClickListener(mNewDeviceClickListener);
- //动态注册广播接收者
- IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
- registerReceiver(mReceiver, filter);
- filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
- registerReceiver(mReceiver, filter);
- mBtAdapter = BluetoothAdapter.getDefaultAdapter();
- Set<BluetoothDevice> pairedDevices = mBtAdapter.getBondedDevices();
- if (pairedDevices.size() > 0) {
- findViewById(R.id.title_paired_devices).setVisibility(View.VISIBLE);
- for (BluetoothDevice device : pairedDevices) {
- mPairedDevicesArrayAdapter.add(device.getName() + "\n" + device.getAddress());
- }
- } else {
- String noDevices;
- noDevices = getResources().getText(R.string.none_paired).toString();
- mPairedDevicesArrayAdapter.add(noDevices);
- }
- }
-
- @Override
- protected void onDestroy() {
- super.onDestroy();
- if(mBtAdapter!=null){
- mBtAdapter.cancelDiscovery();
- }
- this.unregisterReceiver(mReceiver);
- }
-
- private void doDiscovery() {
- findViewById(R.id.title_new_devices).setVisibility(View.VISIBLE);
- if (mBtAdapter.isDiscovering()) {
- mBtAdapter.cancelDiscovery();
- }
- mBtAdapter.startDiscovery(); //开始搜索蓝牙设备并产生广播
- //startDiscovery是一个异步方法
- //找到一个设备时就发送一个BluetoothDevice.ACTION_FOUND的广播
- }
-
- private AdapterView.OnItemClickListener mPaireDeviceClickListener = new AdapterView.OnItemClickListener() {
- public void onItemClick(AdapterView<?> av, View v, int arg2, long arg3) {
- mBtAdapter.cancelDiscovery();
- String info = ((TextView) v).getText().toString();
- String address = info.substring(info.length() - 17);
- Intent intent = new Intent();
- intent.putExtra(EXTRA_DEVICE_ADDRESS, address); //Mac地址
- setResult(Activity.RESULT_OK, intent);
- finish();
- }
- };
-
- private AdapterView.OnItemClickListener mNewDeviceClickListener = new AdapterView.OnItemClickListener() {
- public void onItemClick(AdapterView<?> av, View v, int arg2, long arg3) {
- mBtAdapter.cancelDiscovery();
- Toast.makeText(DeviceList.this, "请在蓝牙设置界面手动连接设备",Toast.LENGTH_SHORT).show();
- Intent intent = new Intent(Settings.ACTION_BLUETOOTH_SETTINGS);
- startActivityForResult(intent,1);
- }
- };
-
- @Override
- protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
- super.onActivityResult(requestCode, resultCode, data);
- init();
- }
- }
- package com.e.bluetooth_chat;
-
- import android.Manifest;
- import android.app.Activity;
- import android.bluetooth.BluetoothAdapter;
- import android.bluetooth.BluetoothDevice;
- import android.content.Intent;
- import android.content.pm.PackageManager;
- import android.os.Build;
- import android.os.Bundle;
-
- import androidx.annotation.NonNull;
- import androidx.annotation.RequiresApi;
- import androidx.core.app.ActivityCompat;
- import androidx.core.content.ContextCompat;
- import androidx.fragment.app.Fragment;
-
- import android.os.Handler;
- import android.os.Message;
- import android.view.KeyEvent;
- import android.view.LayoutInflater;
- import android.view.MenuItem;
- import android.view.View;
- import android.view.ViewGroup;
- import android.view.inputmethod.EditorInfo;
- import android.widget.ArrayAdapter;
- import android.widget.Button;
- import android.widget.EditText;
- import android.widget.ListView;
- import android.widget.TextView;
- import android.widget.Toast;
- import androidx.appcompat.widget.Toolbar;
-
-
- /**
- * A simple {@link Fragment} subclass.
- */
- public class weixinFragment extends Fragment {
-
- // 蓝牙通信
- 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;
- public static final String DEVICE_NAME = "device_name";
- public static final String TOAST = "toast";
- private static final int REQUEST_CONNECT_DEVICE = 1; //请求连接设备
- private static final int REQUEST_ENABLE_BT = 2;
- private TextView mTitle;
- private ListView mConversationView;
- private EditText mOutEditText;
- private Button mSendButton;
- private String mConnectedDeviceName = null;
- private ArrayAdapter<String> mConversationArrayAdapter;
- private StringBuffer mOutStringBuffer;
- private BluetoothAdapter mBluetoothAdapter = null;
- private ChatService mChatService = null;
-
- View view;
-
-
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container,
- Bundle savedInstanceState) {
- view = inflater.inflate(R.layout.tab01, container, false);
- Toolbar toolbar = view.findViewById(R.id.toolbar);
- setHasOptionsMenu(true);
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
- if (ContextCompat.checkSelfPermission(view.getContext(), Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
- ActivityCompat.requestPermissions(getActivity(), new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, 1);
- }
- }
- //创建选项菜单
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
- toolbar.inflateMenu(R.menu.option_menu);
- }
- //选项菜单监听
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
- toolbar.setOnMenuItemClickListener(new MyMenuItemClickListener());
- }
- mTitle = view.findViewById(R.id.title_left_text);
- mTitle.setText("蓝牙通信");
- mTitle = view.findViewById(R.id.title_right_text);
- // 得到本地蓝牙适配器
- mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
- if (mBluetoothAdapter == null) {
- Toast.makeText(view.getContext(), "蓝牙不可用", Toast.LENGTH_LONG).show();
- getActivity().finish();
- return view;
- }
- if (!mBluetoothAdapter.isEnabled()) { //若当前设备蓝牙功能未开启
- Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
- startActivityForResult(enableIntent, REQUEST_ENABLE_BT); //
- } else {
- if (mChatService == null) {
- setupChat(); //创建会话
- }
- }
-
- return view;
- }
-
- @Override
- public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
- super.onRequestPermissionsResult(requestCode, permissions, grantResults);
- if(grantResults.length>0){
- if(grantResults[0]!=PackageManager.PERMISSION_GRANTED){
- Toast.makeText(view.getContext(), "未授权,蓝牙搜索功能将不可用!", Toast.LENGTH_SHORT).show();
- }
- }
- }
-
-
- private void setupChat() {
- mConversationArrayAdapter = new ArrayAdapter<String>(view.getContext(), R.layout.message);
- mConversationView = view.findViewById(R.id.in);
- mConversationView.setAdapter(mConversationArrayAdapter);
- mOutEditText = view.findViewById(R.id.edit_text_out);
- mOutEditText.setOnEditorActionListener(mWriteListener);
- mSendButton = view.findViewById(R.id.button_send);
- mSendButton.setOnClickListener(new View.OnClickListener() {
- public void onClick(View v) {
- TextView textView = view.findViewById(R.id.edit_text_out);
- String message = textView.getText().toString();
- sendMessage(message);
- }
- });
- //创建服务对象
- mChatService = new ChatService(view.getContext(), mHandler);
- mOutStringBuffer = new StringBuffer("");
- }
-
- private void sendMessage(String message){
- if(mChatService.getState() != ChatService.STATE_CONNECTED){
- Toast.makeText(view.getContext(),R.string.not_connected,Toast.LENGTH_LONG).show();
- return;
- }
- if(message.length()>0){
- byte[] send = message.getBytes();
- mChatService.write(send);
- mOutStringBuffer.setLength(0);
- mOutEditText.setText(mOutStringBuffer);
- }
- }
-
- 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);
- Toast.makeText(view.getContext(), "已经设置本机蓝牙设备的可见性,对方可搜索了。", Toast.LENGTH_SHORT).show();
- }
- }
-
- private TextView.OnEditorActionListener mWriteListener = new TextView.OnEditorActionListener() {
- @Override
- public boolean onEditorAction(TextView view, int actionId, KeyEvent event) {
- if (actionId == EditorInfo.IME_NULL && event.getAction() == KeyEvent.ACTION_UP) {
- String message = view.getText().toString();
- sendMessage(message);
- }
- return true;
- }
- };
-
- private final Handler mHandler = new Handler() {
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case MESSAGE_STATE_CHANGE:
- switch (msg.arg1) {
- case ChatService.STATE_CONNECTED:
- mTitle.setText(R.string.title_connected_to);
- mTitle.append(mConnectedDeviceName);
- mConversationArrayAdapter.clear();
- break;
- case ChatService.STATE_CONNECTING:
- mTitle.setText(R.string.title_connecting);
- break;
- case ChatService.STATE_LISTEN:
- case ChatService.STATE_NONE:
- mTitle.setText(R.string.title_not_connected);
- break;
- }
- break;
- case MESSAGE_WRITE:
- byte[] writeBuf = (byte[]) msg.obj;
- String writeMessage = new String(writeBuf);
- mConversationArrayAdapter.add("我: " + writeMessage);
- break;
- case MESSAGE_READ:
- byte[] readBuf = (byte[]) msg.obj;
- String readMessage = new String(readBuf, 0, msg.arg1);
- mConversationArrayAdapter.add(mConnectedDeviceName + ": "
- + readMessage);
- break;
- case MESSAGE_DEVICE_NAME:
- mConnectedDeviceName = msg.getData().getString(DEVICE_NAME);
- Toast.makeText(getActivity().getApplicationContext(),"链接到 " + mConnectedDeviceName, Toast.LENGTH_SHORT).show();
- break;
- case MESSAGE_TOAST:
- Toast.makeText(getActivity().getApplicationContext(), msg.getData().getString(TOAST), Toast.LENGTH_SHORT).show();
- break;
- }
- }
- };
-
- //返回进入好友列表操作后的数回调方法
- public void onActivityResult(int requestCode, int resultCode, Intent data) {
- switch (requestCode) {
- case REQUEST_CONNECT_DEVICE:
- if (resultCode == Activity.RESULT_OK) {
- String address = data.getExtras().getString(DeviceList.EXTRA_DEVICE_ADDRESS);
- BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
- mChatService.connect(device);
- }else if(resultCode==Activity.RESULT_CANCELED){
- Toast.makeText(view.getContext(), "未选择任何好友!", Toast.LENGTH_SHORT).show();
- }
- break;
- case REQUEST_ENABLE_BT:
- if (resultCode == Activity.RESULT_OK) {
- setupChat();
- } else {
- Toast.makeText(view.getContext(), R.string.bt_not_enabled_leaving, Toast.LENGTH_SHORT).show();
- getActivity().finish();
- }
- }
- }
-
-
- //内部类,选项菜单的单击事件处理
- @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
- private class MyMenuItemClickListener implements Toolbar.OnMenuItemClickListener {
- @Override
- public boolean onMenuItemClick(MenuItem item) {
- switch (item.getItemId()) {
- case R.id.scan:
- //启动DeviceList这个Activity
- Intent serverIntent = new Intent(getActivity(), DeviceList.class);
- startActivityForResult(serverIntent, REQUEST_CONNECT_DEVICE);
- return true;
- case R.id.discoverable:
- ensureDiscoverable();
- return true;
- case R.id.back:
- getActivity().finish();
- System.exit(0);
- return true;
- }
- return false;
- }
- }
-
-
- @Override
- public synchronized void onResume() {
- //synchronized:同步方法实现排队调用
- super.onResume();
- if (mChatService != null) {
- if (mChatService.getState() == ChatService.STATE_NONE) {
- mChatService.start();
- }
- }
- }
-
- @Override
- public void onDestroy() {
- super.onDestroy();
- if(mChatService != null){
- mChatService.stop();
- }
- }
- }
-
赞
踩
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。