안드로이드 클래식 블루투스 개발
이 밖에 본고는 클래식 블루투스(Classic Bluetooth)의 점대점 통신 개발만 다루고 저소모 블루투스(BLE)의 개발은 언급하지 않는다.
개발 프로세스
1. 획득
BluetoothAdapter
: mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
2. 블루투스 오픈
AndroidManifest
에 권한 추가:
2. 블루투스 기능 오픈:
상수 REQUESTENABLE_BT는 로컬에서 정의한 정수 (0 이상 필요) 이며, 시스템이 onActivity Result () 를 통해 응용 프로그램에 되돌아올 때 RequestCode의 매개 변수로 사용됩니다.블루투스 오픈에 성공하면 당신의 Activity는 RESULTOK 를 resultCode 로 설정합니다.Bluetooth가 성공적으로 켜지지 않은 경우(예: 사용자가 취소를 선택한 경우) ResultCode는 RESULTCANCELED
//1、 BluetoothAdapter
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
//2、 ,
if(mBluetoothAdapter == null ||!mBluetoothAdapter.isEnabled()){
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent,REQUEST_ENABLE_BT);
}
3. 반환값 처리
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode == REQUEST_ENABLE_BT && resultCode == RESULT_OK){
// ,
}else if(requestCode == REQUEST_ENABLE_BT && resultCode == RESULT_CANCELED){
// ,
Toast.makeText(MainActivity.this," ",Toast.LENGTH_SHORT).show();
finish();
}
}
AndroidManifest
에 모호한 포지셔닝 권한을 추가합니다:
2. Bluetooth 사용 권한 확인:
if (Build.VERSION.SDK_INT >= 23) {
//
if (ContextCompat.checkSelfPermission(context,
Manifest.permission.ACCESS_COARSE_LOCATION)!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(context,
new String[]{Manifest.permission.ACCESS_COARSE_LOCATION},
REQUEST_ENABLE_BT
);
} else {
//
}
} else {
// 6.0
}
3. startActivityForResult 메서드와 같이 반환 값을 처리합니다.
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == REQUEST_ENABLE_BT) {
if(grantResults[0] == PackageManager.PERMISSION_GRANTED) {
//
} else {
//
}
}
}
근처 블루투스 장치 검색
1. 면맞춤된 장치 조회 및 목록 추가
// list
Set paireDevices = mBluetoothAdapter.getBondedDevices();
if(paireDevices.size()>0){
for(BluetoothDevice device: paireDevices){
adapter.addData(device); //adapter
}
}
2. 장치가 비동기적인 방법
startDiscovery()
을 호출하여 블루투스 장치를 검색하는 것을 발견한다.이 프로세스는 비동기 프로세스이며, 이 방법은 발견 작업이 성공적으로 시작되었는지 여부를 표시하는 부울 값을 즉시 되돌려줍니다.검색 프로세스는 보통 약 12초의 검색 스캔을 포함하고, 그 다음에 발견된 장치마다 블루투스 이름을 검색하기 위해 페이지를 스캔합니다.
이 방법으로 블루투스 장치를 발견하면 방송
ACTION_FOUND
의Intent
, 검색된 장치 정보EXTRA_DEVICE
가 여기에 포함되어 있기 때문에Intent
에 등록BroadcastReceiver
하여 방송을 처리한다.// IntentFilter
private IntentFilter getIntentFilter(){
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(BluetoothDevice.ACTION_FOUND);
intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
return intentFilter;
}
// BroadcastReceiver
private final BroadcastReceiver receiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if(BluetoothDevice.ACTION_FOUND.equals(action)){
BluetoothDevice device=intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
if(!list.contains(device)){//
adapter.addData(device);
}
}else if(BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)){
Toast.makeText(context," ",Toast.LENGTH_SHORT).show();
}
}
};
// onCreate
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//
registerReceiver(receiver,getIntentFilter());
}
onDestroy()
에서 로그아웃하는 것을 잊지 마십시오.unregisterReceiver(receiver);
디바이스 검색을 수행하는 작업은 막대한 리소스를 소비하는 번거로운 작업입니다.일단 장치를 찾았고 연결을 하려면, 장치 검색을 중지할지 확인하십시오.연결이 완료되면 검색 동작이 연결의 속도를 현저히 낮출 수 있기 때문에 연결할 때 검색을 중단해야 합니다.cancelDiscovery () 방법으로 검색을 중지할 수 있습니다.
쌍 연결
두 장치 사이에 연결을 만들려면 한 장치는 서버로서 개방된
BluetoothServerSocket
를 유지하고 라인에서 호출된 accept()
연결 요청을 탐지하기 시작하고, 다른 장치는 스캔된 서버 MAC를 이용하여 연결 요청을 시작해야 한다.참고: 두 장치가 이전에 쌍을 이루지 않은 경우 연결 중에 Android 프레임이 자동으로 쌍 요청 알림 또는 대화 상자를 사용자에게 표시합니다.
listenUsingRfcommWithServiceRecord(String, UUID)
을 통해 획득BluetoothServerSocket
run()
에서 호출accept()
을 통해 연결 요청을 감청하기 시작합니다.accept()
는 호출을 막기 때문에 전문적인 라인으로 연결하는 작업이 필요합니다.// , ConnectedThread
private class AcceptThread extends Thread {
private final BluetoothServerSocket mmServerSocket;
public AcceptThread() {
BluetoothServerSocket tmp = null;
try {
tmp = mBluetoothAdapter.listenUsingRfcommWithServiceRecord("YourAPPName", MY_UUID);
} catch (IOException e) {
e.printStackTrace();
}
mmServerSocket = tmp;
}
public void run() {
Log.d(TAG, "BEGIN mAcceptThread" + this);
BluetoothSocket socket = null;
// accept
while (mState!=3) {
try {
socket = mmServerSocket.accept();
} catch (IOException e) {
Log.e(TAG, "accept() failed", e);
break;
}
if (socket != null) {
synchronized (MainActivity.this) {
switch (mState) {
case STATE_LISTEN:
case STATE_CONNECTING:
//
connected(socket);
break;
case STATE_NONE:
case STATE_CONNECTED:
// Either not ready or already connected. Terminate new socket.
try {
socket.close();
} catch (IOException e) {
Log.e(TAG, "Could not close unwanted socket", e);
}
break;
}
}
}
}
Log.i(TAG, "END mAcceptThread");
}
public void cancel() {
Log.d(TAG, "Socket cancel " + this);
try {
mmServerSocket.close();
} catch (IOException e) {
Log.e(TAG, "Socket close() of server failed", e);
}
}
}
mState
현재 상태를 표시하는 변수로STATE_NONE = 0; //
STATE_LISTEN = 1; //
STATE_CONNECTING = 2; //
STATE_CONNECTED = 3; //
BluetoothDevice btDev = mBluetoothAdapter.getRemoteDevice(macAddress);
createRfcommSocketToServiceRecord(UUID)
은 안전한 연결을 구축한다.주:
UUID
는 00001101-0000-1000-8000-00805F9B34FB
로 정의하여 휴대전화 블루투스 인터페이스의 통일된 UUID를 위한 것이다.run()
에서 호출conenct
을 통해 연결을 만듭니다. connect()
이 호출을 막기 때문에 이 연결 과정은 주Activity 스레드 이외의 스레드에서 시종일관 실행되어야 합니다.//
private class ConnectThread extends Thread {
private final BluetoothSocket mmSocket;
private final BluetoothDevice mmDevice;
public ConnectThread(BluetoothDevice device) {
mmDevice = device;
BluetoothSocket tmp = null;
try {
//
tmp = mmDevice.createRfcommSocketToServiceRecord(MY_UUID);
//
//tmp = mmDevice.createInsecureRfcommSocketToServiceRecord(MY_UUID);
} catch (IOException e) {
Log.i(TAG," BluetoothSocket ");
e.printStackTrace();
}
mmSocket = tmp;
}
@Override
public void run() {
if(mBluetoothAdapter.isDiscovering()){
mBluetoothAdapter.cancelDiscovery();
}
try {
mmSocket.connect();
} catch (IOException e) {
Log.i(TAG,"socket ");
// Handler
Message msg = mHandler.obtainMessage(Constants.MESSAGE_TOAST);
Bundle bundle = new Bundle();
bundle.putString(Constants.TOAST,"Socket ");
msg.setData(bundle);
mHandler.sendMessage(msg);
return;
}
synchronized (MainActivity.this){
mConnectThread = null;
}
// , connectedThread
connected(mmSocket);
}
public void cancel(){
try {
mmSocket.close();
setState(false);
} catch (IOException e) {
e.printStackTrace();
}
}
}
주:
connected(mmSocket)
는 응용 프로그램의 허구적인 방법으로 데이터 전송에 사용할 라인을 시작합니다.// ConnectedThread
public synchronized void connected(BluetoothSocket socket){
if (mConnectThread != null) {
mConnectThread.cancel();
mConnectThread = null;
}
if (mConnectedThread != null) {
mConnectedThread.cancel();
mConnectedThread = null;
}
setState(STATE_CONNECTED);
mConnectedThread = new ConnectedThread(socket);
mConnectedThread.start();
}
커뮤니케이션
두 장치가 성공적으로 연결되면 각 장치마다 연결된 장치가 하나씩 있습니다
BluetoothSocket
.BluetoothSocket
를 사용하여 데이터를 전송하는 일반적인 절차는 매우 간단합니다.InputStream
과 OutputStream
, 양자는 각각 플러그인과 getInputStream()
와 getOutputStream()
를 통해 데이터 전송을 처리한다.read(byte[])
를 사용하여 데이터를 읽고 스트리밍에 기록합니다.read(byte[])와 write(byte[]) 방법은 모두 호출이 막히기 때문에 읽기 전용 라인이 필요합니다.
//
private 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;
try {
tmpIn = socket.getInputStream();
tmpOut = socket.getOutputStream();
} catch (IOException e) {
Log.e(TAG, "temp sockets not created", e);
}
mmInStream = tmpIn;
mmOutStream = tmpOut;
}
public void run() {
Log.i(TAG, "BEGIN mConnectedThread");
// ,
while(mState == STATE_CONNECTED){
try {
// InputStream
Scanner in = new Scanner(mmInStream,"UTF-8");
String str = in.nextLine();
Log.i(TAG,"read: "+str);
// handle , Toast
Message msg = mHandler.obtainMessage(Constants.MESSAGE_TOAST);
Bundle bundle = new Bundle();
bundle.putString(Constants.TOAST,str);
msg.setData(bundle);
mHandler.sendMessage(msg);
} catch (Exception e) {
Log.e(TAG, "disconnected", e);
}
}
}
public void write(byte[] buffer) {
try {
mmOutStream.write(buffer);
} catch (IOException e) {
e.printStackTrace();
Log.e(TAG, "Exception during write", e);
}
}
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) {
Log.e(TAG, "close() of connect socket failed", e);
}
}
}
write(byte[])
으로 출력합니다.mConnectedThread.write(byte[] buffer)
에서 순환적으로 읽히고 여기run()
처리 데이터 전달을 사용한다.Handler
의 상량은 Constants
에 대한 서로 다른 처리 방식을 대표하고 Message
의ConnectedThread
에서 서로 다른 run()
값을 사용하여 입력 흐름을 조정하는 처리 방식을 나타낸다.예에서 mHandler를 사용했습니다.obtainMessage(Constants.MESSAGE_TOAST); 대표님이 받은 데이터를 MESSAGE로...TOAST 방식으로 처리됩니다.
// Handler
private final Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch(msg.what){
case: Constants.SomeConfig:
// do something
break;
}
}
};
Demo의 GitHub 링크:https://github.com/YangLuYang/android-Demo-ClassicBluetooth
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.