outStream = new FileOutputStream(String.format(
"/sdcard/%d.jpeg", System.currentTimeMillis()));
I'm trying to save an image from the camera onto the phone. I'm able to take the picture, see the taken picture on the SurfaceView and everything, but when I go to my phone's filesystem, the picture is nowhere to be found. I'm thinking it's this specific line of code, however I will post my entire Activity just to be sure.
package com.commonsware.android.skeleton;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.hardware.Camera;
import android.hardware.Camera.*;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.Display;
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.widget.Button;
import android.widget.FrameLayout;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;
// ----------------------------------------------------------------------
public class SimpleBulbActivity extends Activity {
private Preview mPreview;
private static final String TAG = "CameraDemo";
FrameLayout preview;
Camera mCamera;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Hide the window title.
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.main);
}
protected void onResume() {
super.onResume();
//Setup the FrameLayout with the Camera Preview Screen
mPreview = new Preview(this);
preview = (FrameLayout)findViewById(R.id.preview);
preview.addView(mPreview);
}
public void snap(View view) {
mCamera.takePicture(shutterCallback, rawCallback, jpegCallback);
}
ShutterCallback shutterCallback = new ShutterCallback() {
public void onShutter() {
Log.d(TAG, "onShutter'd");
}
};
PictureCallback rawCallback = new PictureCallback() {
public void onPictureTaken(byte[] _data, Camera _camera) {
Log.d(TAG, "onPictureTaken - raw");
}
};
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(
"/sdcard/%d.jpeg", System.currentTimeMillis()));
sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://"+ Environment.getExternalStorageDirectory())));
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");
}
};
// ----------------------------------------------------------------------
class Preview extends SurfaceView implements SurfaceHolder.Callback {
SurfaceHolder mHolder;
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.
mCamera = Camera.open();
try {
mCamera.setPreviewDisplay(holder);
mCamera.setPreviewCallback(new PreviewCallback() {
public void onPreviewFrame(byte[] data, Camera arg1) {
FileOutputStream outStream = null;
try {
outStream = new FileOutputStream(Environment.getExternalStorageDirectory().toString());
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) {
mCamera.release();
mCamera = null;
e.printStackTrace();
}
}
public void surfaceDestroyed(SurfaceHolder holder) {
// Surface will be destroyed when we return, so stop the preview.
// Because the CameraDevice object is not a shared resource, it's very
// important to release it when the activity is paused.
mCamera.stopPreview();
mCamera.release();
mCamera = null;
}
private Size getOptimalPreviewSize(List<Size> sizes, int w, int h) {
final double ASPECT_TOLERANCE = 0.05;
double targetRatio = (double) w / h;
if (sizes == null) return null;
Size optimalSize = null;
double minDiff = Double.MAX_VALUE;
int targetHeight = h;
// Try to find an size match aspect ratio and size
for (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);
}
}
// Cannot find the one match the aspect ratio, ignore the requirement
if (optimalSize == null) {
minDiff = Double.MAX_VALUE;
for (Size size : sizes) {
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
}
return optimalSize;
}
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 = mCamera.getParameters();
List<Size> sizes = parameters.getSupportedPreviewSizes();
Size optimalSize = getOptimalPreviewSize(sizes, w, h);
Display display = ((WindowManager)getSystemService(WINDOW_SERVICE)).getDefaultDisplay();
if(display.getRotation() == Surface.ROTATION_0)
{
parameters.setPreviewSize(optimalSize.height, optimalSize.width);
mCamera.setDisplayOrientation(90);
}
if(display.getRotation() == Surface.ROTATION_90)
{
parameters.setPreviewSize(optimalSize.width, optimalSize.height);
}
if(display.getRotation() == Surface.ROTATION_180)
{
parameters.setPreviewSize(optimalSize.width, optimalSize.height);
}
if(display.getRotation() == Surface.ROTATION_270)
{
parameters.setPreviewSize(optimalSize.width, optimalSize.height);
mCamera.setDisplayOrientation(0);
}
mCamera.setParameters(parameters);
mCamera.startPreview();
}
}
}
do you have
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
in your AndroidManifest.xml?
Related
I am making camera app but when i m running it it shows unfortunately app has stopped.In the code it shows no error but still its not working so help me with it.
the below code is the main code of the app and contains the captured image saving file
package com.example.cam;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.hardware.Camera;
import android.hardware.Camera.PictureCallback;
import android.hardware.Camera.ShutterCallback;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnLongClickListener;
import android.view.ViewGroup.LayoutParams;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.Toast;
public class CamTestActivity extends Activity {
private static final String TAG = "CamTestActivity";
Preview preview;
Button buttonClick;
Camera camera;
Activity act;
Context ctx;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ctx = this;
act = this;
setContentView(R.layout.main);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
preview = new Preview(this, (SurfaceView)findViewById(R.id.surfaceView));
preview.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
((FrameLayout) findViewById(R.id.layout)).addView(preview);
preview.setKeepScreenOn(true);
preview.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
camera.takePicture(shutterCallback, rawCallback, jpegCallback);
}
});
Toast.makeText(ctx,getString(R.string.take_photo_help), Toast.LENGTH_LONG).show();
buttonClick = (Button) findViewById(R.id.btnCapture);
buttonClick.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
preview.mCamera.takePicture(shutterCallback, rawCallback, jpegCallback);
camera.takePicture(shutterCallback, rawCallback, jpegCallback);
}
});
buttonClick.setOnLongClickListener(new View.OnLongClickListener(){
#Override
public boolean onLongClick(View arg0) {
camera.autoFocus(new Camera.AutoFocusCallback(){
#Override
public void onAutoFocus(boolean arg0, Camera arg1) {
camera.takePicture(shutterCallback, rawCallback, jpegCallback);
}
});
return true;
}
});
}
#Override
protected void onResume() {
super.onResume();
int numCams = Camera.getNumberOfCameras();
if(numCams > 0){
try{
camera = Camera.open(0);
camera.startPreview();
preview.setCamera(camera);
} catch (RuntimeException ex){
Toast.makeText(ctx, getString(R.string.camera_not_found), Toast.LENGTH_LONG).show();
}
}
}
#Override
protected void onPause() {
if(camera != null) {
camera.stopPreview();
preview.setCamera(null);
camera.release();
camera = null;
}
super.onPause();
}
private void resetCam() {
camera.startPreview();
preview.setCamera(camera);
}
private void refreshGallery(File file) {
Intent mediaScanIntent = new Intent( Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
mediaScanIntent.setData(Uri.fromFile(file));
sendBroadcast(mediaScanIntent);
}
ShutterCallback shutterCallback = new ShutterCallback() {
public void onShutter() {
Log.d(TAG, "onShutter'd");
}
};
PictureCallback rawCallback = new PictureCallback() {
public void onPictureTaken(byte[] data, Camera camera) {
Log.d(TAG, "onPictureTaken - raw");
}
};
PictureCallback jpegCallback = new PictureCallback() {
public void onPictureTaken(byte[] data, Camera camera) {
new SaveImageTask().execute(data);
resetCam();
Log.d(TAG, "onPictureTaken - jpeg");
}
};
#SuppressLint("StaticFieldLeak")
private class SaveImageTask extends AsyncTask<byte[], Void, Void> {
#Override
protected Void doInBackground(byte[]... data) {
FileOutputStream outStream = null;
// Write to SD Card
try {
File sdCard = Environment.getExternalStorageDirectory();
File dir = new File (sdCard.getAbsolutePath() + "/camtest");
dir.mkdirs();
String fileName = String.format("%d.jpg", System.currentTimeMillis());
File outFile = new File(dir, fileName);
outStream = new FileOutputStream(outFile);
outStream.write(data[0]);
outStream.flush();
outStream.close();
Log.d(TAG, "onPictureTaken - wrote bytes: " + data.length + " to " + outFile.getAbsolutePath());
refreshGallery(outFile);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
}
return null;
}
}
}
hear the preview code and contains preview after capturing the photo
package com.example.cam;
/*
* #author Jose Davis Nidhin
*/
import java.io.IOException;
import java.util.List;
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 android.view.View;
import android.view.ViewGroup;
class Preview extends ViewGroup implements SurfaceHolder.Callback {
private final String TAG = "Preview";
SurfaceView mSurfaceView;
SurfaceHolder mHolder;
Size mPreviewSize;
List<Size> mSupportedPreviewSizes;
Camera mCamera;
Preview(Context context, SurfaceView sv) {
super(context);
mSurfaceView = sv;
addView(mSurfaceView);
mHolder = mSurfaceView.getHolder();
mHolder.addCallback(this);
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
public void setCamera(Camera camera) {
mCamera = camera;
if (mCamera != null) {
mSupportedPreviewSizes = mCamera.getParameters().getSupportedPreviewSizes();
requestLayout();
// get Camera parameters
Camera.Parameters params = mCamera.getParameters();
List<String> focusModes = params.getSupportedFocusModes();
if (focusModes.contains(Camera.Parameters.FOCUS_MODE_AUTO)) {
// set the focus mode
params.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
// set Camera parameters
mCamera.setParameters(params);
}
}
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// We purposely disregard child measurements because act as a
// wrapper to a SurfaceView that centers the camera preview instead
// of stretching it.
final int width = resolveSize(getSuggestedMinimumWidth(), widthMeasureSpec);
final int height = resolveSize(getSuggestedMinimumHeight(), heightMeasureSpec);
setMeasuredDimension(width, height);
if (mSupportedPreviewSizes != null) {
mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes, width, height);
}
}
#Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
if (changed && getChildCount() > 0) {
final View child = getChildAt(0);
final int width = r - l;
final int height = b - t;
int previewWidth = width;
int previewHeight = height;
if (mPreviewSize != null) {
previewWidth = mPreviewSize.width;
previewHeight = mPreviewSize.height;
}
// Center the child SurfaceView within the parent.
if (width * previewHeight > height * previewWidth) {
final int scaledChildWidth = previewWidth * height / previewHeight;
child.layout((width - scaledChildWidth) / 2, 0,
(width + scaledChildWidth) / 2, height);
} else {
final int scaledChildHeight = previewHeight * width / previewWidth;
child.layout(0, (height - scaledChildHeight) / 2,
width, (height + scaledChildHeight) / 2);
}
}
}
public void surfaceCreated(SurfaceHolder holder) {
// The Surface has been created, acquire the camera and tell it where
// to draw.
try {
if (mCamera != null) {
mCamera.setPreviewDisplay(holder);
}
} catch (IOException exception) {
Log.e(TAG, "IOException caused by setPreviewDisplay()", exception);
}
}
public void surfaceDestroyed(SurfaceHolder holder) {
// Surface will be destroyed when we return, so stop the preview.
if (mCamera != null) {
mCamera.stopPreview();
}
}
private Size getOptimalPreviewSize(List<Size> sizes, int w, int h) {
final double ASPECT_TOLERANCE = 0.1;
double targetRatio = (double) w / h;
if (sizes == null) return null;
Size optimalSize = null;
double minDiff = Double.MAX_VALUE;
int targetHeight = h;
// Try to find an size match aspect ratio and size
for (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);
}
}
// Cannot find the one match the aspect ratio, ignore the requirement
if (optimalSize == null) {
minDiff = Double.MAX_VALUE;
for (Size size : sizes) {
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
}
return optimalSize;
}
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
if(mCamera != null) {
Camera.Parameters parameters = mCamera.getParameters();
parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
requestLayout();
mCamera.setParameters(parameters);
mCamera.startPreview();
}
}
}
this is the crash log
I/InstantRun: starting instant run server: is main process
D/AccessibilityManager: getInstance() new sInstance = android.view.accessibility.AccessibilityManager#4ed699a, context = com.example.cam.CamTestActivity#65f12cb, userId = 0
D/AndroidRuntime: Shutting down VM
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.cam, PID: 3386
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.cam/com.example.cam.CamTestActivity}: android.util.AndroidRuntimeException: requestFeature() must be called before adding content
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2417)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2477)
at android.app.ActivityThread.-wrap11(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1345)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5452)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:762)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:652)
Caused by: android.util.AndroidRuntimeException: requestFeature() must be called before adding content
at com.android.internal.policy.PhoneWindow.requestFeature(PhoneWindow.java:326)
at android.app.Activity.requestWindowFeature(Activity.java:3656)
at com.example.cam.CamTestActivity.onCreate(CamTestActivity.java:45)
at android.app.Activity.performCreate(Activity.java:6251)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1110)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2370)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2477)
at android.app.ActivityThread.-wrap11(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1345)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5452)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:762)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:652)
I/Process: Sending signal. PID: 3386 SIG: 9
Application terminated.
now please help me solving the problem
Enable different permissions at a single time on app startup in android programmatically.
Here you need to add only CAMERA permission for above Marshmallow Devices, Add this code before Starting your Camera Screen
References :https://www.android-examples.com/request-check-multiple-runtime-permissions-android-marshmallow/
<uses-permission android:name="android.permission.CAMERA"/>
MainActivity.java Code :
public class MainActivity extends AppCompatActivity {
Button button;
public static final int RequestPermissionCode = 1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button = (Button)findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if(checkPermission()){
Toast.makeText(MainActivity.this, "All Permissions Granted Successfully", Toast.LENGTH_LONG).show();
}
else {
requestPermission();
}
}
});
}
private void requestPermission() {
ActivityCompat.requestPermissions(MainActivity.this, new String[]
{
CAMERA,
}, RequestPermissionCode);
}
#Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
switch (requestCode) {
case RequestPermissionCode:
if (grantResults.length > 0) {
boolean CameraPermission = grantResults[0] == PackageManager.PERMISSION_GRANTED;
if (CameraPermission ) {
Toast.makeText(MainActivity.this, "Permission Granted", Toast.LENGTH_LONG).show();
}
else {
Toast.makeText(MainActivity.this,"Permission Denied",Toast.LENGTH_LONG).show();
}
}
break;
}
}
public boolean checkPermission() {
int FirstPermissionResult = ContextCompat.checkSelfPermission(getApplicationContext(), CAMERA);
return FirstPermissionResult == PackageManager.PERMISSION_GRANTED ;
}
}
Or, If you to check Manually without using this Code, its just for check :
Go to Settings -> Apps -> Select Your App -> tap on permissions -> enable Camera Permission.
In your CamTestActivity, move the line requestWindowFeature(Window.FEATURE_NO_TITLE) so it appears before super.onCreate(savedInstanceState)
I've been working with an app that has a camera activity that takes pictures. The normal behavior is to take a picture, send it as an intent and then close this activity, but on Samsung devices this just closes an restarts the app. I tested it on emulators and an Asus tablet and it worked fine. I also tested it on multiple OS versions but I haven't seen a difference. The Samsung devices with the problem are: S4, S2, and Note.
Here is the camera activity:
package app.xqute.com.xqute.ui;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.hardware.Camera;
import android.os.Bundle;
import android.view.Display;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.ImageButton;
import java.io.IOException;
import java.util.List;
import app.xqute.com.xqute.R;
import butterknife.ButterKnife;
import butterknife.InjectView;
import butterknife.OnClick;
import timber.log.Timber;
/**
* Created by mbarisa on 5/21/15.
*/
public class CameraActivity extends Activity {
#InjectView(R.id.cameraPreview)
FrameLayout mCameraPreview;
#InjectView(R.id.btnCapture)
ImageButton mBtnCapture;
private Camera mCamera;
private CameraPreview mPreview;
private int midScreenHeight, midScreenWidth;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_camera);
ButterKnife.inject(this);
mCamera = getCameraInstance();
// Create the Camera preview view
mPreview = new CameraPreview(this, mCamera);
mCameraPreview.addView(mPreview);
Display display = getWindowManager().getDefaultDisplay();
midScreenHeight = display.getHeight() / 2;
midScreenWidth = display.getWidth() / 2;
// TODO: remove this and enable faceDetectionListener
mBtnCapture.setVisibility(View.VISIBLE);
}
#OnClick(R.id.btnCapture)
void capture() {
// mCamera.setFaceDetectionListener(faceDetectionListener);
mCamera.takePicture(() -> {
}, null, mPicture);
}
final Camera.PictureCallback mPicture = (data, camera) -> {
System.out.println("data = " + data.length);
Intent intent = new Intent();
intent.putExtra("data", data);
setResult(RESULT_OK, intent);
finish();
};
final Camera.FaceDetectionListener faceDetectionListener = (faces, camera) -> {
try {
Timber.v("face: " + faces[0].rect.centerX() + " | " + faces[0].rect.centerY());
int posX = midScreenWidth - faces[0].rect.centerX();
int posY = midScreenHeight + faces[0].rect.centerY();
mBtnCapture.setVisibility(View.VISIBLE);
System.out.println("posY = " + posY);
System.out.println("posX = " + posX);
} catch (ArrayIndexOutOfBoundsException e) {
mBtnCapture.setVisibility(View.GONE);
}
};
#Override
protected void onPause() {
super.onPause();
finish();
mPreview.stopPreview();
}
/**
* A safe way to get an instance of the Camera object.
* <p>
* Returns null if camera is unavailable
*/
private static Camera getCameraInstance() {
Camera c = null;
try {
c = Camera.open(Camera.CameraInfo.CAMERA_FACING_FRONT);
} catch (Exception ignore) {
// Camera is not available (in use or does not exist). Do nothing.
}
return c;
}
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
private SurfaceHolder mHolder;
private Camera mCamera;
private List<Camera.Size> mSupportedPreviewSizes;
private Camera.Size mPreviewSize;
public CameraPreview(Context context, Camera camera) {
super(context);
mCamera = camera;
// Install a SurfaceHolder.Callback so we get notified when the
// underlying surface is created and destroyed.
mHolder = getHolder();
mHolder.addCallback(this);
}
public void surfaceCreated(SurfaceHolder holder) {
// The Surface has been created, now tell the camera where to draw the preview
try {
if (mCamera != null) {
mCamera.setDisplayOrientation(90);
mCamera.setPreviewDisplay(holder);
mCamera.startPreview();
// mCamera.setFaceDetectionListener(faceDetectionListener);
// mCamera.startFaceDetection();
}
} catch (IOException e) {
// Do nothing
}
}
public void surfaceDestroyed(SurfaceHolder holder) {
if (mCamera != null) {
mCamera.stopPreview();
}
}
private void stopPreview() {
if (mCamera != null) {
mCamera.stopPreview();
mCamera.release();
mCamera = null;
}
}
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
// If your preview can change or rotate, take care of those events here.
// Make sure to stop the preview before resizing or reformatting it.
if (mHolder.getSurface() == null) {
// preview surface does not exist
return;
}
// Stop preview before making changes
try {
mCamera.stopPreview();
} catch (Exception ignore) {
// Tried to stop a non-existent preview. Do nothing.
}
try {
// Set preview size and make any resize, rotate or reformatting changes here
mSupportedPreviewSizes = mCamera.getParameters().getSupportedPreviewSizes();
Camera.Parameters parameters = mCamera.getParameters();
parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
mCamera.setParameters(parameters);
mCamera.startPreview();
} catch (Exception ignored) {
}
// Start preview with new settings
try {
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
} catch (Exception ignore) {
// Do nothing
}
}
#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);
}
}
}
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;
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 - h) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - h);
}
}
if (optimalSize == null) {
minDiff = Double.MAX_VALUE;
for (Camera.Size size : sizes) {
if (Math.abs(size.height - h) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - h);
}
}
}
return optimalSize;
}
}
Any ideas why this is happening? Or maybe a way to fix or avoid this?
I have spent some time debugging and can't figure why null is occurring. When I run the application immeditaley it crashes and it points to this line:
mSupportedPreviewSizes = mCamera.getParameters().getSupportedPreviewSizes();
and says the object reference is null. I can't figure out why mCamera is returning null.
My Manifest file has the proper permissions:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />
<uses-feature android:name="android.hardware.camera.front" android:required="false" />
Example:
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import android.app.Activity;
import android.content.Context;
import android.content.pm.PackageManager;
import android.hardware.Camera;
import android.hardware.Camera.CameraInfo;
import android.hardware.Camera.PictureCallback;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.Toast;
public class AndroidCameraExample extends Activity {
private Camera mCamera;
private CameraPreview mPreview;
private PictureCallback mPicture;
private Button capture, switchCamera;
private Context myContext;
private LinearLayout cameraPreview;
private boolean cameraFront = false;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
myContext = this;
initialize();
}
private int findFrontFacingCamera() {
int cameraId = -1;
// Search for the front facing camera
int numberOfCameras = Camera.getNumberOfCameras();
for (int i = 0; i < numberOfCameras; i++) {
CameraInfo info = new CameraInfo();
Camera.getCameraInfo(i, info);
if (info.facing == CameraInfo.CAMERA_FACING_FRONT) {
cameraId = i;
cameraFront = true;
break;
}
}
return cameraId;
}
private int findBackFacingCamera() {
int cameraId = -1;
//Search for the back facing camera
//get the number of cameras
int numberOfCameras = Camera.getNumberOfCameras();
//for every camera check
for (int i = 0; i < numberOfCameras; i++) {
CameraInfo info = new CameraInfo();
Camera.getCameraInfo(i, info);
if (info.facing == CameraInfo.CAMERA_FACING_BACK) {
cameraId = i;
cameraFront = false;
break;
}
}
return cameraId;
}
public void onResume() {
super.onResume();
if (!hasCamera(myContext)) {
Toast toast = Toast.makeText(myContext, "Sorry, your phone does not have a camera!", Toast.LENGTH_LONG);
toast.show();
finish();
}
if (mCamera == null) {
//if the front facing camera does not exist
if (findFrontFacingCamera() < 0) {
Toast.makeText(this, "No front facing camera found.", Toast.LENGTH_LONG).show();
switchCamera.setVisibility(View.GONE);
}
mCamera = Camera.open(findBackFacingCamera());
mPicture = getPictureCallback();
mPreview.refreshCamera(mCamera);
}
}
public void initialize() {
cameraPreview = (LinearLayout) findViewById(R.id.camera_preview);
mPreview = new CameraPreview(myContext, mCamera);
cameraPreview.addView(mPreview);
capture = (Button) findViewById(R.id.button_capture);
capture.setOnClickListener(captrureListener);
switchCamera = (Button) findViewById(R.id.button_ChangeCamera);
switchCamera.setOnClickListener(switchCameraListener);
}
OnClickListener switchCameraListener = new OnClickListener() {
#Override
public void onClick(View v) {
//get the number of cameras
int camerasNumber = Camera.getNumberOfCameras();
if (camerasNumber > 1) {
//release the old camera instance
//switch camera, from the front and the back and vice versa
releaseCamera();
chooseCamera();
} else {
Toast toast = Toast.makeText(myContext, "Sorry, your phone has only one camera!", Toast.LENGTH_LONG);
toast.show();
}
}
};
public void chooseCamera() {
//if the camera preview is the front
if (cameraFront) {
int cameraId = findBackFacingCamera();
if (cameraId >= 0) {
//open the backFacingCamera
//set a picture callback
//refresh the preview
mCamera = Camera.open(cameraId);
mPicture = getPictureCallback();
mPreview.refreshCamera(mCamera);
}
} else {
int cameraId = findFrontFacingCamera();
if (cameraId >= 0) {
//open the backFacingCamera
//set a picture callback
//refresh the preview
mCamera = Camera.open(cameraId);
mPicture = getPictureCallback();
mPreview.refreshCamera(mCamera);
}
}
}
#Override
protected void onPause() {
super.onPause();
//when on Pause, release camera in order to be used from other applications
releaseCamera();
}
private boolean hasCamera(Context context) {
//check if the device has camera
if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)) {
return true;
} else {
return false;
}
}
private PictureCallback getPictureCallback() {
PictureCallback picture = new PictureCallback() {
#Override
public void onPictureTaken(byte[] data, Camera camera) {
//make a new picture file
File pictureFile = getOutputMediaFile();
if (pictureFile == null) {
return;
}
try {
//write the file
FileOutputStream fos = new FileOutputStream(pictureFile);
fos.write(data);
fos.close();
Toast toast = Toast.makeText(myContext, "Picture saved: " + pictureFile.getName(), Toast.LENGTH_LONG);
toast.show();
} catch (FileNotFoundException e) {
} catch (IOException e) {
}
//refresh camera to continue preview
mPreview.refreshCamera(mCamera);
}
};
return picture;
}
OnClickListener captrureListener = new OnClickListener() {
#Override
public void onClick(View v) {
mCamera.takePicture(null, null, mPicture);
}
};
//make picture and save to a folder
private static File getOutputMediaFile() {
//make a new file directory inside the "sdcard" folder
File mediaStorageDir = new File("/sdcard/", "JCG Camera");
//if this "JCGCamera folder does not exist
if (!mediaStorageDir.exists()) {
//if you cannot make this folder return
if (!mediaStorageDir.mkdirs()) {
return null;
}
}
//take the current timeStamp
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
File mediaFile;
//and make a media file:
mediaFile = new File(mediaStorageDir.getPath() + File.separator + "IMG_" + timeStamp + ".jpg");
return mediaFile;
}
private void releaseCamera() {
// stop and release camera
if (mCamera != null) {
mCamera.release();
mCamera = null;
}
}
}
CameraPreview:
import java.io.IOException;
import java.util.List;
import android.content.Context;
import android.hardware.Camera;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
private static final String TAG = "CameraPreview";
private Context mContext;
private SurfaceHolder mHolder;
private Camera mCamera;
private List<Camera.Size> mSupportedPreviewSizes;
private Camera.Size mPreviewSize;
public CameraPreview(Context context, Camera camera) {
super(context);
mContext = context;
mCamera = camera;
// supported preview sizes
mSupportedPreviewSizes = mCamera.getParameters().getSupportedPreviewSizes();
for (Camera.Size str : mSupportedPreviewSizes)
Log.e(TAG, str.width + "/" + str.height);
// Install a SurfaceHolder.Callback so we get notified when the
// underlying surface is created and destroyed.
mHolder = getHolder();
mHolder.addCallback(this);
// deprecated setting, but required on Android versions prior to 3.0
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
public void surfaceCreated(SurfaceHolder holder) {
// empty. surfaceChanged will take care of stuff
}
public void surfaceDestroyed(SurfaceHolder holder) {
// empty. Take care of releasing the Camera preview in your activity.
}
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
Log.e(TAG, "surfaceChanged => w=" + w + ", h=" + h);
// If your preview can change or rotate, take care of those events here.
// Make sure to stop the preview before resizing or reformatting it.
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 {
Camera.Parameters parameters = mCamera.getParameters();
parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
mCamera.setParameters(parameters);
mCamera.setDisplayOrientation(90);
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
} catch (Exception e){
Log.d(TAG, "Error starting camera preview: " + e.getMessage());
}
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
final int width = resolveSize(getSuggestedMinimumWidth(), widthMeasureSpec);
final int height = resolveSize(getSuggestedMinimumHeight(), heightMeasureSpec);
if (mSupportedPreviewSizes != null) {
mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes, width, height);
}
float ratio;
if(mPreviewSize.height >= mPreviewSize.width)
ratio = (float) mPreviewSize.height / (float) mPreviewSize.width;
else
ratio = (float) mPreviewSize.width / (float) mPreviewSize.height;
// One of these methods should be used, second method squishes preview slightly
setMeasuredDimension(width, (int) (width * ratio));
// setMeasuredDimension((int) (width * ratio), height);
}
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.height / size.width;
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;
}
public void refreshCamera(Camera camera) {
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
setCamera(camera);
try {
Camera.Parameters parameters = mCamera.getParameters();
parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
mCamera.setParameters(parameters);
mCamera.setDisplayOrientation(90);
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
} catch (Exception e) {
Log.d(VIEW_LOG_TAG, "Error starting camera preview: " + e.getMessage());
}
}
public void setCamera(Camera camera) {
//method to set a camera instance
mCamera = camera;
}
}
As I am using a tutorial, if I use this CameraPreview.java instead (keeping the same Example class) it works, but I needed to make some modifications to the tutorial for the aspect ratio reasons:
import java.io.IOException;
import android.content.Context;
import android.hardware.Camera;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
private SurfaceHolder mHolder;
private Camera mCamera;
public CameraPreview(Context context, Camera camera) {
super(context);
mCamera = camera;
mHolder = getHolder();
mHolder.addCallback(this);
// deprecated setting, but required on Android versions prior to 3.0
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
public void surfaceCreated(SurfaceHolder holder) {
try {
// create the surface and start camera preview
if (mCamera == null) {
mCamera.setPreviewDisplay(holder);
mCamera.startPreview();
}
} catch (IOException e) {
Log.d(VIEW_LOG_TAG, "Error setting camera preview: " + e.getMessage());
}
}
public void refreshCamera(Camera camera) {
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
setCamera(camera);
try {
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
} catch (Exception e) {
Log.d(VIEW_LOG_TAG, "Error starting camera preview: " + e.getMessage());
}
}
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
// If your preview can change or rotate, take care of those events here.
// Make sure to stop the preview before resizing or reformatting it.
refreshCamera(mCamera);
}
public void setCamera(Camera camera) {
//method to set a camera instance
mCamera = camera;
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
// mCamera.release();
}
}
UPDATE: Additionally I tried to put chooseCamera(); right before the mPreview = new CameraPreview(myContext, mCamera); but it did not work.
I have a guess, as I haven't tested this code, but from looking at it as is, I think that you are calling initialize() before you are instantiating your actually Camera object. Observe this picture of the Android life cycle:
diagram source
You will notice that onResume() is called AFTER onCreate(). In your code you are creating the CameraPreview class with your null mCamera reference in the by calling the initialize() method in onCreate(). Therefore, the line in CameraPreview:
mSupportedPreviewSizes = mCamera.getParameters().getSupportedPreviewSizes();
is calling a null object reference, mCamera. Instead, move
mCamera = Camera.open(findBackFacingCamera());
to onCreate() (before the call to initialize CameraPreview of course!), keeping the same call in onResume(). Keep the check for a null Camera in onResume() in case the user leaves the activity and Camera is closed for some reason.
EDIT: As Oren Bengigi suggested, I tried enclosing the bit of code that saves the data in a post(Runnable), but I'm still getting the same results:
final Handler handler = new Handler();
void savePicture(final byte[] data) {
handler.post(new Runnable() {
public void run() {
try {
FrameLayout view = (FrameLayout)findViewById(R.id.image);
view.setDrawingCacheEnabled(true);
Bitmap b = view.getDrawingCache();
b.compress(CompressFormat.PNG, 50, new FileOutputStream(Environment.getExternalStorageDirectory() + String.format(
"/SimpleBulb/%d.png", System.currentTimeMillis())));
Log.d(TAG, "onPictureTaken - wrote bytes: " + data.length);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
}
}
});
}
I am trying to take a picture with an overlay and save both as one .png. I am able to save the image the camera captures, and I'm able to save the overlay, but when I try to save both as one image, I only see the overlay and a black background. I've switched the two layers and the entire image was black, so the picture from the camera is just being rendered black. Any help on this would be GREATLY appreciated. Here's my code:
package com.commonsware.android.skeleton;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.BitmapFactory;
import android.hardware.Camera;
import android.hardware.Camera.*;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.Display;
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.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;
// ----------------------------------------------------------------------
public class SimpleBulbActivity extends Activity {
private Preview mPreview;
private static final String TAG = "CameraDemo";
RelativeLayout preview;
Camera mCamera;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Hide the window title.
requestWindowFeature(Window.FEATURE_NO_TITLE);
// create a File object for the parent directory
File imageDirectory = new File(Environment.getExternalStorageDirectory() + "/SimpleBulb/");
// Check if the directory exists
if(!imageDirectory.exists()) {
// have the object build the directory structure, if needed.
imageDirectory.mkdirs();
}
setContentView(R.layout.main);
}
protected void onResume() {
super.onResume();
//Setup the FrameLayout with the Camera Preview Screen
mPreview = new Preview(this);
preview = (RelativeLayout)findViewById(R.id.preview);
preview.addView(mPreview);
}
public void snap(View view) {
mCamera.takePicture(shutterCallback, rawCallback, jpegCallback);
}
ShutterCallback shutterCallback = new ShutterCallback() {
public void onShutter() {
Log.d(TAG, "onShutter'd");
}
};
PictureCallback rawCallback = new PictureCallback() {
public void onPictureTaken(byte[] _data, Camera _camera) {
Log.d(TAG, "onPictureTaken - raw");
}
};
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);
// Save image to SD Card
/*BitmapFactory.Options options=new BitmapFactory.Options();
options.inSampleSize = 5;
String filename = Environment.getExternalStorageDirectory() + String.format(
"/SimpleBulb/%d.png", System.currentTimeMillis());
Bitmap myImage = BitmapFactory.decodeByteArray(data, 0,data.length,options);
outStream = new FileOutputStream(filename);
BufferedOutputStream bos = new BufferedOutputStream(outStream);
myImage.compress(CompressFormat.PNG, 95, bos);
bos.flush();
bos.close();
// Replace view with Picture taken
ImageView cameraImage = (ImageView)findViewById(R.id.taken_image);
cameraImage.setImageBitmap(myImage);*/
// Save as one
FrameLayout view = (FrameLayout)findViewById(R.id.image);
view.setDrawingCacheEnabled(true);
Bitmap b = view.getDrawingCache();
b.compress(CompressFormat.PNG, 50, new FileOutputStream(Environment.getExternalStorageDirectory() + String.format(
"/SimpleBulb/%d.png", System.currentTimeMillis())));
Log.d(TAG, "onPictureTaken - wrote bytes: " + data.length);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
}
Log.d(TAG, "onPictureTaken - jpeg");
}
};
// ----------------------------------------------------------------------
class Preview extends SurfaceView implements SurfaceHolder.Callback {
SurfaceHolder mHolder;
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.
mCamera = Camera.open();
try {
mCamera.setPreviewDisplay(holder);
mCamera.setPreviewCallback(new PreviewCallback() {
public void onPreviewFrame(byte[] data, Camera arg1) {
Log.d(TAG, "onPreviewFrame - wrote bytes: "
+ data.length);
Preview.this.invalidate();
}
});
} catch (IOException e) {
mCamera.release();
mCamera = null;
e.printStackTrace();
}
}
public void surfaceDestroyed(SurfaceHolder holder) {
// Surface will be destroyed when we return, so stop the preview.
// Because the CameraDevice object is not a shared resource, it's very
// important to release it when the activity is paused.
mCamera.stopPreview();
mCamera.release();
mCamera = null;
}
private Size getOptimalPreviewSize(List<Size> sizes, int w, int h) {
final double ASPECT_TOLERANCE = 0.05;
double targetRatio = (double) w / h;
if (sizes == null) return null;
Size optimalSize = null;
double minDiff = Double.MAX_VALUE;
int targetHeight = h;
// Try to find an size match aspect ratio and size
for (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);
}
}
// Cannot find the one match the aspect ratio, ignore the requirement
if (optimalSize == null) {
minDiff = Double.MAX_VALUE;
for (Size size : sizes) {
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
}
return optimalSize;
}
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 = mCamera.getParameters();
List<Size> sizes = parameters.getSupportedPreviewSizes();
Size optimalSize = getOptimalPreviewSize(sizes, w, h);
Display display = ((WindowManager)getSystemService(WINDOW_SERVICE)).getDefaultDisplay();
if(display.getRotation() == Surface.ROTATION_0)
{
parameters.setPreviewSize(optimalSize.height, optimalSize.width);
mCamera.setDisplayOrientation(90);
}
if(display.getRotation() == Surface.ROTATION_90)
{
parameters.setPreviewSize(optimalSize.width, optimalSize.height);
}
if(display.getRotation() == Surface.ROTATION_180)
{
parameters.setPreviewSize(optimalSize.width, optimalSize.height);
}
if(display.getRotation() == Surface.ROTATION_270)
{
parameters.setPreviewSize(optimalSize.width, optimalSize.height);
mCamera.setDisplayOrientation(0);
}
mCamera.setParameters(parameters);
mCamera.startPreview();
}
}
}
Here's my layout:
<?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">
<FrameLayout android:id="#+id/image" android:layout_weight="1" android:layout_width="fill_parent"
android:layout_height="fill_parent">
<RelativeLayout android:id="#+id/preview"
android:layout_weight="1" android:layout_width="fill_parent"
android:layout_height="fill_parent">
</RelativeLayout>
<RelativeLayout android:id="#+id/bulb_pic" android:layout_width="match_parent" android:layout_height="112dip">
<ImageView android:id="#+id/bulb" android:src="#drawable/litbulb"
android:layout_width="match_parent"
android:layout_height="112dip" />
</RelativeLayout>
</FrameLayout>
<Button android:layout_width="match_parent"
android:layout_height="wrap_content" android:id="#+id/buttonClick"
android:text="Snap!" android:layout_gravity="center" android:onClick="snap"></Button>
</LinearLayout>
It might be that the ImageView that you set, doesn't update immediately.
What I would try is running the follwoing code:
Bitmap b = view.getDrawingCache();
b.compress(CompressFormat.PNG, 50, new FileOutputStream(Environment.getExternalStorageDirectory() + String.format(
"/SimpleBulb/%d.png", System.currentTimeMillis())));
Log.d(TAG, "onPictureTaken - wrote bytes: " + data.length);
in a handler with postRunaable and see if it works.
I thought WINDOW_SERVICE was supposed to be a constant defined in android.content.Context.
http://developer.android.com/reference/android/content/Context.html#WINDOW_SERVICE
When I use it in the following segment of code it throws an error saying it cannot be resolved as a variable.
Display display = ((WindowManager)getSystemService(WINDOW_SERVICE)).getDefaultDisplay();
Here's the full code:
package com.commonsware.android.skeleton;
import android.app.Activity;
import android.content.Context;
import android.hardware.Camera;
import android.hardware.Camera.*;
import android.os.Bundle;
import android.view.Display;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.Window;
import android.view.WindowManager;
import android.widget.FrameLayout;
import java.io.IOException;
import java.util.List;
// ----------------------------------------------------------------------
public class SimpleBulbActivity extends Activity {
private Preview mPreview;
FrameLayout preview;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Hide the window title.
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.main);
}
protected void onResume() {
super.onResume();
//Setup the FrameLayout with the Camera Preview Screen
mPreview = new Preview(this);
preview = (FrameLayout)findViewById(R.id.preview);
preview.addView(mPreview);
}
}
// ----------------------------------------------------------------------
class Preview extends SurfaceView implements SurfaceHolder.Callback {
SurfaceHolder mHolder;
Camera mCamera;
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.
mCamera = Camera.open();
try {
mCamera.setPreviewDisplay(holder);
} catch (IOException exception) {
mCamera.release();
mCamera = null;
// TODO: add more exception handling logic here
}
}
public void surfaceDestroyed(SurfaceHolder holder) {
// Surface will be destroyed when we return, so stop the preview.
// Because the CameraDevice object is not a shared resource, it's very
// important to release it when the activity is paused.
mCamera.stopPreview();
mCamera.release();
mCamera = null;
}
private Size getOptimalPreviewSize(List<Size> sizes, int w, int h) {
final double ASPECT_TOLERANCE = 0.05;
double targetRatio = (double) w / h;
if (sizes == null) return null;
Size optimalSize = null;
double minDiff = Double.MAX_VALUE;
int targetHeight = h;
// Try to find an size match aspect ratio and size
for (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);
}
}
// Cannot find the one match the aspect ratio, ignore the requirement
if (optimalSize == null) {
minDiff = Double.MAX_VALUE;
for (Size size : sizes) {
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
}
return optimalSize;
}
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 = mCamera.getParameters();
List<Size> sizes = parameters.getSupportedPreviewSizes();
Size optimalSize = getOptimalPreviewSize(sizes, w, h);
parameters.setPreviewSize(optimalSize.width, optimalSize.height);
Display display = ((WindowManager)getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
if(display.getRotation() == Surface.ROTATION_0)
{
parameters.setPreviewSize(h, w);
mCamera.setDisplayOrientation(90);
}
if(display.getRotation() == Surface.ROTATION_90)
{
parameters.setPreviewSize(w, h);
}
if(display.getRotation() == Surface.ROTATION_180)
{
parameters.setPreviewSize(h, w);
}
if(display.getRotation() == Surface.ROTATION_270)
{
parameters.setPreviewSize(w, h);
mCamera.setDisplayOrientation(180);
}
mCamera.setParameters(parameters);
mCamera.startPreview();
}
}
Try...
Display display = ((WindowManager)getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();