2022年2月18日 星期五

Android Studio - Bluetooth 即時通訊服務端(Server)程式(四十四)

Android Studio - Bluetooth 即時通訊服務端(Server)程式(四十四):

雖然 IM / Instant Messaging(即時通訊)互連程式可以使用行業上的協定規範,但需要更多的設置和編程,所以筆者現在是利用 Bluetooth(藍牙)來使到兩部手機互相直接溝通,不用架構服務器或線上代理,祇是利用 Bluetooth(藍牙)直接互相傳輸資料,使用到 Socket 通訊協定,直接實現點對點傳輸。。程式是 IM / Instant Messaging(即時通訊)服務端(Server)程式。

Android Studio - Bluetooth 即時通訊服務端(Server)程式(四十四):

  • 操作系統:Windows 7 64-bit 版本
  • 開發環境:Android Studio 4.0.1 版本
  • 原程式:C:\Development\Development_Android\Android_Project\DIY-Android-010-01D Bluetooth IM Server
  • 程式:C:\Development\Development_Android\Android_Project\DIY-Android-010-01D Bluetooth IM Server
Bluetooth 即時通訊服務端(Server)程式編程步驟:
  • 設定 Bluetooth 許可權限後
  • 設定 Bluetooth 許可權限後
  • 設定手機藍牙
  • 啟動手機藍牙
  • 等待 Client 掃描周邊的藍牙設備
  • 連接設備
  • 在手機設備之間設定傳輸資料

當連接兩台設備設備時,要在兩台設備間創建連接,必須同時實現服務端(Server)和用戶端(Client)機制,其中一台設備(可檢測到的設備)需將自身設置為可接收傳入的連接請求。首先是要配對(配對意味著兩台設備知曉彼此的存在),然後連接完成綁定過程,因此其中一台設備必須開放的服務端,而另一台設備必須發起連接,具有可用於身份驗證的共用鏈路金鑰,並且能夠與彼此建立加密連接。當服務端和用戶端在同一 RFCOMM 通道上分別擁有已連接的 BluetoothSocket 時,二者將被視為彼此連接。藍牙通訊介面與 TCP Socket 相似。可以允許通過 InputStream 和 OutputStream 與其他藍牙設備交換資料,使用 read(byte[]) 和 write(byte[]) 讀取資料並寫入到資料流。

MainActivity.java:

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;

import android.content.Intent;

import android.os.Handler;

import android.os.Message;

import android.view.View;

import android.widget.Button;

import android.widget.EditText;

import android.widget.ListView;

import android.widget.TextView;

import java.io.IOException;

import java.io.InputStream;

import java.io.OutputStream;

import java.util.UUID;

 

import android.bluetooth.BluetoothAdapter;

import android.bluetooth.BluetoothDevice;

import android.bluetooth.BluetoothServerSocket;

import android.bluetooth.BluetoothSocket;

 

public class MainActivity extends AppCompatActivity {

    Button mbtn_server, mbtn_send, mbtn_scan;

    ListView mlv_device;

    TextView mtv_msg, mtv_status, mtv_mode;

    EditText met_msg;

    BluetoothAdapter bluetoothAdapter;

 

    // BluetoothDevice Array Definition

    BluetoothDevice [] bluetoothDevices;

 

    // SendReceive variable

    SendReceive sendReceive;

 

    // Fixed value

    static final int STATE_LISTENING = 1;

    static final int STATE_CONNECTING = 2;

    static final int STATE_CONNECTED = 3;

    static final int STATE_CONNECTION_FAILED = 4;

    static final int STATE_MESSAGE_RECEIVED = 5;

 

    int REQUEST_ENABLE_BLUETOOTH = 1;

    int mStatus;

 

    private static final String APP_NAME = "BluetoothIMApp";

    private static final UUID MY_UUID = UUID.fromString("318c6089-985c-4773-b7ca-4c6130e4209e");

 

    @Override

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);

 

        mbtn_server = findViewById(R.id.btn_server);

        mbtn_send = findViewById(R.id.btn_send);

        mbtn_scan = findViewById(R.id.btn_scan);

        mlv_device = findViewById(R.id.lv_device);

        mtv_status = findViewById(R.id.tv_status);

        mtv_msg = findViewById(R.id.tv_msg);

        met_msg = findViewById(R.id.et_msg);

        mtv_mode = findViewById(R.id.tv_mode);

 

        bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();

 

        mtv_status.setText("Disconnect");

        mtv_mode.setText("Mode ?");

        mStatus = 0;

 

        if (!bluetoothAdapter.isEnabled()){

            Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);

            startActivityForResult(enableIntent,REQUEST_ENABLE_BLUETOOTH);

        }

 

        implementListeners();

    }

 

    private void implementListeners() {

        mbtn_server.setOnClickListener(new View.OnClickListener() {

            @Override

            public void onClick(View v) {

                mtv_mode.setText("Server Mode");

                ServerClass serverClass = new ServerClass();

                serverClass.start();

            }

        });

 

        mbtn_send.setOnClickListener(new View.OnClickListener() {

            @Override

            public void onClick(View v) {

                String string = String.valueOf(met_msg.getText());

                if (mStatus == 3) {

                    sendReceive.write(string.getBytes());

                }

            }

        });

    }

 

    Handler handler = new Handler(new Handler.Callback() {

        @Override

        public boolean handleMessage(Message msg) {

 

            // Handler : UI Thread is enable communication

            switch (msg.what){

                case STATE_LISTENING:

                    mtv_status.setText("Listening");

                    mStatus = 1;

                    break;

 

                case STATE_CONNECTING:

                    mtv_status.setText("Connecting");

                    mStatus = 2;

                    break;

 

                case STATE_CONNECTED:

                    mtv_status.setText("Connected");

                    mStatus = 3;

                    break;

 

                case STATE_CONNECTION_FAILED:

                    mtv_status.setText("Connection Failed");

                    mStatus = 0;

                    break;

 

                case STATE_MESSAGE_RECEIVED:

                    byte[] readBuffer = (byte[]) msg.obj;

                    String tempMessage = new String(readBuffer,0,msg.arg1);

                    mtv_msg.setText(tempMessage);

                    break;

            }

            return true;

        }

    });

 

    // SendReceive

    private class SendReceive extends Thread{

 

        private final BluetoothSocket bluetoothSocket;

        private final InputStream inputStream;

        private final OutputStream outputStream;

 

        public SendReceive(BluetoothSocket socket){

            bluetoothSocket = socket;

            InputStream tempInput = null;

            OutputStream tempOutput = null;

 

            try {

                tempInput = bluetoothSocket.getInputStream();

                tempOutput = bluetoothSocket.getOutputStream();

            } catch (IOException e) {

                e.printStackTrace();

            }

 

            inputStream = tempInput;

            outputStream = tempOutput;

        }

 

        public void run(){

            byte [] buffer = new byte[1024];

            int bytes;

 

            while (true){

                try {

                    bytes = inputStream.read(buffer);

                    handler.obtainMessage(STATE_MESSAGE_RECEIVED,bytes,-1,buffer).sendToTarget();

                } catch (IOException e) {

                    e.printStackTrace();

                }

            }

        }

 

        // write

        public void write (byte[] bytes){

            try {

                outputStream.write(bytes);

            } catch (IOException e) {

                e.printStackTrace();

            }

        }

 

    }

 

}


MainActivity.java - Server Class:

    // Server Class

    private class ServerClass extends Thread{

        private BluetoothServerSocket serverSocket;

 

        public ServerClass(){

            try{

                serverSocket = bluetoothAdapter.listenUsingRfcommWithServiceRecord(APP_NAME,MY_UUID);

            }catch (IOException e){

                e.printStackTrace();

            }

        }

 

        public void run(){

            BluetoothSocket socket = null;

            while (socket == null){

                try{

                    Message message = Message.obtain();

                    message.what = STATE_CONNECTING;

                    handler.sendMessage(message);

                    socket = serverSocket.accept();

                } catch (IOException e) {

                    e.printStackTrace();

                    Message message = Message.obtain();

                    message.what = STATE_CONNECTION_FAILED;

                    handler.sendMessage(message);

                }

 

                if (socket!=null){

                    Message message = Message.obtain();

                    message.what = STATE_CONNECTED;

                    handler.sendMessage(message);

                    sendReceive = new SendReceive(socket);

                    sendReceive.start();

                    break;

                }

            }

        }

    }


activity¬main.xml:

<?xml version="1.0" encoding="utf-8"?>

<RelativeLayout 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/tv_status"

        android:layout_width="120dp"

        android:layout_height="wrap_content"

        android:layout_alignParentTop="true"

        android:layout_alignParentEnd="true"

        android:layout_alignParentRight="true"

        android:layout_marginTop="6dp"

        android:layout_marginEnd="31dp"

        android:layout_marginRight="31dp"

        android:text="STATUS" />

 

    <Button

        android:id="@+id/btn_server"

        android:layout_width="wrap_content"

        android:layout_height="wrap_content"

        android:layout_alignParentStart="true"

        android:layout_alignParentLeft="true"

        android:layout_alignParentTop="true"

        android:layout_marginStart="12dp"

        android:layout_marginLeft="12dp"

        android:layout_marginTop="5dp"

        android:text="SERVER" />

 

    <Button

        android:id="@+id/btn_scan"

        android:layout_width="wrap_content"

        android:layout_height="wrap_content"

        android:layout_alignParentTop="true"

        android:layout_marginStart="19dp"

        android:layout_marginLeft="19dp"

        android:layout_marginTop="5dp"

        android:layout_toEndOf="@+id/btn_server"

        android:layout_toRightOf="@+id/btn_server"

        android:text="DEVICE" />

 

    <ListView

        android:id="@+id/lv_device"

        android:layout_width="358dp"

        android:layout_height="110dp"

        android:layout_alignParentBottom="true"

        android:layout_centerInParent="true"

        android:layout_marginStart="16dp"

        android:layout_marginLeft="16dp"

        android:layout_marginBottom="11dp"

        android:background="@android:color/holo_green_dark" />

 

    <Button

        android:id="@+id/btn_send"

        android:layout_width="wrap_content"

        android:layout_height="wrap_content"

        android:layout_alignParentTop="true"

        android:layout_marginStart="37dp"

        android:layout_marginLeft="37dp"

        android:layout_marginTop="57dp"

        android:background="@android:color/black"

        android:textColor="@android:color/white"

        android:layout_toEndOf="@+id/et_msg"

        android:layout_toRightOf="@+id/et_msg"

        android:text="Send" />

 

    <TextView

        android:id="@+id/tv_msg"

        android:layout_width="390dp"

        android:layout_height="494dp"

        android:layout_below="@+id/et_msg"

        android:layout_alignParentStart="true"

        android:layout_alignParentLeft="true"

        android:layout_centerHorizontal="true"

        android:layout_marginStart="15dp"

        android:layout_marginLeft="15dp"

        android:layout_marginTop="-17dp"

        android:text="Message" />

 

    <EditText

        android:id="@+id/et_msg"

        android:layout_width="wrap_content"

        android:layout_height="wrap_content"

        android:layout_below="@+id/btn_server"

        android:layout_marginStart="16dp"

        android:layout_marginLeft="16dp"

        android:layout_marginTop="5dp"

        android:layout_marginBottom="28dp"

        android:ems="10"

        android:inputType="textPersonName"

        android:textColor="@android:color/black"

        app:layout_constraintBottom_toBottomOf="parent"

        app:layout_constraintStart_toStartOf="parent" />

 

    <TextView

        android:id="@+id/tv_mode"

        android:layout_width="120dp"

        android:layout_height="wrap_content"

        android:layout_below="@+id/tv_status"

        android:layout_alignParentEnd="true"

        android:layout_alignParentRight="true"

        android:layout_marginTop="5dp"

        android:layout_marginEnd="29dp"

        android:layout_marginRight="29dp"

        android:text="MODE" />

</RelativeLayout>


Android Studio Bluetooth 即時通訊服務程式
2022年 2月 18日(Fri)天氣報告
氣溫:43.0°F / 6.0°C @ 07:00
風速:每小時 3公里
降雨機會:4%
相對濕度:百分之 91%
天氣:多雲

沒有留言:

張貼留言