I am creating an app where i can use the camera inside it without going to the default app of the phone.So i have used a surface view and tried to save it onto the phone, but the onPictureTaken never gets called.The complete code is shown below:
package com.example.surfaceviewcamera;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.hardware.Camera;
import android.os.Bundle;
import android.app.Activity;
import android.content.Context;
import android.content.ContextWrapper;
import android.view.Menu;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;
public class MainActivity extends Activity implements SurfaceHolder.Callback {
SurfaceView mSurfaceView;
SurfaceHolder mSurfaceHolder;
Camera mCamera;
boolean mPreviewRunning;
Button btncapture;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btncapture=(Button) findViewById(R.id.btncapture);
mSurfaceView = (SurfaceView) findViewById(R.id.surface_camera);
mSurfaceHolder = mSurfaceView.getHolder();
mSurfaceHolder.addCallback(this);
mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
btncapture.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Camera.PictureCallback mPictureCallback = new Camera.PictureCallback() {
public void onPictureTaken(byte[] imageData, Camera c) {
Bitmap bitmap = BitmapFactory.decodeByteArray(imageData , 0, imageData .length);
String file_path=saveToInternalSorage(bitmap);
Toast.makeText(getApplicationContext(),"Image stored succesfully at "+file_path,Toast.LENGTH_LONG).show();
}
};
}
});
}
private String saveToInternalSorage(Bitmap bitmapImage){
ContextWrapper cw = new ContextWrapper(getApplicationContext());
// path to /data/data/yourapp/app_data/imageDir
File directory = cw.getDir("imageDir", Context.MODE_PRIVATE);
// Create imageDir
File mypath=new File(directory,"marina1.jpg");
FileOutputStream fos = null;
try {
fos = new FileOutputStream(mypath);
// Use the compress method on the BitMap object to write image to the OutputStream
bitmapImage.compress(Bitmap.CompressFormat.PNG, 100, fos);
fos.close();
} catch (Exception e) {
e.printStackTrace();
}
return directory.getAbsolutePath();
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
mCamera=Camera.open();
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int w,
int h) {
if (mPreviewRunning) {
mCamera.stopPreview();
}
Camera.Parameters p = mCamera.getParameters();
p.setPreviewSize(w, h);
mCamera.setParameters(p);
try {
mCamera.setPreviewDisplay(holder);
} catch (IOException e) {
e.printStackTrace();
}
mCamera.startPreview();
mPreviewRunning = true;
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
mCamera.stopPreview();
mPreviewRunning = false;
mCamera.release();
}
}
My XML file:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<SurfaceView
android:id="#+id/surface_camera"
android:layout_width="fill_parent"
android:layout_height="10dip"
android:layout_weight="1">
</SurfaceView>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="CAPTURE IMAGE"
android:id="#+id/btncapture"
android:layout_gravity="center"
/>
</LinearLayout>
call camera.takePicture(null, null, callback); from onClick() and define the callback outside the onCreate()
for reference look into this link
public class MainActivity extends Activity implements SurfaceHolder.Callback {
SurfaceView mSurfaceView;
SurfaceHolder mSurfaceHolder;
Camera mCamera;
boolean mPreviewRunning;
Button btncapture;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btncapture=(Button) findViewById(R.id.btncapture);
mSurfaceView = (SurfaceView) findViewById(R.id.surface_camera);
mSurfaceHolder = mSurfaceView.getHolder();
mSurfaceHolder.addCallback(this);
mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
btncapture.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
//take picture here
mCamera.takePicture(null, null, mPictureCallback);
}
});
}
Camera.PictureCallback mPictureCallback = new Camera.PictureCallback() {
public void onPictureTaken(byte[] imageData, Camera c) {
Bitmap bitmap = BitmapFactory.decodeByteArray(imageData , 0, imageData .length);
String file_path=saveToInternalSorage(bitmap);
Toast.makeText(getApplicationContext(),"Image stored succesfully at "+file_path,Toast.LENGTH_LONG).show();
}
};
private String saveToInternalSorage(Bitmap bitmapImage){
ContextWrapper cw = new ContextWrapper(getApplicationContext());
// path to /data/data/yourapp/app_data/imageDir
File directory = cw.getDir("imageDir", Context.MODE_PRIVATE);
// Create imageDir
File mypath=new File(directory,"marina1.jpg");
FileOutputStream fos = null;
try {
fos = new FileOutputStream(mypath);
// Use the compress method on the BitMap object to write image to the OutputStream
bitmapImage.compress(Bitmap.CompressFormat.PNG, 100, fos);
fos.close();
} catch (Exception e) {
e.printStackTrace();
}
return directory.getAbsolutePath();
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
mCamera=Camera.open();
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int w,
int h) {
if (mPreviewRunning) {
mCamera.stopPreview();
}
Camera.Parameters p = mCamera.getParameters();
p.setPreviewSize(w, h);
mCamera.setParameters(p);
try {
mCamera.setPreviewDisplay(holder);
} catch (IOException e) {
e.printStackTrace();
}
mCamera.startPreview();
mPreviewRunning = true;
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
mCamera.stopPreview();
mPreviewRunning = false;
mCamera.release();
}
}
Related
I am trying to use Camera API for my app. When I click take photo button, the UI hangs for about 10 seconds before responding further.
I found a post on SO here, but the solution wasn't much specific. I think it is a problem of multi-threading. I am a beginner in android development and not proficient with multi-threading.
UploadPrescription.java :
package com.example.ayusch.medomo;
import android.Manifest;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.ImageFormat;
import android.graphics.Matrix;
import android.hardware.Camera;
import android.media.ExifInterface;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.support.annotation.NonNull;
import android.support.v4.app.Fragment;
import android.support.v4.app.ShareCompat;
import android.support.v4.content.ContextCompat;
import android.util.Log;
import android.util.Size;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.Toast;
import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
/**
* A simple {#link Fragment} subclass.
*/
public class UploadPrescription extends Fragment {
private static final int REQUEST_EXTERNAL_STORAGE_PERMISSION = 2;
private Camera mCamera = null;
private CameraPreview mCameraPreview;
private final int REQUEST_CAMERA_PERMISSION = 1;
private FrameLayout preview;
private File pictureFile;
private FileOutputStream fos;
private byte[] byteArray;
public UploadPrescription() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View root = inflater.inflate(R.layout.fragment_upload_prescription, container, false);
preview = (FrameLayout) root.findViewById(R.id.camera_preview);
setPreview();
Button captureButton = (Button) root.findViewById(R.id.button_capture);
captureButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.i("ayusch", "inside on click");
mCamera.takePicture(null, null, mPicture);
}
});
return root;
}
private void setPreview() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (ContextCompat.checkSelfPermission(getContext(), Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED) {
setup();
} else {
if (shouldShowRequestPermissionRationale(Manifest.permission.CAMERA)) {
Toast.makeText(getContext(), "Permission needed to use camera", Toast.LENGTH_LONG).show();
}
requestPermissions(new String[]{Manifest.permission.CAMERA}, REQUEST_CAMERA_PERMISSION);
}
} else {
setup();
}
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
if (requestCode == REQUEST_CAMERA_PERMISSION) {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
setup();
} else {
Toast.makeText(getContext(), "Camera Permission not granted", Toast.LENGTH_LONG).show();
return;
}
} else if (requestCode == REQUEST_EXTERNAL_STORAGE_PERMISSION) {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
proceedtowrite();
} else {
Toast.makeText(getContext(), "Storage permission not granted", Toast.LENGTH_LONG).show();
return;
}
}
}
public void setup() {
mCamera = getCameraInstance();
Camera.Parameters parameters = mCamera.getParameters();
parameters.set("jpeg-quality", 70);
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
parameters.setPictureFormat(ImageFormat.JPEG);
List<Camera.Size> sizes = parameters.getSupportedPictureSizes();
Camera.Size size = sizes.get(Integer.valueOf((sizes.size() - 1) / 2)); //choose a medium resolution
parameters.setPictureSize(size.width, size.height);
mCamera.setParameters(parameters);
mCameraPreview = new CameraPreview(getContext(), mCamera);
preview.addView(mCameraPreview);
}
private Camera getCameraInstance() {
Camera camera = null;
try {
camera = Camera.open(0);
} catch (Exception e) {
e.printStackTrace();
// cannot get camera or does not exist
}
return camera;
}
Camera.PictureCallback mPicture = new Camera.PictureCallback() {
#Override
public void onPictureTaken(byte[] data, Camera camera) {
Log.i("ayusch", "inside onPictureTaken");
pictureFile = getOutputMediaFile();
if (pictureFile == null) {
Log.i("ayusch", "Null Picture file, returning...");
return;
}
try {
fos = new FileOutputStream(pictureFile);
////////////////////////////////////
Bitmap realImage = BitmapFactory.decodeByteArray(data, 0, data.length);
ExifInterface exif = new ExifInterface(pictureFile.toString());
Log.d("ayusch", exif.getAttribute(ExifInterface.TAG_ORIENTATION));
if (exif.getAttribute(ExifInterface.TAG_ORIENTATION).equalsIgnoreCase("6")) {
realImage = rotate(realImage, 90);
} else if (exif.getAttribute(ExifInterface.TAG_ORIENTATION).equalsIgnoreCase("8")) {
realImage = rotate(realImage, 270);
} else if (exif.getAttribute(ExifInterface.TAG_ORIENTATION).equalsIgnoreCase("3")) {
realImage = rotate(realImage, 180);
} else if (exif.getAttribute(ExifInterface.TAG_ORIENTATION).equalsIgnoreCase("0")) {
realImage = rotate(realImage, 90);
}
ByteArrayOutputStream stream = new ByteArrayOutputStream();
realImage.compress(Bitmap.CompressFormat.PNG, 100, stream);
byteArray = stream.toByteArray();
////////////////////////////////////
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (ContextCompat.checkSelfPermission(getContext(), Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
proceedtowrite();
} else {
if (shouldShowRequestPermissionRationale(Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
Toast.makeText(getContext(), "Permission needed to store and upload Prescription", Toast.LENGTH_LONG).show();
}
requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_EXTERNAL_STORAGE_PERMISSION);
}
} else {
proceedtowrite();
}
} catch (FileNotFoundException e) {
} catch (IOException e) {
}
}
};
public void proceedtowrite() {
try {
fos.write(byteArray);
fos.close();
} catch (Exception e) {
e.printStackTrace();
}
Intent i = new Intent(getActivity(), PrescriptionUpload.class);
i.putExtra("prescription", pictureFile);
startActivity(new Intent(i));
}
public static Bitmap rotate(Bitmap bitmap, int degree) {
int w = bitmap.getWidth();
int h = bitmap.getHeight();
Matrix mtx = new Matrix();
// mtx.postRotate(degree);
mtx.setRotate(degree);
return Bitmap.createBitmap(bitmap, 0, 0, w, h, mtx, true);
}
private static File getOutputMediaFile() {
Log.i("ayusch", "Getting output media file");
File mediaStorageDir = new File(
Environment
.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
"MyCameraApp");
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;
mediaFile = new File(mediaStorageDir.getPath() + File.separator
+ "IMG_" + timeStamp + ".jpg");
Log.i("ayusch", "Filename = " + mediaFile);
return mediaFile;
}
#Override
public void onPause() {
super.onPause();
if (mCamera != null) {
mCamera.setPreviewCallback(null);
mCameraPreview.getHolder().removeCallback(mCameraPreview);
mCamera.stopPreview();
mCamera.release();
}
}
#Override
public void onResume() {
super.onResume();
try {
mCameraPreview.getHolder().removeCallback(mCameraPreview);
setPreview();
} catch (Exception e) {
e.printStackTrace();
}
}
}
CameraPreview.java :
package com.example.ayusch.medomo;
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 Ayusch on 09-Feb-17.
*/
public class CameraPreview extends SurfaceView implements
SurfaceHolder.Callback {
private SurfaceHolder mSurfaceHolder;
private Camera mCamera;
// Constructor that obtains context and camera
#SuppressWarnings("deprecation")
public CameraPreview(Context context, Camera camera) {
super(context);
this.mCamera = camera;
this.mSurfaceHolder = this.getHolder();
this.mSurfaceHolder.addCallback(this);
this.mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
#Override
public void surfaceCreated(SurfaceHolder surfaceHolder) {
try {
mCamera.setPreviewDisplay(surfaceHolder);
mCamera.setDisplayOrientation(90);
mCamera.startPreview();
} catch (IOException e) {
// left blank for now
}
}
#Override
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
Log.i("ayusch", "Inside surfaceDestroyed");
mCamera.stopPreview();
mCamera.release();
}
#Override
public void surfaceChanged(SurfaceHolder surfaceHolder, int format,
int width, int height) {
// start preview with new settings
try {
mCamera.setPreviewDisplay(surfaceHolder);
mCamera.startPreview();
} catch (Exception e) {
// intentionally left blank for a test
}
}
}
MainActivity.java :
package com.example.ayusch.medomo;
import android.Manifest;
import android.content.pm.PackageManager;
import android.os.Build;
import android.support.annotation.NonNull;
import android.support.design.widget.TabLayout;
import android.support.v4.content.ContextCompat;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.View;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
private static final int REQUEST_CAMERA_PERMISSION = 1;
Toolbar toolbar;
TabLayout tabLayout;
ViewPager viewPager;
ViewPagerAdapter viewPagerAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
tabLayout = (TabLayout) findViewById(R.id.tabLayout);
viewPager = (ViewPager) findViewById(R.id.viewPager);
viewPagerAdapter = new ViewPagerAdapter(getSupportFragmentManager());
viewPagerAdapter.addFragments(new UploadPrescription(), "Upload Prescription");
viewPagerAdapter.addFragments(new OrderByName(), "Enter Medicine Name");
viewPagerAdapter.addFragments(new Contact(), "Contact Us");
viewPager.setAdapter(viewPagerAdapter);
tabLayout.setupWithViewPager(viewPager);
}
}
Also, during the hang time if I press the button again, app crashes :
02-10 19:57:31.481 966-966/com.example.ayusch.medomo E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.ayusch.medomo, PID: 966
java.lang.RuntimeException: Camera is being used after Camera.release() was called
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.example.ayusch.medomo.UploadPrescription$1.onClick(UploadPrescription.java:73)
at android.view.View.performClick(View.java:5714)
at android.widget.TextView.performClick(TextView.java:10926)
at android.view.View$PerformClick.run(View.java:22589)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:7325)
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)
It is due to the line mCamera.takePicture(null, null, mPicture); in the onClick method of UploadPrescription.java
I have been trying to get my head around it since 2 days without any success. Please Help !!
Thanks in advance
I did a quick and dirty workaround for a similar problem, where I filled the screen with a camera preview and then just captured a screengrab as and when required (responds pretty much immediately) - this actually allowed me to basically film a sequence of frames at a reasonable frame rate.
Hopefully that's enough for you to go on for now. Let me know if not.
ByteArrayOutputStream stream = new ByteArrayOutputStream();
realImage.compress(Bitmap.CompressFormat.PNG, 100, stream);
byteArray = stream.toByteArray();
Bitmap#compress is extremely inefficient for PNG format (lack of hardware acceleration etc). Try either resizing the bitmap prior to saving, compressing to JPEG or dumping raw bitmap using native io.
As the title says, this is my problem.
My camera successfully goes to front camera, but on the second button click, it doesn't change back to back view and stays front view.
CameraActivity.java:
package mano.whatever;
import android.app.Activity;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Picture;
import android.graphics.RectF;
import android.hardware.Camera;
import android.media.Image;
import android.net.Uri;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.os.Environment;
import android.provider.MediaStore;
import android.support.annotation.Nullable;
import android.util.Base64;
import android.util.Log;
import android.view.View;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.Toast;
import android.os.AsyncTask;
import com.google.android.gms.identity.intents.AddressConstants;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
public class CameraActivity extends Activity {
private Camera.Size mSize = null;
private Camera mCamera = null;
private CameraView mCameraView=null;
private SurfaceView mPreview;
private SurfaceHolder mSurfaceHolder;
Camera.PictureCallback jpegCallback;
final int CAMERA_CAPTURE = 1;
private Camera.PictureCallback mPictureCallback;
boolean isFront;
int camBackId = Camera.CameraInfo.CAMERA_FACING_BACK;
int camFrontId = Camera.CameraInfo.CAMERA_FACING_FRONT;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_camera);
if (mCamera == null){
initCamera(0);
}
//btn to close the application
ImageView imgClose = (ImageView) findViewById(R.id.left_button);
imgClose.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
toThanksActivity();
}
});
ImageView photo = (ImageView) findViewById(R.id.photo_button);
photo.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
mCamera.autoFocus(new Camera.AutoFocusCallback() {
#Override
public void onAutoFocus(boolean b, Camera camera) {
mCamera.takePicture(shutterCall, PictureCallback, mPicture);
}
});
}
});
ImageView rotate = (ImageView) findViewById(R.id.rotate_camera);
rotate.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
rotateCamera();
}
});
}
public void rotateCamera() {
boolean isFront = false;
int CamId = 0;
CamId = Camera.getNumberOfCameras();
int cameraId = Camera.CameraInfo.CAMERA_FACING_BACK;
Camera.CameraInfo currentCamInfo = new Camera.CameraInfo();
if (mCamera != null) {
mCamera.stopPreview();
mCamera.release();
mCamera = null;
}
if (currentCamInfo.facing == Camera.CameraInfo.CAMERA_FACING_BACK){
initCamera(1);
}
else{
initCamera(0);
}
}
public void initCamera(int potato){
mCamera = Camera.open(potato);//you can use open(int) to use different cameras
FrameLayout camera_view = (FrameLayout) findViewById(R.id.camera_view);
camera_view.removeView(mCameraView);
if (mCamera != null) {
mCameraView = new CameraView(this, mCamera);//create a SurfaceView to show camera data
camera_view.addView(mCameraView);//add the SurfaceView to the layout
}
}
public void toThanksActivity() {
mCamera.stopPreview();
mCamera.release();
finish();
}
public void toCaptureImage() {
mCamera.takePicture(shutterCall, PictureCallback, mPicture);
}
Camera.ShutterCallback shutterCall = new Camera.ShutterCallback() {
#Override
public void onShutter() {
}
};
Camera.PictureCallback PictureCallback = new Camera.PictureCallback() {
#Override
public void onPictureTaken(byte[] bytes, Camera camera) {
}
};
Camera.PictureCallback mPicture = new Camera.PictureCallback() {
#Override
public void onPictureTaken(byte[] data, Camera camera) {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyymmddhhmmss");
String date = dateFormat.format(new Date());
String photoFile = "Picture_" + date + ".jpg";
File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM), "Camera");
String filename = mediaStorageDir.getPath() + File.separator + photoFile;
File pictureFile = new File(filename);
try {
FileOutputStream fos = new FileOutputStream(pictureFile);
fos.write(data);
fos.flush();
fos.close();
ByteArrayOutputStream stream = new ByteArrayOutputStream();
Bitmap bm = BitmapFactory.decodeFile(filename);
Matrix matrix = new Matrix();
matrix.postRotate(90);
Bitmap rotatedBitmap = Bitmap.createBitmap(bm, 0, 0, bm.getWidth(), bm.getHeight(), matrix, true);
FileOutputStream fos2 = new FileOutputStream(pictureFile);
rotatedBitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream);
byte[] byteArray = stream.toByteArray();
mCamera.stopPreview();
mCamera.release();
Intent intent = new Intent();
intent.putExtra("image", byteArray);
setResult(250, intent);
finish();
} catch (IOException e) {
}
}
};
Camera.AutoFocusCallback myAutoFocusCallback = new Camera.AutoFocusCallback() {
#Override
public void onAutoFocus(boolean b, Camera camera) {
}
};
}
CameraView.java:
package mano.whatever;
import android.content.Context;
import android.hardware.Camera;
import android.hardware.Camera.Size;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import java.io.IOException;
import java.util.List;
public class CameraView extends SurfaceView implements SurfaceHolder.Callback {
private SurfaceHolder mHolder;
private Camera mCamera;
private Camera.Size mSize = null;
public CameraView(Context context, Camera camera) {
super(context);
mCamera = camera;
mCamera.setDisplayOrientation(90);
//get the holder and set this class as the callback, so we can get camera data here
mHolder = getHolder();
mHolder.addCallback(this);
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
#Override
public void surfaceCreated(SurfaceHolder surfaceHolder) {
//when the surface is created, we can set the camera to draw images in this surfaceholder
Camera.Parameters parameters = mCamera.getParameters();
List<Camera.Size> previewSizes = parameters.getSupportedPreviewSizes();
// You need to choose the most appropriate previewSize for your app
Size optimalSize = getOptimalPreviewSize(previewSizes, getResources().getDisplayMetrics().widthPixels, getResources().getDisplayMetrics().heightPixels);
parameters.setPreviewSize(optimalSize.width, optimalSize.height);
mCamera.setParameters(parameters);
mCamera.startPreview();
}
#Override
public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i2, int i3) {
//before changing the application orientation, you need to stop the preview, rotate and then start it again
if (mHolder.getSurface() == null)//check if the surface is ready to receive camera data
return;
try {
mCamera.stopPreview();
} catch (Exception e) {
//this will happen when you are trying the camera if it's not running
}
//now, recreate the camera preview
try {
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
} catch (IOException e) {
Log.d("ERROR", "Camera error on surfaceChanged " + e.getMessage());
}
}
#Override
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
//our app has only one screen, so we'll destroy the camera in the surface
//if you are unsing with more screens, please move this code your activity
}
private Camera.Size getOptimalPreviewSize(List<Camera.Size> sizes, int w, int h) {
final double ASPECT_TOLERANCE = 0.1;
double targetRatio=(double)h / w;
if (sizes == null) return null;
Camera.Size optimalSize = null;
double minDiff = Double.MAX_VALUE;
int targetHeight = h;
for (Camera.Size size : sizes) {
double ratio = (double) size.width / size.height;
if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) continue;
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
if (optimalSize == null) {
minDiff = Double.MAX_VALUE;
for (Camera.Size size : sizes) {
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
}
return optimalSize;
}
}
I know this is a sketchy code, but I'd love to hear some suggestions.
Thank you in advance.:)
EDIT
I completely reworked my code, got rid of the CameraView.java class and it works fluently thanks to Android camera preview freezes when switching cameras?
Haven't try but try something like this, hope it works?
public void rotateCamera() {
boolean isFront = false;
int CamId = 0;
CamId = Camera.getNumberOfCameras();
int cameraId = Camera.CameraInfo.CAMERA_FACING_BACK;
Camera.CameraInfo currentCamInfo = new Camera.CameraInfo();
if (mCamera != null) {
mCamera.stopPreview();
mCamera.release();
mCamera = null;
}
if (currentCamInfo.facing == Camera.CameraInfo.CAMERA_FACING_BACK){
camera = Camera.open(Camera.CameraInfo.CAMERA_FACING_BACK);
}
else{
camera = Camera.open(Camera.CameraInfo.CAMERA_FACING_FRONT);
}
if (mCamera != null) {
try {
mCamera.setPreviewDisplay(surfaceView.getHolder());
mCamera.startPreview();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Please, can anybody help me with this?
I have a project using CameraBridgeViewBase and I want to take a picture and save a file, but CameraBridgeViewBase doesn't implement the function takePicture.
Result: I implemented a new class extends JavaCameraView and implemented myself the function takePicture.
import org.opencv.android.JavaCameraView;
import java.io.FileOutputStream;
import java.util.List;
import android.content.Context;
import android.hardware.Camera;
import android.hardware.Camera.PictureCallback;
import android.hardware.Camera.Size;
import android.util.AttributeSet;
import android.util.Log;
public class MyCameraView extends JavaCameraView implements PictureCallback {
private static final String TAG = "myCameraView";
private String mPictureFileName;
public MyCameraView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public List<String> getEffectList() {
return mCamera.getParameters().getSupportedColorEffects();
}
public boolean isEffectSupported() {
return (mCamera.getParameters().getColorEffect() != null);
}
public String getEffect() {
return mCamera.getParameters().getColorEffect();
}
public void setEffect(String effect) {
Camera.Parameters params = mCamera.getParameters();
params.setColorEffect(effect);
mCamera.setParameters(params);
}
public List<Size> getResolutionList() {
return mCamera.getParameters().getSupportedPreviewSizes();
}
public void setResolution(Size resolution) {
disconnectCamera();
mMaxHeight = resolution.height;
mMaxWidth = resolution.width;
connectCamera(getWidth(), getHeight());
}
public Size getResolution() {
return mCamera.getParameters().getPreviewSize();
}
public void takePicture(final String fileName) {
Log.i(TAG, "Taking picture");
this.mPictureFileName = fileName;
// Postview and jpeg are sent in the same buffers if the queue is not empty when performing a capture.
// Clear up buffers to avoid mCamera.takePicture to be stuck because of a memory issue
mCamera.setPreviewCallback(null);
// PictureCallback is implemented by the current class
mCamera.takePicture(null, null, this);
}
#Override
public void onPictureTaken(byte[] data, Camera camera) {
Log.i(TAG, "Saving a bitmap to file");
// The camera preview was automatically stopped. Start it again.
mCamera.startPreview();
mCamera.setPreviewCallback(this);
// Write the image in a file (in jpeg format)
try {
FileOutputStream fos = new FileOutputStream(mPictureFileName);
fos.write(data);
fos.close();
} catch (java.io.IOException e) {
Log.e("PictureDemo", "Exception in photoCallback", e);
}
}
}
-
private MyCameraView mOpenCvCameraView;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
mOpenCvCameraView = (MyCameraView) view.findViewById(R.id.fd_activity_surface_view);
mOpenCvCameraView.setCvCameraViewListener(this);
return view;
}
#Override
public void onResume() {
super.onResume();
mOpenCvCameraView.enableView();
String filename = "teste.jpg";
mOpenCvCameraView.takePicture(filename);
mOpenCvCameraView.disableView();
}
I am currently designing an app that calls the Camera with a simple button click. I want to now change the shape that appears in the center of the camera (e.g. it is now a circle/rectangle depending on the device) to a custom shape. I am making a custom camera using a main activity class and a camera preview class. This is my code so far:
Layout File
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="fill_parent"
android:layout_height="fill_parent" android:id="#+id/layout">
<TextView android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:contentDescription="#string/camstring"
android:textSize="24sp" />
<FrameLayout android:id="#+id/preview"
android:layout_weight="1"
android:layout_width="fill_parent"
android:layout_height="0dp">
</FrameLayout>
<Button android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/buttonClick"
android:contentDescription="#string/action"
android:layout_gravity="center"></Button>
</LinearLayout>
MainActivity
package com.test.Nurse_Cam;
import android.os.Bundle;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import android.app.Activity;
import android.hardware.Camera;
import android.hardware.Camera.PictureCallback;
import android.hardware.Camera.ShutterCallback;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.FrameLayout;
public class MainActivity extends Activity {
private static final String TAG = "CameraDemo";
Camera camera;
Preview preview;
Button buttonClick;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
preview = new Preview(this);
((FrameLayout) findViewById(R.id.preview)).addView(preview);
buttonClick = (Button) findViewById(R.id.buttonClick);
buttonClick.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
preview.camera.takePicture(shutterCallback, rawCallback,
jpegCallback);
}
});
Log.d(TAG, "onCreate'd");
}
ShutterCallback shutterCallback = new ShutterCallback() {
public void onShutter() {
Log.d(TAG, "onShutter'd");
}
};
/** Handles data for raw picture */
PictureCallback rawCallback = new PictureCallback() {
public void onPictureTaken(byte[] data, Camera camera) {
Log.d(TAG, "onPictureTaken - raw");
}
};
/** Handles data for jpeg picture */
PictureCallback jpegCallback = new PictureCallback() {
public void onPictureTaken(byte[] data, Camera camera) {
FileOutputStream outStream = null;
try {
// write to local sandbox file system
// outStream =
// CameraDemo.this.openFileOutput(String.format("%d.jpg",
// System.currentTimeMillis()), 0);
// Or write to sdcard
outStream = new FileOutputStream(String.format(
getString(R.string._sdcard_d_jpg), System.currentTimeMillis()));
outStream.write(data);
outStream.close();
Log.d(TAG, "onPictureTaken - wrote bytes: " + data.length);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
}
Log.d(TAG, "onPictureTaken - jpeg");
}
};
}
Preview Class
package com.test.Nurse_Cam;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
//import java.util.Iterator;
import java.util.List;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.hardware.Camera;
import android.hardware.Camera.PreviewCallback;
import android.hardware.Camera.Size;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
#SuppressLint("SdCardPath")
class Preview extends SurfaceView implements SurfaceHolder.Callback {
private static final String TAG = "Preview";
//private final static double epsilon = 0.17;
private Size mPreviewSize;
SurfaceHolder mHolder;
public Camera camera;
public List<Size> mSupportedPreviewSizes = camera.getParameters().getSupportedPreviewSizes();
#SuppressWarnings("deprecation")
Preview(Context context) {
super(context);
// Install a SurfaceHolder.Callback so we get notified when the
// underlying surface is created and destroyed.
mHolder = getHolder();
mHolder.addCallback(this);
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
public void surfaceCreated(SurfaceHolder holder) {
// The Surface has been created, acquire the camera and tell it where
// to draw.
camera = Camera.open();
try {
camera.setPreviewDisplay(holder);
camera.setPreviewCallback(new PreviewCallback() {
public void onPreviewFrame(byte[] data, Camera arg1) {
FileOutputStream outStream = null;
try {
outStream = new FileOutputStream(String.format(
"/sdcard/%d.jpg", System.currentTimeMillis()));
outStream.write(data);
outStream.close();
Log.d(TAG, "onPreviewFrame - wrote bytes: "
+ data.length);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
}
Preview.this.invalidate();
}
});
} catch (IOException e) {
e.printStackTrace();
}
}
public void surfaceDestroyed(SurfaceHolder holder) {
// Stopping preview because surface will be destroyed upon return
camera.stopPreview();
camera = null;
}
private Camera.Size getOptimalPreviewSize(List<Camera.Size> sizes, int w, int h) {
final double ASPECT_TOLERANCE = 0.1;
double targetRatio=(double)h / w;
if (sizes == null) return null;
Camera.Size optimalSize = null;
double minDiff = Double.MAX_VALUE;
int targetHeight = h;
for (Camera.Size size : sizes) {
double ratio = (double) size.width / size.height;
if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) continue;
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
if (optimalSize == null) {
minDiff = Double.MAX_VALUE;
for (Camera.Size size : sizes) {
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
}
return optimalSize;
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
final int width = resolveSize(getSuggestedMinimumWidth(), widthMeasureSpec);
final int height = resolveSize(getSuggestedMinimumHeight(), heightMeasureSpec);
setMeasuredDimension(width, height);
if (mSupportedPreviewSizes != null) {
mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes, width, height);
}
}
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
// Now that the size is known, set up the camera parameters and begin
// the preview.
Camera.Parameters parameters = camera.getParameters();
parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
camera.setParameters(parameters);
camera.startPreview();
}
// This adds a canvas to the app
#Override
public void draw(Canvas canvas) {
super.draw(canvas);
Paint p = new Paint(Color.RED);
Log.d(TAG, "draw");
canvas.drawText("PREVIEW", canvas.getWidth() / 2,
canvas.getHeight() / 2, p);
}
}
The camera preview appears distorted when I use the app on my Galaxy S5 and I am unable to see the shape that usually appears in the center. Any input on the best way to place a custom shape in the center, replacing the usual one, would be appreciated. Thanks!
Use relative layout as parent layout of your XML and keep button into center by using centerInParent=true property hope it will not distorted on any device from now
The following code takes a picture with the camera and works fine.
When I pause the application (by going back to the home menu) and restart the app, the camera image does not get saved anymore.
Even though I release and re-open the camera on pause/resume, I get the error when calling snapPicture: "Method called after release()".
This is my code, and the line 'Log.w("Error message: ", e.getLocalizedMessage());' displays the error.
Can anyone help me to solve this problem?
camerapreview.java
package com.example.testproject;
import java.io.IOException;
import android.content.Context;
import android.hardware.Camera;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class CameraPreview extends SurfaceView implements
SurfaceHolder.Callback {
private SurfaceHolder mSurfaceHolder;
private Camera mCamera;
// Constructor that obtains context and camera
#SuppressWarnings("deprecation")
public CameraPreview(Context context, Camera camera) {
super(context);
this.mCamera = camera;
this.mSurfaceHolder = this.getHolder();
this.mSurfaceHolder.addCallback(this);
this.mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
#Override
public void surfaceCreated(SurfaceHolder surfaceHolder) {
try {
mCamera.setPreviewDisplay(surfaceHolder);
mCamera.startPreview();
} catch (IOException e) {
// left blank for now
}
}
#Override
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
mCamera.stopPreview();
mCamera.release();
mCamera = null;
}
#Override
public void surfaceChanged(SurfaceHolder surfaceHolder, int format,
int width, int height) {
// start preview with new settings
try {
mCamera.setPreviewDisplay(surfaceHolder);
mCamera.startPreview();
} catch (Exception e) {
// intentionally left blank for a test
}
}
}
custom_cameraactivity.java
package com.example.testproject;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.sql.Date;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.hardware.Camera;
import android.hardware.Camera.PictureCallback;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
public class Custom_CameraActivity extends Activity {
private Camera mCamera;
private CameraPreview mCameraPreview;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
public void setCameraAndCameraPreview(Camera mcamera,
CameraPreview mCameraPreview) {
this.mCamera = mcamera;
this.mCameraPreview = mCameraPreview;
}
public String snapPicture() {
TakePictureTaskAsync takePictureTask = new TakePictureTaskAsync();
takePictureTask.setCamera(mCamera);
Calendar cal = Calendar.getInstance();
String useThisTimeStamp = new SimpleDateFormat("HHmmss").format(cal
.getTime());
takePictureTask.configureTimestamp(useThisTimeStamp);
takePictureTask.execute();
return useThisTimeStamp;
}
/**
* Helper method to access the camera returns null if it cannot get the
* camera or does not exist
*
* #return
*/
}
class TakePictureTaskAsync extends AsyncTask<Void, Void, Void> {
private Camera mCamera;
private String myTimeStamp;
public void setCamera(Camera mCamera) {
this.mCamera = mCamera;
}
public void configureTimestamp(String timeStamp) {
this.myTimeStamp = timeStamp;
}
#Override
protected void onPostExecute(Void result) {
}
#Override
protected Void doInBackground(Void... params) {
try {
mCamera.takePicture(null, null, mPicture);
} catch (Exception e) {
Log.w("Error message: ", e.getLocalizedMessage());
//this is where the error "method called after release" comes in
}
return null;
}
PictureCallback mPicture = new PictureCallback() {
#Override
public void onPictureTaken(byte[] data, Camera camera) {
File pictureFile = getOutputMediaFile();
if (pictureFile == null) {
return;
}
try {
FileOutputStream fos = new FileOutputStream(pictureFile);
fos.write(resizeImage(data));
fos.close();
} catch (FileNotFoundException e) {
} catch (IOException e) {
}
try {
HTTPPost postPictureToURL = new HTTPPost();
postPictureToURL.setTimestamp(myTimeStamp);
postPictureToURL.executeImagePOST();
} catch (Exception e) {
e.printStackTrace();
}
}
};
private File getOutputMediaFile() {
File mediaStorageDir = new File(
Environment
.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
"testdir");
if (!mediaStorageDir.exists()) {
if (!mediaStorageDir.mkdirs()) {
return null;
}
}
File mediaFile;
mediaFile = new File(mediaStorageDir.getPath() + File.separator
+ "cameraView_" + myTimeStamp + ".jpg");
return mediaFile;
}
byte[] resizeImage(byte[] input) {
Bitmap original = BitmapFactory.decodeByteArray(input, 0, input.length);
Bitmap resized = Bitmap.createScaledBitmap(original, 800, 600, true);
ByteArrayOutputStream blob = new ByteArrayOutputStream();
resized.compress(Bitmap.CompressFormat.JPEG, 70, blob);
return blob.toByteArray();
}
}
Mainactivity.java
#Override
protected void onPause() {
super.onPause();
try {
mCamera.stopPreview();
mCamera.setPreviewCallback(null);
mCameraPreview.getHolder().removeCallback(mCameraPreview);
mCamera.release();
mCamera = null;
} catch (Exception e) {
e.printStackTrace();
}
}
protected void onResume() {
super.onResume();
if (mCamera != null) {
mCamera.startPreview();
} else {
mCamera = getCameraInstance();
mCamera.startPreview();
}
}
private Camera getCameraInstance() {
Camera camera = null;
try {
camera = Camera.open();
} catch (Exception e) {
//do nothing
}
return camera;
}