Чтобы разработать приложение для Android, использующее передачу данных через Bluetooth (BT), можно логически начать со страницы Bluetooth разработчика Android, где подробно описаны все необходимые шаги: обнаружение устройства, сопряжение, сокеты клиент / сервер, каналы RFCOMM, и т.п.
Но прежде чем переходить к программированию сокетов и потоков только для выполнения базовой операции BT, давайте рассмотрим более простую альтернативу, основанную на одной из самых важных функций Android: возможность для одного приложения отправлять пользователя другому, что в данном случае , будет приложение BT устройства по умолчанию. При этом сама ОС Android сделает всю работу на низком уровне за нас.
Перво-наперво, немного защитного программирования:
01
02
03
04
05
06
07
08
09
10
|
import android.bluetooth.BluetoothAdapter; //... // inside method // Check if bluetooth is supported BluetoothAdapter btAdapter = BluetoothAdapter.getDefaultAdapter(); if (btAdapter == null ) { // Device does not support Bluetooth // Inform user that we're done. } |
Выше приведена первая проверка, которую нам нужно выполнить. Сделав это, давайте посмотрим, как он может запустить BT из нашего собственного приложения.
В предыдущем посте о программировании SMS мы говорили о неявных намерениях , которые в основном позволяют нам указать действие, которое мы хотели бы, чтобы система выполняла для нас. Android отобразит все действия, которые могут выполнить требуемое действие, в списке выбора . Вот пример:
1
2
3
4
5
6
7
|
// bring up Android chooser Intent intent = new Intent(); intent.setAction(Intent.ACTION_SEND); intent.setType( "text/plain" ); intent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(file_to_transfer) ); //... startActivity(intent); |
В приведенном выше фрагменте кода мы сообщаем системе Android, что намереваемся отправить текстовый файл. Затем система отображает все установленные приложения, способные выполнить это действие:
Мы видим, что приложение BT входит в число этих обработчиков. Конечно, мы можем позволить пользователю выбрать это приложение из списка и покончить с ним. Но если мы чувствуем, что должны быть немного более удобными для пользователя, нам нужно пойти дальше и запустить приложение самостоятельно, а не просто отображать его в окружении других ненужных опций … Но как?
Один из способов сделать это — использовать PackageManager для Android следующим образом:
1
2
3
4
5
6
7
|
//list of apps that can handle our intent PackageManager pm = getPackageManager(); List appsList = pm.queryIntentActivities( intent, 0 ); if (appsList.size() > 0 { // proceed } |
Приведенный выше метод PackageManager возвращает список всех ранее обнаруженных нами действий, которые могут обрабатывать наше намерение передачи файла, в виде списка объектов ResolveInfo, которые инкапсулируют необходимую нам информацию:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
|
//select bluetooth String packageName = null ; String className = null ; boolean found = false ; for (ResolveInfo info: appsList){ packageName = info.activityInfo.packageName; if ( packageName.equals( "com.android.bluetooth" )){ className = info.activityInfo.name; found = true ; break ; // found } } if (! found){ Toast.makeText( this , R.string.blu_notfound_inlist, Toast.LENGTH_SHORT).show(); // exit } |
Теперь у нас есть необходимая информация для запуска BT:
1
2
3
|
//set our intent to launch Bluetooth intent.setClassName(packageName, className); startActivity(intent); |
Мы использовали пакет и соответствующий ему класс, полученный ранее. Поскольку мы любопытная группа, мы можем задаться вопросом, как называется класс для пакета «com.android.bluetooth». Вот что мы получили бы, если бы распечатали: com.broadcom.bt.app.opp.OppLauncherActivity OPP означает Object Push Profile и является компонентом Android, позволяющим обмениваться файлами по беспроводной сети.
Все в порядке, но для того, чтобы весь приведенный выше код был полезен, BT не просто должен поддерживаться устройством, но и включаться пользователем. Поэтому первое, что мы хотим сделать, это попросить пользователя включить BT на время, которое мы считаем необходимым (здесь, 300 секунд):
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
|
import android.bluetooth.BluetoothAdapter; //... // duration that the device is discoverable private static final int DISCOVER_DURATION = 300 ; // our request code (must be greater than zero) private static final int REQUEST_BLU = 1 ; //... public void enableBlu(){ // enable device discovery - this will automatically enable Bluetooth Intent discoveryIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE); discoveryIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, DISCOVER_DURATION ); startActivityForResult(discoveryIntent, REQUEST_BLU); } |
Как только мы укажем, что хотим получить результат от нашей деятельности с помощью startActivityForResult , пользователю предоставляется следующий включающий диалог:
Теперь, когда действие заканчивается, оно возвращает код запроса, который мы отправили (REQUEST_BLU), вместе с данными и кодом результата нашей основной деятельности через метод обратного вызова onActivityResult . Мы знаем, какой код запроса мы должны проверить, но как насчет кода результата ? Просто: если пользователь отвечает «Нет» на вышеуказанный запрос на разрешение (или если возникает ошибка), код результата будет RESULT_CANCELED. С другой стороны, если пользователь принимает, в документации BT указывается, что код результата будет равен продолжительности обнаружения устройства (т. Е. DISCOVER_DURATION, т. Е. 300).
Таким образом, способ обработки диалогового окна BT выше будет:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
|
// When startActivityForResult completes... protected void onActivityResult ( int requestCode, int resultCode, Intent data) { if (resultCode == DISCOVER_DURATION && requestCode == REQUEST_BLU) { // processing code goes here } else { // cancelled or error Toast.makeText( this , R.string.blu_cancelled, Toast.LENGTH_SHORT).show(); } } Putting all our processing flow in order, here’s what we are basically doing: |
Мы уже закончили? Почти. И последнее, но не менее важное: нам нужно запросить разрешения BT в манифесте Android:
1
2
|
< uses-permission android:name = "android.permission.BLUETOOTH" /> < uses-permission android:name = "android.permission.BLUETOOTH_ADMIN" /> |
Мы готовы развернуть сейчас. Чтобы проверить все это, нам нужно использовать как минимум два устройства Android, одно из которых является отправителем файла (где установлено наше приложение), а другое — любым принимающим устройством, поддерживающим BT. Вот скриншоты. Для отправителя:
И соответствующее приемное устройство:
Обратите внимание, что как только получатель примет соединение. полученный файл ( kmemo.dat ) сохраняется в папке BT на SD-карте. Вся передача данных нижнего уровня была обработана ОС Android.