Android 8.0 (API düzeyi 26) ve sonraki sürümleri çalıştıran cihazlarda, yardımcı cihaz eşleme işlemi, ACCESS_FINE_LOCATION
izni gerektirmeden uygulamanız adına yakındaki cihazların Bluetooth veya Kablosuz ağ taramasını gerçekleştirir. Bu, kullanıcı gizliliği korumalarını en üst düzeye çıkarmaya yardımcı olur. Bu yöntemi, BLE özellikli akıllı saat gibi tamamlayıcı cihazın ilk yapılandırmasını yapmak için kullanın. Ayrıca, eşlik eden cihaz eşleme işlemi için Konum Hizmetleri'nin etkinleştirilmesi gerekir.
Tamamlayıcı cihaz eşleme özelliği kendi başına bağlantı oluşturmaz veya sürekli taramayı etkinleştirmez. Uygulamalar, bağlantı kurmak için Bluetooth veya kablosuz bağlantı API'lerini kullanabilir.
Cihaz eşleştirildikten sonra, uygulama arka planda başlatılırken REQUEST_COMPANION_RUN_IN_BACKGROUND
ve REQUEST_COMPANION_USE_DATA_IN_BACKGROUND
izinleri kullanılabilir. Uygulamalar, arka plandan ön plan hizmeti başlatmak için
REQUEST_COMPANION_START_FOREGROUND_SERVICES_FROM_BACKGROUND
iznini de kullanabilir.
Kullanıcılar listeden bir cihaz seçip uygulamaya cihaza erişim izni verebilir. Uygulamayı kaldırırsanız veya disassociate()
'ı ararsanız bu izinler iptal edilir.
Kullanıcının artık ihtiyacı kalmadığında (ör. oturumu kapattığında veya bağlı cihazları kaldırdığında) kendi ilişkilendirmelerini temizlemekten tamamlayıcı uygulama sorumludur.
Tamamlayıcı cihaz eşlemeyi uygulama
Bu bölümde, uygulamanızı Bluetooth, BLE ve Kablosuz üzerinden yardımcı cihazlarla eşlemek için CompanionDeviceManager
'ı nasıl kullanacağınız açıklanmaktadır.
Tamamlayıcı cihazları belirtme
Aşağıdaki kod örneğinde, manifest dosyasına <uses-feature>
işaretinin nasıl ekleneceği gösterilmektedir. Bu, sisteme uygulamanızın yardımcı cihazlar kurmayı amaçladığını bildirir.
<uses-feature android:name="android.software.companion_device_setup"/>
Cihazları DeviceFilter
kuruluş birimine göre listeleyin.
Sağladığınız DeviceFilter
ile eşleşen tüm kapsam içi yardımcı cihazları gösterebilirsiniz (Şekil 1'de gösterilmiştir). Tarama işlemini yalnızca bir cihazla sınırlamak istiyorsanız setSingleDevice()
simgesine dokunarak true
simgesine (Şekil 2'de gösterilmiştir) geçebilirsiniz.


DeviceFilter
sınıfının AssociationRequest
içinde belirtilebilecek alt sınıfları şunlardır:
Üç alt sınıfın tümünde filtrelerin yapılandırılmasını kolaylaştıran oluşturucular bulunur.
Aşağıdaki örnekte, bir cihaz BluetoothDeviceFilter
ile Bluetooth cihazı tarıyor.
Kotlin
val deviceFilter: BluetoothDeviceFilter = BluetoothDeviceFilter.Builder() // Match only Bluetooth devices whose name matches the pattern. .setNamePattern(Pattern.compile("My device")) // Match only Bluetooth devices whose service UUID matches this pattern. .addServiceUuid(ParcelUuid(UUID(0x123abcL, -1L)), null) .build()
Java
BluetoothDeviceFilter deviceFilter = new BluetoothDeviceFilter.Builder() // Match only Bluetooth devices whose name matches the pattern. .setNamePattern(Pattern.compile("My device")) // Match only Bluetooth devices whose service UUID matches this pattern. .addServiceUuid(new ParcelUuid(new UUID(0x123abcL, -1L)), null) .build();
DeviceFilter
değerini AssociationRequest
olarak ayarlayın. Böylece CompanionDeviceManager
, hangi tür cihazların aranacağını belirleyebilir.
Kotlin
val pairingRequest: AssociationRequest = AssociationRequest.Builder() // Find only devices that match this request filter. .addDeviceFilter(deviceFilter) // Stop scanning as soon as one device matching the filter is found. .setSingleDevice(true) .build()
Java
AssociationRequest pairingRequest = new AssociationRequest.Builder() // Find only devices that match this request filter. .addDeviceFilter(deviceFilter) // Stop scanning as soon as one device matching the filter is found. .setSingleDevice(true) .build();
Uygulamanız bir AssociationRequest
başlattıktan sonra CompanionDeviceManager
üzerinde associate()
işlevini çalıştırın. associate()
işlevi, AssociationRequest
ve Callback
değerlerini alır.
Callback
, CompanionDeviceManager
bir cihazı bulup kullanıcı izni iletişim kutusunu başlatmaya hazır olduğunda onAssociationPending
içinde IntentSender
değerini döndürür.
Kullanıcı cihazı onayladıktan sonra cihazın AssociationInfo
, onAssociationCreated
içinde döndürülür.
Uygulamanız herhangi bir cihaz bulamazsa geri çağırma işlevi, hata mesajıyla birlikte onFailure
değerini döndürür.
Android 13 (API düzeyi 33) ve sonraki sürümlerin yüklü olduğu cihazlarda:
Kotlin
val deviceManager = requireContext().getSystemService(Context.COMPANION_DEVICE_SERVICE) val executor: Executor = Executor { it.run() } deviceManager.associate(pairingRequest, executor, object : CompanionDeviceManager.Callback() { // Called when a device is found. Launch the IntentSender so the user // can select the device they want to pair with. override fun onAssociationPending(intentSender: IntentSender) { intentSender?.let { startIntentSenderForResult(it, SELECT_DEVICE_REQUEST_CODE, null, 0, 0, 0) } } override fun onAssociationCreated(associationInfo: AssociationInfo) { // An association is created. } override fun onFailure(errorMessage: CharSequence?) { // To handle the failure. } })
Java
CompanionDeviceManager deviceManager = (CompanionDeviceManager) getSystemService(Context.COMPANION_DEVICE_SERVICE); Executor executor = new Executor() { @Override public void execute(Runnable runnable) { runnable.run(); } }; deviceManager.associate(pairingRequest, new CompanionDeviceManager.Callback() { executor, // Called when a device is found. Launch the IntentSender so the user can // select the device they want to pair with. @Override public void onDeviceFound(IntentSender chooserLauncher) { try { startIntentSenderForResult( chooserLauncher, SELECT_DEVICE_REQUEST_CODE, null, 0, 0, 0 ); } catch (IntentSender.SendIntentException e) { Log.e("MainActivity", "Failed to send intent"); } } @Override public void onAssociationCreated(AssociationInfo associationInfo) { // An association is created. } @Override public void onFailure(CharSequence errorMessage) { // To handle the failure. });
Android 12L (API düzeyi 32) veya önceki sürümleri çalıştıran cihazlarda (kullanımdan kaldırıldı):
Kotlin
val deviceManager = requireContext().getSystemService(Context.COMPANION_DEVICE_SERVICE) deviceManager.associate(pairingRequest, object : CompanionDeviceManager.Callback() { // Called when a device is found. Launch the IntentSender so the user // can select the device they want to pair with. override fun onDeviceFound(chooserLauncher: IntentSender) { startIntentSenderForResult(chooserLauncher, SELECT_DEVICE_REQUEST_CODE, null, 0, 0, 0) } override fun onFailure(error: CharSequence?) { // To handle the failure. } }, null)
Java
CompanionDeviceManager deviceManager = (CompanionDeviceManager) getSystemService(Context.COMPANION_DEVICE_SERVICE); deviceManager.associate(pairingRequest, new CompanionDeviceManager.Callback() { // Called when a device is found. Launch the IntentSender so the user can // select the device they want to pair with. @Override public void onDeviceFound(IntentSender chooserLauncher) { try { startIntentSenderForResult( chooserLauncher, SELECT_DEVICE_REQUEST_CODE, null, 0, 0, 0 ); } catch (IntentSender.SendIntentException e) { Log.e("MainActivity", "Failed to send intent"); } } @Override public void onFailure(CharSequence error) { // To handle the failure. } }, null);
Kullanıcı seçiminin sonucu, etkinliğinizin onActivityResult()
bölümündeki fragmana geri gönderilir. Ardından seçilen cihaza erişebilirsiniz.
Kullanıcı bir Bluetooth cihazı seçtiğinde BluetoothDevice
beklenir.
Kullanıcı bir Bluetooth LE cihazı seçtiğinde android.bluetooth.le.ScanResult
beklenir.
Kullanıcı bir kablosuz cihaz seçtiğinde android.net.wifi.ScanResult
beklenir.
Kotlin
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { when (requestCode) { SELECT_DEVICE_REQUEST_CODE -> when(resultCode) { Activity.RESULT_OK -> { // The user chose to pair the app with a Bluetooth device. val deviceToPair: BluetoothDevice? = data?.getParcelableExtra(CompanionDeviceManager.EXTRA_DEVICE) deviceToPair?.let { device -> device.createBond() // Continue to interact with the paired device. } } } else -> super.onActivityResult(requestCode, resultCode, data) } }
Java
@Override protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { if (resultCode != Activity.RESULT_OK) { return; } if (requestCode == SELECT_DEVICE_REQUEST_CODE && data != null) { BluetoothDevice deviceToPair = data.getParcelableExtra(CompanionDeviceManager.EXTRA_DEVICE); if (deviceToPair != null) { deviceToPair.createBond(); // Continue to interact with the paired device. } } else { super.onActivityResult(requestCode, resultCode, data); } }
Tam örneği inceleyin:
Android 13 (API düzeyi 33) ve sonraki sürümlerin yüklü olduğu cihazlarda:
Kotlin
private const val SELECT_DEVICE_REQUEST_CODE = 0 class MainActivity : AppCompatActivity() { private val deviceManager: CompanionDeviceManager by lazy { getSystemService(Context.COMPANION_DEVICE_SERVICE) as CompanionDeviceManager } val mBluetoothAdapter: BluetoothAdapter by lazy { val java = BluetoothManager::class.java getSystemService(java)!!.adapter } val executor: Executor = Executor { it.run() } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // To skip filters based on names and supported feature flags (UUIDs), // omit calls to setNamePattern() and addServiceUuid() // respectively, as shown in the following Bluetooth example. val deviceFilter: BluetoothDeviceFilter = BluetoothDeviceFilter.Builder() .setNamePattern(Pattern.compile("My device")) .addServiceUuid(ParcelUuid(UUID(0x123abcL, -1L)), null) .build() // The argument provided in setSingleDevice() determines whether a single // device name or a list of them appears. val pairingRequest: AssociationRequest = AssociationRequest.Builder() .addDeviceFilter(deviceFilter) .setSingleDevice(true) .build() // When the app tries to pair with a Bluetooth device, show the // corresponding dialog box to the user. deviceManager.associate(pairingRequest, executor, object : CompanionDeviceManager.Callback() { // Called when a device is found. Launch the IntentSender so the user // can select the device they want to pair with. override fun onAssociationPending(intentSender: IntentSender) { intentSender?.let { startIntentSenderForResult(it, SELECT_DEVICE_REQUEST_CODE, null, 0, 0, 0) } } override fun onAssociationCreated(associationInfo: AssociationInfo) { // AssociationInfo object is created and get association id and the // macAddress. var associationId: int = associationInfo.id var macAddress: MacAddress = associationInfo.deviceMacAddress } override fun onFailure(errorMessage: CharSequence?) { // Handle the failure. } ) override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { when (requestCode) { SELECT_DEVICE_REQUEST_CODE -> when(resultCode) { Activity.RESULT_OK -> { // The user chose to pair the app with a Bluetooth device. val deviceToPair: BluetoothDevice? = data?.getParcelableExtra(CompanionDeviceManager.EXTRA_DEVICE) deviceToPair?.let { device -> device.createBond() // Maintain continuous interaction with a paired device. } } } else -> super.onActivityResult(requestCode, resultCode, data) } } }
Java
class MainActivityJava extends AppCompatActivity { private static final int SELECT_DEVICE_REQUEST_CODE = 0; Executor executor = new Executor() { @Override public void execute(Runnable runnable) { runnable.run(); } }; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); CompanionDeviceManager deviceManager = (CompanionDeviceManager) getSystemService( Context.COMPANION_DEVICE_SERVICE ); // To skip filtering based on name and supported feature flags, // do not include calls to setNamePattern() and addServiceUuid(), // respectively. This example uses Bluetooth. BluetoothDeviceFilter deviceFilter = new BluetoothDeviceFilter.Builder() .setNamePattern(Pattern.compile("My device")) .addServiceUuid( new ParcelUuid(new UUID(0x123abcL, -1L)), null ) .build(); // The argument provided in setSingleDevice() determines whether a single // device name or a list of device names is presented to the user as // pairing options. AssociationRequest pairingRequest = new AssociationRequest.Builder() .addDeviceFilter(deviceFilter) .setSingleDevice(true) .build(); // When the app tries to pair with the Bluetooth device, show the // appropriate pairing request dialog to the user. deviceManager.associate(pairingRequest, new CompanionDeviceManager.Callback() { executor, // Called when a device is found. Launch the IntentSender so the user can // select the device they want to pair with. @Override public void onDeviceFound(IntentSender chooserLauncher) { try { startIntentSenderForResult( chooserLauncher, SELECT_DEVICE_REQUEST_CODE, null, 0, 0, 0 ); } catch (IntentSender.SendIntentException e) { Log.e("MainActivity", "Failed to send intent"); } } @Override public void onAssociationCreated(AssociationInfo associationInfo) { // AssociationInfo object is created and get association id and the // macAddress. int associationId = associationInfo.getId(); MacAddress macAddress = associationInfo.getDeviceMacAddress(); } @Override public void onFailure(CharSequence errorMessage) { // Handle the failure. }); } @Override protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { if (resultCode != Activity.RESULT_OK) { return; } if (requestCode == SELECT_DEVICE_REQUEST_CODE) { if (resultCode == Activity.RESULT_OK && data != null) { BluetoothDevice deviceToPair = data.getParcelableExtra( CompanionDeviceManager.EXTRA_DEVICE ); if (deviceToPair != null) { deviceToPair.createBond(); // ... Continue interacting with the paired device. } } } else { super.onActivityResult(requestCode, resultCode, data); } } }
Android 12L (API düzeyi 32) veya önceki sürümleri çalıştıran cihazlarda (kullanımdan kaldırıldı):
Kotlin
private const val SELECT_DEVICE_REQUEST_CODE = 0 class MainActivity : AppCompatActivity() { private val deviceManager: CompanionDeviceManager by lazy { getSystemService(Context.COMPANION_DEVICE_SERVICE) as CompanionDeviceManager } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // To skip filters based on names and supported feature flags (UUIDs), // omit calls to setNamePattern() and addServiceUuid() // respectively, as shown in the following Bluetooth example. val deviceFilter: BluetoothDeviceFilter = BluetoothDeviceFilter.Builder() .setNamePattern(Pattern.compile("My device")) .addServiceUuid(ParcelUuid(UUID(0x123abcL, -1L)), null) .build() // The argument provided in setSingleDevice() determines whether a single // device name or a list of them appears. val pairingRequest: AssociationRequest = AssociationRequest.Builder() .addDeviceFilter(deviceFilter) .setSingleDevice(true) .build() // When the app tries to pair with a Bluetooth device, show the // corresponding dialog box to the user. deviceManager.associate(pairingRequest, object : CompanionDeviceManager.Callback() { override fun onDeviceFound(chooserLauncher: IntentSender) { startIntentSenderForResult(chooserLauncher, SELECT_DEVICE_REQUEST_CODE, null, 0, 0, 0) } override fun onFailure(error: CharSequence?) { // Handle the failure. } }, null) } override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { when (requestCode) { SELECT_DEVICE_REQUEST_CODE -> when(resultCode) { Activity.RESULT_OK -> { // The user chose to pair the app with a Bluetooth device. val deviceToPair: BluetoothDevice? = data?.getParcelableExtra(CompanionDeviceManager.EXTRA_DEVICE) deviceToPair?.let { device -> device.createBond() // Maintain continuous interaction with a paired device. } } } else -> super.onActivityResult(requestCode, resultCode, data) } } }
Java
class MainActivityJava extends AppCompatActivity { private static final int SELECT_DEVICE_REQUEST_CODE = 0; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); CompanionDeviceManager deviceManager = (CompanionDeviceManager) getSystemService( Context.COMPANION_DEVICE_SERVICE ); // To skip filtering based on name and supported feature flags, // don't include calls to setNamePattern() and addServiceUuid(), // respectively. This example uses Bluetooth. BluetoothDeviceFilter deviceFilter = new BluetoothDeviceFilter.Builder() .setNamePattern(Pattern.compile("My device")) .addServiceUuid( new ParcelUuid(new UUID(0x123abcL, -1L)), null ) .build(); // The argument provided in setSingleDevice() determines whether a single // device name or a list of device names is presented to the user as // pairing options. AssociationRequest pairingRequest = new AssociationRequest.Builder() .addDeviceFilter(deviceFilter) .setSingleDevice(true) .build(); // When the app tries to pair with the Bluetooth device, show the // appropriate pairing request dialog to the user. deviceManager.associate(pairingRequest, new CompanionDeviceManager.Callback() { @Override public void onDeviceFound(IntentSender chooserLauncher) { try { startIntentSenderForResult(chooserLauncher, SELECT_DEVICE_REQUEST_CODE, null, 0, 0, 0); } catch (IntentSender.SendIntentException e) { // failed to send the intent } } @Override public void onFailure(CharSequence error) { // handle failure to find the companion device } }, null); } @Override protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { if (requestCode == SELECT_DEVICE_REQUEST_CODE) { if (resultCode == Activity.RESULT_OK && data != null) { BluetoothDevice deviceToPair = data.getParcelableExtra( CompanionDeviceManager.EXTRA_DEVICE ); if (deviceToPair != null) { deviceToPair.createBond(); // ... Continue interacting with the paired device. } } } else { super.onActivityResult(requestCode, resultCode, data); } } }
Yardımcı cihaz profilleri
Android 12 (API düzeyi 31) ve sonraki sürümlerde, kol saatleri gibi cihazları yöneten yardımcı uygulamalar, eşleme sırasında gerekli izinleri vererek kurulum sürecini kolaylaştırmak için yardımcı cihaz profillerini kullanabilir. Daha fazla bilgi için Yardımcı Cihaz Profilleri başlıklı makaleyi inceleyin.
Tamamlayıcı uygulamaları uyanık tutma
Android 16'dan (API düzeyi 36) itibaren:
CompanionDeviceManager.startObservingDevicePresence(String)
ve
CompanionDeviceService.onDeviceAppeared()
desteği sonlandırıldı.
Uyguladığınız
CompanionDeviceService
bağlamasını otomatik olarak yönetmek içinCompanionDeviceManager.startObservingDevicePresence (ObservingDevicePresenceRequest)
kullanmalısınız.CompanionDeviceService
cihazınızın bağlama durumu, ilişkili tamamlayıcı cihazın varlık durumuna göre otomatik olarak yönetilir:- Hizmet, yardımcı cihaz BLE kapsama alanı içindeyken veya Bluetooth kullanılarak bağlandığında etkinleştirilir.
- Yardımcı cihaz BLE menzilinin dışına çıktığında veya Bluetooth bağlantısı sonlandırıldığında hizmetin bağlantısı kaldırılır.
Uygulama, çeşitli
DevicePresenceEvent
'lere göre geri arama alır.Ayrıntılı bilgi için
CompanionDeviceService.onDeviceEvent()
başlıklı makaleyi inceleyin.