Ответ 1
Я бы посоветовал вам использовать сторонние библиотеки.
Сравнение фотокамер для камеры Android Fotoapparat против CameraKit
Ошибка возникает внутри CameraFragment
- фрагмент, содержащий только FrameLayout (для предварительного просмотра камеры) и ImageButton (используется для захвата изображения). В моем фрагменте у меня есть PictureCallback:
private static Camera.PictureCallback mPicture = new Camera.PictureCallback() {
@Override
public void onPictureTaken(byte[] data, Camera camera) {
CameraFragment.DATA=data;
final int permission = ActivityCompat.checkSelfPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE);
if (permission != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(
activity,
PERMISSIONS_STORAGE,
REQUEST_STORAGE
);
return;
}
saveImageToDevice();
}
};
и я получаю экземпляр своей камеры из HandlerThread:
private CameraHandlerThread mThread = null;
private static class CameraHandlerThread extends HandlerThread {
Handler mHandler = null;
private Camera handlerCamera;
CameraHandlerThread() {
super("CameraHandlerThread");
start();
mHandler = new Handler(getLooper());
}
synchronized void notifyCameraOpened() {
notify();
}
void openCamera() {
mHandler.post(new Runnable() {
@Override
public void run() {
handlerCamera = getCameraInstance();
notifyCameraOpened();
}
});
try {
wait();
}
catch (InterruptedException e) {
}
}
public Camera getCamera() {
return handlerCamera;
}
}
то я вызываю этот метод (где возникает исключение) в OnCreateView():
private void launchCamera() {
newOpenCamera();
mPreview = new CameraPreview(getContext(), mCamera, activity);
mPreview.setCameraDisplayOrientation(activity, CAMERA_ID, mCamera);
preview = (FrameLayout) view.findViewById(R.id.tvCamera);
preview.addView(mPreview);
ivCaptureImage = (ImageView) view.findViewById(R.id.ivCaptureImage);
ivCaptureImage.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mCamera.takePicture(null, null, mPicture);
}
});
}
где newOpenCamera:
private void newOpenCamera() {
if (mThread == null) {
mThread = new CameraHandlerThread();
}
synchronized (mThread) {
mThread.openCamera();
mCamera = mThread.getCamera();
}
}
Я запустил отладчик и вижу, что строка, в которой произошла ошибка (mCamera.takePicture(...) в launchCamera()), вызывается, но ошибка возникает перед PictureCallback. Ошибка:
E/UncaughtException: java.lang.RuntimeException: takePicture failed
at android.hardware.Camera.native_takePicture(Native Method)
at android.hardware.Camera.takePicture(Camera.java:1523)
at android.hardware.Camera.takePicture(Camera.java:1468)
at com.myapp.myapp.camera.CameraFragment$2.onClick(CameraFragment.java:175)
at android.view.View.performClick(View.java:5697)
at android.view.View$PerformClick.run(View.java:22526)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:158)
at android.app.ActivityThread.main(ActivityThread.java:7229)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)
05-28 17:09:22.600 1171-1171/com.myapp.myapp E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.myapp.myapp, PID: 1171
java.lang.RuntimeException: takePicture failed
at android.hardware.Camera.native_takePicture(Native Method)
at android.hardware.Camera.takePicture(Camera.java:1523)
at android.hardware.Camera.takePicture(Camera.java:1468)
at com.myapp.myapp.camera.CameraFragment$2.onClick(CameraFragment.java:175)
at android.view.View.performClick(View.java:5697)
at android.view.View$PerformClick.run(View.java:22526)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:158)
at android.app.ActivityThread.main(ActivityThread.java:7229)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)
Кто-нибудь знает, что может быть неправильным? Как вы можете видеть, я всегда получаю две одинаковые ошибки с каждым сделанным снимком.
Любая помощь высоко ценится, приветствует.
Редактировать:
Я поставил охранников, чтобы остановить одиночные касания, регистрирующиеся как multi, как описано здесь: java.lang.RuntimeException: takePicture failed
Еще не повезло
Я бы посоветовал вам использовать сторонние библиотеки.
Сравнение фотокамер для камеры Android Fotoapparat против CameraKit
Я думаю, что вы забыли вызвать метод startPreview() на свой объект камеры. Из официальной документации:
6.Important: вызвать startPreview(), чтобы начать обновление поверхности предварительного просмотра. Прежде чем вы сможете сделать снимок.
https://developer.android.com/reference/android/hardware/Camera
Используйте этот способ для открытия камеры с использованием поверхностного вида Java Code
public class CameraOverlayActivity extends AppCompatActivity implements SurfaceHolder.Callback {
Camera camera;
SurfaceView surfaceView;
SurfaceHolder surfaceHolder;
boolean previewing = false;
LayoutInflater controlInflater = null;
private File videoPath;
private ImageView imgCapture;
int camBackId;
String strVideoFolderPath;
private ProgressDialog progressDialog;
Camera.Parameters parameters;
public boolean hasFlash;
public boolean camRotation = false;
private RelativeLayout relativeLayout;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_camera_overlay);
relativeLayout = findViewById(R.id.control);
camBackId = Camera.CameraInfo.CAMERA_FACING_BACK;
hasFlash = this.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH);
surfaceView = findViewById(R.id.surface);
progressDialog = new ProgressDialog(this);
progressDialog.setTitle(null);
progressDialog.setCancelable(false);
surfaceHolder = surfaceView.getHolder();
surfaceHolder.addCallback(this);
strVideoFolderPath = Environment.getExternalStorageDirectory().getAbsolutePath();
surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
controlInflater = LayoutInflater.from(getBaseContext());
videoPath = new File(Environment.getExternalStorageDirectory() + "/sw/raw");
if (videoPath.exists()) {
if (videoPath.isDirectory()) {
if (videoPath.listFiles().length != 0) {
String[] children = videoPath.list();
for (int i = 0; i < children.length; i++) {
new File(videoPath, children[i]).delete();
}
}
}
}
if (!videoPath.exists()) {
videoPath.mkdirs();
}
imgCapture = findViewById(R.id.img_capture);
imgCapture.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (camera != null) {
if (previewing) {
System.gc();
try {
capturePhoto();
} catch (Exception e) {
Log.v("ERRORR", e.getMessage());
e.printStackTrace();
}
}
}
}
});
}
public void capturePhoto() throws Exception {
camera.takePicture(null, null, myPictureCallback_JPG);
}
@Override
protected void onResume() {
super.onResume();
Display display = ((WindowManager) getSystemService(WINDOW_SERVICE)).getDefaultDisplay();
}
Camera.PictureCallback myPictureCallback_JPG = new Camera.PictureCallback() {
@Override
public void onPictureTaken(byte[] arg0, Camera arg1) {
// TODO Auto-generated method stub
FileOutputStream outStream = null;
//camera.startPreview();
try {
Date date = new Date();
String filename = "/rec" + date.toString().replace(" ", "_").replace(":", "_") + ".jpg";
filename = filename.replace("+", "");
File file = new File(Environment.getExternalStorageDirectory() + "/Switch It");
if (!file.exists())
file.mkdirs();
outStream = new FileOutputStream(file + filename);
outStream.write(arg0);
outStream.close();
Log.v("File_Path", file.getAbsolutePath());
Intent returnIntent = new Intent();
returnIntent.putExtra("img_capture", file.getAbsolutePath() + filename);
setResult(Activity.RESULT_OK, returnIntent);
finish();
} catch (FileNotFoundException e) {
Log.e("ERROR 1", e.getMessage());
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
Log.e("ERROR 2", e.getMessage());
} finally {
}
}
};
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
// TODO Auto-generated method stub
if (previewing) {
camera.stopPreview();
previewing = false;
}
if (camera != null) {
try {
camera.setPreviewDisplay(surfaceHolder);
parameters = camera.getParameters();
if (getPackageManager().hasSystemFeature("android.hardware.camera.autofocus")) {
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
}
camera.startPreview();
if (hasFlash) {
parameters.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
}
camera.setParameters(parameters);
previewing = true;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
// TODO Auto-generated method stub
camera = Camera.open();
if (android.os.Build.VERSION.SDK_INT > 7) {
Display display = ((WindowManager) getSystemService(WINDOW_SERVICE)).getDefaultDisplay();
if (display.getRotation() == Surface.ROTATION_0) {
camera.setDisplayOrientation(90);
camRotation = true;
}
}
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
if (camera != null) {
camera.stopPreview();
camera.release();
camera = null;
previewing = false;
}
}
}
XML-код
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/control"
android:layout_width="match_parent"
android:layout_height="match_parent">
<SurfaceView
android:id="@+id/surface"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<ImageView
android:id="@+id/img_capture"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_marginRight="5dp"
android:src="@drawable/ic_lens_black_24dp" />
</RelativeLayout>
Проверьте, установлено ли разрешение на использование камеры для данного конкретного приложения. Перейдите в Настройки → Приложения → "Имя вашего приложения" → Разрешения → Включите разрешение для камеры. Также убедитесь, что разрешение указано в файле manifest.xml. Он задается как:
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Проверьте эту ссылку для получения более подробной информации:
Попробуйте это для меня, и проверьте разрешение, указанное в файле манифеста.
mCamera = Camera.open(id);
setCameraDisplayOrientation(mContext, id, mCamera);
mCamera.setPreviewDisplay(new DummySurfaceHolder());
SurfaceTexture st = new SurfaceTexture(MODE_PRIVATE);
mCamera.setPreviewTexture(st);
mCamera.startPreview();
mCamera.autoFocus(new Camera.AutoFocusCallback() {
@Override
public void onAutoFocus(boolean b, Camera camera) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
mCamera.takePicture(null, null, null, new PictureCapture(mContext));
}
});