Android Things做一个简易相机
Android Things已经发布有一段时间了,最近买了块树莓派3的板子,研究一下Android Things开发。刷系统、配置这些我就不说了,网上搜索一下一大堆。
开始
最开始是跟着Android Things官网上的两个例子熟悉一下,第二个例子是做个带摄像头的门铃 官网地址。突然就自己想做一个简易的摄像机,可以预览图像,点击按钮后,LED灯亮,拍照。
第一步:搭建硬件
其实这一步也是最简单的,只需要把摄像头卡入固定卡槽,再连接一个按钮和一个LED灯就OK了。
第二步:软件依赖
新建一个工程,build.gradle中添加
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:25.1.0'
compile 'com.google.android.things.contrib:driver-button:0.1'
provided 'com.google.android.things:androidthings:0.1-devpreview'
}
并在Manifest文件中如下
<uses-library android:name="com.google.android.things" />
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<category android:name="android.intent.category.IOT_LAUNCHER" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
这样就在工程中添加了Android Things的支持,我们就可以开始写代码了。
第三步:按钮和LED事件监听逻辑
Android Thing对很多硬件上的驱动都已经做了封装,我们只需要在Java层调用封装好的方法就可以实现监听硬件层的功能。Android Things可以使用的驱动列表GitHub
我使用了BCM6和BCM21两个GPIO口,树莓派GPIO编号规范可以看这里
private void InitDriver() {
PeripheralManagerService pioService = new PeripheralManagerService();
try {
mLedGpio = pioService.openGpio("BCM6");
mLedGpio.setDirection(Gpio.DIRECTION_OUT_INITIALLY_LOW);
mButtonInputDriver = new ButtonInputDriver(
"BCM21",
Button.LogicState.PRESSED_WHEN_LOW,
KeyEvent.KEYCODE_SPACE);
mButtonInputDriver.register();
} catch (IOException e) {
Log.e(TAG, "Error configuring GPIO pins", e);
}
}
然后是对按钮和LED进行控制
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_SPACE) {
// Turn on the LED
setLedValue(true);
//takePicture(); //拍照
Log.e(TAG, "onKeyDown");
return true;
}
return super.onKeyDown(keyCode, event);
}
@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_SPACE) {
// Turn off the LED
setLedValue(false);
Log.e(TAG, "onKeyUp");
return true;
}
return super.onKeyUp(keyCode, event);
}
/**
* Update the value of the LED output.
*/
private void setLedValue(boolean value) {
try {
mLedGpio.setValue(value);
} catch (IOException e) {
Log.e(TAG, "Error updating GPIO value", e);
}
}
到这一步的时候我们就只剩下关于摄像头的问题了。而且摄像头的驱动什么的我们也完全不用担心,插上就可以用,并且编程是跟正常的自定义Camera相同,不会涉及到硬件上的问题。可以看我另一篇博客《Android Camera2 自定义相机》。
发现的问题
在实际开发的过程中发现一个问题,Camera2在手机上正常的逻辑在树莓派上却出现了问题。主要问题在于
mCameraDevice.createCaptureSession(Arrays.asList(surface, mImageReader.getSurface()), new CameraCaptureSession.StateCallback()){}
创建Session时手机上是可以surface, mImageReader.getSurface()两个作为Target,可以预览和拍照,但是在树莓派上这一步只能传入一个,否则100%创建失败,报的错误是
v4l2 only supports 1 stream configuration at a time
涉及到了硬件驱动层的东西,有可能是Android Things自己的Bug吧,所以暂时还没有解决。目前就是预览和拍照功能不能同时实现,也让我很无奈了,只有继续努力,争取解决问题了。