안드로이드로 블루투스 통신 코드를 찾다가 다 오래된거고, 같은 코드만 올라와있어서
안드로이드 자체에서 사라진 메소드랑 v7코드 오류 수정, 주석 등등 달아서 올려본다.
( 틀린부분 있으면 댓글 남겨주세요! )
그리고 필자는 통신 연결은 되고 송수신은 안되는 문제를 겪었는데
라즈베리파이에 Port번호를 3에서 1로 바꾸니 통신이 되었다.
https://webnautes.tistory.com/995?category=924825
https://m.blog.naver.com/beaqon/221412580559
MainActivity.java
package com.example.bluetoothtestapplication;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Set;
import java.util.UUID;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import androidx.activity.result.ActivityResult;
import androidx.activity.result.ActivityResultCallback;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity
{
private final int REQUEST_BLUETOOTH_ENABLE = 100;
private ActivityResultLauncher<Intent> resultLauncher;
private TextView mConnectionStatus;
private EditText mInputEditText;
ConnectedTask mConnectedTask = null;
static BluetoothAdapter mBluetoothAdapter;
private String mConnectedDeviceName = null;
private ArrayAdapter<String> mConversationArrayAdapter;
static boolean isConnectionError = false;
private static final String TAG = "BluetoothClient";
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
/* send 버튼 누르면 sendMessage호출로 메세지를 보냄 */
Button sendButton = (Button)findViewById(R.id.send_button);
sendButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v){
String sendMessage = mInputEditText.getText().toString();
if ( sendMessage.length() > 0 ) {
sendMessage(sendMessage);
}
}
});
mConnectionStatus = (TextView)findViewById(R.id.connection_status_textview);
mInputEditText = (EditText)findViewById(R.id.input_string_edittext);
ListView mMessageListview = (ListView) findViewById(R.id.message_listview);
mConversationArrayAdapter = new ArrayAdapter<>( this,
android.R.layout.simple_list_item_1 );
mMessageListview.setAdapter(mConversationArrayAdapter);
Log.d( TAG, "Initalizing Bluetooth adapter...");
/* 기기가 블루투스를 지원하지 않으면 종료 */
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (mBluetoothAdapter == null) {
showErrorDialog("This device is not implement Bluetooth.");
return;
}
/* 블루투스 연결을 확인하고 showPairedDevicesListDialog()를 호출해 기기리스트 호출 */
if (!mBluetoothAdapter.isEnabled()) {
Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
intent.putExtra("Call", REQUEST_BLUETOOTH_ENABLE);
resultLauncher.launch(intent);
}
else {
Log.d(TAG, "Initialisation successful.");
showPairedDevicesListDialog();
}
resultLauncher = registerForActivityResult(
new ActivityResultContracts.StartActivityForResult(),
new ActivityResultCallback<ActivityResult>() {
@Override
public void onActivityResult(ActivityResult result) {
if(result.getResultCode() == RESULT_OK){ //블루투스가 활성화되었음
Intent intent = result.getData();
int CallType = intent.getIntExtra("CallType", 0);
if(CallType == 0){
//실행될 코드
}else if(CallType == 1){
//실행될 코드
}else if(CallType == 2){
//실행될 코드
}
}
}
});
}
@Override
protected void onDestroy() {
super.onDestroy();
if ( mConnectedTask != null ) {
mConnectedTask.cancel(true);
}
}
/* 디바이스 연결 후 송수신을 위한 소켓 생성 */
private class ConnectTask extends AsyncTask<Void, Void, Boolean> {
private BluetoothSocket mBluetoothSocket = null;
private BluetoothDevice mBluetoothDevice = null;
//시리얼 통신(SPP)을 하기위한 RFCOMM 블루투스 소켓 생성
ConnectTask(BluetoothDevice bluetoothDevice) {
mBluetoothDevice = bluetoothDevice;
mConnectedDeviceName = bluetoothDevice.getName();
//SPP
UUID uuid = UUID.fromString("00001101-0000-1000-8000-00805f9b34fb");
try {
mBluetoothSocket = mBluetoothDevice.createRfcommSocketToServiceRecord(uuid);
//Log.~~ 로그캣에 찍기위해 사용
Log.d( TAG, "create socket for "+mConnectedDeviceName);
} catch (IOException e) {
Log.e( TAG, "socket create failed " + e.getMessage());
}
mConnectionStatus.setText("connecting...");
}
@Override
protected Boolean doInBackground(Void... params) {
// 디바이스 검색 중지. 느려짐 방지
mBluetoothAdapter.cancelDiscovery();
// 연결
try {
mBluetoothSocket.connect();
} catch (IOException e) {
// 오류 시 종료
try {
mBluetoothSocket.close();
} catch (IOException e2) {
Log.e(TAG, "unable to close() " +
" socket during connection failure", e2);
}
return false;
}
return true;
}
/* 소켓 생성 성공시 connectedTask AsyncTask 실행*/
@Override
protected void onPostExecute(Boolean isSucess) {
if ( isSucess ) {
connected(mBluetoothSocket);
}
else{
isConnectionError = true;
Log.d( TAG, "Unable to connect device");
showErrorDialog("Unable to connect device");
}
}
}
/* 소켓 실행 */
public void connected( BluetoothSocket socket ) {
mConnectedTask = new ConnectedTask(socket);
mConnectedTask.execute();
}
/* 실제 데이터 주고 받기 */
private class ConnectedTask extends AsyncTask<Void, String, Boolean> {
private InputStream mInputStream = null;
private OutputStream mOutputStream = null;
private BluetoothSocket mBluetoothSocket = null;
ConnectedTask(BluetoothSocket socket){
mBluetoothSocket = socket;
try {
mInputStream = mBluetoothSocket.getInputStream();
mOutputStream = mBluetoothSocket.getOutputStream();
} catch (IOException e) {
Log.e(TAG, "socket not created", e );
}
Log.d( TAG, "connected to "+mConnectedDeviceName);
mConnectionStatus.setText( "connected to "+mConnectedDeviceName);
}
/* 이 메소드에서 대기하며 수신되는 문자열이 있을 시 버퍼에 저장 */
@Override
protected Boolean doInBackground(Void... params) {
byte [] readBuffer = new byte[1024];
int readBufferPosition = 0;
while (true) {
if ( isCancelled() ) return false;
try {
int bytesAvailable = mInputStream.available();
if(bytesAvailable > 0) {
byte[] packetBytes = new byte[bytesAvailable];
mInputStream.read(packetBytes);
for(int i=0;i<bytesAvailable;i++) {
byte b = packetBytes[i];
if(b == '\n')
{
byte[] encodedBytes = new byte[readBufferPosition];
System.arraycopy(readBuffer, 0, encodedBytes, 0,
encodedBytes.length);
String recvMessage = new String(encodedBytes, "UTF-8");
readBufferPosition = 0;
Log.d(TAG, "recv message: " + recvMessage);
publishProgress(recvMessage);
}
else
{
readBuffer[readBufferPosition++] = b;
}
}
}
} catch (IOException e) {
Log.e(TAG, "disconnected", e);
return false;
}
}
}
/* 수신된 문자 리스트에 업데이트 */
/* 다른곳에 업데이트 하고자 하면 아래 메소드 수정 */
@Override
protected void onProgressUpdate(String... recvMessage) {
mConversationArrayAdapter.insert(mConnectedDeviceName + ": " + recvMessage[0], 0);
}
@Override
protected void onPostExecute(Boolean isSucess) {
super.onPostExecute(isSucess);
if ( !isSucess ) {
closeSocket();
Log.d(TAG, "Device connection was lost");
isConnectionError = true;
showErrorDialog("Device connection was lost");
}
}
/* 소켓 닫기 */
@Override
protected void onCancelled(Boolean aBoolean) {
super.onCancelled(aBoolean);
closeSocket();
}
void closeSocket(){
try {
mBluetoothSocket.close();
Log.d(TAG, "close socket()");
} catch (IOException e2) {
Log.e(TAG, "unable to close() " +
" socket during connection failure", e2);
}
}
/* 받은 메세지 출력 */
void write(String msg){
msg += "\n";
try {
mOutputStream.write(msg.getBytes());
mOutputStream.flush();
} catch (IOException e) {
Log.e(TAG, "Exception during send", e );
}
mInputEditText.setText(" ");
}
}
/* 페어링 되어있는 블루투스 장치들의 목록확인.*/
public void showPairedDevicesListDialog()
{
Set<BluetoothDevice> devices = mBluetoothAdapter.getBondedDevices();
final BluetoothDevice[] pairedDevices = devices.toArray(new BluetoothDevice[0]);
if ( pairedDevices.length == 0 ){ //연결 할 디바이스 없을 때
showQuitDialog( "No devices have been paired.\n"
+"You must pair it with another device.");
return;
}
String[] items;
items = new String[pairedDevices.length];
for (int i=0;i<pairedDevices.length;i++) {
items[i] = pairedDevices[i].getName();
}
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Select device");
builder.setCancelable(false);
builder.setItems(items,new DialogInterface.OnClickListener() {
//디바이스 선택하면 기기 선택 종료
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
//다비이스 연결
ConnectTask task = new ConnectTask(pairedDevices[which]);
task.execute();
}
});
builder.create().show();
}
public void showErrorDialog(String message)
{
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Quit");
builder.setCancelable(false);
builder.setMessage(message);
builder.setPositiveButton("OK",new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
if ( isConnectionError ) {
isConnectionError = false;
finish();
}
}
});
builder.create().show();
}
public void showQuitDialog(String message)
{
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Quit");
builder.setCancelable(false);
builder.setMessage(message);
builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
finish();
}
});
builder.create().show();
}
/* 메세지 보내기 */
void sendMessage(String msg){
if ( mConnectedTask != null ) {
mConnectedTask.write(msg);
Log.d(TAG, "send message: " + msg);
mConversationArrayAdapter.insert("Me: " + msg, 0);
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_BLUETOOTH_ENABLE) {
if (resultCode == RESULT_OK) {
//BlueTooth is now Enabled
showPairedDevicesListDialog();
}
if (resultCode == RESULT_CANCELED) {
showQuitDialog("You need to enable bluetooth");
}
}
}
}
activity_main_xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:paddingBottom="10dp"
android:paddingTop="10dp"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="connection state : "/>
<TextView
android:id="@+id/connection_status_textview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text=""/>
</LinearLayout>
<LinearLayout
android:weightSum="1"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText
android:id="@+id/input_string_edittext"
android:hint="input text here"
android:layout_weight="0.8"
android:layout_width="0dp"
android:layout_height="wrap_content"/>
<Button
android:id="@+id/send_button"
android:layout_weight="0.2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="Send" />
</LinearLayout>
<ListView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/message_listview"/>
</LinearLayout>
'PROGRAMMING CODE > ANDROID STUDIO' 카테고리의 다른 글
[Android Studio] Activity 생명주기 (0) | 2021.12.05 |
---|---|
[Android Studio] 신경쓰지 않아도 되는 로그캣 오류 (계속 업데이트) (0) | 2021.12.04 |
[Android Studio] 내장 센서 확인 (0) | 2021.11.30 |