Android 8.0 (API düzeyi 26) ve sonraki sürümleri çalıştıran cihazlarda, tamamlayıcı cihaz eşleme işlevi ACCESS_FINE_LOCATION
izni gerekmeksizin 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. Eşlenen cihaz, uygulamayı arka planda başlatmak için REQUEST_COMPANION_RUN_IN_BACKGROUND
ve REQUEST_COMPANION_USE_DATA_IN_BACKGROUND
izinlerinden yararlanabilir. BLE özellikli bir akıllı saat gibi tamamlayıcı cihazın ilk yapılandırmasını gerçekleştirmek için bu yöntemi kullanın. Ayrıca, tamamlayıcı cihaz eşleme için Konum Hizmetleri'nin etkinleştirilmesi gerekir.
Tamamlayıcı cihaz eşleme kendi başına bağlantı oluşturmaz. Bluetooth ve kablosuz bağlantı API'leri bağlantı kurar. Tamamlayıcı cihaz eşleme özelliği de sürekli taramayı etkinleştirmez.
Kullanıcı listeden bir cihaz seçebilir ve uygulamaya erişmesi için izin verebilir.
Uygulamayı kaldırırsanız veya disassociate()
numaralı telefonu ararsanız bu izinler iptal edilir.
Kullanıcının artık ihtiyaç duymadığı durumlarda (örneğin, oturumu kapattığında veya bağlı cihazları kaldırdığında) kendi ilişkilendirmelerini temizlemek bir uygulamadır.
Tamamlayıcı cihaz eşlemesini uygulayın
Tamamlayıcı bir cihazla bağlantı kurup yönetmek için şunu kullanın: CompanionDeviceManager
.
Bu bölümde, uygulamanızı Bluetooth, BLE ve kablosuz ağ üzerinden tamamlayıcı cihazlarla eşlediğinizde eşleme isteği iletişim kutunuzu nasıl özelleştireceğiniz açıklanmaktadır.
Tamamlayıcı cihazları belirtin
Aşağıdaki kod örneğinde, <uses-feature>
işaretinin manifest dosyasına nasıl ekleneceği gösterilmektedir. Bu, sisteme uygulamanızın tamamlayıcı cihazlar kurmayı amaçladığını bildirir.
<uses-feature android:name="android.software.companion_device_setup"/>
Cihazları türe göre listeleme
Sağladığınız filtreyle eşleşen tüm olası tamamlayıcı cihazları görüntüleyebilir veya görüntülemeyi tek bir seçenekle sınırlandırabilirsiniz (Şekil 1'de gösterilmiştir). Uygulamanızın ne tür cihazlar aradığını belirten bir filtre oluşturarak veya setSingleDevice()
özelliğini true
olarak ayarlayarak (Şekil 2'de gösterilmiştir) bunu yapılandırabilirsiniz.
İstek iletişim kutunuzda gösterilen tamamlayıcı cihazların listesine filtre uygulamak için Bluetooth'un açık olup olmadığını veya kablosuz bağlantının açık olup olmadığını kontrol edin.
Bağlantı etkinleştirildikten sonra DeviceFilter
ekleyebilirsiniz. Aşağıdaki DeviceFilter
alt sınıfları, uygulamanızın bir bağlantı türüne göre ilişkilendirebileceği cihaz türlerini belirtir:
Üç alt sınıfın tümü, filtrelerin yapılandırmasını kolaylaştıran oluşturuculara sahiptir.
Aşağıdaki örnekte, bir cihaz BluetoothDeviceFilter
özelliğine sahip bir Bluetooth cihazı tarar.
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();
Cihaz yöneticisinin ne tür bir cihaz aranacağını belirleyebilmesi için DeviceFilter
değerini 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();
Bir AssociationRequest
başlattıktan sonra CompanionDeviceManager
üzerinde associate()
işlevini çalıştırın. associate()
işlevi, eşleme isteği nesnesini ve geri çağırmayı üstlenir. Geri çağırma işlevleri, bir uygulamanın bir cihazı bulduğunda ve kullanıcının seçimini girmesi için bir iletişim kutusu başlatmaya hazır olduğunda bunu belirtir.
Bir uygulama herhangi bir cihaz bulamazsa geri arama bir hata mesajı döndürür.
Android 13 (API düzeyi 33) ve sonraki sürümleri çalıştıran 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) { // The association is created. } override fun onFailure(errorMessage: CharSequence?) { // 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) { // The association is created. } @Override public void onFailure(CharSequence errorMessage) { // Handle the failure. });
Android 12L (API düzeyi 32) ve önceki sürümleri (kullanımdan kaldırıldı) çalıştıran cihazlarda:
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?) { // 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) { // Handle the failure. } }, null);
Kullanıcıların, bağlanmak istedikleri cihaz türlerini seçmelerine olanak tanımak için onAssociationPending()
işlevinde intentSender
parametresiyle bir tercih etkinliği başlatın. Bu işlemin sonuçları, tercihler etkinliğinizin onActivityResult()
işlevindeki parçaya geri gönderilir. Bu, kullanıcı sonuca göre bir seçim yaptığında sizi bilgilendirir. Ardından, seçilen cihaza erişebilirsiniz. Kullanıcı bir Bluetooth cihazı seçtiğinde gönderilen sonuç bir BluetoothDevice
nesnesi olur.
Benzer şekilde, onAssociationPending()
işlevi kullanıcının bir Bluetooth LE cihaz seçtiğini algıladığında bir android.bluetooth.le.ScanResult
nesnesi görüntülenir. Kablosuz cihazlar için bir android.net.wifi.ScanResult
nesnesi görürsünüz.
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); } }
Tamamlayıcı cihaz eşlemesini, cihazları belirtebilen ve türe göre listeleyebilen filtrelerle uygulamak için aşağıdaki örnekleri inceleyin:
Android 13 (API düzeyi 33) ve sonraki sürümleri çalıştıran 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) ve önceki sürümleri (kullanımdan kaldırıldı) çalıştıran 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 } 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ümlerdeki iş ortağı uygulamaları, bir saate bağlanırken tamamlayıcı cihaz profillerini kullanabilir. Daha fazla bilgi için Wear OS'te izin isteme rehberine bakın.
Tamamlayıcı uygulamaları uyanık tutun
Android 12 (API düzeyi 31) ve sonraki sürümlerde, tamamlayıcı cihaz kapsama alanındayken tamamlayıcı uygulamanızın çalışmaya devam etmesine yardımcı olan ek API'ler kullanabilirsiniz. Bu API'ler aşağıdakileri yapmanıza imkan tanır:
Kapsama alanında bir tamamlayıcı cihaz olduğunda uygulamanızı uyandırın.
Ayrıntılı bilgi için
CompanionDeviceManager.startObservingDevicePresence()
adresini inceleyin.Bir uygulama işleminin, tamamlayıcı cihaz kapsama alanında kaldığı sürece çalışmaya devam edeceğini garanti eder.
Ayrıntılı bilgi için
CompanionDeviceService.onDeviceAppeared()
adresini inceleyin.