Статьи

Передача данных через Bluetooth с Android

Чтобы разработать приложение для 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 , пользователю предоставляется следующий включающий диалог:

blu2

Теперь, когда действие заканчивается, оно возвращает код запроса, который мы отправили (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-processflow

Мы уже закончили? Почти. И последнее, но не менее важное: нам нужно запросить разрешения BT в манифесте Android:

1
2
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />

Мы готовы развернуть сейчас. Чтобы проверить все это, нам нужно использовать как минимум два устройства Android, одно из которых является отправителем файла (где установлено наше приложение), а другое — любым принимающим устройством, поддерживающим BT. Вот скриншоты. Для отправителя:

посыла shots1

И соответствующее приемное устройство:

RECV-shots2
Обратите внимание, что как только получатель примет соединение. полученный файл ( kmemo.dat ) сохраняется в папке BT на SD-карте. Вся передача данных нижнего уровня была обработана ОС Android.

Ссылка: Bluetooth Data Transfer с Android от нашего партнера JCG Тони Сицилиана в блоге Tony’s Blog .