Android 8.0 (API seviyesi 26) ve sonraki sürümleri çalıştıran cihazlarda, tamamlayıcı cihaz eşleme, ACCESS_FINE_LOCATION
izni gerektirmeden uygulamanız adına yakındaki cihazların Bluetooth veya kablosuz tarama işlemini gerçekleştirir. Bu, kullanıcı gizliliği korumalarını en üst düzeye çıkarmaya yardımcı olur. BLE özellikli akıllı saat gibi tamamlayıcı cihazın ilk yapılandırmasını yapmak için bu yöntemi kullanın. Ayrıca, tamamlayıcı cihaz eşlemesi için Konum Hizmetleri'nin etkinleştirilmesi gerekir.
Tamamlayıcı cihaz eşleme, 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.
Eşlendikten sonra cihaz, uygulamayı arka plandan başlatmak için REQUEST_COMPANION_RUN_IN_BACKGROUND
ve REQUEST_COMPANION_USE_DATA_IN_BACKGROUND
izinlerini kullanabilir. Uygulamalar, arka plandan ön plan hizmeti başlatmak için REQUEST_COMPANION_START_FOREGROUND_SERVICES_FROM_BACKGROUND
iznine de başvurabilir.
Kullanıcılar listeden bir cihaz seçip uygulamaya cihaza erişme izni verebilir. Uygulamayı kaldırırsanız veya disassociate()
'i ararsanız bu izinler iptal edilir.
Kullanıcı artık bu ilişkilendirmelere ihtiyaç duymadığında (ör. oturumu kapattığında veya bağlı cihazları kaldırdığında) tamamlayıcı uygulama, kendi ilişkilendirmelerini temizlemekten sorumludur.
Tamamlayıcı cihaz eşlemeyi uygulama
Bu bölümde, uygulamanızı Bluetooth, BLE ve kablosuz bağlantı üzerinden tamamlayıcı cihazlarla eşlemek için CompanionDeviceManager
'yi nasıl kullanacağınız açıklanmaktadır.
Tamamlayıcı cihazları belirtme
Aşağıdaki kod örneğinde, <uses-feature>
işaretinin manifest dosyasına nasıl ekleneceği gösterilmektedir. Bu, uygulamanızın tamamlayıcı cihazlar kurmayı amaçladığını sisteme bildirir.
<uses-feature android:name="android.software.companion_device_setup"/>
Cihazları DeviceFilter
'e göre listeleme
Sağladığınız DeviceFilter
ile eşleşen tüm menzil içi tamamlayıcı cihazları görüntüleyebilirsiniz (Şekil 1'de gösterilmiştir). Taramayı yalnızca bir cihazla sınırlamak istiyorsanız setSingleDevice()
true
olarak ayarlayabilirsiniz (Şekil 2'de gösterilmiştir).
AssociationRequest
içinde belirtilebilecek DeviceFilter
alt sınıfları şunlardır:
Üç alt sınıfın da filtrelerin yapılandırmasını kolaylaştıran oluşturucuları vardır.
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();
CompanionDeviceManager
'ın hangi tür cihazları arayacağını belirlemesi için bir DeviceFilter
'yi AssociationRequest
olarak ayarlayın.
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 bir AssociationRequest
ve bir Callback
alır.
CompanionDeviceManager
bir cihazı bulup kullanıcı izni iletişim kutusunu başlatmaya hazır olduğunda Callback
, onAssociationPending
içinde bir IntentSender
döndürür.
Kullanıcı cihazı onayladıktan sonra onAssociationCreated
içinde cihazın AssociationInfo
döndürülür.
Uygulamanız herhangi bir cihaz bulamazsa geri çağırma işlevi, bir hata mesajıyla birlikte onFailure
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 (desteği sonlandı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 parçaya geri gönderilir. Ardından, seçilen cihaza erişebilirsiniz.
Kullanıcı bir Bluetooth cihazı seçtiğinde BluetoothDevice
gösterilir.
Kullanıcı bir Bluetooth LE cihazı seçtiğinde android.bluetooth.le.ScanResult
gösterilir.
Kullanıcı bir kablosuz cihaz seçtiğinde android.net.wifi.ScanResult
gösterilir.
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); } }
Örneğin tamamını 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 (desteği sonlandı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); } } }
Tamamlayıcı cihaz profilleri
Android 12 (API düzeyi 31) ve sonraki sürümlerde, kol saati gibi cihazları yöneten tamamlayıcı uygulamalar, eşleme sırasında gerekli izinleri vererek kurulum sürecini kolaylaştırmak için tamamlayıcı cihaz profillerini kullanabilir. Daha fazla bilgi için Eşlik Eden Cihaz Profilleri başlıklı makaleyi inceleyin.
Tamamlayıcı uygulamaları uyanık tutma
Android 12 (API düzeyi 31) ve sonraki sürümlerde, tamamlayıcı cihaz menzil içindeyken tamamlayıcı uygulamanızın çalışmaya devam etmesine yardımcı olmak için ek API'ler kullanabilirsiniz. Bu API'ler şunları yapmanıza olanak tanır:
Bir tamamlayıcı cihaz kapsama alanındayken uygulamanızı uyandırın.
Ayrıntılı bilgi için
CompanionDeviceManager.startObservingDevicePresence()
başlıklı makaleyi inceleyin.Arkadaş cihaz kapsama alanında kaldığı sürece bir uygulama sürecinin çalışmaya devam etmesini garanti eder.
Ayrıntılı bilgi için
CompanionDeviceService.onDeviceAppeared()
başlıklı makaleyi inceleyin.