我正在使用表面视图构建相机应用程序。该应用程序正确加载相机并捕获图像。图像捕获有两种情况:
捕获图像,并且没有任何内容,即字节数组被发送到预览活动。它在这里工作正常。
捕获图像,并将图片回调中的字节数组发送到预览活动。
在第二种情况下,应用程序显示黑屏并变得无响应。我不相信我知道其原因,因为我已经查看了许多教程并看过相同的代码。
到目前为止,这是我的代码:
public class ImageActivity extends AppCompatActivity implements SurfaceHolder.Callback {
private static final String TAG = ImageActivity.class.getSimpleName();
private ImageButton closeIV;
private ImageView flipCameraIV;
private FloatingActionButton fab_capture;
private LinearLayout galleryLayout;
private Camera camera;
private Camera.PictureCallback jpegCallback;
private SurfaceView surfaceView;
private SurfaceHolder holder;
private int currCamId = 0;
private boolean isGalleryImg = false;
private boolean isCameraImg = false;
private byte[] camBytes = null;
private static final int GAL_REQ_CODE = 240;
private static final int CAM_PERM_CODE = 242;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.activity_image);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
getWindow().setStatusBarColor(getResources().getColor(R.color.black));
}
init();
holder = surfaceView.getHolder();
holder.addCallback(this);
holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
currCamId = Camera.CameraInfo.CAMERA_FACING_BACK;
}
private void handleClicks() {
closeIV.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
finish();
}
});
flipCameraIV.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Log.d(TAG, "Flip Clicked");
switchCamera();
}
});
galleryLayout.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
isGalleryImg = true;
Log.d(TAG, "Gallery Button Clicked");
Intent galleryIntent = new Intent(Intent.ACTION_GET_CONTENT);
galleryIntent.setType("image/*");
startActivityForResult(galleryIntent, GAL_REQ_CODE);
}
});
fab_capture.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
captureImage();
}
});
jpegCallback = new Camera.PictureCallback() {
@Override
public void onPictureTaken(byte[] bytes, Camera camera) {
assert bytes != null;
Log.d(TAG, "Camera Bytes Array Length:\t" + bytes.length);
isCameraImg = true;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
Intent intent = new Intent(ImageActivity.this, PreviewActivity.class);
intent.putExtra("camera_bytes", bytes);
intent.putExtra("fromCamera", isCameraImg);
startActivity(intent);
return;
//refreshCamera();
}
};
}
private void captureImage() {
camera.takePicture(null, null, jpegCallback);
}
public void refreshCamera() {
if (holder.getSurface() == null) {
return; // preview surface is empty
}
// stop preview, then make changes
try {
camera.stopPreview();
} catch (Exception ex) {
ex.printStackTrace();
}
try {
camera.setPreviewDisplay(holder);
camera.startPreview();
} catch (IOException e) {
e.printStackTrace();
}
}
private void init() {
closeIV = findViewById(R.id.closeIV);
fab_capture = findViewById(R.id.fab_capture);
galleryLayout = findViewById(R.id.galleryLayout);
flipCameraIV = findViewById(R.id.flipCameraIV);
surfaceView = findViewById(R.id.surfaceView);
handleClicks();
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == GAL_REQ_CODE && resultCode == RESULT_OK) {
Uri imgUri = data.getData();
Intent intent = new Intent(ImageActivity.this, PreviewActivity.class);
intent.putExtra("fromGallery", isGalleryImg);
intent.putExtra("gallery_image", imgUri.toString());
startActivity(intent);
}
}
@TargetApi(Build.VERSION_CODES.M)
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
for (int mResults : grantResults) {
if (mResults == PackageManager.PERMISSION_DENIED) {
requestPermissions(new String[]{Manifest.permission.CAMERA,
Manifest.permission.WRITE_EXTERNAL_STORAGE},
CAM_PERM_CODE);
} else {
Toast.makeText(ImageActivity.this, "Permission Already Granted", Toast.LENGTH_SHORT).show();
}
}
}
@Override
public void surfaceCreated(SurfaceHolder surfaceHolder) {
openCamera();
}
private void openCamera() {
try {
camera = Camera.open(currCamId);
} catch (RuntimeException rex) {
rex.printStackTrace();
}
Camera.Parameters parameters = camera.getParameters();
parameters.setPreviewFrameRate(20);
parameters.setPreviewSize(352, 288);
camera.setDisplayOrientation(90);
camera.setParameters(parameters);
try {
camera.setPreviewDisplay(holder);
} catch (IOException e) {
e.printStackTrace();
}
camera.startPreview();
}
@Override
public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {
refreshCamera();
}
@Override
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
camera.stopPreview();
camera.release();
camera = null;
}
@Override
protected void onPause() {
super.onPause();
camera.stopPreview();
}
@Override
protected void onDestroy() {
super.onDestroy();
if (camera != null){
camera.stopPreview();
camera.release();
camera = null;
}
}
}
此外,我尝试使用此代码段切换到前置摄像头并再次返回,但无法正常工作。
private void switchCamera() {
// code I tried to switch camera with but not working
if (currCamId == Camera.CameraInfo.CAMERA_FACING_BACK){
currCamId = Camera.CameraInfo.CAMERA_FACING_FRONT;
} else {
currCamId = Camera.CameraInfo.CAMERA_FACING_BACK;
}
camera = Camera.open(currCamId);
Camera.CameraInfo info = new Camera.CameraInfo();
Camera.getCameraInfo(Camera.CameraInfo.CAMERA_FACING_FRONT, info);
int rotation = this.getWindowManager().getDefaultDisplay().getRotation();
int degrees = 0;
switch (rotation){
case Surface.ROTATION_0: degrees = 0; break;
case Surface.ROTATION_90: degrees = 90; break;
case Surface.ROTATION_180: degrees = 180; break;
case Surface.ROTATION_270: degrees = 270; break;
}
int rotate = (info.orientation - degrees + 360) % 360;
Camera.Parameters parameters = camera.getParameters();
parameters.setRotation(rotate);
try {
camera.setPreviewDisplay(surfaceView.getHolder());
} catch (IOException e) {
e.printStackTrace();
}
camera.setParameters(parameters);
camera.setDisplayOrientation(90);
camera.startPreview();
//openCamera();
}
我需要帮助来解决这个问题。感谢。
答案 0 :(得分:0)
正如我所见,您尝试将图片作为字节数组发送,这是不可能的。因为自api23以来对意图大小有限制。发送附加内容时,您必须考虑附加内容的大小,它确实会破坏用户体验并导致新活动的负载变慢。
无论如何,你的字节数组太大了所有的图片数据,我认为这会导致anr。你该怎么办?您必须首先将该字节数组保存为jpeg文件,然后将filepath添加到您的意图中。 Take a look to this solution
哦,而且,只是基于经验的友好建议,使用好的相机库而不是android-sdk的经典用法会更好。我可以说,Android开发的最糟糕的部分是媒体,特别是相机api。与ios相比,它的羞辱和谷歌自2015年以来没有对这种缺乏做任何开发。