Android Things(以前称为 Brillo)是针对小型化和物联网设备而设计的 Android 精简版。下面是一个简单的事物(Things)应用程序示例,它提供了一个 REST 风格的 Web 界面来控制 Raspberry Pi GPIO 端口上的 LED 状态。
你将需要的东西有:
有许多 Raspberry Pi 3 套件可用,与你需要的一切开始。查看 Android Things Raspberry Pi 硬件页面,获取有关将事物预览图像加载到 SD 卡上并启动的更多信息。
您还需要从命令行使用 adb
访问。
拔掉你的 Raspberry Pi,并连接带状电缆和面包板。在 BCM 21(见引脚)和 LED 的长脚(阳极/+)之间连接一个 330 欧姆的电阻。使用跳线将 LED 的短路(阴极/-)接地。 例如:
仔细检查您的连接并启动设备。连接 Android 调试器:
adb connect <ipaddress>
这个 IP 地址应该显示在 Android Things 引导屏幕的底部。
这个例子的完整源代码可以在 Github 上找到。
打开 Android Studio 并创建一个新项目。
API: 24 Android 7.0 (Nougat)
作为最低的 SDK。下载并解压 Android 版本的 Restlet Framework。 将 lib 目录中的下列 jar 文件复制到应用程序的 app/libs
文件夹中:
现在,在 Android Studio 中,编辑“Module:app” 中的 build.gradle
文件,并将 Restlet 和 Android Things 的必要库添加到 dependencies
部分,如下所示:
compile files('libs/org.restlet.ext.nio.jar')
compile files('libs/org.restlet.ext.json.jar')
compile files('libs/org.restlet.jar')
以及:
provided 'com.google.android.things:androidthings:0.1-devpreview'
打开 app/manifests/AndroidManifest.xml
文件,并将以下内容添加到 application
部分:
<uses-library android:name="com.google.android.things"></uses-library>
并将 main activity 修改为如下的内容:
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"></action>
<category android:name="android.intent.category.LAUNCHER"></category>
<category android:name="android.intent.category.IOT_LAUNCHER"></category>
<category android:name="android.intent.category.DEFAULT"></category>
</intent-filter>
</activity>
这会将您的应用程序设置为设备的默认 activity。
此时,您应该能够在 Raspberry Pi 上启动应用程序,并看到 “Hello,World!”消息。确保 adb 已连接(请参阅上文),然后单击 Android Studio 中的 “运行” 图标。
创建一个名为 LEDModel
的新类。该类将提供对控制 LED 状态的 GPIO 引脚的访问:
package com.example.restfulthings;
import com.google.android.things.pio.Gpio;
import com.google.android.things.pio.PeripheralManagerService;
import java.io.IOException;
public class LEDModel {
private static LEDModel instance = null;
private PeripheralManagerService mPMSvc;
private Gpio mBCM21;
public static LEDModel getInstance() {
if (instance == null) {
instance = new LEDModel();
}
return instance;
}
private LEDModel() {
mPMSvc = new PeripheralManagerService();
try {
mBCM21 = mPMSvc.openGpio("BCM21");
mBCM21.setDirection(Gpio.DIRECTION_OUT_INITIALLY_LOW);
} catch (Exception e) {
e.printStackTrace();
}
}
public static void setState(boolean state) {
try {
getInstance().mBCM21.setValue(state);
} catch (IOException e) {
e.printStackTrace();
}
}
public static boolean getState() {
boolean value = false;
try {
value = getInstance().mBCM21.getValue();
} catch (IOException e) {
e.printStackTrace();
}
return value;
}
}
有关控制设备的 GPIO 输出的更多信息,请参阅 Android Things SDK 文档。
创建一个名为 LEDResource
的新类,它继承 org.restlet.resource.ServerResource
。 该类提供了 LED 状态的 RESTful 表示形式:
package com.example.restfulthings;
import android.util.Log;
import org.json.JSONObject;
import org.restlet.data.MediaType;
import org.restlet.ext.json.JsonRepresentation;
import org.restlet.representation.Representation;
import org.restlet.representation.StringRepresentation;
import org.restlet.resource.Get;
import org.restlet.resource.Post;
import org.restlet.resource.ServerResource;
public class LEDResource extends ServerResource {
@Get("json")
public Representation getState() {
JSONObject result = new JSONObject();
try {
result.put("state", LEDModel.getState());
} catch (Exception e) {
e.printStackTrace();
}
return new StringRepresentation(result.toString(), MediaType.APPLICATION_ALL_JSON);
}
@Post("json")
public Representation postState(Representation entity) {
JSONObject result = new JSONObject();
try {
JsonRepresentation json = new JsonRepresentation(entity);
result = json.getJsonObject();
boolean state = (boolean)result.get("state");
Log.d(this.getClass().getSimpleName(), "new LED state: "+state);
LEDModel.setState(state);
} catch (Exception e) {
e.printStackTrace();
}
return new StringRepresentation(result.toString(), MediaType.APPLICATION_ALL_JSON);
}
}
HTTP 服务器将作为后台服务在与用户界面活动不同的线程上运行。 添加一个名为 RESTfulService 的新类,继承 IntentService:
package com.example.restfulthings;
import android.app.IntentService;
import android.content.Intent;
import android.content.Context;
import android.util.Log;
import org.restlet.Component;
import org.restlet.data.Protocol;
import org.restlet.engine.Engine;
import org.restlet.ext.nio.HttpServerHelper;
import org.restlet.routing.Router;
public class RESTfulService extends IntentService {
// IntentService can perform, e.g. ACTION_FETCH_NEW_ITEMS
private static final String ACTION_START = "com.example.restfulthings.action.START";
private static final String ACTION_STOP = "com.example.restfulthings.action.STOP";
private Component mComponent;
public RESTfulService() {
super("RESTfulService");
Engine.getInstance().getRegisteredServers().clear();
Engine.getInstance().getRegisteredServers().add(new HttpServerHelper(null));
mComponent = new Component();
mComponent.getServers().add(Protocol.HTTP, 8080);
Router router = new Router(mComponent.getContext().createChildContext());
router.attach("/led", LEDResource.class);
mComponent.getDefaultHost().attach("/rest", router);
}
public static void startServer(Context context) {
Intent intent = new Intent(context, RESTfulService.class);
intent.setAction(ACTION_START);
context.startService(intent);
}
public static void stopServer(Context context) {
Intent intent = new Intent(context, RESTfulService.class);
intent.setAction(ACTION_STOP);
context.startService(intent);
}
@Override
protected void onHandleIntent(Intent intent) {
if (intent != null) {
final String action = intent.getAction();
if (ACTION_START.equals(action)) {
handleStart();
} else if (ACTION_STOP.equals(action)) {
handleStop();
}
}
}
private void handleStart() {
try {
mComponent.start();
} catch (Exception e) {
Log.e(getClass().getSimpleName(), e.toString());
}
}
private void handleStop() {
try {
mComponent.stop();
} catch (Exception e) {
Log.e(getClass().getSimpleName(), e.toString());
}
}
}
该服务提供了主要活动可用于启动和停止服务器的 Intent 操作。
最后,编辑 MainActivity
类来启动和停止服务:
package com.example.restfulthings;
import android.app.Activity;
import android.os.Bundle;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// start the server
RESTfulService.startServer(this);
}
@Override
protected void onDestroy() {
super.onDestroy();
// stop the server
RESTfulService.stopServer(this);
}
}
启动应用程序。您应该在 logcat 输出中看到一条消息:Starting the internal [HTTP/1.1] server on port 8080
。
打开命令行窗口,并使用 curl
来请求 LED 的状态:
curl http://<ipaddress>:8080/rest/led
这里的 <ipaddress>
是您的设备的 IP 地址。 这应该返回 JSON 格式的当前状态(false):
{"state":false}
打开 LED 只需要:
curl -H "Content-type: application/json" -X POST -d '{"state": true}' http://<ipaddress>:8080/rest/led
LED 现在应该点亮。再次关闭它:
curl -H "Content-type: application/json" -X POST -d '{"state": false}' http://<ipaddress>:8080/rest/led
完整的代码见:GitHub。
英语原文链接:https://keathmilligan.net/implement-a-restful-interface-with-android-things-and-raspberry-pi/
观光\评论区