|
@@ -6,12 +6,19 @@ import android.annotation.SuppressLint;
|
|
|
import android.app.ProgressDialog;
|
|
|
import android.bluetooth.BluetoothAdapter;
|
|
|
import android.bluetooth.BluetoothDevice;
|
|
|
+import android.bluetooth.BluetoothSocket;
|
|
|
+import android.content.BroadcastReceiver;
|
|
|
import android.content.Context;
|
|
|
+import android.content.DialogInterface;
|
|
|
import android.content.Intent;
|
|
|
+import android.content.IntentFilter;
|
|
|
+import android.content.pm.PackageManager;
|
|
|
+import android.os.Build;
|
|
|
import android.os.Bundle;
|
|
|
-import android.os.PersistableBundle;
|
|
|
-import android.support.annotation.Nullable;
|
|
|
+import android.os.Handler;
|
|
|
+import android.support.annotation.NonNull;
|
|
|
import android.support.v7.app.AppCompatActivity;
|
|
|
+import android.support.v7.app.AppCompatDelegate;
|
|
|
import android.view.Menu;
|
|
|
import android.view.MenuItem;
|
|
|
import android.view.View;
|
|
@@ -23,9 +30,15 @@ import android.widget.Toast;
|
|
|
|
|
|
import com.joanzapata.iconify.widget.IconTextView;
|
|
|
|
|
|
+import java.io.IOException;
|
|
|
+import java.lang.reflect.InvocationTargetException;
|
|
|
+import java.lang.reflect.Method;
|
|
|
import java.util.ArrayList;
|
|
|
import java.util.List;
|
|
|
import java.util.Set;
|
|
|
+import java.util.Timer;
|
|
|
+import java.util.TimerTask;
|
|
|
+import java.util.UUID;
|
|
|
|
|
|
import butterknife.BindView;
|
|
|
import butterknife.ButterKnife;
|
|
@@ -59,7 +72,15 @@ public class ScanDeviceActivity extends AppCompatActivity {
|
|
|
|
|
|
private ProgressDialog dialog;
|
|
|
|
|
|
- private BluetoothAdapter adapter;
|
|
|
+ private BluetoothAdapter adapter = App.getApp().getBluetoothAdapter();
|
|
|
+ List<DeviceListAdapter.ItemBean> matchItemBeanList = new ArrayList<>();
|
|
|
+ List<DeviceListAdapter.ItemBean> searchItemBeanList = new ArrayList<>();
|
|
|
+ private DeviceListAdapter matchDeviceListAdapter;
|
|
|
+ private DeviceListAdapter searchDeviceListAdapter;
|
|
|
+
|
|
|
+ static {
|
|
|
+ AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
|
|
|
+ }
|
|
|
|
|
|
@Override
|
|
|
protected void onCreate(Bundle savedInstanceState) {
|
|
@@ -67,11 +88,48 @@ public class ScanDeviceActivity extends AppCompatActivity {
|
|
|
setContentView(R.layout.activity_scan_device);
|
|
|
ButterKnife.bind(this);
|
|
|
|
|
|
+ // 设置广播信息过滤
|
|
|
+ IntentFilter intentFilter = new IntentFilter();
|
|
|
+ intentFilter.addAction(BluetoothDevice.ACTION_FOUND);
|
|
|
+ intentFilter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
|
|
|
+ intentFilter.addAction(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED);
|
|
|
+ intentFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
|
|
|
+ // 注册广播接收器,接收并处理搜索结果
|
|
|
+ this.registerReceiver(receiver, intentFilter);
|
|
|
+
|
|
|
+ // 检查设备是否支持蓝牙
|
|
|
+ if (adapter == null) {
|
|
|
+ // 设备不支持蓝牙
|
|
|
+ Toast.makeText(ScanDeviceActivity.this, "设备不支持蓝牙", Toast.LENGTH_LONG).show();
|
|
|
+ ScanDeviceActivity.this.finish();
|
|
|
+ } else {
|
|
|
+ if (!adapter.isEnabled()) {
|
|
|
+ Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
|
|
|
+ // 设置蓝牙可见性,最多 300 秒
|
|
|
+ intent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 60);
|
|
|
+ ScanDeviceActivity.this.startActivityForResult(intent, 0);
|
|
|
+ }
|
|
|
+ Set<BluetoothDevice> devices = adapter.getBondedDevices();
|
|
|
+ for (BluetoothDevice device : devices) {
|
|
|
+ matchItemBeanList.add(new DeviceListAdapter.ItemBean(device));
|
|
|
+ }
|
|
|
+ matchDeviceListAdapter = new DeviceListAdapter(this, matchItemBeanList);
|
|
|
+ matchList.setAdapter(matchDeviceListAdapter);
|
|
|
+ searchDeviceListAdapter = new DeviceListAdapter(this, searchItemBeanList);
|
|
|
+ searchList.setAdapter(searchDeviceListAdapter);
|
|
|
+ }
|
|
|
+
|
|
|
initView();
|
|
|
setListener();
|
|
|
loadData();
|
|
|
}
|
|
|
|
|
|
+ @Override
|
|
|
+ protected void onDestroy() {
|
|
|
+ super.onDestroy();
|
|
|
+ this.unregisterReceiver(receiver);
|
|
|
+ }
|
|
|
+
|
|
|
private void initView() {
|
|
|
App.setupActionBar(this);
|
|
|
}
|
|
@@ -80,25 +138,34 @@ public class ScanDeviceActivity extends AppCompatActivity {
|
|
|
matchList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
|
|
|
@Override
|
|
|
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
|
|
|
+ // 尝试连接
|
|
|
+ }
|
|
|
+ });
|
|
|
+ searchList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
|
|
|
+ @Override
|
|
|
+ public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
|
|
+ // 尝试配对
|
|
|
+ try {
|
|
|
+ Method createBondMethod = BluetoothDevice.class.getMethod("createBond");
|
|
|
+ createBondMethod.invoke(searchItemBeanList.get(position).device);
|
|
|
+ } catch (NoSuchMethodException e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ } catch (IllegalAccessException e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ } catch (InvocationTargetException e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
}
|
|
|
});
|
|
|
}
|
|
|
|
|
|
private void loadData() {
|
|
|
- // 检查设备是否支持蓝牙
|
|
|
- adapter = BluetoothAdapter.getDefaultAdapter();
|
|
|
- if (adapter == null) {
|
|
|
- // 设备不支持蓝牙
|
|
|
- Toast.makeText(ScanDeviceActivity.this, "设备不支持蓝牙", Toast.LENGTH_LONG).show();
|
|
|
- ScanDeviceActivity.this.finish();
|
|
|
- }
|
|
|
- List<DeviceListAdapter.ItemBean> matchItemBeanList = new ArrayList<>();
|
|
|
- Set<BluetoothDevice> devices = adapter.getBondedDevices();
|
|
|
- for (BluetoothDevice device : devices) {
|
|
|
- matchItemBeanList.add(new DeviceListAdapter.ItemBean(device.getName(), device.getAddress()));
|
|
|
- System.out.println("name = " + device.getName());
|
|
|
+ // 请求定位权限
|
|
|
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
|
|
+ if (this.checkSelfPermission(android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
|
|
|
+ requestPermissions(new String[]{android.Manifest.permission.ACCESS_COARSE_LOCATION}, 1);
|
|
|
+ }
|
|
|
}
|
|
|
- matchList.setAdapter(new DeviceListAdapter(this, matchItemBeanList));
|
|
|
}
|
|
|
|
|
|
public static void start(Context context) {
|
|
@@ -112,6 +179,13 @@ public class ScanDeviceActivity extends AppCompatActivity {
|
|
|
dialog.setTitle("蓝牙串口");
|
|
|
dialog.setMessage("搜索设备中······");
|
|
|
dialog.setCancelable(false);
|
|
|
+ dialog.setButton(DialogInterface.BUTTON_NEGATIVE, "取消", new DialogInterface.OnClickListener() {
|
|
|
+ @Override
|
|
|
+ public void onClick(DialogInterface dialogInterface, int i) {
|
|
|
+ adapter.cancelDiscovery();
|
|
|
+ dialog.dismiss();
|
|
|
+ }
|
|
|
+ });
|
|
|
}
|
|
|
if (show) {
|
|
|
dialog.show();
|
|
@@ -173,6 +247,14 @@ public class ScanDeviceActivity extends AppCompatActivity {
|
|
|
return (int) (dpValue * density + 0.5f);
|
|
|
}
|
|
|
|
|
|
+ private void connect(BluetoothDevice device) throws IOException {
|
|
|
+ // 固定的 UUID
|
|
|
+ String SPP_UUID = "00001101-0000-1000-8000-00805F9B34FB";
|
|
|
+ UUID uuid = UUID.fromString(SPP_UUID);
|
|
|
+ BluetoothSocket socket = device.createRfcommSocketToServiceRecord(uuid);
|
|
|
+ socket.connect();
|
|
|
+ }
|
|
|
+
|
|
|
@OnClick({R.id.matchListToggle, R.id.searchListToggle})
|
|
|
public void onViewClicked(View view) {
|
|
|
switch (view.getId()) {
|
|
@@ -187,7 +269,7 @@ public class ScanDeviceActivity extends AppCompatActivity {
|
|
|
|
|
|
@Override
|
|
|
public boolean onCreateOptionsMenu(Menu menu) {
|
|
|
- menu.add(0, 0, 0, "扫描").setIcon(R.drawable.ic_search_white_24dp).setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
|
|
|
+ menu.add(0, 0, 0, "搜索设备").setIcon(R.drawable.ic_search_white_24dp).setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
|
|
|
return super.onCreateOptionsMenu(menu);
|
|
|
}
|
|
|
|
|
@@ -198,6 +280,8 @@ public class ScanDeviceActivity extends AppCompatActivity {
|
|
|
ScanDeviceActivity.this.finish();
|
|
|
break;
|
|
|
case 0:
|
|
|
+ showProgress(true);
|
|
|
+ matchItemBeanList.clear();
|
|
|
// 打开蓝牙
|
|
|
if (!adapter.isEnabled()) {
|
|
|
Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
|
|
@@ -205,8 +289,123 @@ public class ScanDeviceActivity extends AppCompatActivity {
|
|
|
intent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);
|
|
|
ScanDeviceActivity.this.startActivity(intent);
|
|
|
}
|
|
|
+ // 寻找蓝牙设备,Android 会将查找到的设备以广播形式发出去
|
|
|
+ if (!adapter.isDiscovering()) {
|
|
|
+ adapter.startDiscovery();
|
|
|
+ }
|
|
|
+ // 弹出是否允许扫描蓝牙设备的选择对话框
|
|
|
+ // Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
|
|
|
+ // startActivityForResult(intent, 1);
|
|
|
+ new Handler().postDelayed(() -> runOnUiThread(() -> {
|
|
|
+ showProgress(false);
|
|
|
+ adapter.cancelDiscovery();
|
|
|
+ }), 20000);
|
|
|
break;
|
|
|
}
|
|
|
return super.onOptionsItemSelected(item);
|
|
|
}
|
|
|
+
|
|
|
+ @Override
|
|
|
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
|
|
+ super.onActivityResult(requestCode, resultCode, data);
|
|
|
+ switch (requestCode) {
|
|
|
+ case 0:
|
|
|
+ if (resultCode == RESULT_CANCELED) {
|
|
|
+ ScanDeviceActivity.this.finish();
|
|
|
+ Toast.makeText(this, "蓝牙未打开", Toast.LENGTH_SHORT).show();
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case 1:
|
|
|
+ new Handler().postDelayed(() -> runOnUiThread(() -> {
|
|
|
+ // 刷新蓝牙设备列表
|
|
|
+ System.out.println("刷新蓝牙设备列表");
|
|
|
+ }), 50);
|
|
|
+ if (resultCode == RESULT_OK) {
|
|
|
+ Toast.makeText(this, "允许本地蓝牙被附近的其它蓝牙设备发现", Toast.LENGTH_SHORT).show();
|
|
|
+ } else if (resultCode == RESULT_CANCELED) {
|
|
|
+ Toast.makeText(this, "不允许蓝牙被附近的其它蓝牙设备发现", Toast.LENGTH_SHORT).show();
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
|
|
|
+ super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
|
|
+ switch (requestCode) {
|
|
|
+ case 1:
|
|
|
+ if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
|
|
|
+ System.out.println("权限请求成功");
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private BroadcastReceiver receiver = 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);
|
|
|
+
|
|
|
+ matchItemBeanList.add(new DeviceListAdapter.ItemBean(device));
|
|
|
+ searchDeviceListAdapter.notifyDataSetChanged();
|
|
|
+
|
|
|
+ // 如果查找到的设备符合要连接的设备,处理
|
|
|
+ if (device.getName().equalsIgnoreCase(device.getName())) {
|
|
|
+ // 搜索蓝牙设备的过程占用资源比较多,一旦找到需要连接的设备后需要及时关闭搜索
|
|
|
+ App.getApp().getBluetoothAdapter().cancelDiscovery();
|
|
|
+ // 获取蓝牙设备的连接状态
|
|
|
+ switch (device.getBondState()) {
|
|
|
+ // 未配对
|
|
|
+ case BluetoothDevice.BOND_NONE:
|
|
|
+ // 配对
|
|
|
+ try {
|
|
|
+ Method createBondMethod = BluetoothDevice.class.getMethod("createBond");
|
|
|
+ createBondMethod.invoke(device);
|
|
|
+ } catch (Exception e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ // 已配对
|
|
|
+ case BluetoothDevice.BOND_BONDED:
|
|
|
+ // 连接
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else if (BluetoothDevice.ACTION_BOND_STATE_CHANGED.equals(action)) {
|
|
|
+ // 状态改变的广播
|
|
|
+ BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
|
|
|
+ if (device.getName().equalsIgnoreCase(device.getName())) {
|
|
|
+ switch (device.getBondState()) {
|
|
|
+ case BluetoothDevice.BOND_NONE:
|
|
|
+ // 取消配对
|
|
|
+ break;
|
|
|
+ case BluetoothDevice.BOND_BONDING:
|
|
|
+ // 正在配对
|
|
|
+ break;
|
|
|
+ case BluetoothDevice.BOND_BONDED:
|
|
|
+ // 完成配对
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else if (BluetoothAdapter.ACTION_STATE_CHANGED.equals(action)) {
|
|
|
+ new Handler().postDelayed(() -> runOnUiThread(() -> {
|
|
|
+ if (!adapter.isEnabled()) {
|
|
|
+ Toast.makeText(ScanDeviceActivity.this, "蓝牙已关闭", Toast.LENGTH_SHORT).show();
|
|
|
+ ScanDeviceActivity.this.finish();
|
|
|
+ } else {
|
|
|
+ matchItemBeanList.clear();
|
|
|
+ Set<BluetoothDevice> devices = adapter.getBondedDevices();
|
|
|
+ for (BluetoothDevice device : devices) {
|
|
|
+ matchItemBeanList.add(new DeviceListAdapter.ItemBean(device));
|
|
|
+ }
|
|
|
+ matchDeviceListAdapter.notifyDataSetChanged();
|
|
|
+ }
|
|
|
+ }), 500);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ };
|
|
|
}
|