本文探讨了如何使用Android附近,展示了如何集成Android和Android Things。 我们可以使用多种策略来整合Android和Android Things,Android邻近技术就是其中之一。 Android提供了一组API,可简化两个不同设备之间的数据交换。 一个有趣的方面是Android附近还支持iOS操作系统。
“ Android附近”是一项支持三种不同策略来集成Android设备的技术:
- Android附近消息 :这使用发布者/订阅者范例在两个不同的Android设备之间交换简单的有效负载。
- Android附近的连接 :这是一个点对点网络,使应用程序可以发现,连接和在设备之间交换数据。 这种策略支持高带宽,在多种情况下(游戏,文件共享等)很有用。
- Android附近通知 :这项技术使用户可以使用应用或网站接收周围的通知
本文发现了如何使用Android附近的连接来集成Android和Android Things设备。 主要目标是展示如何将数据从Android智能手机发送到Android Things设备,以及如何使用与Android Things连接的LCD显示器显示此信息。
目录
Android附近的连接
Android附近的连接是点对点网络。 该网络中有两个主要角色:
- 自己做广告的广告商等待传入的连接
- 寻找广告商进行连接的Discoverer
发现者找到广告商后,便可以建立连接并交换数据。 在后台,Android附近API使用了一套技术来建立不同设备之间的连接。 它可以是蓝牙或Wifi。 API利用每种技术的强度来确保可靠的连接。 开发人员和用户不必担心,它是完全透明的。
在本教程中,Android Things设备充当等待传入的Discoverer的广告商的角色。 Android设备是Discoverer,用于查找要连接的广告商。 为了完成本教程,有必要实现两个不同的应用程序:
- 接收数据并处理LCD显示屏的Android Things应用
- 将数据发送到Android Things的Android应用
此外,Android附近的连接支持不同的发现和广告策略。 一般来说,这两种策略是:
- 支持M对N网络拓扑的P2P_Cluster ,其中每个设备都可以接受传入的连接并启动与其他设备的新连接
- P2P_STAR,这是经典的启动拓扑网络,其中一个设备充当广告商,而其他设备充当发现者
在本Android Things教程中,我们将使用P2P_STAR拓扑。 让我们开始实施广告客户。
使用Android Things的Android附近广告商
第一步是使用Android Thing设备实施广告商。 在这种情况下,我们将使用Raspberry Pi 3,但您可以使用其他与Android Things兼容的原型开发板。
要实施Android附近的广告客户,我们必须遵循三个不同的步骤:
- 开始广告
- 接受传入的连接
- 监听传入的负载
第四步是可选步骤,它管理与Android Things连接的LCD显示屏,以便Android Things应用将在LCD显示屏上显示有效载荷内容。
开始使用Android Things刊登广告
第一件事是创建一个新类,该类将处理所有附近的连接详细信息。 让我们将其称为名为NearbyAdvManager
类。 在构造函数中,Android Thing应用开始广告:
private ConnectionsClient client;
..
client = Nearby.getConnectionsClient(ctx);
client.startAdvertising("AndroidThings",
SERVICE_ID,
connectionLifeCycleCB,
new AdvertisingOptions(Strategy.P2P_STAR))
.addOnSuccessListener(
new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void aVoid) {
Log.i(TAG, "OnSuccess...");
}
}
)
.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
Log.e(TAG, "OnFailure 1");
e.printStackTrace();
}
});
}
其中"Android Things"
是一个昵称,而SERVICE_ID
是我们服务的ID。 通常,SERVICE_ID是我们应用程序的软件包名称。 另一个参数connectionLifeCycleCB
是一个回调类。
小费
请注意,Android附近具有一组新的API。 创建广告客户时,我们不再需要使用GoogleApiClient。
现在该实现连接回调,以便Android Things应用得到有关连接的通知。 为此,让我们将此代码添加到管理器中:
private ConnectionLifecycleCallback connectionLifeCycleCB =
new ConnectionLifecycleCallback() {
@Override
public void onConnectionInitiated(String s,
ConnectionInfo connectionInfo) {
Log.i(TAG, "Connection initiated. Endpont ["+s+"]");
// Let us accept the connection
}
@Override
public void onConnectionResult(String s,
ConnectionResolution connectionResolution) {
Log.i(TAG, "Connection result. Endpont ["+s+"]");
}
@Override
public void onDisconnected(String s) {
Log.i(TAG, "Disconnected. Endpont ["+s+"]");
};
};
在Android Things应用中接受传入连接
Android Things应用开始投放广告后,有必要处理传入的连接。 如前所述,在连接回调接口中,我们进行了更改以处理连接。 当发现者想要开始与广告商的新连接时,将调用onConnectionInitiated
。 在此方法中,添加以下行:
Nearby.getConnectionsClient(ctx)
.acceptConnection(s, payloadCallback);
使用此代码,Android Things应用无需接受身份验证机制即可接受所有传入连接。 可以对客户端进行身份验证,以便我们可以应用一些安全策略。
最后一步是传入payloadCallback
以便应用程序可以处理传入的payload。
处理Android附近的有效负载
这是Android附近广告客户的最后一步。 Android Things应用必须实现PayloadCallback
接口才能读取传入的有效负载。
private PayloadCallback payloadCallback = new PayloadCallback() {
@Override
public void onPayloadReceived(String s, Payload payload) {
Log.i(TAG, "Payload received");
byte[] b = payload.asBytes();
String content = new String(b);
Log.i(TAG, "Content ["+content+"]");
}
@Override
public void onPayloadTransferUpdate(String s,
PayloadTransferUpdate payloadTransferUpdate) {
Log.d(TAG, "Payload Transfer update ["+s+"]");
}
};
在onPayloadReceived
,我们将处理LCD显示屏以显示有效内容。
实施Android Things附近的应用
经理准备就绪后,就可以实施Android Things附近的应用了。 让我们创建MainActivity
类:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.i(TAG, "Starting Android Things app...");
NearbyAdvManager advManager = new NearbyAdvManager(this);
}
稍后,我们将处理连接到Android Things的LCD显示屏,以便它可以显示有效内容。
小费
销毁应用程序时,不要忘记关闭连接并停止广告
最后,我们可以要求拥有AndroidManifest.xml
的权限
<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设备。 在本教程中,我们将使用运行Android Things 1.0.3的Raspberry Pi 3。
小费
启动Android Things应用程序时,请确保这是第一个应用程序,否则可能会出现一些错误
使用“附近”实施Android应用
在本段中,我们将描述如何实现扮演发现者角色并将数据发送到Android Things应用程序的Android应用程序。 实施此应用的步骤几乎与之前实施Android Things Nearyby应用的步骤相同。 让我们开始创建一个名为NearbyDsvManager
的类。 此类将管理所有详细信息,以使用Android Things应用发现,连接和交换数据。
将此构造函数添加到此类:
public NearbyDsvManager(Context ctx, final EventListener listener) {
this.listener = listener;
this.ctx = ctx;
Log.i(TAG, "NearbyDsvManager");
Nearby.getConnectionsClient(ctx)
.startDiscovery(SERVICE_ID,
endpointDiscoveryCB,
new DiscoveryOptions(Strategy.P2P_STAR))
.addOnSuccessListener(
new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void aVoid) {
Log.i(TAG, "OnSuccess...");
listener.startDiscovering();
}
}
)
.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
Log.e(TAG, "OnFailure", e);
e.printStackTrace();
}
});
}
该类几乎执行与前面所述相同的操作。 它开始发现试图找出准备交换数据的广告商。 此外,在此类中,定义了一个回调接口,该接口用于在发现和连接过程中向调用方(MainActivity)通知事件。 该回调接口是:
public interface EventListener {
public void onDiscovered();
public void startDiscovering();
public void onConnected();
}
此外,Neighborhood API使用另一个回调接口来通知调用方发现状态。 在列表器上方的代码中是endpointDiscoveryCB
:
private EndpointDiscoveryCallback endpointDiscoveryCB = new EndpointDiscoveryCallback() {
@Override
public void onEndpointFound(String s, DiscoveredEndpointInfo discoveredEndpointInfo) {
Log.i(TAG, "Endpoint found ["+s+"]. Connecting....");
listener.onDiscovered();
getConnection(s);
}
@Override
public void onEndpointLost(String s) {
Log.e(TAG, "Endpoint lost ["+s+"]");
}
};
将附近的发现者连接到附近的广告客户
发现者找到有效端点(由广告商提供)后,发现者将尝试启动连接getConnection(s)
,其中s是发现的端点:
private void getConnection(String endpointId) {
Nearby.getConnectionsClient(ctx)
.requestConnection(endpointId, endpointId,connectionLifecycleCallback)
.addOnSuccessListener(new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void aVoid) {
Log.d(TAG, "Requesting connection..");
}
})
.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
Log.e(TAG, "Error requesting connection", e);
}
});
}
在这种方法中,发现者使用在上一步中发现的endpointId请求新连接。 此外,它添加了一个新的回调接口,以了解何时建立连接或出现错误。
private ConnectionLifecycleCallback connectionLifecycleCallback =
new ConnectionLifecycleCallback() {
@Override
public void onConnectionInitiated(String s, ConnectionInfo connectionInfo) {
Log.i(TAG, "Connected to endpoint ["+s+"]");
NearbyDsvManager.this.currentEndpoint = s;
Nearby.getConnectionsClient(ctx).acceptConnection(s, payloadCallback);
}
@Override
public void onConnectionResult(String s, ConnectionResolution connectionResolution) {
switch (connectionResolution.getStatus().getStatusCode()) {
case ConnectionsStatusCodes.STATUS_OK:
listener.onConnected();
break;
case ConnectionsStatusCodes.STATUS_CONNECTION_REJECTED:
Log.i(TAG, "Connection rejected");
break;
case ConnectionsStatusCodes.STATUS_ERROR:
Log.i(TAG, "Connection error");
break;
}
}
@Override
public void onDisconnected(String s) { }
};
建立连接并且双方都接受连接后,该过程完成,并且应用程序已准备好发送数据。 这是将有效载荷从Android应用发送到Android Things应用的方法:
public void sendData(String data) {
Log.i(TAG, "Sending data ["+data+"]");
Log.i(TAG, "Current endpoint ["+currentEndpoint+"]");
if (currentEndpoint != null) {
Log.d(TAG, "Sending data to ["+data+"]");
Payload payload = Payload.fromBytes(data.getBytes());
Nearby.getConnectionsClient(ctx).sendPayload(currentEndpoint, payload);
}
}
就这样。
实施Android应用界面
最后一步实现了Android应用程序用户界面,以便用户可以插入有效负载并将其发送到Android Things应用程序(Nearyby广告客户)。 用户界面非常简单:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Content"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:layout_marginTop="8dp"
android:id="@+id/txt"/>
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:hint="text here"
android:maxLength="40"
android:id="@+id/ed"
app:layout_constraintTop_toBottomOf="@id/txt"
android:layout_marginTop="8dp"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toRightOf="parent"
app:layout_constraintRight_toLeftOf="parent"
android:id="@+id/btn"
android:text="Send"/>
</android.support.constraint.ConstraintLayout>
最后:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn = findViewById(R.id.btn);
et = (EditText) findViewById(R.id.ed);
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String txt = et.getText().toString();
Log.d(TAG, "Txt ["+txt+"]");
dsvManager.sendData(txt);
}
});
}
将LCD显示器连接到Android Things
此步骤是可选的,因为它描述了如何将LCD显示器连接到Android Things以显示从Android应用发送的内容有效内容。 本Android Things教程使用Hd44780 LCD。 更详细地说,该液晶显示器基于HD44780芯片和PCF8574。 有几种具有不同显示尺寸的版本,此示例之一是20×4。 这是一个I2C外设,它使用4个不同的引脚连接到Android Things板:
- Vcc(+ 5V)
- 地线
- SDA
- 时钟
要管理此LCD,必须导入驱动程序。 让我们将这一行添加到build.gradle
:
implementation 'com.leinardi.android.things:driver-hd44780:<version>'
此外,有必要创建一个新类来处理LCD连接详细信息以及显示数据的所有步骤。
public class ManageLCD {
private Hd44780 mLcd;
public void displayString(data) {
try {
Log.d("LCd", "Writing");
if (mLCD == null)
mLcd = new Hd44780("I2C1", 0x27, Hd44780.Geometry.LCD_20X4);
mLcd.setBacklight(true);
mLcd.cursorHome();
mLcd.clearDisplay();
mLcd.setText(data);
} catch (Exception e) {
e.printStackTrace();
}
}
}
收到新的有效负载时,您必须在Android Things应用程序的MainActivity
中调用此类。
摘要
最后,本文展示了如何使用Android附近功能连接不同的Android设备。 本教程使用“ Android附近”来连接Android应用程序和Android Things应用程序,以便它们可以交换数据。 此外,Android Things使用与其连接的LCD来显示来自Android应用程序的有效负载。 希望您了解了如何使用Android附近的广告客户和发现者,以及如何按照Android附近的规范进行连接。
翻译自: https://www.javacodegeeks.com/2018/09/android-nearby-android-things.html