赞
踩
【AndroidStudio开发】(一):新建页面切换项目
【AndroidStudio开发】(二):加入摇杆控制
【AndroidStudio开发】(三):经典蓝牙+BLE蓝牙搜索
【AndroidStudio开发】(四):蓝牙BLE设备连接
目录
(2) 增加activity_listview.xml 文件
前言
上一次我们改造的是第二个页面,在页面中加入摇杆按钮,虽然我们可以拖动界面的按钮到任何一个方向,但是还是处于模拟器的操纵,没有用手机进行真机调试。现在我们需要对第一个页面进行改造,加入我们的蓝牙搜索及连接,这样我们就可以通过蓝牙连接设备,然后通过摇杆遥控,实际控制现实世界的物品。
蓝牙其实分经典蓝牙和BLE两种,比如我们常见的HC-05、HC-06蓝牙模块都属于经典蓝牙,ESP32自带的蓝牙是属于BLE这种的,BLE是蓝牙协议4.0之后开始升级的,叫做低功耗蓝牙,这两种蓝牙使用过程中是存在区别的。
第一个,BLE在安卓6.0之后,不仅需要动态获取系统蓝牙权限,还需要获取系统定位权限。
第二个,蓝牙的搜索模式差不多,但是连接操作和写入操作完全不一样了。搜索的话,都是先通过注册一个蓝牙广播BtReceiver,再通过startDiscovery进行搜索,添加设备都是通过跟系统建立intent来获取搜索到的设备。但在连接和写入方面,经典蓝牙是通过创建一个Scoket,再通过其输入流getInputStream、输出流getOutputStream完成。BLE是通过BluetoothGatt的connectGatt、disconnect完成连接和断连,而发送消息必须要通过UUID获取BluetoothGatt的服务再进行写入。
因为创建项目选的是API 28,所以需要修改下面红色的配置。大部分点击搜索按钮后,没有显示任何蓝牙设备的时候,可以看看这个地方配置是否跟API版本一致,手机安卓系统是否支持该版本。
compileSdkVersion 28 buildToolsVersion '28.0.3' defaultConfig { applicationId "com.example.myapplication" minSdkVersion 21 targetSdkVersion 28 versionCode 1 versionName "1.0" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" }
- <uses-permission android:name="android.permission.BLUETOOTH" />
- <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
- <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
- <uses-feature android:name="android.hardware.bluetooth_le" android:required="true" />
完整的AndroidManifest.xml文件,并增加一个后面的文本框类的关联,android:name=".APP"
- <?xml version="1.0" encoding="utf-8"?>
- <manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.example.myapplication">
-
- <uses-permission android:name="android.permission.BLUETOOTH" />
- <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
- <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
- <uses-feature android:name="android.hardware.bluetooth_le" android:required="true" />
-
- <application
- android:name=".APP"
- android:allowBackup="true"
- android:icon="@mipmap/ic_launcher"
- android:label="@string/app_name"
- android:roundIcon="@mipmap/ic_launcher_round"
- android:supportsRtl="true"
- android:theme="@style/Theme.MyApplication">
- <activity
- android:name=".MainActivity"
- android:label="@string/app_name"
- android:theme="@style/Theme.MyApplication.NoActionBar">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
-
- <category android:name="android.intent.category.LAUNCHER" />
- </intent-filter>
- </activity>
- </application>
-
- </manifest>
- package com.example.myapplication;
-
- import android.annotation.SuppressLint;
- import android.app.Application;
- import android.os.Handler;
- import android.widget.Toast;
-
- public class APP extends Application {
- private static final Handler sHandler = new Handler();
- private static Toast sToast; // 单例Toast,避免重复创建,显示时间过长
-
- @SuppressLint("ShowToast")
- @Override
- public void onCreate() {
- super.onCreate();
- sToast = Toast.makeText(this, "", Toast.LENGTH_SHORT);
- }
-
- public static void toast(String txt, int duration) {
- sToast.setText(txt);
- sToast.setDuration(duration);
- sToast.show();
- }
-
- public static void runUi(Runnable runnable) {
- sHandler.post(runnable);
- }
- }
增加静态常量,删除fab按钮,增加蓝牙硬件的检查,蓝牙是否开启,动态获取定位授权。
- private static final int PERMISSION_REQUEST_COARSE_LOCATION = 1;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
-
- // 检查蓝牙开关
- BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
- if (adapter == null) {
- APP.toast("本机没有找到蓝牙硬件或驱动!", 0);
- finish();
- return;
- } else {
- if (!adapter.isEnabled()) {
- //直接开启蓝牙
- adapter.enable();
- //跳转到设置界面
- //startActivityForResult(new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE), 112);
- }
- }
-
- //检查是否支持BLE
- if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
- APP.toast("系统不支持BLE", Toast.LENGTH_SHORT);
- finish();
- }
-
- // Make sure we have access coarse location enabled, if not, prompt the user to enable it
- if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
- final android.app.AlertDialog.Builder builder = new AlertDialog.Builder(this);
- builder.setTitle("定位授权");
- builder.setMessage("请授予位置访问权限,以便此应用可以检测外围设备");
- builder.setPositiveButton(android.R.string.ok, null);
- builder.setOnDismissListener(dialog -> requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, PERMISSION_REQUEST_COARSE_LOCATION));
- builder.show();
- }
-
- Toolbar toolbar = findViewById(R.id.toolbar);
- setSupportActionBar(toolbar);
- }
- package com.example.myapplication;
-
- import android.bluetooth.BluetoothAdapter;
- import android.bluetooth.BluetoothDevice;
- import android.content.Context;
- import android.view.LayoutInflater;
- import android.view.View;
- import android.view.ViewGroup;
- import android.widget.BaseAdapter;
- import android.widget.TextView;
-
- import java.util.ArrayList;
- import java.util.List;
- import java.util.Set;
-
- /**
- * Created by xanadw on 10/24/2021.
- */
- public class LeDeviceListAdapter extends BaseAdapter {
- private ArrayList<BluetoothDevice> deviceArrayList;
- private Context context;
- private LayoutInflater mInflater;
- private List<Integer> mRssis;
- private List<String> mBletype;
-
-
- public LeDeviceListAdapter(Context context, ArrayList<BluetoothDevice> devices, List<Integer> rssis, List<String> bletype) {
- this.context = context;
- this.deviceArrayList = devices;
- mInflater = LayoutInflater.from(this.context);
- mRssis = rssis;
- mBletype = bletype;
- }
-
- @Override
- public int getCount() {
- return deviceArrayList.size();
- }
-
- @Override
- public BluetoothDevice getItem(int position){
- return deviceArrayList.get(position);
- }
-
- @Override
- public long getItemId(int position) {
- return position;
- }
-
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- MyViewHolder mViewHolder;
-
- if (convertView == null) {
- convertView = mInflater.inflate(R.layout.activity_listview, parent, false);
- mViewHolder = new MyViewHolder(convertView);
- convertView.setTag(mViewHolder);
- }else {
- mViewHolder = (MyViewHolder) convertView.getTag();
- }
-
- BluetoothDevice currentListData = getItem(position);
-
- if (currentListData.getName()==null) {
- mViewHolder.tvname.setText("No name");
- }
- else{
- mViewHolder.tvname.setText(currentListData.getName());
- }
- mViewHolder.tvmac.setText(currentListData.getAddress());
- mViewHolder.tvRssi.setText(String.format("%ddBm", mRssis.get(position)));
- mViewHolder.tvBletype.setText(mBletype.get(position));
-
- return convertView;
- }
-
- private class MyViewHolder {
- TextView tvname, tvmac, tvRssi, tvSate, tvBletype;
-
- public MyViewHolder(View item) {
- tvname = (TextView)item.findViewById(R.id.name);
- tvmac = (TextView)item.findViewById(R.id.mac);
- tvRssi = (TextView)item.findViewById(R.id.rssi);
- tvBletype = (TextView)item.findViewById(R.id.bluetoothtype);
- }
- }
-
- public void clear() {
- deviceArrayList.clear();
- mRssis.clear();
- mBletype.clear();
- }
-
- public boolean addDevice (BluetoothDevice device) {
- boolean returnValue;
- if (!deviceArrayList.contains(device)) {
- deviceArrayList.add(device);
- returnValue = true;
- } else {
- returnValue = false;
- }
-
- return returnValue;
- }
-
- public void addBound() {
- Set<BluetoothDevice> bondedDevices = BluetoothAdapter.getDefaultAdapter().getBondedDevices();
- if (bondedDevices != null)
- deviceArrayList.addAll(bondedDevices);
- }
- }
这个类放在util包里面,下面这个是目录结构。
- package com.example.myapplication.util;
-
- import android.bluetooth.BluetoothA2dp;
- import android.bluetooth.BluetoothAdapter;
- import android.bluetooth.BluetoothDevice;
- import android.bluetooth.BluetoothHeadset;
- import android.content.BroadcastReceiver;
- import android.content.Context;
- import android.content.Intent;
- import android.content.IntentFilter;
- import android.util.Log;
-
- /**
- * 监听蓝牙广播-各种状态
- */
- public class BtReceiver extends BroadcastReceiver {
- private static final String TAG = BtReceiver.class.getSimpleName();
- private final Listener mListener;
-
- public BtReceiver(Context cxt, Listener listener) {
- mListener = listener;
- IntentFilter filter = new IntentFilter();
- filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);//蓝牙开关状态
- filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);//蓝牙开始搜索
- filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);//蓝牙搜索结束
-
- filter.addAction(BluetoothDevice.ACTION_FOUND);//蓝牙发现新设备(未配对的设备)
- filter.addAction(BluetoothDevice.ACTION_PAIRING_REQUEST);//在系统弹出配对框之前(确认/输入配对码)
- filter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);//设备配对状态改变
- filter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED);//最底层连接建立
- filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);//最底层连接断开
-
- filter.addAction(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED); //BluetoothAdapter连接状态
- filter.addAction(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED); //BluetoothHeadset连接状态
- filter.addAction(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED); //BluetoothA2dp连接状态
- cxt.registerReceiver(this, filter);
- }
-
- @Override
- public void onReceive(Context context, Intent intent) {
- String action = intent.getAction();
- if (action == null)
- return;
- Log.i(TAG, "===" + action);
- BluetoothDevice dev = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
- if (dev != null)
- Log.i(TAG, "BluetoothDevice: " + dev.getName() + ", " + dev.getAddress());
- switch (action) {
- case BluetoothAdapter.ACTION_STATE_CHANGED:
- int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, 0);
- Log.i(TAG, "STATE: " + state);
- break;
- case BluetoothAdapter.ACTION_DISCOVERY_STARTED:
- break;
- case BluetoothAdapter.ACTION_DISCOVERY_FINISHED:
- break;
-
- case BluetoothDevice.ACTION_FOUND:
- short rssi = intent.getShortExtra(BluetoothDevice.EXTRA_RSSI, Short.MAX_VALUE);
- Log.i(TAG, "EXTRA_RSSI:" + rssi);
- mListener.foundDev(dev, rssi);
- break;
- case BluetoothDevice.ACTION_PAIRING_REQUEST: //在系统弹出配对框之前,实现自动配对,取消系统配对框
- /*try {
- abortBroadcast();//终止配对广播,取消系统配对框
- boolean ret = dev.setPin("1234".getBytes()); //设置PIN配对码(必须是固定的)
- } catch (Exception e) {
- e.printStackTrace();
- }*/
- break;
- case BluetoothDevice.ACTION_BOND_STATE_CHANGED:
- Log.i(TAG, "BOND_STATE: " + intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, 0));
- break;
- case BluetoothDevice.ACTION_ACL_CONNECTED:
- break;
- case BluetoothDevice.ACTION_ACL_DISCONNECTED:
- break;
-
- case BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED:
- Log.i(TAG, "CONN_STATE: " + intent.getIntExtra(BluetoothAdapter.EXTRA_CONNECTION_STATE, 0));
- break;
- case BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED:
- Log.i(TAG, "CONN_STATE: " + intent.getIntExtra(BluetoothHeadset.EXTRA_STATE, 0));
- break;
- case BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED:
- Log.i(TAG, "CONN_STATE: " + intent.getIntExtra(BluetoothA2dp.EXTRA_STATE, 0));
- break;
- }
- }
-
- public interface Listener {
- void foundDev(BluetoothDevice dev, short devrssi);
- }
- }
(I)引入BtReceiver,修改主类
import com.example.myapplication.util.BtReceiver;
public class FirstFragment extends Fragment implements BtReceiver.Listener {
然后根据错误提示需要新增foundDev函数,这个函数是经典蓝牙搜索的结果
- @Override
- public void foundDev(BluetoothDevice dev, short devrssi) {
- mLeDeviceListAdapter.addDevice(dev);
- mRssis.add((int) devrssi);
- mfbletype.add("old");
- mLeDeviceListAdapter.notifyDataSetChanged();
- }
新建蓝牙相关的变量以及一些常量
- private static final String TAG = "FirstFragment";
- private final static int REQUEST_ENABLE_BT = 1;
-
- //获取主页面
- MainActivity mActivity;
-
- BluetoothManager btManager;
- BluetoothAdapter btAdapter;
- BluetoothLeScanner btScanner;
- private BtReceiver mBtReceiver;
(II)获取主页面的Activity,因为我们的first页面是fragment页面,只能用主页面Activity去获取系统设备,第一个OnAttach是从Activity创建Fragment时调用的,第二个是OnDetach是从Fragment销毁返回到Activity时调用的。
- @Override
- public void onAttach(@NonNull Activity activity) {
- super.onAttach(activity);
- mActivity = (MainActivity) activity;
- }
-
- @Override
- public void onDetach() {
- super.onDetach();
- mActivity = null;
- }
(III)修改onCreateView函数页面创建方式
- // Inflate the layout for this fragment
- View view=inflater.inflate(R.layout.fragment_first, container, false);
-
- return view;
(IV)判断系统是否支持蓝牙,并获取,并跟蓝牙建立一个Intent数据链接,放在onCreateView函数return前面。
- btManager = (BluetoothManager)mActivity.getSystemService(Context.BLUETOOTH_SERVICE);
- btAdapter = btManager.getAdapter();
- if (btAdapter == null || !btAdapter.isEnabled()) {
- Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
- startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
- }
- btScanner = btAdapter.getBluetoothLeScanner();
(V)FirstFragment继续增加变量
- final ArrayList<BluetoothDevice> availableBT = new ArrayList<>();
- private static List<String> mfbletype;
- private static List<Integer> mRssis;
- private static LeDeviceListAdapter mLeDeviceListAdapter;
- private static BluetoothGatt firstGatt = null;
- private static String conbletype = "";
- private static BluetoothDevice condev = null;
(VI)增加界面显示搜索到的设备,同样放置在onCreateView函数的return之前。
- mLeDeviceListAdapter = new LeDeviceListAdapter(mActivity.getApplicationContext(), availableBT, mRssis, mfbletype);
- final ListView listView_available = view.findViewById(R.id.listview2);
- listView_available.setOnItemClickListener(new AdapterView.OnItemClickListener() {
- @Override
- public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
- firstGatt = null;
- conbletype = mfbletype.get(position);
- condev = mLeDeviceListAdapter.getItem(position);
-
- if (btAdapter.isDiscovering()) {
- btAdapter.cancelDiscovery();
- }
-
- NavHostFragment.findNavController(FirstFragment.this)
- .navigate(R.id.action_FirstFragment_to_SecondFragment);
- }
- });
(VII)增加一个蓝牙扫描设备的按钮,蓝牙扫描是最消耗能量的动作了,不符合BLE的思想所以一般手机都设置了30秒内扫描5次的限制,所以改成手动触发扫描,一次扫描时间挺长的,靠近一点等一等就会扫描到你要连接的蓝牙设备。
增加一个变量和常量
- private Handler mHandler;
- private static final long SCAN_PERIOD = 15000;
- mHandler = new Handler();
- mfbletype = new ArrayList<>();
- mRssis = new ArrayList<>();
-
- Button scan = view.findViewById(R.id.scan);
- scan.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- APP.toast("Scanning...", Toast.LENGTH_SHORT);
- mLeDeviceListAdapter.clear();
- mfbletype.clear();
- mRssis.clear();
-
- conbletype = "";
- condev = null;
-
-
- if (!btAdapter.isDiscovering()) {
- btAdapter.startDiscovery();
- }
-
- mHandler.postDelayed(new Runnable() {
- @Override
- public void run() {
- stopScanning();
-
- }
- },SCAN_PERIOD);
-
- scanLeDevice(true);
-
- mLeDeviceListAdapter.notifyDataSetChanged();
- listView_available.setAdapter(mLeDeviceListAdapter);
- }
- });
(VIII)onViewCreated这个原来用来控制页面一(蓝牙搜索页面)跳转到页面二(按钮控制页面)函数删除,之后采用点击对应的蓝牙设备直接跳转到页面二,然后增加缺少的一些函数,
添加已搜索到的设备到列表的回调函数leScanCallback,这个是BLE蓝牙搜索的结果。
-
- private final ScanCallback leScanCallback = new ScanCallback() {
- @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
- @Override
- public void onScanResult(int callbackType, ScanResult result) {
- if (!(mActivity == null || mActivity.isFinishing())) {
- mActivity.runOnUiThread(() -> {
- if (mLeDeviceListAdapter.addDevice(result.getDevice())) {
- mRssis.add(result.getRssi());
- mfbletype.add("ble");
- }
- mLeDeviceListAdapter.notifyDataSetChanged();
- });
- }
- }
- };
添加停止扫描函数stopScanning
- public void stopScanning() {
- Log.d(TAG, "stopping scanning" );
-
- AsyncTask.execute(new Runnable() {
- @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
- @Override
- public void run() {
- btScanner.stopScan(leScanCallback);
- }
- });
- }
添加扫描函数scanLeDevice
- private void scanLeDevice(final boolean enable) {
- if (enable) {
- mHandler.postDelayed(new Runnable() {
- @Override
- public void run() {
- stopScanning();
-
- }
- },SCAN_PERIOD);
-
- startScanning();
- } else {
- try {
- stopScanning();
- } catch (Exception e) {
- }
- }
- }
添加开始扫描函数startScanning
- public void startScanning() {
- //scan.setVisibility(View.INVISIBLE);
- //dc.setVisibility(View.VISIBLE);
- AsyncTask.execute(() -> btScanner.startScan(leScanCallback));
- }
(IX)onCreateView函数添加广播接收
- mBtReceiver = new BtReceiver(mActivity.getApplicationContext(), this);//注册蓝牙广播
- BluetoothAdapter.getDefaultAdapter().startDiscovery();
(X)onCreateView函数添加按钮的可见性
- Button button_first = view.findViewById(R.id.button_first);
- button_first.setVisibility(View.INVISIBLE);
上面的代码添加完毕后,还是存在一些报错,那是因为我们还缺少一些页面的组件元素。
删除textview_first,包含activity_listview页面
<include layout="@layout/activity_listview" />
增加available、listview2、scan元素
- <TextView
- android:text="Available Devices"
- android:id="@+id/available"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- app:layout_constraintLeft_toLeftOf="parent"
- app:layout_constraintTop_toTopOf="parent"/>
-
- <ListView
- android:id="@+id/listview2"
- android:layout_width="match_parent"
- android:layout_height="500dp"
- android:layout_alignParentStart="true"
- android:layout_below="@+id/available"
- app:layout_constraintLeft_toLeftOf="parent"
- app:layout_constraintTop_toTopOf="parent"
- android:layout_marginTop="30dp"/>
-
- <Button
- android:id="@+id/scan"
- android:text="Scan Devices"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentBottom="true"
- android:layout_alignParentLeft="true"
- app:layout_constraintBottom_toBottomOf="parent"
- app:layout_constraintLeft_toLeftOf="parent"
- android:layout_marginBottom="30dp"/>
修改button_first元素
- <Button
- android:id="@+id/button_first"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/next"
- android:layout_toStartOf="@+id/scan"
- app:layout_constraintBottom_toBottomOf="parent"
- app:layout_constraintLeft_toRightOf="@+id/scan"
- android:layout_marginBottom="30dp"/>
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:background="#ffffff"
- android:gravity="center_vertical"
- android:orientation="vertical">
-
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
- android:paddingBottom="8dp"
- android:paddingLeft="12dp"
- android:paddingRight="12dp"
- android:paddingTop="8dp">
-
- <LinearLayout
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- android:orientation="vertical">
-
- <TextView
- android:id="@+id/name"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:ellipsize="end"
- android:singleLine="true"
- android:textSize="17sp" />
-
- <TextView
- android:id="@+id/mac"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_below="@+id/name"
- android:ellipsize="end"
- android:singleLine="true"
- android:textColor="#999999"
- android:textSize="12sp" />
-
- <TextView
- android:id="@+id/rssi"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_below="@+id/mac"
- android:text=""
- android:textColor="#303030"
- android:textSize="12sp" />
-
- <TextView
- android:id="@+id/bluetoothtype"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_below="@+id/rssi"
- android:ellipsize="end"
- android:singleLine="true"
- android:textSize="12sp" />
- </LinearLayout>
- </LinearLayout>
-
- </LinearLayout>
删除id为fab的图标
content_main.xml文件不用修改,fragment_second.xml保持上次的修改。
完整的项目地址--【AndroidStudio】经典蓝牙+BLE蓝牙搜索APP
手机需要打开开发人员选项,开发人员选项大部分是通过点击关于手机的版本号6次以上打开的,再去系统和更新里面找到开发人员选项,然后将开发人员选项、USB调试打开。
然后USB连接电脑后,选择传输文件选项。然后AndroidStudio里面就会显示手机的型号了。
右键选择Run MainActivity,不要直接点击Run和小三角键,会直接运行另外一个主类app。运行一次后你就可以直接点击小三角键了。
请求打开蓝牙,定位权限获取,第一次获取位置信息权限之后,除非删除APP才会再次请求获取定位权限。
点击Scan按钮,开启蓝牙扫描,扫描结果如下图,点击任何一个设备都会跳转至页面2。
但要注意的是这个地方点击是没有加入连接蓝牙设备的,由于篇幅的原因,这个部分留到下一次再写。
再附上完整的项目地址--【AndroidStudio】经典蓝牙+BLE蓝牙搜索APP
总结
蓝牙连接和控制属于AndroidStudio前期入门里面比较难的一类的了,后面可能还有屏幕的渲染,横竖屏的切换。下一次蓝牙连接文章都会涉及到。
赞
踩
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。