android - 使用带线程的相机
问题描述
我正在尝试获取相机的图像并连续处理它,所以,我使用的是 CameraKit 包:
package com.example.alex.tfmobile;
import android.annotation.SuppressLint;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.os.Handler;
import android.os.HandlerThread;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import com.camerakit.CameraKitView;
import java.io.InputStream;
public class MainActivity extends AppCompatActivity {
private HandlerThread backgroundThread;
private Handler backgroundHandler;
private final Object lock = new Object();
private boolean runClassifier = false;
private static final String HANDLE_THREAD_NAME = "CameraBackground";
TextView resultView;
private CameraKitView cameraView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
cameraView = (CameraKitView) findViewById(R.id.camera);
resultView = (TextView) findViewById(R.id.results);
startBackgroundThread();
}
@Override
protected void onResume() {
super.onResume();
cameraView.onResume();
startBackgroundThread();
}
@Override
protected void onPause() {
cameraView.onPause();
stopBackgroundThread();
super.onPause();
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
cameraView.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
private void startBackgroundThread() {
backgroundThread = new HandlerThread(HANDLE_THREAD_NAME);
backgroundThread.start();
backgroundHandler = new Handler(backgroundThread.getLooper());
synchronized (lock) {
runClassifier = true;
}
backgroundHandler.post(periodicClassify);
}
private Runnable periodicClassify =
new Runnable() {
@Override
public void run() {
synchronized (lock) {
if (runClassifier) {
classifyFrame();
}
}
backgroundHandler.post(periodicClassify);
}
};
private void classifyFrame() {
cameraView.captureImage(new CameraKitView.ImageCallback() {
@Override
public void onImage(CameraKitView cameraKitView, final byte[] picture) {
Bitmap bitmap = BitmapFactory.decodeByteArray(picture, 0, picture.length);
}
});
}
private void stopBackgroundThread() {
backgroundThread.quitSafely();
try {
backgroundThread.join();
backgroundThread = null;
backgroundHandler = null;
synchronized (lock) {
runClassifier = false;
}
} catch (InterruptedException e) {
Log.e("TfMobile", "Interrupted when stopping background thread", e);
}
}
}
布局:
<?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">
<com.camerakit.CameraKitView
android:id="@+id/camera"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:camera_facing="back"/>
<TextView
android:id="@+id/results"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
但问题出在classifyFrame
方法上,当我尝试访问变量cameraView
时,它抛出了 Null 指针异常。我想知道如何使用带有线程的相机来处理帧。
错误:
Process: com.example.alex.tfmobile, PID: 26659
java.lang.NullPointerException: Attempt to invoke virtual method 'int com.camerakit.CameraKitView$Size.getWidth()' on a null object reference
at com.camerakit.CameraKitView$Camera2$1$7.run(CameraKitView.java:1844)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.os.HandlerThread.run(HandlerThread.java:61)
10-06 02:07:29.848 26659-26659/? E/ViewRootImpl@3b4860a[MainActivity]: ViewRootImpl #2 Surface is not valid.
解决方案
看起来您正在尝试在表面准备之前访问它,您可以尝试注释掉 startBackgroundThread(); 从 onCreate. 您已经从 onResume 调用它。希望它应该工作,或者你可以等到表面准备好。
推荐阅读
- api - 接受类型无效,INVALID_ACCEPT_TYPE.GMP_ITEM_QUERY_API(Walmart ItemSearch API 错误)
- excel - 使用 SSIS 导入 excel 文件始终默认为 255 个字符
- javascript - React Hooks 延迟 setState 更新导致功能异常
- python - Pandas 重新索引大于和小于索引的数据帧
- postgresql - 访问联合中的子查询返回值到其他表 postgres
- python - python 3:在进程替换中,子进程无法打开文件描述符
- gremlin - 在 tinkerpop gremlin 中,如何搜索属性值是参数子集的顶点?
- reactjs - Kubernetes Ingress 部署未在裸机上正确加载
- javascript - 检测用户的时区在本地工作正常,但在部署时不能
- vtk - 如何将地理从 vtk 传递到 netgen 并将网格从 netgen 直接传递到 vtk 而无需导出/读取文件?