用户希望使用新的智能家居设备进行操作的第一件事就是将其连接到无线网络。 许多物联网设备缺少屏幕或键盘,因此一种实现方法是允许用户将智能手机与设备配对,以便他们可以控制和配置设备。 这样,Nest和Google Home便可以工作,而Nearest Connections 2.0 API使其成为可能。
在本文中,您将获得有关Nearest Connections 2.0 API的介绍,以及如何将其用于将Android智能手机与Android Things设备配对,从而为用户提供伴随的设备体验。
什么是“附近的连接” API?
附近的连接API允许两个设备直接通过蓝牙或无线方式彼此通信,而无需使用集中式访问点。 设备可能会扮演两个角色: advertiser (使其他设备知道可以连接到该设备)和Discoverer (尝试寻找并与他们建立联系)。 一旦一组设备(在此阶段也称为“端点”)连接在一起,它们便可以将数据发送到“附近的连接”网络上的任何其他端点。
“附近的连接” API可使用两种策略将设备连接在一起。 第一个P2P_STAR是最简单的处理方法。 它由一个广告商组成,可以支持与其连接的多个发现者。 第二个P2P_CLUSTER允许任何数量的设备连接到任何其他数量的设备并接受来自这些设备的连接。 这创建了一个具有较少集中故障点的网状网络,尽管它也占用了更多带宽。 对于不需要通过中央设备的较小有效负载(例如游戏),此策略是理想的选择。
本教程将重点介绍如何使用更简单的星形策略将IoT设备连接为广告商,并将用户的智能手机用作发现者。 但是,最后,您还应该有足够的信息来实施集群策略。
让我们开始吧!
本教程将有两个模块:移动应用程序和Android Things应用程序。 在Android Studio中创建这些应用程序后,您需要在两个应用程序的模块级build.gradle文件中包括“附近连接”的Google Play服务依赖项。
compile ‘com.google.android.gms:play-services-nearby:11.6.2’
运行gradle同步后,打开两个模块的AndroidManifest.xml文件,并在application
节点中包含以下权限。
<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服务回调的接口,如下所示:
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()
具有适当的位置权限后,就可以开始连接到Google Play服务以使用“附近的连接” API。
mGoogleApiClient = new GoogleApiClient
.Builder(this, this, this)
.addApi(Nearby.CONNECTIONS_API)
.enableAutoManage(this, this)
.build();
GoogleApiClient
完成连接后,将调用onConnected()
方法。 在这里,您将开始为设备进行广告或发现过程。 此外,两个应用程序都需要一个服务ID,这是一个唯一的String
标识符。
private static final String SERVICE_ID = "UNIQUE_SERVICE_ID";
在附近连接上投放广告
使用邻近连接API时,您将需要创建一个ConnectionLifecycleCallback
,顾名思义,它将在各种连接生命周期事件中触发。 对于此演示,我们将仅使用onConnectionInitiated()
方法。 它将保存对尝试连接到该端点的第一个终结点的引用,接受该连接,然后停止播发。 如果连接失败,则该应用程序可以重新启动广告。
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
。
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设备上做广告:
Nearby.Connections.startAdvertising(
mGoogleApiClient,
"Device Name",
SERVICE_ID,
mConnectionLifecycleCallback,
new AdvertisingOptions(Strategy.P2P_STAR));
您可能会注意到,这就是我们将P2P_STAR策略应用于“附近的连接”网络的地方。
当您要将有效负载发送到另一台设备时,可以将Nearby.Connections.sendPayload()
方法与Google API客户端引用,端点名称以及要发送的数据的字节数组一起使用。
Nearby.Connections.sendPayload(mGoogleApiClient, endpoint, Payload.fromBytes("Message".getBytes()));
提示:在重新启动时启用WiFi
我发现在Android Things设备上使用“附近的连接” API时有用的一个技巧是在重新启动时重新启用WiFi,因为如果设备关闭或在投放广告时断电,设备最终可能会禁用无线功能。 您可以通过检索WifiManager
系统服务并调用setWifiEnabled()
来完成此操作。
wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
wifiManager.setWifiEnabled(true);
发现具有附近连接的设备
发现设备所遵循的模式与广告大体相似。 设备将连接到Google API客户端并开始发现。 找到广告商后,发现者将请求连接到该广告商。 如果广告客户批准了该请求,则这两个设备将连接并能够来回发送有效载荷。 发现者将像广告客户一样使用PayloadCallback
。
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
看起来也类似于广告商的:
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
,该发现者将在找到广告商但尚未连接时使用。 该对象将发起连接广告商的请求。
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服务后,您可以使用以下命令启动发现:
Nearby.Connections.startDiscovery(
mGoogleApiClient,
SERVICE_ID,
mEndpointDiscoveryCallback,
new DiscoveryOptions(Strategy.P2P_STAR));
最后,当您想与广告客户断开连接时,可以使用Nearest Connections API中的disconnectFromEndpoint()
方法。 通常,最好在Activity
的onDestroy()
回调中执行此操作。
Nearby.Connections.disconnectFromEndpoint(mGoogleApiClient, mEndpoint);
结论
在本文中,您在为Android Things IoT设备创建配套应用程序的背景下了解了Android的Nearest Connections 2.0 API。
值得注意的是,此API可以用于您想要联网的任何Android设备,从手机和平板电脑到Android电视盒和Android Wear智能手表。 该API提供了一种无需使用Internet或集中式路由器即可进行连接和通信的简单方法,并且为您的Android开发工具集增加了一个实用工具。