안드로이드가 개발한 블루투스 통신
블루투스 개발 필수 기본기
Bluetooth 사용 권한
응용 프로그램에서 블루투스 기능을 사용하기 위해서는 블루투스 권한을 설명해야 합니다.연결을 요청하고 연결을 받아들이고 데이터를 전송하는 등 블루투스 통신을 수행할 수 있는 권한이 필요합니다.응용 프로그램 시작 장치에서 블루투스 설정을 발견하거나 조종하려면 블루투스 설정을 신고해야 합니다admin 라이센스.대부분의 응용 프로그램은 로컬 블루투스 장치를 발견하는 능력에만 이 권한을 필요로 한다.이 권한이 부여한 다른 권한은 사용할 수 없습니다. 프로그램이 '전원 관리자' 가 아니면 사용자가 요청한 블루투스 설정을 수정합니다.주의: 블루투스를 사용하면관리자 허가, 그럼 너도 블루투스 허가가 있어야 해.
<manifest ... >
<uses-permission android:name="android.permission.BLUETOOTH" />
...
</manifest>
Bluetooth 설정
응용 프로그램이 블루투스를 통해 통신할 수 있기 전에 블루투스 장치에서 지원되는지 확인해야 합니다. 만약 그렇다면, 블루투스 장치가 활성화되었는지 확인하십시오.만약 블루투스가 지원되지 않는다면, 어떤 블루투스 기능도 우아하게 비활성화해야 합니다.만약 블루투스가 지원되지만, 사용하지 않는다면, 사용자는 블루투스를 사용하도록 요구할 수 있으며, 응용 프로그램을 떠나지 않을 것이다.이 설정은 블루투스 어댑터를 사용하는 두 단계로 이루어집니다.
BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (mBluetoothAdapter == null) {
//
}
다음 단계에서는 블루투스 기능이 활성화되었는지 확인해야 합니다.isenabled () 는 블루투스가 현재 활성화되어 있는지 확인합니다.이 방법이 오류를 반환하면 블루투스를 사용하지 않습니다.블루투스 활성화, startactivityforresult() 및 actionrequest_enable 작업 의도.이것은 블루투스가 시스템 설정을 통과하도록 요청할 것입니다. (응용 프로그램을 막지 않습니다.)예를 들면 다음과 같습니다.
if (!mBluetoothAdapter.isEnabled()) {
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
}
면맞춤 장치 조회
Bluetooth 어댑터 Bluetooth Adapter를 사용하면 조회 목록을 통해 원격 Bluetooth 장치 쌍을 찾을 수 있습니다.장치 발견은 검색 프로그램으로 로컬 지역의 블루투스 기능을 검색한 장치입니다. 그리고 일부 정보를 요구합니다. (때로는 '발견', '조회' 또는 '스캔' 이라고 불리기도 합니다.) 그러나 랜 내의 블루투스 장치는 발견 요청에 응답할 수 있는 것만 발견됩니다.만약 장치가 발견될 수 있다면, 장치 이름, 클래스, 그리고 독특한 MAC 주소로 검색 요청에 응답하고 정보를 공유할 것입니다.이 정보를 사용하여 검색된 장치를 실행하면 검색된 장치에 연결을 시작할 수 있습니다.
한 연결이 처음으로 원격 장치와 연결되면, 짝짓기 요청이 자동으로 사용자에게 제출됩니다.장치가 연결되면 장치의 기본 정보 (예를 들어 장치 이름, 클래스, 주소) 가 저장되고 블루투스 이어폰을 사용할 수 있습니다.원격 장치의 알려진 맥 주소를 사용하면 언제든지 연결을 시작할 수 있습니다. (장치가 범위 내에 있다고 가정합니다.)
짝짓기와 연결된 것 사이의 차이가 있다는 것을 명심해라.짝짓기는 두 장치가 서로의 존재를 알고 있다는 것을 의미한다. 공유된 체인 키가 있어 인증에 사용할 수 있고 암호화된 상호 연결을 구축할 수 있다.연결하려면 현재 장치가 RFCOMM 채널을 공유하여 서로 데이터를 전달할 수 있음을 의미한다.현재 안드로이드 블루투스 API의 장치는 RFCOMM에 짝을 지어 연결할 수 있어야 한다.(블루투스 인터페이스와의 암호화 연결을 시작할 때 자동으로 짝짓기를 실행합니다.
BluetoothDevices는 본 컴퓨터의 블루투스와 연결된 원격 블루투스 정보를 가져옵니다. BluetoothDevice 클래스의 실례로 되돌아옵니다. 블루투스가 켜지면 이 함수는 빈 집합을 되돌려줍니다.
Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();
// If there are paired devices
if (pairedDevices.size() > 0) {
// Loop through paired devices
for (BluetoothDevice device : pairedDevices) {
// Add the name and address to an array adapter to show in a ListView
mArrayAdapter.add(device.getName() + "
" + device.getAddress());
}
}
검색 장치
디바이스를 검색하고 startdiscovery ()를 호출합니다.이 프로세스는 비동기적이며, 이 방법은 부울 값을 즉시 되돌려 성공적으로 시작되었는지 여부를 표시합니다.발견 과정은 보통 약 12초의 조회 스캔과 관련된 것이고, 한 페이지를 통해 모든 발견된 장치를 스캔해서 블루투스 이름을 검색한다.
응용 프로그램은 ACTION 을 등록해야 합니다.FOUND는 각 장치에 대한 검색BroadcastReceiver를 수신하려고 합니다.우리는 브로드캐스트 수신기를 등록하여 브로드캐스트를 수신함으로써 다음과 같은 작업을 처리합니다.
// Create a BroadcastReceiver for ACTION_FOUND
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
// When discovery finds a device
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
// Get the BluetoothDevice object from the Intent
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
// Add the name and address to an array adapter to show in a ListView
mArrayAdapter.add(device.getName() + "
" + device.getAddress());
}
}
};
// Register the BroadcastReceiver
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
registerReceiver(mReceiver, filter); // Don't forget to unregister during onDestroy
경고: 실행 장치가 블루투스 어댑터를 발견하는 것은 무거운 과정이며 대량의 자원을 소모할 수 있습니다.장치 연결을 찾으면 canceldiscovery () 를 호출해서 이전 검색을 취소합니다.
디바이스를 검색하기 위한 Intent 의도의 기본 검색 시간은 120초이며, 한 애플리케이션에서 최대 기간을 3600초로 설정할 수 있으며, 0 값은 디바이스가 항상 검색됨을 나타냅니다.0보다 낮거나 3600보다 높으면 120초로 자동 설정됨) (블루투스 장치가 얼마나 오래 실행되는지 스캔하고 연결할 수 있는지 이해할 수 있음)
Intent discoverableIntent = new
Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);
startActivity(discoverableIntent);
블루투스와 서비스 측, 클라이언트에 대한 링크는 Bluetooth ServerSocket, Bluetooth Socket과 관련이 있기 때문에 할 말이 없습니다. 잠시 후에 공식 단순을 통해 보면 됩니다.
Bluetooth 저전력 Android 기반 4.3
위와 비교하면 권한은 다음과 같은 두 가지가 있어야 한다(4.3의 저소모 블루투스 스캐닝 startLeScan 방법은 BLUETOOTH ADMIN 권한이 있어야 한다)
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
만약 응용 프로그램이 4.3 이상의 휴대전화 장치로 설치되어 있고 저소모 블루투스를 지원한다고 확신한다면 명세서 파일에서 다음과 같이 설명할 수 있다
<uses-feature android:name="android.hardware.bluetooth_le" android:required="true"/>
만약 당신의 앱이 사용하는 장치가 저소모 블루투스를 지원하는지 확실하지 않지만, 지원하는 장치가 저소모 블루투스를 사용하도록 하려면, 당신은 이렇게 할 수 있습니다
<uses-feature android:name="android.hardware.bluetooth_le" android:required="false"/>
if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
Toast.makeText(this, R.string.ble_not_supported, Toast.LENGTH_SHORT).show();
finish();
}
Bluetooth Adapter는 Bluetooth Manager를 통해 얻을 수 있습니다. Bluetooth Manager가 불러올 때 구조 함수가 Bluetooth Adapter를 호출했기 때문입니다.getDefualtA..adapter 객체 초기화
// Initializes Bluetooth adapter.
final BluetoothManager bluetoothManager =
(BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
mBluetoothAdapter = bluetoothManager.getAdapter();
public static synchronized BluetoothAdapter getDefaultAdapter() {
if (sAdapter == null) {
IBinder b = ServiceManager.getService(BLUETOOTH_MANAGER_SERVICE);
if (b != null) {
IBluetoothManager managerService = IBluetoothManager.Stub.asInterface(b);
sAdapter = new BluetoothAdapter(managerService);
} else {
Log.e(TAG, "Bluetooth binder is null");
}
}
return sAdapter;
}
블루투스 장치의 스캐닝도 변화가 생겼고adapter를 통해startScan stopScan은 스캔 스위치를 제어합니다. 스캔 시간은postDelayed를 통해 스캔 시간을 설정할 수 있습니다
/** * Activity for scanning and displaying available BLE devices. */
public class DeviceScanActivity extends ListActivity {
private BluetoothAdapter mBluetoothAdapter;
private boolean mScanning;
private Handler mHandler;
// Stops scanning after 10 seconds.
private static final long SCAN_PERIOD = 10000;
...
private void scanLeDevice(final boolean enable) {
if (enable) {
// Stops scanning after a pre-defined scan period.
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
mScanning = false;
mBluetoothAdapter.stopLeScan(mLeScanCallback);
}
}, SCAN_PERIOD);
mScanning = true;
mBluetoothAdapter.startLeScan(mLeScanCallback);
} else {
mScanning = false;
mBluetoothAdapter.stopLeScan(mLeScanCallback);
}
...
}
...
}
LeScanCallback 리셋 인터페이스의 실현을 통해 리셋 결과의 UI 리셋 등 기능의 실현을 처리한다.
private LeDeviceListAdapter mLeDeviceListAdapter;
...
// Device scan callback.
private BluetoothAdapter.LeScanCallback mLeScanCallback =
new BluetoothAdapter.LeScanCallback() {
@Override
public void onLeScan(final BluetoothDevice device, int rssi,
byte[] scanRecord) {
runOnUiThread(new Runnable() {
@Override
public void run() {
mLeDeviceListAdapter.addDevice(device);
mLeDeviceListAdapter.notifyDataSetChanged();
}
});
}
};
Bluetooth Gatt Bluetooth Gatt Callback 등과 관련된 Gat류는 대동소이하며 구글이 공식적으로 제공한 단순에 따라 한 번 훑어보면 된다.블루투스 개발 디버깅https://developer.android.com/training/wearables/apps/bt-debugging.html
구글 공식 블루투스 오픈 프로젝트
홈페이지를 통해 세 개의 소스 오픈 프로젝트를 찾았지만 다운로드할 수 없을 것 같아서github를 통해 구글 창고를 검색할 수 밖에 없습니다.
먼저 android-Bluetooth Advertisements 실행 효과도를 보십시오
Bluetooth Advertisements에서 프로젝트를 시작하려면 먼저 get에서 한 점까지 생명주기를 박리하세요!관련 코드 블록은 다음과 같다.
public class ScannerFragment extends ListFragment {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
setRetainInstance(true);
// Activity, Activity Application, Activity
mAdapter = new ScanResultAdapter(getActivity().getApplicationContext(),
LayoutInflater.from(getActivity()));
mHandler = new Handler();
}
스캔 코드 블록은 Bluetooth Adapter를 사용하지 않습니다.start Scan, 원본 코드를 보니 여전히 유행이 지난 방법입니다. 단순함에서 adapter를 통해 Bluetooth Le Scanner를 직접 가져오고, scanner의 start Scan을 호출했습니다.
public void startScanning() {
// ......... ............
mScanCallback = new SampleScanCallback();
mBluetoothLeScanner.startScan(buildScanFilters(), buildScanSettings(), mScanCallback);
}
그러나 이 소스 항목을 다운로드하고 효과를 보려고 한다면, 점원은 절대로 성공하지 못할 것이라고 말할 수 밖에 없다. buildscanFilters에 스캔 필터 규칙이 추가되어 있어 uiid가 일치하지 않으면 아무것도 볼 수 없다. 코드 알림에 따라 아래의 필터 조건을 설명하면 모든 블루투스 장치를 볼 수 있다.
private List<ScanFilter> buildScanFilters() {
List<ScanFilter> scanFilters = new ArrayList<>();
ScanFilter.Builder builder = new ScanFilter.Builder();
// , (uuid )
// builder.setServiceUuid(Constants.Service_UUID);
//scanFilters.add(builder.build());
return scanFilters;
}
저전력 모드에서 Bluetooth LE 검색을 수행합니다.최소 전력을 소비하기 때문에 기본 스캔 모드입니다.
private ScanSettings buildScanSettings() {
ScanSettings.Builder builder = new ScanSettings.Builder();
builder.setScanMode(ScanSettings.SCAN_MODE_LOW_POWER);
return builder.build();
}
스캔 결과의 리셋은 우리가 자신의 수요에 따라 구현할 수 있다
private class SampleScanCallback extends ScanCallback {
@Override
public void onBatchScanResults(List<ScanResult> results) {
super.onBatchScanResults(results);
//
for (ScanResult result : results) {
mAdapter.add(result);
}
mAdapter.notifyDataSetChanged();
}
@Override
public void onScanResult(int callbackType, ScanResult result) {
super.onScanResult(callbackType, result);
//
}
@Override
public void onScanFailed(int errorCode) {
super.onScanFailed(errorCode);
//
}
}
스캔이 시작되기 전의 논리적 판단은 단순 MainActivity를 참조합니다.Advertiser Service와 관련된 차이는 생략하겠습니다. android-Bluetooth LeGatt라는 단순함은 개인적으로 별로 특별하지 않다고 생각하는 핵심에 언급되어 있습니다. android 4.3+버전의 블루투스 개발 단순,mainfest를 보면 서비스 개인이 좀 엉망진창인 것 같아요.
BluetoothChat을 보면 우선 블루투스가 스캐닝 링크를 감지하고 해당하는 패턴과 스캐닝을 허용하는 시간을 설정해야 한다.
/** * Makes this device discoverable. */
private void ensureDiscoverable() {
if (mBluetoothAdapter.getScanMode() !=
BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE) {
Intent discoverableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);
startActivity(discoverableIntent);
}
}
블루투스 어댑터 getRemoteDevice(address) 후 연결하고 핵심 코드는 BluetoothChatService를 참조합니다.ConnectThread 스레드 섹션데이터의 발송 핵심 코드는 발송된string 메시지를byte[]로 변환하고ChatServiced의 write 방법을 호출하면 된다
/** * Write to the ConnectedThread in an unsynchronized manner * * @param out The bytes to write * @see ConnectedThread#write(byte[]) */
public void write(byte[] out) {
// Create temporary object
ConnectedThread r;
// Synchronize a copy of the ConnectedThread
synchronized (this) {
if (mState != STATE_CONNECTED) return;
r = mConnectedThread;
}
// Perform the write unsynchronized
r.write(out);
}
마지막으로 도구 클래스 BluetoothHelper를 제공합니다.자바(이 도구류는 정리가 완벽하지 않아서 스캔과 링크 호환에 대해 모두 쓰지 않았습니다. 구체적인 개발 링크는 공식 단순한ChartService를 참조하고 LE와 관련된 스캔은 단순을 참조하십시오. 호환은 주로api11,api18LE,api21)
/** * Created by idea on 2016/7/4. */
public class BluetoothHelper {
private static BluetoothHelper instance;
private BluetoothAdapter mBluetoothAdapter;
private Activity mContext;
/** * BluetoothHelper , Application Activity * @param activity * @return BluetoothHelper */
public static BluetoothHelper getInstance(Activity activity) {
if (instance == null) {
synchronized (BluetoothHelper.class) {
if (instance == null) {
instance = new BluetoothHelper(activity);
}
}
}
return instance;
}
/** * * @param activity * @hide */
private BluetoothHelper(Activity activity) {
this.mContext = activity;
mBluetoothAdapter = getAdapter();
}
/*** * BluetoothAdapter * * @return BluetoothAdapter * @hide */
private BluetoothAdapter getAdapter() {
BluetoothAdapter mBluetoothAdapter;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
mBluetoothAdapter = ((BluetoothManager) mContext.getSystemService(Context.BLUETOOTH_SERVICE)).getAdapter();
} else {
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
}
return mBluetoothAdapter;
}
/** * adapter * @return */
public BluetoothAdapter getBluetoothAdapter() {
return mBluetoothAdapter;
}
/** * * * @return boolean */
public boolean checkSupperBluetooth() {
return mBluetoothAdapter == null;
}
/** * * * @return boolean */
public boolean checkBluetoothEnable() {
return mBluetoothAdapter.isEnabled();
}
/** * , , */
public void requestOpenBluetooth() {
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
mContext.startActivityForResult(enableBtIntent, Constants.REQUEST_ENABLE_BT);
}
/** * * * @param requestCode * @param resultCode * @param onOpenBluetoothLisenter */
public void performResult(int requestCode, int resultCode, OnBluetoothListener.OnOpenBluetoothLisenter onOpenBluetoothLisenter) {
switch (requestCode) {
case Constants.REQUEST_ENABLE_BT:
if (onOpenBluetoothLisenter != null) {
if (resultCode == Activity.RESULT_OK) {
if (checkBluetoothEnable()) {
onOpenBluetoothLisenter.onSuccess();
} else {
onOpenBluetoothLisenter.onFail(" , ");
}
} else {
onOpenBluetoothLisenter.onFail("Error");
}
}
}
}
/*** * (4.3+) * * @return boolean * @hide */
@Deprecated
public boolean isSupperBluetoothLE() {
return mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE);
}
/** * LE * * @return boolean * @hide */
@Deprecated
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public boolean isMultipleAdvertisementSupported() {
return mBluetoothAdapter.isMultipleAdvertisementSupported();
}
/** * , * * @return boolean */
public boolean checkSupperBluetoothLE() {
final int version = Build.VERSION.SDK_INT;
if (version >= Build.VERSION_CODES.LOLLIPOP) {
return isMultipleAdvertisementSupported();
} else {
return isSupperBluetoothLE();
}
}
/** * * * @param duration */
private void ensureDiscoverable(int duration) {
if (mBluetoothAdapter.getScanMode() != BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE) {
Intent discoverableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, duration);
mContext.startActivity(discoverableIntent);
}
}
/** * APi21 * @param mScanCallback */
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public void startScanningApi21(ScanCallback mScanCallback){
mBluetoothAdapter.getBluetoothLeScanner().startScan(buildScanFilters(), buildScanSettings(),mScanCallback);
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
private List<ScanFilter> buildScanFilters() {
List<ScanFilter> scanFilters = new ArrayList<>();
ScanFilter.Builder builder = new ScanFilter.Builder();
// , (uuid )
// builder.setServiceUuid(Constants.Service_UUID);
//scanFilters.add(builder.build());
return scanFilters;
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
private ScanSettings buildScanSettings() {
ScanSettings.Builder builder = new ScanSettings.Builder();
builder.setScanMode(ScanSettings.SCAN_MODE_LOW_POWER);
return builder.build();
}
/** * ,Api11 */
public void registerReceiver(){
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
mContext.registerReceiver(receiver, filter);
filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
mContext.registerReceiver(receiver, filter);
}
/** * */
protected void onDestroy() {
if (mBluetoothAdapter != null) {
mBluetoothAdapter.cancelDiscovery();
}
mContext.unregisterReceiver(receiver);
}
/** * Api11+ */
private void doDiscovery() {
if (mBluetoothAdapter.isDiscovering()) {
mBluetoothAdapter.cancelDiscovery();
}
mBluetoothAdapter.startDiscovery();
}
/** * The BroadcastReceiver that listens for discovered devices and changes the title when * discovery is finished */
private final BroadcastReceiver receiver = new BroadcastReceiver() {
ArrayList<BluetoothDevice> results = new ArrayList<>();
@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 (device.getBondState() != BluetoothDevice.BOND_BONDED) {
results.add(device);
}
} else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
}
}
};
}
소결
지식을 정리하고 맥락을 파악하면 아무리 변해도 근본을 떠나지 않는다.
참고 자료
https://developer.android.com/guide/topics/connectivity/bluetooth.html#ConnectingDevices https://developer.android.com/guide/topics/connectivity/bluetooth-le.html
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Kotlin의 기초 - 2부지난 글에서는 Kotlin이 무엇인지, Kotlin의 특징, Kotlin에서 변수 및 데이터 유형을 선언하는 방법과 같은 Kotlin의 기본 개념에 대해 배웠습니다. 유형 변환은 데이터 변수의 한 유형을 다른 데이터...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.