Android附近:如何集成Android和Android Things

本文探讨了如何使用Android附近,展示了如何集成Android和Android Things。 我们可以使用多种策略来整合Android和Android Things,Android邻近技术就是其中之一。 Android提供了一组API,可简化两个不同设备之间的数据交换。 一个有趣的方面是Android附近还支持iOS操作系统。

“ Android附近”是一项支持三种不同策略来集成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附近的广告客户,我们必须遵循三个不同的步骤:

  1. 开始广告
  2. 接受传入的连接
  3. 监听传入的负载

第四步是可选步骤,它管理与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
  • 时钟

连接模式如下图所示:
Android附近

要管理此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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值