반응형
SMALL
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 | import android.bluetooth.BluetoothSocket; import android.os.SystemClock; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; public class ConnectedThread extends Thread { private final BluetoothSocket mmSocket; private final InputStream mmInStream; private final OutputStream mmOutStream; public ConnectedThread(BluetoothSocket socket) { mmSocket = socket; InputStream tmpIn = null; OutputStream tmpOut = null; // Get the input and output streams, using temp objects because // member streams are final try { tmpIn = socket.getInputStream(); tmpOut = socket.getOutputStream(); } catch (IOException e) { } mmInStream = tmpIn; mmOutStream = tmpOut; } @Override public void run() { byte[] buffer = new byte[1024]; // buffer store for the stream int bytes; // bytes returned from read() // Keep listening to the InputStream until an exception occurs while (true) { try { // Read from the InputStream bytes = mmInStream.available(); if (bytes != 0) { buffer = new byte[1024]; SystemClock.sleep(100); //pause and wait for rest of data. Adjust this depending on your sending speed. bytes = mmInStream.available(); // how many bytes are ready to be read? bytes = mmInStream.read(buffer, 0, bytes); // record how many bytes we actually read } } catch (IOException e) { e.printStackTrace(); break; } } } /* Call this from the main activity to send data to the remote device */ public void write(String input) { byte[] bytes = input.getBytes(); //converts entered String into bytes try { mmOutStream.write(bytes); } catch (IOException e) { } } /* Call this from the main activity to shutdown the connection */ public void cancel() { try { mmSocket.close(); } catch (IOException e) { } } } | cs |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 | package com.example.mybluetooth001_002; import android.Manifest; import android.annotation.SuppressLint; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothGatt; import android.bluetooth.BluetoothGattCallback; import android.bluetooth.BluetoothManager; import android.bluetooth.BluetoothProfile; import android.bluetooth.BluetoothSocket; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.pm.PackageManager; import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.os.SystemClock; import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AppCompatActivity; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; import android.widget.Toast; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.UnsupportedEncodingException; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.List; import java.util.Set; import java.util.UUID; public class MainActivity extends AppCompatActivity { TextView mTvBluetoothStatus; TextView mTvReceiveData; TextView mTvSendData; TextView mTvReceiveDataView; Button mBtnConnect; Button mBtnSendData; private BluetoothAdapter mBluetoothAdapter; Set<BluetoothDevice> mPairedDevices; List<String> mListPairedDevices; Handler mBluetoothHandler; ConnectedBluetoothThread mThreadConnectedBluetooth; BluetoothDevice mBluetoothDevice; BluetoothSocket mBluetoothSocket; final static int BT_MESSAGE_READ = 2; final static int BT_CONNECTING_STATUS = 3; final static UUID BT_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"); ConnectedThread connectedThread; //tag를 사용하기 위한 선언 private static final String TAG = "MainActivity"; private int readBufferPosition; // 버퍼 내 문자 저장 위치 private BluetoothGatt mBluetoothGatt; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //블루투스가 되는지 설정 if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) { Toast.makeText(this, "블루투스 미지원 기기입니다.", Toast.LENGTH_SHORT).show(); finish(); } //권한 설정 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { requestPermissions( new String[]{ Manifest.permission.BLUETOOTH, Manifest.permission.BLUETOOTH_SCAN, Manifest.permission.BLUETOOTH_ADVERTISE, Manifest.permission.BLUETOOTH_CONNECT, Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION }, 1); } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { requestPermissions( new String[]{ Manifest.permission.BLUETOOTH }, 1); } mTvBluetoothStatus = (TextView)findViewById(R.id.tvBluetoothStatus); mTvReceiveData = (TextView)findViewById(R.id.tvReceiveData); mTvReceiveDataView = (TextView)findViewById(R.id.tvReceiveDataView); mTvSendData = (EditText) findViewById(R.id.tvSendData); mBtnConnect = (Button)findViewById(R.id.btnConnect); mBtnSendData = (Button)findViewById(R.id.btnSendData); // 블루투스 기능을 지원하는지 알아오는 메서드 mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); //mBluetoothLeScanner = mBluetoothAdapter.getBluetoothLeScanner(); //mBluetoothLeAdvertiser = mBluetoothAdapter.getBluetoothLeAdvertiser(); // Initializes Bluetooth adapter. final BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE); mBluetoothAdapter = bluetoothManager.getAdapter(); // 버튼 눌렀을 때 동작하는 기능들 mBtnConnect.setOnClickListener(new Button.OnClickListener() { @Override public void onClick(View view) { listPairedDevices(); } }); mBtnSendData.setOnClickListener(new Button.OnClickListener() { @Override public void onClick(View view) { if(mThreadConnectedBluetooth != null) { mThreadConnectedBluetooth.write(mTvSendData.getText().toString()); mTvSendData.setText(""); } } }); // 블루투스 핸들러로 연결 뒤, 수신된 데이터를 읽어와 ReceiveData텍스트 뷰에 표시해주는 부분 mBluetoothHandler = new Handler(Looper.getMainLooper()){ public void handleMessage(android.os.Message msg){ if(msg.what == BT_MESSAGE_READ){ String readMessage = null; try { readMessage = new String((byte[]) msg.obj, "UTF-8"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } mTvReceiveData.setText(readMessage); } } }; } void listPairedDevices() { // 블루투스 활성화 상태 확인 try{ if (mBluetoothAdapter.isEnabled()) { // 이미 Paired된 Device목록을 얻어옴 mPairedDevices = mBluetoothAdapter.getBondedDevices(); //페어링 된 장치가 존재한다면 새로운 알림창을 생성 if (mPairedDevices.size() > 0) { AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setTitle("장치 선택"); mListPairedDevices = new ArrayList<String>(); for (BluetoothDevice device : mPairedDevices) { mListPairedDevices.add(device.getName()); //mListPairedDevices.add(device.getName() + "\n" + device.getAddress()); } final CharSequence[] items = mListPairedDevices.toArray(new CharSequence[mListPairedDevices.size()]); mListPairedDevices.toArray(new CharSequence[mListPairedDevices.size()]); //장치를 누르면 connectSelectedDevice로 전달 builder.setItems(items, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int item) { for (BluetoothDevice device : mPairedDevices) { if (device.getName().equals(items[item].toString())) { connectSelectedDevice(String.valueOf(device)); break; } } } }); // 알림창을 뛰어줌 AlertDialog alert = builder.create(); alert.show(); } else { Toast.makeText(getApplicationContext(), "페어링된 장치가 없습니다.", Toast.LENGTH_LONG).show(); } } else { Toast.makeText(getApplicationContext(), "블루투스가 비활성화 되어 있습니다.", Toast.LENGTH_SHORT).show(); } }catch (SecurityException e) { e.printStackTrace(); } } // listPairedDevices를 통하여 전달받은 매개변수 값은 장치 이름 @SuppressWarnings({"MissingPermission"}) private void connectSelectedDevice(String address) { BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address); mBluetoothGatt = device.connectGatt(this, false, mGattCallback); } private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() { @SuppressLint("MissingPermission") @Override public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) { super.onConnectionStateChange(gatt, status, newState); if (newState == BluetoothProfile.STATE_CONNECTED) { gatt.discoverServices(); } else if (newState == BluetoothProfile.STATE_DISCONNECTED) { mBluetoothGatt.close(); mBluetoothGatt = null; } } @Override public void onServicesDiscovered(BluetoothGatt gatt, int status) { super.onServicesDiscovered(gatt, status); // do something with the services } }; @SuppressLint("MissingPermission") private BluetoothSocket createBluetoothLEConnection(BluetoothDevice device) { BluetoothSocket socket = null; try { socket = device.createRfcommSocketToServiceRecord(UUID.fromString("00001101-0000-1000-8000-00805F9B34FB")); } catch (IOException e) { e.printStackTrace(); } return socket; } @SuppressLint("MissingPermission") private BluetoothGatt connectGatt(BluetoothDevice device) { return device.connectGatt(this, false, mGattCallback); } @SuppressWarnings({"MissingPermission"}) private class ConnectedBluetoothThread extends Thread { private final BluetoothSocket mmSocket; private InputStream mmInStream; private OutputStream mmOutStream; //쓰레드 초기화 public void run() { readBufferPosition = 0; byte[] buffer = new byte[1024]; int bytes; //데이터를 지속적으로 확인하는... while (true) {//계속 확인하는 중인데 어떻게 안보내진다 try { //inputStream 계속 읽기(값을 받는다) //bytes = mmInStream.available(); bytes = mmInStream.read(buffer); String incomingMessage = new String(buffer, 0, bytes); Log.d(TAG, "Input Stream : " + incomingMessage); if (bytes >= 0) { SystemClock.sleep(100); bytes = mmInStream.available(); bytes = mmInStream.read(buffer, 0, bytes); mBluetoothHandler.obtainMessage(BT_MESSAGE_READ, bytes, -1, buffer).sendToTarget(); } } catch (IOException e) { try { mmSocket.connect(); } catch (IOException ex) { Log.e(TAG, "Unable to connect to socket", ex); break; } } } } public ConnectedBluetoothThread(BluetoothSocket socket) { mmSocket = socket; InputStream tmpIn = null; OutputStream tmpOut = null; // 소켓을 통한 전송을 처리 // BluetoothSocket의 inputstream 과 outputstream을 얻는다. try { tmpIn = socket.getInputStream(); tmpOut = socket.getOutputStream(); } catch (IOException e) { Toast.makeText(getApplicationContext(), "소켓 연결 중 오류가 발생했습니다.", Toast.LENGTH_LONG).show(); } mmInStream = tmpIn; mmOutStream = tmpOut; } //데이터 전송을 위한 스레드 메서드 public void write(String str) { byte[] bytes = str.getBytes(); try { //값을 쓰는 부분(값을 보낸다.) mmOutStream.write(bytes); } catch (IOException e) { //e: "java.io.IOException: socket closed" Toast.makeText(getApplicationContext(), "데이터 전송 중 오류가 발생했습니다.", Toast.LENGTH_LONG).show(); // 소켓을 다시 생성하고 연결한다. try { mBluetoothSocket = mBluetoothDevice.createRfcommSocketToServiceRecord(BT_UUID); mBluetoothSocket.connect(); mmOutStream = mBluetoothSocket.getOutputStream(); } catch (IOException ex) { ex.printStackTrace(); } } } public void cancel() { try { mmSocket.close(); } catch (IOException e) { Toast.makeText(getApplicationContext(), "소켓 해제 중 오류가 발생했습니다.", Toast.LENGTH_LONG).show(); } } } } | cs |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 | <?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"> <Button android:id="@+id/btnConnect" android:layout_width="wrap_content" android:layout_height="0dp" android:layout_marginStart="30dp" android:layout_marginLeft="30dp" android:layout_marginTop="30dp" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" android:text="연결하기" app:layout_constraintTop_toBottomOf="@+id/tvBluetoothStatus" /> <TextView android:id="@+id/tvBluetoothStatus" android:layout_width="170dp" android:layout_height="20dp" android:layout_marginStart="8dp" android:text="status" app:layout_constraintBottom_toBottomOf="@+id/btnConnect" app:layout_constraintStart_toEndOf="@+id/btnConnect" app:layout_constraintTop_toTopOf="@+id/btnConnect" /> <TextView android:id="@+id/tvReceiveData" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="10dp" android:text="Receive" app:layout_constraintStart_toStartOf="@+id/btnSendData" app:layout_constraintTop_toBottomOf="@+id/btnSendData" /> <TextView android:id="@+id/tvReceiveDataView" android:layout_width="307dp" android:layout_height="427dp" android:layout_marginBottom="128dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toStartOf="@+id/tvReceiveData" /> <Button android:id="@+id/btnSendData" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="10dp" android:text="전송" app:layout_constraintStart_toStartOf="@+id/btnConnect" app:layout_constraintTop_toBottomOf="@+id/btnConnect" /> <EditText android:id="@+id/tvSendData" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="8dp" android:layout_marginLeft="8dp" android:ems="10" android:inputType="textPersonName" android:text="Send Data" app:layout_constraintStart_toEndOf="@+id/btnSendData" app:layout_constraintTop_toTopOf="@+id/btnSendData" /> </androidx.constraintlayout.widget.ConstraintLayout> | cs |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 | <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools"> <!-- 블루투스 사용하기 위해 정의 --> <uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30" /> <!-- 장치를 찾거나 블루투스 설정을 관리 --> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" android:maxSdkVersion="30" /> <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" /> <uses-permission android:name="android.permission.BLUETOOTH_SCAN" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <!-- 저전력 블루투스(지원하지 않는 기기에도 앱 제공 --> <uses-feature android:name="android.hardware.bluetooth_le" android:required="false"/> <uses-feature android:name="android.hardware.bluetooth" android:required="true" /> <uses-feature android:name="android.hardware.bluetooth_le" android:required="false" /> <uses-feature android:name="android.hardware.location.gps" android:required="true" /> <application android:allowBackup="true" android:dataExtractionRules="@xml/data_extraction_rules" android:fullBackupContent="@xml/backup_rules" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/Theme.MyBluetooth001_002" tools:targetApi="31"> <activity android:name=".MainActivity" android:exported="true"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> <meta-data android:name="android.app.lib_name" android:value="" /> </activity> </application> </manifest> | cs |
아직 완성된 건 아니고 일단 연결을 하는건데
핸드폰의 블루투스를 키고 - 대상 기기를 연결한 후 어플내에서 다시 연결을 해줘야한다.
권한은 있는데로 다 넣어줬다 혹시 몰라서..
반응형
LIST
'혼자 코딩(안드로이드 feat.JAVA)' 카테고리의 다른 글
[안드로이드 스튜디오 - 자바] 블루투스 연결 _ 002 (0) | 2023.02.14 |
---|
댓글