Первое, что пользователи захотят сделать с новым умным домашним устройством, — это подключить его к своей беспроводной сети. На многих устройствах IoT отсутствует экран или клавиатура, поэтому один из способов сделать это — дать пользователям возможность подключить смартфон к устройству, чтобы они могли контролировать и настраивать устройство. Так работают Nest и Google Home, в том числе API-интерфейс Nearby Connections 2.0.
В этой статье вы познакомитесь с API-интерфейсом Nearby Connections 2.0 и узнаете, как его можно использовать для сопряжения смартфона Android с устройством Android Things, чтобы предоставить своим пользователям опыт сопутствующего устройства.
Что такое API ближайших соединений?
API соседних подключений позволяет двум устройствам связываться друг с другом напрямую через Bluetooth или по беспроводной сети без использования централизованной точки доступа. Устройство может выполнять две роли: рекламодатель , который сообщает другим устройствам, что оно доступно для подключения, и обнаружитель , который пытается найти рекламодателей и подключиться к ним. Как только набор устройств (также известный как «конечные точки» на этом этапе) соединяются вместе, они могут отправлять данные в любую другую конечную точку в сети Nearby Connections.
Существует две стратегии, которые API-интерфейс Nearby Connections может использовать для соединения устройств друг с другом. Первый, P2P_STAR , самый простой для работы. Он состоит из одного рекламодателя, который может поддерживать несколько открывателей, подключающихся к нему. Второй, P2P_CLUSTER , позволяет любому количеству устройств подключаться и принимать подключения от любого другого количества устройств. Это создает ячеистую сеть с менее централизованной точкой отказа, хотя она также требует большей пропускной способности. Эта стратегия идеально подходит для небольших полезных нагрузок, которым не нужно проходить через центральное устройство, например, для игр.
В этом руководстве основное внимание будет уделено использованию более простой стратегии «звезда» для подключения устройства IoT в качестве рекламодателя и использованию смартфона пользователя в качестве первооткрывателя. Однако к концу у вас также должно быть достаточно информации для реализации кластерной стратегии.
Давайте настроимся!
Для этого урока будет два модуля: мобильное приложение и приложение Android Things. После того, как вы создали их в Android Studio, вам нужно будет включить зависимость служб Google Play для ближайших подключений в файл build.gradle уровня модуля для обоих приложений.
1
|
compile ‘com.google.android.gms:play-services-nearby:11.6.2’
|
После того, как вы запустите синхронизацию, откройте файлы AndroidManifest.xml для обоих модулей и включите следующие разрешения в узлы application
.
01
02
03
04
05
06
07
08
09
10
|
<uses-permission
android:name=»android.permission.BLUETOOTH»/>
<uses-permission
android:name=»android.permission.BLUETOOTH_ADMIN»/>
<uses-permission
android:name=»android.permission.ACCESS_WIFI_STATE» />
<uses-permission
android:name=»android.permission.CHANGE_WIFI_STATE» />
<uses-permission
android:name=»android.permission.ACCESS_COARSE_LOCATION» />
|
Устройствам Android Things будут предоставлены эти разрешения устройству после перезагрузки, хотя вам потребуется запросить разрешение на местоположение у пользователей в приложении для телефона.
Класс MainActivity
в вещах и мобильных модулях должен будет реализовывать интерфейсы, используемые для обратных вызовов служб Google Play, например:
01
02
03
04
05
06
07
08
09
10
11
|
public class MainActivity extends FragmentActivity implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener {
@Override
public void onConnected(@Nullable Bundle bundle) {}
@Override
public void onConnectionSuspended(int i) {}
@Override
public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {}
}
|
После того, как вы подтвердите, что у пользователя есть соответствующие разрешения для onCreate()
местоположения в onCreate()
, вы можете начать подключаться к сервисам Google Play, чтобы использовать API onCreate()
подключений.
1
2
3
4
5
|
mGoogleApiClient = new GoogleApiClient
.Builder(this, this, this)
.addApi(Nearby.CONNECTIONS_API)
.enableAutoManage(this, this)
.build();
|
Когда GoogleApiClient
завершит подключение, будет вызван метод onConnected()
. Здесь вы начнете процесс рекламы или поиска для вашего устройства. Кроме того, обоим приложениям потребуется идентификатор службы, который является уникальным идентификатором String
.
1
|
private static final String SERVICE_ID = «UNIQUE_SERVICE_ID»;
|
Реклама на близлежащих соединениях
При работе с API-интерфейсом Nearby Connections вам потребуется создать ConnectionLifecycleCallback
, который, как следует из названия, будет запускаться при различных событиях жизненного цикла соединения. Для этой демонстрации мы будем использовать только метод onConnectionInitiated()
. Он сохранит ссылку на первую конечную точку, которая пытается подключиться к ней, примет подключение и затем прекратит рекламу. Если соединение не установлено, приложение может перезапустить рекламу.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
private final ConnectionLifecycleCallback mConnectionLifecycleCallback =
new ConnectionLifecycleCallback() {
@Override
public void onConnectionInitiated(String endpointId, ConnectionInfo connectionInfo) {
endpoint = endpointId;
Nearby.Connections.acceptConnection(mGoogleApiClient, endpointId, mPayloadCallback)
.setResultCallback(new ResultCallback<com.google.android.gms.common.api.Status>() {
@Override
public void onResult(@NonNull com.google.android.gms.common.api.Status status) {
if( status.isSuccess() ) {
//Connection accepted
}
}
});
Nearby.Connections.stopAdvertising(mGoogleApiClient);
}
@Override
public void onConnectionResult(String endpointId, ConnectionResolution result) {}
@Override
public void onDisconnected(String endpointId) {}
};
|
Возможно, вы заметили, что вышеуказанный метод также ссылается на объект PayloadCallback
. У этого объекта есть методы, которые вызываются, когда полезная информация отправляется от рекламодателя конечной точке, а также когда данные принимаются от конечной точки. Метод onPayloadReceived()
предназначен для обработки любых данных, отправляемых на наше устройство Android Things. Этот метод содержит объект Payload
который можно превратить в массив байтов, и String
представляющую адрес конечной точки отправляющего устройства.
1
2
3
4
5
6
7
8
9
|
private PayloadCallback mPayloadCallback = new PayloadCallback() {
@Override
public void onPayloadReceived(String endpoint, Payload payload) {
Log.e(«Tuts+», new String(payload.asBytes()));
}
@Override
public void onPayloadTransferUpdate(String endpoint, PayloadTransferUpdate payloadTransferUpdate) {}
};
|
На этом этапе вы можете начать рекламу на своем IoT-устройстве следующим способом:
1
2
3
4
5
6
|
Nearby.Connections.startAdvertising(
mGoogleApiClient,
«Device Name»,
SERVICE_ID,
mConnectionLifecycleCallback,
new AdvertisingOptions(Strategy.P2P_STAR));
|
Вы можете заметить, что именно здесь мы применяем стратегию P2P_STAR к нашей сети Nearby Connections.
Если вы хотите отправить полезную нагрузку на другое устройство, вы можете использовать метод Nearby.Connections.sendPayload()
со ссылкой на клиент API Google, именем вашей конечной точки и байтовым массивом данных, которые вы хотите отправить.
1
|
Nearby.Connections.sendPayload(mGoogleApiClient, endpoint, Payload.fromBytes(«Message».getBytes()));
|
Совет: включите WiFi при перезагрузке
Один прием, который я нашел полезным при работе с API-интерфейсом Nearby Connections на устройстве Android Things, заключается в повторном включении WiFi при перезагрузке, поскольку устройство может в конечном итоге отключить беспроводную связь, если устройство выключено или теряет питание во время рекламы. Вы можете сделать это, WifiManager
системную службу setWifiEnabled()
и вызвав setWifiEnabled()
.
1
2
|
wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
wifiManager.setWifiEnabled(true);
|
Обнаружение устройств с соседними подключениями
Обнаружение устройства следует в основном аналогично рекламе. Устройство подключится к клиенту Google API и начнет обнаружение. Когда рекламодатель найден, обнаружитель запросит подключение к рекламодателю. Если рекламодатель одобрит запрос, оба устройства подключатся и смогут отправлять полезные данные туда и обратно. Обнаружитель будет использовать PayloadCallback
же, как рекламодатель.
1
2
3
4
5
6
7
8
9
|
private PayloadCallback mPayloadCallback = new PayloadCallback() {
@Override
public void onPayloadReceived(String s, Payload payload) {
Log.e(«Tuts+», new String(payload.asBytes()));
}
@Override
public void onPayloadTransferUpdate(String s, PayloadTransferUpdate payloadTransferUpdate) {}
};
|
ConnectionLifecycleCallback
открывателя (мобильного приложения) также будет выглядеть аналогично рекламодателю:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
|
private final ConnectionLifecycleCallback mConnectionLifecycleCallback =
new ConnectionLifecycleCallback() {
@Override
public void onConnectionInitiated(String endpointId, ConnectionInfo connectionInfo) {
Nearby.Connections.acceptConnection(mGoogleApiClient, endpointId, mPayloadCallback);
mEndpoint = endpointId;
Nearby.Connections.stopDiscovery(mGoogleApiClient);
}
@Override
public void onConnectionResult(String endpointId, ConnectionResolution result) {}
@Override
public void onDisconnected(String endpointId) {}
};
|
Отличие заключается в том, что обнаружителям потребуется EndpointDiscoveryCallback
который будет использоваться, когда рекламодатель найден, но еще не подключен к нему. Этот объект инициирует запрос на подключение к рекламодателю.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
|
private final EndpointDiscoveryCallback mEndpointDiscoveryCallback =
new EndpointDiscoveryCallback() {
@Override
public void onEndpointFound(
String endpointId, DiscoveredEndpointInfo discoveredEndpointInfo) {
if( discoveredEndpointInfo.getServiceId().equalsIgnoreCase(SERVICE_ID)) {
Nearby.Connections.requestConnection(
mGoogleApiClient,
«Name»,
endpointId,
mConnectionLifecycleCallback);
}
}
@Override
public void onEndpointLost(String endpointId) {
Log.e(«Tuts+», «Disconnected»);
}
};
|
После того как ваш обнаружитель подключится к Сервисам Google Play, вы можете запустить обнаружение с помощью следующей команды:
1
2
3
4
5
|
Nearby.Connections.startDiscovery(
mGoogleApiClient,
SERVICE_ID,
mEndpointDiscoveryCallback,
new DiscoveryOptions(Strategy.P2P_STAR));
|
Наконец, когда вы хотите отключиться от рекламодателя, вы можете использовать метод disconnectFromEndpoint()
из API ближайших подключений. Как правило, это хорошая идея сделать это в onDestroy()
вашего Activity
.
1
|
Nearby.Connections.disconnectFromEndpoint(mGoogleApiClient, mEndpoint);
|
Вывод
В этой статье вы узнали об API Nearby Connections 2.0 для Android в контексте создания сопутствующего приложения для устройства Android Things IoT.
Стоит отметить, что этот API можно использовать для любых устройств Android, которые вы хотели бы объединить в сеть, от телефонов и планшетов до коробок Android TV и умных часов Android Wear. API предоставляет простой способ подключения и связи без использования Интернета или централизованного маршрутизатора и добавляет отличную утилиту для вашей коллекции инструментов для разработки под Android.
Пока вы здесь, ознакомьтесь с некоторыми другими нашими статьями по разработке Android Things IoT!