I have a custom camera application , everything works fine .But whenever the app gets paused (when the onPause or onDestroyed is called) camera is released and afterwards when onResume is called and capture button is clicked is to take an image ,my Application crashes.How do i fix this ? Please help me , Thanks in advance
CameraActivity Code
package com.example.skmishra.plates.Activities;
import android.app.ActionBar;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.hardware.Camera;
import android.hardware.SensorManager;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.util.Log;
import android.view.MotionEvent;
import android.view.OrientationEventListener;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.ZoomControls;
import com.example.skmishra.plates.Asyncs.CameraAsync;
import com.example.skmishra.plates.CameraHandler;
import com.example.skmishra.plates.Library.Fonts;
import com.example.skmishra.plates.R;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.SortedSet;
import java.util.TreeSet;
/**
* Created by skmishra on 12/28/2015.
*/
public class camera extends Activity {
private static final int RESULT_LOAD_IMAGE = 200 ;
private Camera mCamera=null;
private CameraHandler surface_view;
public static final int MEDIA_TYPE_IMAGE = 1;
public static final int MEDIA_TYPE_VIDEO = 2;
public static final String TAG = "Aloo";
int toRotate = 90;
public int currentCameraID = 0;
OrientationEventListener myOrientationEventListener;
private ZoomControls zoomControls;
private double mDist;
Boolean imageSwitchClicked = false;
Boolean mShowFlash = false;
ImageView mSwitch_cam;
ImageView mFlashBut;
FrameLayout preview;
CameraAsync mCamAsync;
ImageView imageGallery;
TextView raleway;
TextView headerCameraText;
Fonts mFonts;
int permCode=4;
Camera.Parameters params;
String recievedType=null;
#Override
protected void onCreate(Bundle savedInstanceState) {
Log.e("I Called Thus "," cda");
mCamAsync=new CameraAsync(this);
mCamAsync.execute();
super.onCreate(savedInstanceState);
setContentView(R.layout.camera);
imageGallery = (ImageView) findViewById(R.id.select_gallery);
mFonts = new Fonts();
preview = (FrameLayout) findViewById(R.id.camera_preview);
mFlashBut = (ImageView) findViewById(R.id.flash);
mSwitch_cam = (ImageView) findViewById(R.id.white_switch);
raleway = (TextView) findViewById(R.id.textView2);
headerCameraText = (TextView) findViewById(R.id.imageHead);
// mFonts.setRalewayBold(this, headerCameraText);
Intent gets = getIntent();
recievedType = gets.getExtras().getString("recievedCameraPurpose");
handleHeaderText(recievedType);
mFonts.setRalewayBold(this, raleway);
myOrientationEventListener
= new OrientationEventListener(this, SensorManager.SENSOR_DELAY_NORMAL) {
#Override
public void onOrientationChanged(int arg0) {
int rotation = arg0;
if (rotation > 340) {
if (currentCameraID == 0) {
toRotate = 90;
} else {
toRotate =270;
Log.e("POSITION_TITLT", "-> Potrait Front camera");
}
} else if (rotation < 80 && rotation > 30) {
toRotate = 180;
Log.e("POSITION_TILT", "-> Landscape Right " + rotation);
} else if (rotation < 280 && rotation > 240) {
toRotate = 0;
Log.e("POSITION_TILT", "-> Landscape Left " + rotation);
}
}
};
if (myOrientationEventListener.canDetectOrientation()) {
myOrientationEventListener.enable();
} else {
Toast.makeText(this, "Can't DetectOrientation", Toast.LENGTH_LONG).show();
finish();
}
}
private boolean checkifCamera(Context context) {
if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)) {
return true;
} else {
return false;
}
}
public Camera getCameraInstance() {
Camera c = null;
try {
releaseCameraAndPreview();
c = Camera.open();
} catch (Exception e) {
Toast.makeText(this, "Print error" + e.getMessage(), Toast.LENGTH_LONG).show();
}
return c;
}
public void onCompleteInstanceCameraAysnc(Camera camera)
{
mCamera = camera;
surface_view = new CameraHandler(this, mCamera);
params = mCamera.getParameters();
preview.addView(surface_view);
set_image_gallery();
}
public void switchC(View view) {
if (!imageSwitchClicked) {
mSwitch_cam.setAlpha(1.0f);
imageSwitchClicked = true;
} else {
mSwitch_cam.setAlpha(0.5f);
imageSwitchClicked = false;
}
setCameraID();
mCamera = surface_view.switchCamera();
params=mCamera.getParameters();
}
public void flash_onOf(View view) {
if (!mShowFlash) {
params.setFlashMode(Camera.Parameters.FLASH_MODE_ON);
mFlashBut.setAlpha(1.0f);
mShowFlash = true;
} else {
params.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
mFlashBut.setAlpha(0.5f);
mShowFlash = false;
}
}
private void releaseCameraAndPreview() {
if (mCamera != null) {
mCamera.stopPreview();
mCamera.setPreviewCallback(null);
mCamera.lock();
mCamera.release();
mCamera=null;
}
else
{
Log.e("Cert","Lerts");
}
}
#Override
protected void onResume() {
super.onResume();
}
#Override
protected void onDestroy() {
Log.e("LLL", "Dessssdccc");
super.onDestroy();
try {
mCamera.stopPreview();
mCamera.setPreviewCallback(null);
mCamera.lock();
myOrientationEventListener.disable();
mCamera.release();
mCamera=null;
permCode=15;
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
protected void onPause() {
Log.e("LLL", "Dessssdccc");
super.onPause();
try {
mCamera.stopPreview();
mCamera.setPreviewCallback(null);
mCamera.lock();
myOrientationEventListener.disable();
mCamera.release();
mCamera=null;
permCode=15;
} catch (Exception e) {
e.printStackTrace();
}
}
public void takePH(View view) {
if(mShowFlash && !imageSwitchClicked)
{
params.setFlashMode(Camera.Parameters.FLASH_MODE_ON);
}
params.set("rotation", toRotate);
mCamera.setParameters(params);
mCamera.takePicture(null, null, mPicture);
}
Camera.PictureCallback mPicture = new Camera.PictureCallback() {
#Override
public void onPictureTaken(byte[] data, Camera camera) {
File pictureFile = getOutputMediaFile(MEDIA_TYPE_IMAGE);
if (pictureFile == null) {
Log.d(TAG, "Error creating media file, check storage permissions: ");
return;
}
try {
FileOutputStream fos = new FileOutputStream(pictureFile);
fos.write(data);
fos.close();
} catch (FileNotFoundException e) {
Log.d(TAG, "File not found: " + e.getMessage());
} catch (IOException e) {
Log.d(TAG, "Error accessing file: " + e.getMessage());
}
Intent i=new Intent(getApplicationContext(),ShowOut.class);
i.putExtra("purpose",recievedType);
i.putExtra("img-url",pictureFile.toString());
startActivity(i);
}
};
/**
* Create a file Uri for saving an image or video
*/
private static Uri getOutputMediaFileUri(int type) {
return Uri.fromFile(getOutputMediaFile(type));
}
/**
* Create a File for saving an image or video
*/
private static File getOutputMediaFile(int type) {
// To be safe, you should check that the SDCard is mounted
// using Environment.getExternalStorageState() before doing this.
File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES), "Plates");
// This location works best if you want the created images to be shared
// between applications and persist after your app has been uninstalled.
// Create the storage directory if it does not exist
if (!mediaStorageDir.exists()) {
if (!mediaStorageDir.mkdirs()) {
Log.d("MyCameraApp", "failed to create directory");
return null;
}
}
// Create a media file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
File mediaFile;
if (type == MEDIA_TYPE_IMAGE) {
mediaFile = new File(mediaStorageDir.getPath() + File.separator +
"IMG_" + timeStamp + ".jpg");
} else if (type == MEDIA_TYPE_VIDEO) {
mediaFile = new File(mediaStorageDir.getPath() + File.separator +
"VID_" + timeStamp + ".mp4");
} else {
return null;
}
return mediaFile;
}
public void handleHeaderText(String type) {
Log.e("Type",type);
headerCameraText.setText("");
if (type.equals("ADD_COVER_PLATES")) {
headerCameraText.setText("Take a cover image for your plate");
}
else if(type.equals("ADD_PROFILE_USER"))
{
imageGallery.setVisibility(View.GONE);
}
else if(type.equals("PLATE_UPLOAD_SINGLETON")) {
headerCameraText.setText("Click an image for a plate");
}
}
public void setCameraID() {
if (currentCameraID == Camera.CameraInfo.CAMERA_FACING_BACK) {
currentCameraID = Camera.CameraInfo.CAMERA_FACING_FRONT;
toRotate = 270;
} else {
currentCameraID = Camera.CameraInfo.CAMERA_FACING_BACK;
toRotate = 90;
}
}
#Override
public boolean onTouchEvent(MotionEvent event) {
// Get the pointer ID
Camera.Parameters params = mCamera.getParameters();
int action = event.getAction();
if (event.getPointerCount() > 1) {
// handle multi-touch events
if (action == MotionEvent.ACTION_POINTER_DOWN) {
mDist = getFingerSpacing(event);
} else if (action == MotionEvent.ACTION_MOVE && params.isZoomSupported()) {
mCamera.cancelAutoFocus();
handleZoom(event, params);
}
} else {
// handle single touch events
if (action == MotionEvent.ACTION_UP) {
handleFocus(event, params);
}
}
return true;
}
private void handleZoom(MotionEvent event, Camera.Parameters params) {
int maxZoom = params.getMaxZoom();
int zoom = params.getZoom();
double newDist = getFingerSpacing(event);
if (newDist > mDist) {
//zoom in
if (zoom < maxZoom)
zoom++;
} else if (newDist < mDist) {
//zoom out
if (zoom > 0)
zoom--;
}
mDist = newDist;
params.setZoom(zoom);
mCamera.setParameters(params);
}
public void handleFocus(MotionEvent event, Camera.Parameters params) {
int pointerId = event.getPointerId(0);
int pointerIndex = event.findPointerIndex(pointerId);
// Get the pointer's current position
float x = event.getX(pointerIndex);
float y = event.getY(pointerIndex);
List<String> supportedFocusModes = params.getSupportedFocusModes();
if (supportedFocusModes != null && supportedFocusModes.contains(Camera.Parameters.FOCUS_MODE_AUTO)) {
mCamera.autoFocus(new Camera.AutoFocusCallback() {
#Override
public void onAutoFocus(boolean b, Camera camera) {
// currently set to auto-focus on single touch
}
});
}
}
/**
* Determine the space between the first two fingers
*/
private double getFingerSpacing(MotionEvent event) {
// ...
float x = event.getX(0) - event.getX(1);
float y = event.getY(0) - event.getY(1);
double pres;
pres = Math.sqrt(x * x + y * y);
return pres;
}
public void set_image_gallery() {
// Find the last picture
String[] projection = new String[]{
MediaStore.Images.ImageColumns._ID,
MediaStore.Images.ImageColumns.DATA,
MediaStore.Images.ImageColumns.BUCKET_DISPLAY_NAME,
MediaStore.Images.ImageColumns.DATE_TAKEN,
MediaStore.Images.ImageColumns.MIME_TYPE
};
final Cursor cursor = getContentResolver()
.query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, projection, null,
null,MediaStore.Images.ImageColumns._ID + " DESC");
// Put it in the image view
if (cursor.moveToFirst()) {
String imageLocation = cursor.getString(1);
File imageFile = new File(imageLocation);
if (imageFile.exists()) { // TODO: is there a better way to do this?
Bitmap bm=decodeFile(imageFile);
imageGallery.setImageBitmap(bm);
}
}
cursor.close();
}
public Bitmap decodeFile(File f) {
try {
//Decode image size
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeStream(new FileInputStream(f), null, o);
//The new size we want to scale to
final int REQUIRED_SIZE = 490;
//Find the correct scale value. It should be the power of 2.
int scale = 1;
while (o.outWidth / scale / 2 >= REQUIRED_SIZE && o.outHeight / scale / 2 >= REQUIRED_SIZE)
scale *= 2;
//Decode with inSampleSize
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize = scale;
return BitmapFactory.decodeStream(new FileInputStream(f), null, o2);
} catch (FileNotFoundException e) {
}
return null;
}
public void imagePick(View view)
{
Intent photoPickerIntent = new Intent(Intent.ACTION_PICK);
photoPickerIntent.setType("image/*");
startActivityForResult(photoPickerIntent, RESULT_LOAD_IMAGE);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == RESULT_LOAD_IMAGE && resultCode == RESULT_OK && null != data) {
Uri selectedImage = data.getData();
String[] filePathColumn = {MediaStore.Images.Media.DATA};
Cursor cursor = getContentResolver().query(selectedImage,
filePathColumn, null, null, null);
cursor.moveToFirst();
int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
String picturePath = cursor.getString(columnIndex);
cursor.close();
Intent transfer=null;
if(recievedType.equals("ADD_COVER_PLATES")) {
transfer = new Intent(this, create_plates.class);
}
else if(recievedType.equals("PLATE_UPLOAD_SINGLETON"))
{
transfer=new Intent(this,plate_select_upload.class);
}
transfer.putExtra("imagUrl",picturePath);
startActivity(transfer);
}
}
}
Camera Handler Code
package com.example.skmishra.plates;
import android.content.Context;
import android.hardware.Camera;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import java.io.IOException;
/**
* Created by skmishra on 12/28/2015.
*/
public class CameraHandler extends SurfaceView implements SurfaceHolder.Callback {
private SurfaceHolder mHolder;
private Camera mCamera=null;
public int currentCameraID=0;
public CameraHandler(Context context,Camera camera) {
super(context);
mCamera=camera;
mHolder=getHolder();
mHolder.addCallback(this);
mHolder.setType(SurfaceHolder.SURFACE_TYPE_GPU);
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
try {
if(mCamera==null)
{
mCamera=Camera.open();
}
mCamera.setPreviewDisplay(holder);
Camera.Parameters p = mCamera.getParameters();
}
catch (IOException e)
{
Log.d("--DS", "Error setting camera preview: " + e.getMessage());
}
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
fixOr();
if(mHolder.getSurface()==null)
{
return;
}
if (mHolder.getSurface() == null){
// preview surface does not exist
return;
}
// stop preview before making changes
try {
mCamera.stopPreview();
} catch (Exception e){
// ignore: tried to stop a non-existent preview
}
// set preview size and make any resize, rotate or
// reformatting changes here
// start preview with new settings
try {
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
} catch (Exception e){
Log.d("--DS", "Error starting camera preview: " + e.getMessage());
}
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
mCamera.release();
mCamera = null;
}
public void fixOr()
{
mCamera.stopPreview();
mCamera.setDisplayOrientation(90);
mCamera.startPreview();
}
public Camera switchCamera() {
mCamera.stopPreview();
mCamera.release();
if(currentCameraID==Camera.CameraInfo.CAMERA_FACING_BACK)
{
currentCameraID = Camera.CameraInfo.CAMERA_FACING_FRONT;
}
else
{
currentCameraID=Camera.CameraInfo.CAMERA_FACING_BACK;
}
mCamera=Camera.open(currentCameraID);
fixOr();
try {
mCamera.setPreviewDisplay(mHolder);
} catch (IOException e) {
e.printStackTrace();
}
mCamera.startPreview();
return mCamera;
}
}
UPDATE **
StackTrace
Process: com.example.skmishra.plates, PID: 10575
java.lang.RuntimeException: Fail to connect to camera service
at android.hardware.Camera.<init>(Camera.java:545)
at android.hardware.Camera.open(Camera.java:403)
at com.example.skmishra.plates.CameraHandler.surfaceCreated(CameraHandler.java:35)
at android.view.SurfaceView.updateWindow(SurfaceView.java:599)
at android.view.SurfaceView.onWindowVisibilityChanged(SurfaceView.java:243)
at android.view.View.dispatchWindowVisibilityChanged(View.java:9034)
at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1275)
at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1275)
at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1275)
at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1275)
at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1275)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1319)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1062)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:5873)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:767)
at android.view.Choreographer.doCallbacks(Choreographer.java:580)
at android.view.Choreographer.doFrame(Choreographer.java:550)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:753)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5753)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1405)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1200)
After a lot of research , i finally found out what the problem was . Problem was with the FrameLayout , i had to remove it on Pause and recreate it on OnResume
#Override
protected void onResume() {
super.onResume();
mCamAsync = new CameraAsync(this);//Async task to get the camera instance
mCamAsync.execute();
}
#Override
protected void onPause() {
super.onPause();
releaseCameraAndPreview();
preview = (FrameLayout) findViewById(R.id.camera_preview);
preview.removeViewAt(0);
}
** EDIT **
i also removed the execution of cameraAsync from onCreate , that means i instantiate the camera only in OnResume
Related
The camera preview is freezing when I press the Capture button, but when I move the camera while the preview is frozen, the image turns out blurry. I am trying to just simply take a picture when the camera button is clicked and not have to worry about holding the camera still while the preview is frozen.
MainActivity:
package com.example.androidcamera2api;
import android.Manifest;
import android.content.Context;
import android.content.pm.PackageManager;
import android.graphics.ImageFormat;
import android.graphics.SurfaceTexture;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCaptureSession;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.CameraManager;
import android.hardware.camera2.CameraMetadata;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.TotalCaptureResult;
import android.hardware.camera2.params.StreamConfigurationMap;
import android.media.Image;
import android.media.ImageReader;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.HandlerThread;
import android.util.Log;
import android.util.Size;
import android.util.SparseIntArray;
import android.view.Surface;
import android.view.TextureView;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import com.example.androidcamera2api.R;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class MainActivity extends AppCompatActivity {
private static final String TAG = "AndroidCameraApi";
private Button takePictureButton;
private TextureView textureView;
private static final SparseIntArray ORIENTATIONS = new SparseIntArray();
static {
ORIENTATIONS.append(Surface.ROTATION_0, 90);
ORIENTATIONS.append(Surface.ROTATION_90, 0);
ORIENTATIONS.append(Surface.ROTATION_180, 270);
ORIENTATIONS.append(Surface.ROTATION_270, 180);
}
private String cameraId;
protected CameraDevice cameraDevice;
protected CameraCaptureSession cameraCaptureSessions;
protected CaptureRequest captureRequest;
protected CaptureRequest.Builder captureRequestBuilder;
private Size imageDimension;
private ImageReader imageReader;
private File file;
private static final int REQUEST_CAMERA_PERMISSION = 200;
private boolean mFlashSupported;
private Handler mBackgroundHandler;
private HandlerThread mBackgroundThread;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textureView = (TextureView) findViewById(R.id.texture);
assert textureView != null;
textureView.setSurfaceTextureListener(textureListener);
takePictureButton = (Button) findViewById(R.id.btn_takepicture);
assert takePictureButton != null;
takePictureButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
takePicture();
}
});
}
TextureView.SurfaceTextureListener textureListener = new TextureView.SurfaceTextureListener() {
#Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
//open your camera here
openCamera();
}
#Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
// Transform you image captured size according to the surface width and height
}
#Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
return false;
}
#Override
public void onSurfaceTextureUpdated(SurfaceTexture surface) {
}
};
private final CameraDevice.StateCallback stateCallback = new CameraDevice.StateCallback() {
#Override
public void onOpened(CameraDevice camera) {
//This is called when the camera is open
Log.e(TAG, "onOpened");
cameraDevice = camera;
createCameraPreview();
}
#Override
public void onDisconnected(CameraDevice camera) {
cameraDevice.close();
}
#Override
public void onError(CameraDevice camera, int error) {
cameraDevice.close();
cameraDevice = null;
}
};
final CameraCaptureSession.CaptureCallback captureCallbackListener = new CameraCaptureSession.CaptureCallback() {
#Override
public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request, TotalCaptureResult result) {
super.onCaptureCompleted(session, request, result);
Toast.makeText(MainActivity.this, "Saved:" + file, Toast.LENGTH_SHORT).show();
createCameraPreview();
}
};
protected void startBackgroundThread() {
mBackgroundThread = new HandlerThread("Camera Background");
mBackgroundThread.start();
mBackgroundHandler = new Handler(mBackgroundThread.getLooper());
}
protected void stopBackgroundThread() {
mBackgroundThread.quitSafely();
try {
mBackgroundThread.join();
mBackgroundThread = null;
mBackgroundHandler = null;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
protected void takePicture() {
if(null == cameraDevice) {
Log.e(TAG, "cameraDevice is null");
return;
}
CameraManager manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
try {
CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraDevice.getId());
Size[] jpegSizes = null;
if (characteristics != null) {
jpegSizes = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP).getOutputSizes(ImageFormat.JPEG);
}
int width = 640;
int height = 480;
if (jpegSizes != null && 0 < jpegSizes.length) {
width = jpegSizes[0].getWidth();
height = jpegSizes[0].getHeight();
}
ImageReader reader = ImageReader.newInstance(width, height, ImageFormat.JPEG, 1);
List<Surface> outputSurfaces = new ArrayList<Surface>(2);
outputSurfaces.add(reader.getSurface());
outputSurfaces.add(new Surface(textureView.getSurfaceTexture()));
final CaptureRequest.Builder captureBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
captureBuilder.addTarget(reader.getSurface());
captureBuilder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO);
// Orientation
int rotation = getWindowManager().getDefaultDisplay().getRotation();
captureBuilder.set(CaptureRequest.JPEG_ORIENTATION, ORIENTATIONS.get(rotation));
final File file = new File(Environment.getExternalStorageDirectory()+"/pic.jpg");
ImageReader.OnImageAvailableListener readerListener = new ImageReader.OnImageAvailableListener() {
#Override
public void onImageAvailable(ImageReader reader) {
Image image = null;
try {
image = reader.acquireLatestImage();
ByteBuffer buffer = image.getPlanes()[0].getBuffer();
byte[] bytes = new byte[buffer.capacity()];
buffer.get(bytes);
save(bytes);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (image != null) {
image.close();
}
}
}
private void save(byte[] bytes) throws IOException {
OutputStream output = null;
try {
output = new FileOutputStream(file);
output.write(bytes);
} finally {
if (null != output) {
output.close();
}
}
}
};
reader.setOnImageAvailableListener(readerListener, mBackgroundHandler);
final CameraCaptureSession.CaptureCallback captureListener = new CameraCaptureSession.CaptureCallback() {
#Override
public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request, TotalCaptureResult result) {
super.onCaptureCompleted(session, request, result);
Toast.makeText(MainActivity.this, "Saved:" + file, Toast.LENGTH_SHORT).show();
createCameraPreview();
}
};
cameraDevice.createCaptureSession(outputSurfaces, new CameraCaptureSession.StateCallback() {
#Override
public void onConfigured(CameraCaptureSession session) {
try {
session.capture(captureBuilder.build(), captureListener, mBackgroundHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
#Override
public void onConfigureFailed(CameraCaptureSession session) {
}
}, mBackgroundHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
protected void createCameraPreview() {
try {
SurfaceTexture texture = textureView.getSurfaceTexture();
assert texture != null;
texture.setDefaultBufferSize(imageDimension.getWidth(), imageDimension.getHeight());
Surface surface = new Surface(texture);
captureRequestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
captureRequestBuilder.addTarget(surface);
cameraDevice.createCaptureSession(Arrays.asList(surface), new CameraCaptureSession.StateCallback(){
#Override
public void onConfigured(#NonNull CameraCaptureSession cameraCaptureSession) {
//The camera is already closed
if (null == cameraDevice) {
return;
}
// When the session is ready, we start displaying the preview.
cameraCaptureSessions = cameraCaptureSession;
updatePreview();
}
#Override
public void onConfigureFailed(#NonNull CameraCaptureSession cameraCaptureSession) {
Toast.makeText(MainActivity.this, "Configuration change", Toast.LENGTH_SHORT).show();
}
}, null);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
private void openCamera() {
CameraManager manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
Log.e(TAG, "is camera open");
try {
cameraId = manager.getCameraIdList()[0];
CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId);
StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
assert map != null;
imageDimension = map.getOutputSizes(SurfaceTexture.class)[0];
// Add permission for camera and let user grant the permission
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_CAMERA_PERMISSION);
return;
}
manager.openCamera(cameraId, stateCallback, null);
} catch (CameraAccessException e) {
e.printStackTrace();
}
Log.e(TAG, "openCamera X");
}
protected void updatePreview() {
if(null == cameraDevice) {
Log.e(TAG, "updatePreview error, return");
}
captureRequestBuilder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO);
try {
cameraCaptureSessions.setRepeatingRequest(captureRequestBuilder.build(), null, mBackgroundHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
private void closeCamera() {
if (null != cameraDevice) {
cameraDevice.close();
cameraDevice = null;
}
if (null != imageReader) {
imageReader.close();
imageReader = null;
}
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
if (requestCode == REQUEST_CAMERA_PERMISSION) {
if (grantResults[0] == PackageManager.PERMISSION_DENIED) {
// close the app
Toast.makeText(MainActivity.this, "Sorry!!!, you can't use this app without granting permission", Toast.LENGTH_LONG).show();
finish();
}
}
}
#Override
protected void onResume() {
super.onResume();
Log.e(TAG, "onResume");
startBackgroundThread();
if (textureView.isAvailable()) {
openCamera();
} else {
textureView.setSurfaceTextureListener(textureListener);
}
}
#Override
protected void onPause() {
Log.e(TAG, "onPause");
//closeCamera();
stopBackgroundThread();
super.onPause();
}
}
Android Manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.androidcamera2api">
<uses-sdk
android:minSdkVersion="21"
android:targetSdkVersion="21" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-feature android:name="android.hardware.camera2.full" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Hear is the code of my fragment. I am Using the Media Player for recording
this code work when i use only single camera Like ForntCamera and BackCamera But When i use switch the camera using camaraId then it media Player give an Exception of " Invalid preview surface ". Where am I wrong?
Please Help Me. Thanks is Advance
import android.hardware.Camera;
import android.media.CamcorderProfile;
import android.media.MediaPlayer;
import android.media.MediaRecorder;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.TextClock;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import static android.provider.MediaStore.Files.FileColumns.MEDIA_TYPE_IMAGE;
import static android.provider.MediaStore.Files.FileColumns.MEDIA_TYPE_VIDEO;
import static mms.dweb.buzzcutz.ApplicationContext.TAG;
public class VideoRecordFragmentB extends BaseFragment {
#BindView(R.id.record_btn_frb)
ImageView record_btn;
#BindView(R.id.cameraSwitch)
ImageView cameraSwitch;
#BindView(R.id.mTextField)
TextClock mTextField;
int camId = 0;
#BindView(R.id.camera_preview)
FrameLayout preview;
MediaPlayer mediaPlayer;
String catId;
Boolean back = true;
private View fragmentView;
private MainActivity mainActivity;
private Camera mCamera;
private CameraPreview mPreview;
private MediaRecorder mMediaRecorder;
private boolean isRecording = false;
private CategoryResponce.Responsedata categoryData;
private static Uri getOutputMediaFileUri(int type) {
return Uri.fromFile(getOutputMediaFile(type));
}
/**
* Create a File for saving an image or video
*/
private static File getOutputMediaFile(int type) {
// To be safe, you should check that the SDCard is mounted
// using Environment.getExternalStorageState() before doing this.
File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES), "Buzzcut");
// This location works best if you want the created images to be shared
// between applications and persist after your app has been uninstalled.
// Create the storage directory if it does not exist
if (!mediaStorageDir.exists()) {
if (!mediaStorageDir.mkdirs()) {
Log.d("MyCameraApp", "failed to create directory");
return null;
}
}
// Create a media file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
File mediaFile;
if (type == MEDIA_TYPE_IMAGE) {
mediaFile = new File(mediaStorageDir.getPath() + File.separator +
"IMG_" + timeStamp + ".jpg");
} else if (type == MEDIA_TYPE_VIDEO) {
mediaFile = new File(mediaStorageDir.getPath() + File.separator +
"VID_" + timeStamp + ".mp4");
} else {
return null;
}
return mediaFile;
}
#OnClick(R.id.cameraSwitch)
void changeCam() {
if (camId == 0) {
camId = 1;
} else {
camId = 0;
}
managView();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
fragmentView =
inflater.inflate(R.layout.fragment_video_record_fragment_b, container, false);
ButterKnife.bind(this, fragmentView);
initializeView();
return fragmentView;
}
#Override
public void initializeView() {
super.initializeView();
if (getActivity() instanceof MainActivity) {
mainActivity = (MainActivity) getActivity();
}
managView();
}
private void managView() {
mCamera = getCameraInstance(camId);
mPreview = new CameraPreview(getContext(), mCamera);
preview.addView(mPreview);
Bundle bundle = getArguments();
categoryData = (CategoryResponce.Responsedata)
bundle.getSerializable("CategoryResponceData");
catId = categoryData.getId();
Bundle bundle1 = new Bundle();
bundle1.putSerializable("CategoryResponceData", categoryData);
record_btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (isRecording) {
// stop recording and release camera
mMediaRecorder.stop(); // stop the recording
releaseMediaRecorder(); // release the MediaRecorder object
mCamera.lock();// take camera access back from MediaRecorder
record_btn.setImageResource(R.drawable.record_btn);
// inform the user that recording has stopped
isRecording = false;
Bundle bundle = new Bundle();
bundle.putString("fileUri",
getOutputMediaFileUri(MEDIA_TYPE_VIDEO).toString());
bundle.putSerializable("CategoryResponceData", categoryData);
mainActivity.replaceFragment(FragmentNames.VideoUploadFragment, bundle, false, false);
} else {
// initialize video camera
if (prepareVideoRecorder(camId)) {
// Camera is available and unlocked, MediaRecorder is prepared,
// now you can start recording
record_btn.setImageResource(R.drawable.recoder);
mMediaRecorder.start();
// inform the user that recording has started
isRecording = true;
} else {
// prepare didn't work, release the camera
releaseMediaRecorder();
// inform user
}
}
}
});
}
#Override
public void onStop() {
super.onStop();
}
public Camera getCameraInstance(int camid) {
releaseCameraAndPreview();
Camera c = null;
try {
c = Camera.open(camid); // attempt to get a Camera instance
} catch (Exception e) {
// Camera is not available (in use or does not exist)
}
return c; // returns null if camera is unavailable
}
private void releaseCameraAndPreview() {
preview.removeAllViews();
if (mCamera != null) {
mCamera.release();
mCamera = null;
}
}
private boolean prepareVideoRecorder(int camid) {
mCamera = getCameraInstance(camid);
mMediaRecorder = new MediaRecorder();
mCamera.unlock();
mMediaRecorder.setCamera(mCamera);
mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
mMediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH));
mMediaRecorder.setOutputFile(getOutputMediaFile(MEDIA_TYPE_VIDEO).toString());
mMediaRecorder.setPreviewDisplay(mPreview.getHolder().getSurface());
try {
mMediaRecorder.prepare();
} catch (IllegalStateException e) {
Log.d(TAG, "IllegalStateException preparing MediaRecorder: " + e.getMessage());
releaseMediaRecorder();
return false;
} catch (IOException e) {
Log.d(TAG, "IOException preparing MediaRecorder: " + e.getMessage());
releaseMediaRecorder();
return false;
}
return true;
}
#Override
public void onPause() {
super.onPause();
releaseMediaRecorder(); // if you are using MediaRecorder, release it first
releaseCamera(); // release the camera immediately on pause event
}
private void releaseMediaRecorder() {
if (mMediaRecorder != null) {
mMediaRecorder.reset(); // clear recorder configuration
mMediaRecorder.release(); // release the recorder object
mMediaRecorder = null;
mCamera.lock(); // lock camera for later use
}
}
private void releaseCamera() {
if (mCamera != null) {
mCamera.release(); // release the camera for other applications
mCamera = null;
}
}
}
Hear is the Camera Preview Class. I am Using this class for get Camera
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
private SurfaceHolder mHolder;
private Camera mCamera;
private CamcorderProfile camcorderProfile;
public CameraPreview(Context context, Camera camera) {
super(context);
mCamera = camera;
mHolder = getHolder();
mHolder.addCallback(this);
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
public void surfaceCreated(SurfaceHolder holder) {
preview.
try {
mCamera.setPreviewDisplay(holder);
mCamera.setDisplayOrientation(90);
mCamera.startPreview();
} catch (IOException e) {
Log.d(TAG, "Error setting camera preview: " + e.getMessage());
}
}
public void surfaceDestroyed(SurfaceHolder holder) {
}
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
if (mHolder.getSurface() == null){
return;
}
try {
mCamera.stopPreview();
} catch (Exception e){
}
try {
mCamera.setPreviewDisplay(mHolder);
mCamera.setDisplayOrientation(90);
mCamera.startPreview();
} catch (Exception e){
Log.d(TAG, "Error starting camera preview: " + e.getMessage());
}
}
}
Anyway please initialize the view in onResume please
#Override
public void onResume() {
super.onResume();
initializeView();
}
have you declared the permission in the manifest please:
<uses-permission android:name="android.permission.RECORD_AUDIO" />
For most versions, this works fine, but for Api 24-25, the MEDIA_ERROR_SERVER_AD error occurs immediately when the recording starts and you must finish the recording.
If there are any specific reasons, can this be handled in order not to interrupt the recording?
if this helps, then I attach the code. Thaks!
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.hardware.Camera;
import android.media.CamcorderProfile;
import android.media.MediaRecorder;
import android.os.BatteryManager;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.OrientationEventListener;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import javax.inject.Inject;
public class MainCameraFragment extends BaseFragment implements SurfaceHolder.Callback,
MediaRecorder.OnErrorListener, MediaRecorder.OnInfoListener {
private static final String TAG = "MainCameraFragment";
private static final float MIN_BATTERY_CHARGE = 0.1f;
private Camera camera = null;
private int cameraId = -1;
private MediaRecorder recorder = null;
private boolean inPreview = false;
private Action<RecordingError> recordingErrorAction = null;
/** Surface view container. */
private FrameLayout container;
/** Surface view instance. */
private SurfaceView surfaceView;
/** Orientation listener. */
private OrientationEventListener orientationEventListener;
/** Start recording time. */
private long startRecordingTime = 0;
/** Last video path. */
private File lastVideoPath;
/** Recording manager instance. */
#Inject
RecordingManager recordingManager;
/** Settings manager instance. */
#Inject
SettingsManager settingsManager;
/** Do on resume. */
private Runnable doOnResume;
public enum RecordingError {
ILLEGAL_MEDIA_RECORDER_STATE,
NOT_ENOUGH_MEMORY,
NOT_ENOUGH_BATTERY,
}
/** Start preview from camera. */
private void startPreview() {
if (camera != null && !inPreview) {
try {
camera.setPreviewDisplay(surfaceView.getHolder());
Camera.Parameters parameters = camera.getParameters();
final List<Camera.Size> supportedSizes = parameters.getSupportedPreviewSizes();
Camera.Size bestFitSize = camera.new Size(0, 0);
for( Camera.Size size : supportedSizes ) {
if( size.width <= surfaceView.getWidth() && size.height <= surfaceView.getHeight() ) {
bestFitSize = size;
break;
}
}
if( bestFitSize.width == 0 && bestFitSize.height == 0 ) {
bestFitSize = supportedSizes.get(0);
}
parameters.setPreviewSize(bestFitSize.width, bestFitSize.height);
camera.setParameters(parameters);
camera.startPreview();
inPreview = true;
} catch (IOException e) {
Log.e(TAG, "Error setting camera preview: " + e.getMessage());
}
}
}
/** Stop camera preview. */
private void stopPreview() {
if (camera != null && inPreview) {
try {
camera.stopPreview();
} catch (Exception e) {
Log.i(TAG, "Error setting camera preview: " + e.getMessage());
}
inPreview = false;
}
}
/** Init camera. */
private void initCamera() {
if (camera == null) {
cameraId = recordingManager.getCameraId();
if (cameraId >= 0) {
try {
camera = Camera.open(cameraId);
setupCameraDisplayOrientation();
lockAutoFocus(camera, settingsManager.isLockAutoFocus());
lockAutoExposure(camera, settingsManager.isLockAutoExposure());
}
catch (Exception e) {
Log.e(TAG, e.getMessage(), e);
}
} else {
Log.e(TAG, "Can't find camera id");
}
}
}
/** Release camera. */
private void releaseCamera() {
if (camera != null) {
camera.release();
camera = null;
cameraId = -1;
}
}
/** #return recording state. */
public boolean isRecording() {
return recorder != null;
}
/** Start recording. */
public void startRecording(final Action<RecordingError> recordingErrorAction, boolean micUsage) {
if (camera != null && !isRecording()) {
camera.stopPreview();
final RecordingError recordingError = checkEnoughs();
if (recordingError != null) {
if (recordingErrorAction != null) {
recordingErrorAction.act(recordingError);
}
return;
}
startRecordingTime = System.currentTimeMillis();
final CamcorderProfile profile = recordingManager.getCamcorderProfile(cameraId, camera.getParameters());
stopPreview();
camera.unlock();
MediaRecorder recorder = null;
try {
recorder = new MediaRecorder();
recorder.setCamera(camera);
recorder.setAudioSource(MediaRecorder.AudioSource.VOICE_COMMUNICATION);
recorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
recorder.setProfile(profile);
final String ts = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.US).format(new Date());
lastVideoPath = new File(recordingManager.getRecordsDirPath(), "Video_" + ts + ".mp4");
recorder.setOutputFile(lastVideoPath.getAbsolutePath());
final int orientationHint = getRecorderOrientationHint();
if (orientationHint != -1) {
recorder.setOrientationHint(orientationHint);
}
recorder.setMaxFileSize(Long.MAX_VALUE);
recorder.setMaxDuration(Integer.MAX_VALUE);
stopPreview();
recorder.setPreviewDisplay(surfaceView.getHolder().getSurface());
recorder.setOnErrorListener(this);
recorder.setOnInfoListener(this);
recorder.prepare();
recorder.start();
this.recordingErrorAction = recordingErrorAction;
} catch (IOException e) {
Log.d(TAG, "Error " + e.getMessage(), e);
if (recorder != null) {
recorder.release();
recorder = null;
}
} finally {
this.recorder = recorder;
}
}
}
/** Stop recording. */
public void stopRecording() {
if (isRecording()) {
final MediaRecorder recorder = this.recorder;
this.recorder = null;
recorder.stop();
recorder.reset();
recorder.release();
this.recordingErrorAction = null;
try {
camera.reconnect();
startPreview();
} catch (IOException e) {
Log.w(TAG, e.getMessage(), e);
}
}
}
#Override
public void onError(final MediaRecorder mr, final int what, final int extra) {
Log.e(TAG, "Media recorder error: " + what + " extra: " + extra);
if (recordingErrorAction != null) {
recordingErrorAction.act(RecordingError.ILLEGAL_MEDIA_RECORDER_STATE);
}
}
}
You can catch the MEDIA_ERROR_SERVER_DIED message inside the onError method and try to re instantiate your recorder.
public void onError(final MediaRecorder mr, final int what, final int extra) {
Log.e(TAG, "Media recorder error: " + what + " extra: " + extra);
if (what == MediaPlayer.MEDIA_ERROR_SERVER_DIED) {
Log.i(LOGTAG, "MediaPlayer died, restarting");
recorder.release();
recorder = new MediaRecorder();
}
if (recordingErrorAction != null) {
recordingErrorAction.act(RecordingError.ILLEGAL_MEDIA_RECORDER_STATE);
}
}
In my sample code above I just re instantiate the recorder via the line: recorder = new MediaRecorder();. Perhaps it might need more settings applied on it afterwards.
I wish to keep buffered portions of video which is played in a VideoView. I found out that the VideoView's SurfaceDestroyed has release(true); call, caused releasing of mMediaPlayer instance according to this question
VideoView onResume loses buffered portion of the video
I don't want to hack into the internal API so I decides to rewrite SurfaceHolder.Callback and replace it to the mSHCallback field instead to avoid calling release(true); using reflection.
But it seems very strange when I call VideoView.start() in SurfaceCreated override, I've got "Can't play this video' message multiple times but the audio is continue playing through the end even I switch to other activity.
Here is my custom callback
package com.tirkx.aos;
import android.util.Log;
import android.widget.MediaController;
import android.media.MediaPlayer;
import android.view.SurfaceHolder;
import android.widget.VideoView;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
public class CustomVidViewCallbackLoader implements SurfaceHolder.Callback
{
private final String TAG = "CustomCallbackLoader";
private Map<String, Field> PrivateFields;
private Map<String, Method> PrivateMethods;
private VideoView VideoView;
boolean VideoOpened;
public CustomVidViewCallbackLoader(VideoView videoView)
{
VideoView = videoView;
PrivateFields = new HashMap<String, Field>();
PrivateMethods = new HashMap<String, Method>();
Class VideoViewClass = videoView.getClass();
//Reflection things
try
{
PrivateFields.put("mSHCallback", VideoViewClass.getDeclaredField("mSHCallback"));
PrivateFields.put("mSurfaceHolder", VideoViewClass.getDeclaredField("mSurfaceHolder"));
PrivateFields.put("mMediaController", VideoViewClass.getDeclaredField("mMediaController"));
PrivateFields.put("mMediaPlayer", VideoViewClass.getDeclaredField("mMediaPlayer"));
PrivateFields.put("mSurfaceWidth", VideoViewClass.getDeclaredField("mSurfaceWidth"));
PrivateFields.put("mSurfaceHeight", VideoViewClass.getDeclaredField("mSurfaceHeight"));
PrivateFields.put("mTargetState", VideoViewClass.getDeclaredField("mTargetState"));
PrivateFields.put("mVideoWidth", VideoViewClass.getDeclaredField("mVideoWidth"));
PrivateFields.put("mVideoHeight", VideoViewClass.getDeclaredField("mVideoHeight"));
PrivateFields.put("mSeekWhenPrepared", VideoViewClass.getDeclaredField("mSeekWhenPrepared"));
PrivateMethods.put("openVideo", VideoViewClass.getDeclaredMethod("openVideo"));
for(Map.Entry<String, Method> m : PrivateMethods.entrySet())
m.getValue().setAccessible(true);
for(Map.Entry<String, Field> f : PrivateFields.entrySet())
f.getValue().setAccessible(true);
}
catch(Exception ex)
{
ex.printStackTrace();
}
try
{
SurfaceHolder.Callback SHCallback = (SurfaceHolder.Callback) PrivateFields
.get("mSHCallback").get(videoView);
if (SHCallback != null)
{
videoView.getHolder().removeCallback(SHCallback);
PrivateFields.get("mSHCallback").set(videoView, this);
videoView.getHolder().addCallback((SurfaceHolder.Callback) PrivateFields
.get("mSHCallback").get(videoView));
}
}
catch(Exception ex)
{
ex.printStackTrace();
}
}
#Override
public void surfaceCreated(SurfaceHolder holder)
{
try
{
PrivateFields.get("mSurfaceHolder").set(VideoView, holder);
if(!VideoOpened)
{
PrivateMethods.get("openVideo").invoke(VideoView);
VideoOpened = true;
}
else
{
VideoView.start();
}
}
catch(Exception ex)
{
ex.printStackTrace();
}
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height)
{
try
{
//PrivateFields.get("mSurfaceHolder").set(VideoView, holder);
int mVideoWidth = (int) PrivateFields.get("mVideoWidth").get(VideoView);
int mVideoHeight = (int) PrivateFields.get("mVideoHeight").get(VideoView);
int mTargetState = (int) PrivateFields.get("mTargetState").get(VideoView);
int mSeekWhenPrepared = (int) PrivateFields.get("mSeekWhenPrepared").get(VideoView);
MediaPlayer mMediaPlayer = (MediaPlayer) PrivateFields.get("mMediaPlayer").get(VideoView);
PrivateFields.get("mSurfaceWidth").set(VideoView, width);
PrivateFields.get("mSurfaceHeight").set(VideoView, height);
boolean isValidState = (mTargetState == 3);
boolean hasValidSize = (mVideoWidth == width && mVideoHeight == height);
if(mMediaPlayer != null && isValidState && hasValidSize)
{
if(mSeekWhenPrepared != 0)
VideoView.seekTo(mSeekWhenPrepared);
VideoView.start();
}
}
catch(Exception ex)
{
ex.printStackTrace();
}
}
#Override
public void surfaceDestroyed(SurfaceHolder holder)
{
try
{
PrivateFields.get("mSurfaceHolder").set(VideoView, null);
MediaController mediaController = (MediaController) PrivateFields.get("mMediaController")
.get(VideoView);
if(mediaController != null)
mediaController.hide();
VideoView.pause();
}
catch(Exception ex)
{
ex.printStackTrace();
}
}
public void setMediaPlayerOnBufferedChanged(MediaPlayer mediaPlayer)
{
if (mediaPlayer != null)
{
mediaPlayer.setOnBufferingUpdateListener(new MediaPlayer.OnBufferingUpdateListener()
{
#Override
public void onBufferingUpdate(MediaPlayer mp, int percent)
{
Log.i(TAG, "-->" + percent);
}
});
}
}
}
Currently I'm trying to work with the android camera and I got pretty far with my test project. It worked perfectly fine when tested on my HTC Desire S with Gingerbread Android. However after I updated to ICS pictures taken with the test app only show strange vertical lines (it's the exact same code).
Here is what images are created now all of a sudden:
http://imageshack.us/photo/my-images/191/rebuilder1.jpg/
Here is my code (whole class):
package inter.rebuilder;
import inter.rebuilder.R;
import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.graphics.ImageFormat;
import android.graphics.Matrix;
import android.graphics.PixelFormat;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.Rect;
import android.graphics.YuvImage;
import android.hardware.Camera;
import android.hardware.Camera.AutoFocusCallback;
import android.hardware.Camera.ErrorCallback;
import android.hardware.Camera.PreviewCallback;
import android.hardware.Camera.Size;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MotionEvent;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.view.View.OnClickListener;
import android.view.View.OnTouchListener;
public class CameraView extends Activity implements SurfaceHolder.Callback,
OnClickListener {
static final int FOTO_MODE = 0;
private static final String TAG = "CameraTest";
Camera mCamera;
boolean mPreviewRunning = false;
private Context mContext = this;
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
//boolean hasCam = checkCameraHardware(mContext);
Log.e(TAG, "onCreate");
Bundle extras = getIntent().getExtras();
getWindow().setFormat(PixelFormat.TRANSLUCENT);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.main);
mSurfaceView = (SurfaceView) findViewById(R.id.surface_camera);
mSurfaceView.setOnClickListener(this);
mSurfaceHolder = mSurfaceView.getHolder();
mSurfaceHolder.addCallback(this);
mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
#Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
}
Camera.PreviewCallback mPreviewCallback = new PreviewCallback() {
public void onPreviewFrame(byte[] data, Camera camera) {
Camera.Parameters parameters = camera.getParameters();
int width = parameters.getPreviewSize().width;
int height = parameters.getPreviewSize().height;
ByteArrayOutputStream outstr = new ByteArrayOutputStream();
Rect rect = new Rect(0, 0, width, height);
YuvImage yuvimage=new YuvImage(data,ImageFormat.NV21,width,height,null);
yuvimage.compressToJpeg(rect, 100, outstr);
Bitmap bmp = BitmapFactory.decodeByteArray(outstr.toByteArray(), 0, outstr.size());
}
};
Camera.PictureCallback mPictureCallback = new Camera.PictureCallback() {
public void onPictureTaken(byte[] imageData, Camera c) {
if (imageData != null) {
Intent mIntent = new Intent();
storeByteImage(mContext, imageData, 100);
try {
mCamera.unlock();
mCamera.reconnect();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
setResult(FOTO_MODE, mIntent);
startCameraPreview();
//mCamera.startPreview();
//finish();
//Intent intent = new Intent(CameraView.this, AndroidBoxExample.class);
//CameraView.this.startActivity(intent);
}
}
};
private boolean checkCameraHardware(Context context) {
if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)){
// this device has a camera
return true;
} else {
// no camera on this device
return false;
}
}
protected void onResume() {
Log.e(TAG, "onResume");
super.onResume();
}
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
}
protected void onPause() {
Log.e(TAG, "onPause");
super.onPause();
}
protected void onStop() {
Log.e(TAG, "onStop");
super.onStop();
}
public void surfaceCreated(SurfaceHolder holder) {
Log.e(TAG, "surfaceCreated");
mCamera = Camera.open();
//mCamera.unlock();
//mCamera.setDisplayOrientation(180);
}
private void startCameraPreview() {
Camera.Parameters p = mCamera.getParameters();
p.setPictureFormat(PixelFormat.JPEG);
//p.setPreviewSize(w, h);
List<Size> list = p.getSupportedPreviewSizes();
Camera.Size size = list.get(0);
p.setPreviewSize(size.width, size.height);
mCamera.setParameters(p);
mCamera.startPreview();
mPreviewRunning = true;
}
private void startCameraPreview(SurfaceHolder holder) {
Camera.Parameters p = mCamera.getParameters();
//p.setPreviewSize(w, h);
List<Size> list = p.getSupportedPreviewSizes();
Camera.Size size = list.get(0);
p.setPreviewSize(size.width, size.height);
mCamera.setParameters(p);
try {
mCamera.setPreviewDisplay(holder);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
mCamera.startPreview();
mPreviewRunning = true;
//setCameraDisplayOrientation(this, 0, mCamera);
}
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
Log.e(TAG, "surfaceChanged");
// XXX stopPreview() will crash if preview is not running
if (mPreviewRunning) {
mCamera.stopPreview();
mPreviewRunning = false;
}
startCameraPreview(holder);
}
public void surfaceDestroyed(SurfaceHolder holder) {
Log.e(TAG, "surfaceDestroyed");
mCamera.setPreviewCallback(null);
mCamera.stopPreview();
mPreviewRunning = false;
mCamera.release();
}
#Override
public void onConfigurationChanged(Configuration newConfig) {
// TODO Auto-generated method stub
mCamera.setPreviewCallback(null);
mCamera.stopPreview();
mPreviewRunning = false;
mCamera.release();
super.onConfigurationChanged(newConfig);
}
#Override
public void onContentChanged() {
// TODO Auto-generated method stub
super.onContentChanged();
}
#Override
public void onContextMenuClosed(Menu menu) {
// TODO Auto-generated method stub
mCamera.setPreviewCallback(null);
mCamera.stopPreview();
mPreviewRunning = false;
mCamera.release();
super.onContextMenuClosed(menu);
}
private SurfaceView mSurfaceView;
private SurfaceHolder mSurfaceHolder;
public void onClick(View arg0) {
mCamera.takePicture(null, mPictureCallback, mPictureCallback);
}
private static File createDir() throws IOException {
String nameDir = "rebuilder";
File extStorageDir = Environment.getExternalStorageDirectory();
File sdImageMainDirectory = extStorageDir; //new File("/sdcard");
File dirFile = new File(sdImageMainDirectory.getPath()+"/"+nameDir);
boolean fileExisted = dirFile.exists();
if(!fileExisted) {
dirFile.mkdirs();
}
return dirFile;
}
private static File createFile(String name, File dirFile) throws IOException {
int counter = 1;
String fileName = name + counter+".jpg";
File imageFile = new File(dirFile.getPath()+"/"+fileName);
while(imageFile.exists()) {
counter = counter + 1;
fileName = name + counter+".jpg";
imageFile = new File(dirFile.getPath()+"/"+fileName);
}
imageFile.createNewFile();
return imageFile;
}
static Bitmap image1 = null;
static Bitmap image2 = null;
public static void blendTest(Bitmap myImage) throws IOException {
if(image1 == null && image2 == null) {
image1 = myImage;
return;
}
if(image1 != null && image2 != null) {
image2 = null;
image1 = myImage;
return;
}
if(image1 != null && image2 == null) {
image2 = myImage;
}
int width = Math.min(image1.getWidth(), image2.getWidth());
int height = Math.min(image1.getHeight(), image2.getHeight());
int[][] pixels1 = new int[width][height];
int[][] pixels2 = new int[width][height];
for(int i = 0; i < width; i++) {
for(int j = 0; j < height; j++) {
pixels1[i][j] = image1.getPixel(i, j);
}
}
for(int i = 0; i < width; i++) {
for(int j = 0; j < height; j++) {
pixels2[i][j] = image2.getPixel(i, j);
}
}
Bitmap image3 = Bitmap.createBitmap(width, height, image1.getConfig());
for(int i = 0; i < width; i++) {
for(int j = 0; j < height; j++) {
int color1 = pixels1[i][j];
int color2 = pixels2[i][j];
int red1 = Color.red(color1);
int red2 = Color.red(color2);
int green1 = Color.green(color1);
int green2 = Color.green(color2);
int blue1 = Color.blue(color1);
int blue2 = Color.blue(color2);
int newColor = Color.rgb((red1 + red2)/2, (green1 + green2)/2, (blue1 + blue2)/2);
image3.setPixel(i, j, newColor);
}
}
File dirFile = createDir();
File newBlend = createFile("blend", dirFile);
FileOutputStream fileOutputStream = new FileOutputStream(newBlend);
BufferedOutputStream bos = new BufferedOutputStream(
fileOutputStream);
image3.compress(CompressFormat.JPEG, 100, bos);
bos.flush();
bos.close();
}
// public static void setCameraDisplayOrientation(Activity activity,
// int cameraId, android.hardware.Camera camera) {
// android.hardware.Camera.CameraInfo info =
// new android.hardware.Camera.CameraInfo();
// android.hardware.Camera.getCameraInfo(cameraId, info);
// int rotation = activity.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 result;
// if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
// result = (info.orientation + degrees) % 360;
// result = (360 - result) % 360; // compensate the mirror
// } else { // back-facing
// result = (info.orientation - degrees + 360) % 360;
// }
// camera.setDisplayOrientation(result);
// }
public static boolean storeByteImage(Context mContext, byte[] imageData, int quality) {
FileOutputStream fileOutputStream = null;
try {
File dirFile = createDir();
File imageFile = createFile("rebuilder", dirFile);
BitmapFactory.Options options=new BitmapFactory.Options();
options.inSampleSize = 5; //5
options.inDither = false; // Disable Dithering mode
options.inPurgeable = true; // Tell to gc that whether it needs free
// memory, the Bitmap can be cleared
options.inInputShareable = true; // Which kind of reference will be
// used to recover the Bitmap
// data after being clear, when
// it will be used in the future
options.inTempStorage = new byte[32 * 1024];
options.inPreferredConfig = Bitmap.Config.RGB_565;
Bitmap myImage = BitmapFactory.decodeByteArray(imageData, 0,
imageData.length,options);
int orientation;
// others devices
if(myImage.getHeight() < myImage.getWidth()){
orientation = 90;
} else {
orientation = 0;
}
Bitmap bMapRotate;
if (orientation != 0) {
Matrix matrix = new Matrix();
matrix.postRotate(orientation);
bMapRotate = Bitmap.createBitmap(myImage, 0, 0, myImage.getWidth(),
myImage.getHeight(), matrix, true);
} else
bMapRotate = Bitmap.createScaledBitmap(myImage, myImage.getWidth(),
myImage.getHeight(), true);
//blendTest(myImage);
fileOutputStream = new FileOutputStream(imageFile);
BufferedOutputStream bos = new BufferedOutputStream(
fileOutputStream);
bMapRotate.compress(CompressFormat.JPEG, quality, bos);
if (bMapRotate != null) {
bMapRotate.recycle();
bMapRotate = null;
}
bos.flush();
bos.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println("SD Card not ready");
}
return true;
}
}
Camera Hardware permissions and orientation landscape are set in the android manifest.
Please help me here.
Did you installed a custom ROM on your device? if yes then this might be a issue.
Un-Comment the method and all occurences of it (as of OP's code)
// public static void setCameraDisplayOrientation(Activity activity,
// int cameraId, android.hardware.Camera camera) {
// android.hardware.Camera.CameraInfo info =
// new android.hardware.Camera.CameraInfo();
// android.hardware.Camera.getCameraInfo(cameraId, info);
// int rotation = activity.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 result;
// if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
// result = (info.orientation + degrees) % 360;
// result = (360 - result) % 360; // compensate the mirror
// } else { // back-facing
// result = (info.orientation - degrees + 360) % 360;
// }
// camera.setDisplayOrientation(result);
// }