iT邦幫忙

2022 iThome 鐵人賽

DAY 23
0
Mobile Development

Android Studio 30天學習紀錄系列 第 23

Android Studio 30天學習紀錄-Day23 Bluetooth連線

  • 分享至 

  • xImage
  •  

繼昨天的藍芽的掃描與配對後,今天要接續來講藍芽的連線及等等會來發送個字串,首先一樣要先確認已加入藍芽的權限至Manifest中:

    <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
    <uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
    <uses-permission android:name="android.permission.BLUETOOTH" />
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />

接著附上今天UI:

UI

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="240dp"
        android:onClick="pairDevice"
        android:text="配對"
        android:textSize="28dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.498"
        app:layout_constraintStart_toStartOf="parent" />

    <EditText
        android:id="@+id/editTextTextPersonName"
        android:layout_width="400dp"
        android:layout_height="50dp"
        android:layout_marginBottom="60dp"
        android:ems="10"
        android:inputType="textPersonName"
        android:hint="輸入傳送資料"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.497"
        app:layout_constraintStart_toStartOf="parent" />

    <Button
        android:id="@+id/btn_send"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:onClick="sendData"
        android:text="傳送"
        android:textSize="24dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.758"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="1.0" />

    <Button
        android:id="@+id/btn_disconnect"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="斷線"
        android:textSize="24dp"
        android:onClick="disConnect"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.247"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="1.0" />

</androidx.constraintlayout.widget.ConstraintLayout>

藍芽(連、斷線)

繼昨天設計完掃描與配對後,今天要來提提連線與斷線,首先我在ui寫了兩個按鈕:
傳送(監聽方法:sendData)、斷線(監聽方法:disConnect),傳送按鈕在傳送資料之前也會進行迴圈的連線,而連線(BluetoothDevice)的方法又可分為兩種:createInsecureRfcommSocketToServiceRecord(不安全連線)、createRfcommSocketToServiceRecord(安全連線),主要都是通過uuid去連(BluetoothDevice包含),而斷線的話只需要將socket設null,後面就會再重新去進行連線,接著附上這兩個監聽方法(sendData、disConnect)。

    private BluetoothDevice device;
    private BluetoothAdapter adapter;
    private BluetoothSocket socket;
    private ParcelUuid[] deviceUUid;
    private OutputStream os;
    private InputStream is;
    //當按下傳送按鈕
    public void sendData(View view){
        try {
            deviceUUid = device.getUuids();
            Log.d("UUid",""+deviceUUid[0].getUuid());
            Log.d("UUidSize",""+deviceUUid.length);
            if(socket==null){
                //連線方法1(不安全的連線)
//                socket=device.createInsecureRfcommSocketToServiceRecord(deviceUUid[0].getUuid());
                //連線方法2(安全的連線)
                socket=device.createRfcommSocketToServiceRecord(deviceUUid[0].getUuid());
                //迴圈進行連線
                while(!socket.isConnected()){
                    try {
                        sleep(5000);
                        socket.connect();
                        Log.d("Connect State",""+socket.isConnected());
                        if(socket.isConnected()){
                            Toast.makeText(getApplicationContext(),"連線成功",Toast.LENGTH_SHORT).show();
                        }
                    }
                    catch (IOException | InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                os=socket.getOutputStream();//輸入流
                is=socket.getInputStream();//輸出流
            }
            os.write(dataText.getText().toString().getBytes("utf-8"));//utf-8寫入選擇裝置
            Toast.makeText(getApplicationContext(),"已傳送字串",Toast.LENGTH_SHORT).show();
            Log.d("sendText",""+dataText.getText().toString().getBytes());
        }
        catch (Exception e){
            Log.d("Socket Error",""+e);
        }
    }
    //藍芽斷線按鈕
    public void disConnect(View view){
        socket = null;
        is = null;
        os = null;
        Toast.makeText(getApplicationContext(),"已斷線",Toast.LENGTH_SHORT).show();
    }

主程式

接著便將這兩個監聽方法寫入昨天的程式中:

public class MainActivity extends AppCompatActivity {
    private BluetoothDevice device;
    private BluetoothAdapter adapter;
    private String deviceName,deviceAddress;
    private TextView showDevice;
    private EditText dataText;
    private BluetoothSocket socket;
    private ParcelUuid[] deviceUUid;
    private OutputStream os;
    private InputStream is;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        showDevice = findViewById(R.id.textView);
        dataText = findViewById(R.id.editTextTextPersonName);
        //藍芽調配器
        adapter = BluetoothAdapter.getDefaultAdapter();
        // bluetooth抓到設備發送廣播
        IntentFilter filter = new IntentFilter("android.bluetooth.devicepicker.action.DEVICE_SELECTED");
        if(receiver!=null) {
            registerReceiver(receiver, filter);//廣播
        }
    }
    //廣播回傳
    private BroadcastReceiver receiver = new BroadcastReceiver() {
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            Log.d("taggg",""+action);
            device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
            deviceName = device.getName();
            deviceAddress = device.getAddress(); // MAC address
            showDevice.setText("配對裝置:" + deviceName + "\n" + "位址:" + deviceAddress);
            try {
                //回傳的選擇裝置進行配對
                device.createBond();
            } catch (Exception e) {
                Log.e("CreateBondError", e.getMessage());
            }
        }
    };
    //配對按鈕
    public void pairDevice(View view) {
        //當藍芽未開啟
        if(!adapter.isEnabled()) {
            Toast.makeText(view.getContext(),"先開權限後再點擊按鈕",Toast.LENGTH_SHORT).show();
            //打開藍芽窗(問你是否打開藍芽)
            Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
            intent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION,300);
            startActivity(intent);
        }
        else{
            //藍芽scanner
            Toast.makeText(view.getContext(),"PairDevice",Toast.LENGTH_SHORT).show();
            Intent bluetoothPicker = new Intent("android.bluetooth.devicepicker.action.LAUNCH");
            startActivity(bluetoothPicker);
            /*打開手機藍芽頁面
            Intent intentSettings = new Intent();
            intentSettings.setAction(android.provider.Settings.ACTION_BLUETOOTH_SETTINGS);
            startActivity(intentSettings);
            */
        }
    }
    //當按下傳送按鈕
    public void sendData(View view){
        try {
            deviceUUid = device.getUuids();
            Log.d("UUid",""+deviceUUid[0].getUuid());
            Log.d("UUidSize",""+deviceUUid.length);
            if(socket==null){
                //連線方法1(不安全的連線)
//                socket=device.createInsecureRfcommSocketToServiceRecord(deviceUUid[0].getUuid());
                //連線方法2(安全的連線)
                socket=device.createRfcommSocketToServiceRecord(deviceUUid[0].getUuid());
                //迴圈進行連線
                while(!socket.isConnected()){
                    try {
                        sleep(5000);
                        socket.connect();
                        Log.d("Connect State",""+socket.isConnected());
                        if(socket.isConnected()){
                            Toast.makeText(getApplicationContext(),"連線成功",Toast.LENGTH_SHORT).show();
                        }
                    }
                    catch (IOException | InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                os=socket.getOutputStream();//輸入流
                is=socket.getInputStream();//輸出流
            }
            os.write(dataText.getText().toString().getBytes("utf-8"));//utf-8寫入選擇裝置
            Toast.makeText(getApplicationContext(),"已傳送字串",Toast.LENGTH_SHORT).show();
            Log.d("sendText",""+dataText.getText().toString().getBytes());
        }
        catch (Exception e){
            Log.d("Socket Error",""+e);
        }
    }
    //藍芽斷線按鈕
    public void disConnect(View view){
        socket = null;
        is = null;
        os = null;
        Toast.makeText(getApplicationContext(),"已斷線",Toast.LENGTH_SHORT).show();
    }
}

成果

要記得將藍芽裝置打開!
https://ithelp.ithome.com.tw/upload/images/20221004/20139259wIjXCAXfYU.jpg
https://ithelp.ithome.com.tw/upload/images/20221004/20139259yY0U0qk7JP.jpg
https://ithelp.ithome.com.tw/upload/images/20221004/20139259gUy8fCQb2p.jpg


上一篇
Android Studio 30天學習紀錄-Day22 Bluetooth掃描&配對
下一篇
Android Studio 30天學習紀錄-Day24 File Stream
系列文
Android Studio 30天學習紀錄30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言