I have researched for a few days now and my last resort is to ask others that know way more than I do. I having been following tutorials and code picked up along the way. I have not been able to perform the simple function of creating a camera preview. I am not interested in saving snap shots, just simply viewing the onboard camera in an app. Any help would be greatly appreciated. My ultimate goal is to have a preview of an IP camera. Is ther a full code out there for this application that I canplay around with or can someone let me know why this code does not work?
Here is the main:
package com.example.cameracontrol;
import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
The CameraPreview Class:
import java.io.IOException;
import java.util.List;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.hardware.Camera;
import android.hardware.Camera.Size;
import android.util.Log;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
#SuppressLint("ViewConstructor")
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
private static final String TAG = "CameraPreview";
private SurfaceHolder mHolder;
private Camera mCamera;
private Size mPreviewSize;
#SuppressWarnings("deprecation")
public CameraPreview(Context context, Camera camera, Activity activity) {
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);
// deprecated setting, but required on Android versions prior to 3.0
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
public void surfaceCreated(SurfaceHolder holder) {
// The Surface has been created, now tell the camera where to draw the preview.
try {
mCamera.setPreviewDisplay(holder);
mCamera.startPreview();
}
catch (IOException e) {
Log.d(TAG, "Error setting camera preview: " + e.getMessage());
}
}
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) {
// 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
/**Camera.Parameters parameters = mCamera.getParameters();
List<Size> localSizes = mCamera.getParameters().getSupportedPreviewSizes();
mPreviewSize = localSizes.get(0);
Log.d(TAG, "Width " + mPreviewSize.width);
Log.d(TAG, "Height " + mPreviewSize.height);
parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height );
requestLayout();
mCamera.setParameters(parameters);*/
Camera.Parameters p = mCamera.getParameters();
p.setPreviewSize(w, h);
mCamera.setParameters(p);
//start preview with new settings
try {
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
}
catch (Exception e){
Log.d(TAG, "Error starting camera preview: " + e.getMessage());
}
}
#SuppressLint("NewApi")
public static void setCameraDisplayOrientation(Activity activity, int cameraId, android.hardware.Camera camera) {
android.hardware.Camera.CameraInfo info = new android.hardware.Camera.CameraInfo();
android.hardware.Camera.getCameraInfo(cameraId, info);
int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
int degrees = 0;
int result;
switch (rotation) {
case Surface.ROTATION_0: degrees = 0; break;
case Surface.ROTATION_90: degrees = -90; break;
case Surface.ROTATION_180: degrees = 0; break;
case Surface.ROTATION_270: degrees = -90; break;
}
if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
result = (info.orientation + degrees) % 360;
result = (360 - result) % 360; // compensate the mirror
}
else { // back-facing
result = (info.orientation - degrees + 360) % 360;
}
camera.setDisplayOrientation(result);
}
}
The CameraActivity:
import com.example.cameracontrol.R;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.pm.PackageManager;
import android.hardware.Camera;
import android.os.Bundle;
import android.util.Log;
import android.widget.FrameLayout;
public class CameraActivity extends Activity {
private Camera mCamera;
private CameraPreview mPreview;
private FrameLayout preview;
private static final String TAG = "CameraActivity";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (checkCameraHardware(getBaseContext())){
// Create an instance of Camera
mCamera = getCameraInstance();
// Create our Preview view and set it as the content of our activity.
mPreview = new CameraPreview(this, mCamera, CameraActivity.this);
preview = (FrameLayout) findViewById(R.id.camera_preview);
preview.addView(mPreview);
}
}
/** Check if this device has a camera */
private boolean checkCameraHardware(Context context) {
if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)){
Log.d(TAG, "Camera Available");
return true;
} else {
Log.d(TAG, "No Camera Found");
return false;
}
}
/** A safe way to get an instance of the Camera object. */
#SuppressLint("NewApi")
public Camera getCameraInstance(){
Camera c = null;
try {
int i = Camera.getNumberOfCameras();
releaseCamera(); //in case camera is being accessed by any other app.
Log.d(TAG, "Number of Cameras "+i +"\n");
c = Camera.open(); // attempt to get a Camera instance
Log.d(TAG, "Camera Opened");
}
catch (Exception e){
Log.d(TAG, "Camera Can't Be Accessed");
}
return c; // returns null if camera is unavailable
}
#Override
protected void onPause() {
super.onPause();
releaseCamera(); // release the camera immediately on pause event
}
private void releaseCamera(){
if (mCamera != null){
//mCamera.setPreviewCallback(null);
mPreview.getHolder().removeCallback(mPreview);
mCamera.release(); // release the camera for other applications
}
}
}
The activity_main.xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:baselineAligned="false"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".CameraActivity" >
<FrameLayout
android:id="#+id/camera_preview"
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_weight = "1" />
</LinearLayout>
The manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.cameracontrol"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="19" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name="com.example.cameracontrol.MainActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".CameraActivity"
android:label="#string/app_name"
android:screenOrientation="landscape">
<!-- configure this activity to use landscape orientation -->
</activity>
</application>
</manifest>
Related
I want to capture images using the front facing camera "flash" trick similar to Fornt Flash.
I know that it might involves another layer on top of the camera preview
as suggested here and here.
Can anyone post a working solution that includes the camera?
Thanks.
Found out by myself (and some little help from a friend).
Basically you need to create a flash emulator View that has a white background with alpha of 0.7 and visibility gone.
when clicked you need to:
show the view - View.VISIBLE
flashEmulator.setVisibility(View.VISIBLE);
adjust the screenBrightness to the max value
Window window = getWindow();
WindowManager.LayoutParams params = window.getAttributes();
lastScreenBrightness = params.screenBrightness;
params.screenBrightness = 1F;
window.setAttributes(params);
convert the background of the flash emulator to HSV
int color = Color.WHITE;
float[] hsv = new float[3];
Color.colorToHSV(color, hsv);
hsv[2] *= 1f;
color = Color.HSVToColor(hsv);
flashEmulator.setBackgroundColor(color);
Complete Code for android front flash app
Manifest
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.frontflash.android">
<uses-feature android:name="android.hardware.camera" android:required="true" />
<uses-feature android:name="android.hardware.camera.front" android:required="false" />
<uses-feature android:name="android.hardware.camera.flash" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
XML
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:background="#android:color/black"
tools:context=".MainActivity">
<com.frontflash.android.CameraPreview
android:id="#+id/cameraPreview"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
<FrameLayout
android:visibility="gone"
android:alpha="0.7"
android:id="#+id/flashEmulator"
android:background="#android:color/white"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="On"
android:id="#+id/button"
android:layout_centerVertical="false"
android:layout_centerHorizontal="true" />
MainActivity.java
package com.frontflash.android;
import android.app.Activity;
import android.graphics.Color;
import android.hardware.Camera;
import android.os.Bundle;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.FrameLayout;
public class MainActivity extends Activity {
private Button button;
private Camera camera;
private boolean isFlashOn;
private FrameLayout flashEmulator;
private float lastScreenBrightness;
private CameraPreview cameraPreview;
#Override
protected void onCreate(Bundle savedInstanceState) {
int fullScreen = WindowManager.LayoutParams.FLAG_FULLSCREEN;
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(fullScreen, fullScreen);
setContentView(R.layout.activity_main);
button = (Button) findViewById(R.id.button);
flashEmulator = (FrameLayout) findViewById(R.id.flashEmulator);
cameraPreview = (CameraPreview)findViewById(R.id.cameraPreview);
startCamera();
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (isFlashOn) {
turnOffFlash();
button.setText("On");
} else {
turnOnFlash();
button.setText("Off");
}
}
});
}
private void startCamera() {
if (camera == null) {
try {
camera = Camera.open(1);
Camera.Parameters params = camera.getParameters();
params.setPreviewSize(1280, 720);
camera.setDisplayOrientation(90);
camera.setParameters(params);
cameraPreview.connectCamera(camera);
cameraPreview.startPreview();
} catch (Exception e) {
}
}
}
private void turnOnFlash() {
if (!isFlashOn) {
int color = Color.WHITE;
float[] hsv = new float[3];
final Window window = getWindow();
final WindowManager.LayoutParams params = window.getAttributes();
lastScreenBrightness = params.screenBrightness;
params.screenBrightness = 1F;
window.setAttributes(params);
flashEmulator.setVisibility(View.VISIBLE);
Color.colorToHSV(color, hsv);
hsv[2] *= 1f;
color = Color.HSVToColor(hsv);
flashEmulator.setBackgroundColor(color);
isFlashOn = true;
}
}
private void turnOffFlash() {
if (isFlashOn) {
Window window = getWindow();
WindowManager.LayoutParams params = window.getAttributes();
params.screenBrightness = lastScreenBrightness;
window.setAttributes(params);
flashEmulator.setVisibility(View.GONE);
isFlashOn = false;
}
}
#Override
protected void onDestroy() {
super.onDestroy();
}
#Override
protected void onPause() {
super.onPause();
turnOffFlash();
}
#Override
protected void onRestart() {
super.onRestart();
}
#Override
protected void onResume() {
super.onResume();
}
#Override
protected void onStart() {
super.onStart();
startCamera();
}
#Override
protected void onStop() {
super.onStop();
if (camera != null) {
camera.release();
camera = null;
}
}
}
CameraPreview.java
package com.frontflash.android;
import android.content.Context;
import android.hardware.Camera;
import android.util.AttributeSet;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
/**
* Created by sagi on 2/8/2017.
*/
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
private Camera camera;
private SurfaceHolder surfaceHolder;
private final String LOG_TAG = "CameraPreview";
public CameraPreview(Context context, AttributeSet attributeSet) {
super(context, attributeSet);
}
public CameraPreview(Context context) {
super(context);
}
public void connectCamera(Camera camera) {
this.camera = camera;
surfaceHolder = getHolder();
surfaceHolder.addCallback(this);
startPreview();
}
public void releaseCamera() {
if (camera != null) {
stopPreview();
camera = null;
}
}
void startPreview() {
if (camera != null && surfaceHolder.getSurface() != null) {
try {
camera.setPreviewDisplay(surfaceHolder);
camera.startPreview();
} catch (Exception e) {
Log.e(LOG_TAG, String.format("Error setting preview display: %s", e.getMessage()));
}
}
}
void stopPreview() {
if (camera != null) {
try {
camera.stopPreview();
} catch (Exception e) {
Log.e(LOG_TAG, String.format("Error stopping preview: %s", e.getMessage()));
}
}
}
public void surfaceCreated(SurfaceHolder surfaceHolder) {
startPreview();
}
public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {
stopPreview();
startPreview();
}
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
stopPreview();
}
}
I wrote a class for camera preview
public class CameraView extends SurfaceView implements SurfaceHolder.Callback{
private Camera camera;
public CameraView(Context context) {
super(context);
getHolder().addCallback(this);
getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
public static void setCameraDisplayOrientation(Activity activity, int cameraId, Camera camera){
Camera.CameraInfo info = new Camera.CameraInfo();
Camera.getCameraInfo(cameraId, info);
int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
int degrees = 0;
switch (rotation){
case Surface.ROTATION_0:
degrees = 0;
break;
case Surface.ROTATION_90:
degrees = 90;
break;
case Surface.ROTATION_180:
degrees = 180;
break;
case Surface.ROTATION_270:
degrees = 270;
break;
}
int result;
if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT){
result = (info.orientation + degrees) % 360;
result = (360 - result) % 360;
}else{
result = (info.orientation - degrees + 360) % 360;
}
camera.setDisplayOrientation(result);
}
#Override
public void surfaceCreated(SurfaceHolder surfaceHolder) {
camera = Camera.open();
}
#Override
public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {
setCameraDisplayOrientation((Activity)getContext(), Camera.CameraInfo.CAMERA_FACING_BACK, camera);
Camera.Parameters parameters = camera.getParameters();
Camera.Size bestSize = null;
for (Camera.Size size : parameters.getSupportedPictureSizes()){
if (size.width <= i1 && size.height <=i2) {
if (bestSize == null) {
bestSize = size;
} else {
int bestArea = bestSize.width * bestSize.height;
int newArea = size.width * size.height;
if (newArea > bestArea){
bestSize = size;
}
}
}
}
parameters.setPictureSize(bestSize.width, bestSize.height);
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
camera.setParameters(parameters);
try{
camera.setPreviewDisplay(surfaceHolder);
}catch (IOException e){
e.printStackTrace();
}
camera.startPreview();
}
#Override
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
camera.stopPreview();
camera.release();
camera = null;
}
}
And then I wrote a layout file and I want to display the preview in the "SurfaceView"
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<SurfaceView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/camera_view" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:layout_alignParentBottom="true"
android:weightSum="1">
<Button
android:id="#+id/stop_navigation"
android:layout_weight="0.5"
android:layout_height="32dp"
android:layout_width="0dp"
android:text="#string/stop_navigation"
android:textColor="#color/colorWhite"
android:textSize="12sp"
android:background="#color/colorAccent" />
</LinearLayout>
</RelativeLayout>
So how should I do in the main activity? Before I just did the below code and everything is fine.
CameraView cameraView = new CameraView(this);
addContentView(cameraView, new ActionBar.LayoutParams(WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.WRAP_CONTENT));
But now I need to put the preview into the layout I design.
Use FrameLayout and add CameraPreview to it.
// Create an instance of Camera
mCamera = getCameraInstance();
// Create our Preview view and set it as the content of our activity.
mPreview = new CameraPreview(this, mCamera);
FrameLayout preview = (FrameLayout) findViewById(R.id.camera_preview);
preview.addView(mPreview);
/** A basic Camera preview class */
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
private SurfaceHolder mHolder;
private Camera mCamera;
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);
// deprecated setting, but required on Android versions prior to 3.0
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
public void surfaceCreated(SurfaceHolder holder) {
// The Surface has been created, now tell the camera where to draw the preview.
try {
mCamera.setPreviewDisplay(holder);
mCamera.startPreview();
} catch (IOException e) {
Log.d(TAG, "Error setting camera preview: " + e.getMessage());
}
}
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) {
// 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 {
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
} catch (Exception e){
Log.d(TAG, "Error starting camera preview: " + e.getMessage());
}
}
}
<FrameLayout
android:id="#+id/camera_preview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1"
/>
try this:
You need to Change in your SurfaceView in XML File.
Replace your surfaceView with this
<CameraView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/camera_view" />
and your remaining code is Right.let me know after change
Hope this will helps...(:
At first you should add the camera permission in you Manifest.xml :
android:name="android.permission.CAMERA
And, add this in your activity :
#Override
protected void onResume() {
super.onResume();
mCameraView.start();
}
#Override
protected void onPause() {
mCameraView.stop();
super.onPause();
}
Check this link, it's the easiest way to do it :
https://github.com/google/cameraview
For nearly 15 days I 'm stuck on the recording of frames in the event onPreviewFrame Android camera . My goal is very simple, I want to record five consecutive images at the click of a button. Only I do not want to block the preview of the camera , so I use the previewFrame . But during the recording of my image in jpeg on the sd card it is green and pink with many horizontal bars. A term I will send a list of byte [] on a Web API.
I already do a lot of research , trying to change the PictureSize and PreviewSize but nothing changes .
Another option would it not go through recording a video and extract the frame of it ?
Here is the code in my fragment :
package rocketweb.com.videocatcher.fragment;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.ImageFormat;
import android.graphics.Rect;
import android.graphics.YuvImage;
import android.hardware.Camera;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Display;
import android.view.LayoutInflater;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.Toast;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.mime.content.ByteArrayBody;
import org.apache.http.impl.client.BasicResponseHandler;
import org.apache.http.impl.client.DefaultHttpClient;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import rocketweb.com.videocatcher.R;
import rocketweb.com.videocatcher.utilities.ImageHelper;
import org.apache.http.entity.mime.MultipartEntity;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.protocol.HttpContext;
/**
* Created by Bastien on 15/03/2015.
*/
public class CameraFragment extends BaseFragment {
private Camera mCamera;
private CameraPreview mPreview;
private View mCameraView;
private List<byte[]> imagesFrame;
private boolean activeFrameCapture = false;
public CameraFragment(){
super();
}
public static CameraFragment newInstance(int sectionNumber) {
CameraFragment fragment = new CameraFragment();
Bundle args = new Bundle();
args.putInt(ARG_SECTION_NUMBER, sectionNumber);
fragment.setArguments(args);
return fragment;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_video_catcher, container, false);
boolean opened = safeCameraOpenInView(view);
if(opened == false){
Log.d("Camera", "Error, Camera failed to open");
return view;
}
Button captureButton = (Button) view.findViewById(R.id.button_capture);
captureButton.setOnClickListener(
new View.OnClickListener() {
#Override
public void onClick(View v) {
activeFrameCapture = !activeFrameCapture;
}
}
);
imagesFrame = new ArrayList<byte[]>(){};
return view;
}
private boolean safeCameraOpenInView(View view) {
boolean qOpened = false;
releaseCameraAndPreview();
mCamera = getCameraInstance();
mCameraView = view;
qOpened = (mCamera != null);
if(qOpened == true){
mPreview = new CameraPreview(getActivity().getBaseContext(), mCamera,view);
FrameLayout preview = (FrameLayout) view.findViewById(R.id.camera_preview);
preview.addView(mPreview);
mPreview.startCameraPreview();
}
return qOpened;
}
public static Camera getCameraInstance(){
Camera c = null;
try {
c = Camera.open(); // attempt to get a Camera instance
}
catch (Exception e){
e.printStackTrace();
}
return c; // returns null if camera is unavailable
}
#Override
public void onPause() {
super.onPause();
}
#Override
public void onDestroy() {
super.onDestroy();
releaseCameraAndPreview();
}
private void releaseCameraAndPreview() {
if (mCamera != null) {
mCamera.stopPreview();
mCamera.release();
mCamera = null;
}
if(mPreview != null){
mPreview.destroyDrawingCache();
mPreview.mCamera = null;
}
}
class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
private SurfaceHolder mHolder;
private Camera mCamera;
private Context mContext;
private Camera.Size mPreviewSize;
private List<Camera.Size> mSupportedPreviewSizes;
private List<String> mSupportedFlashModes;
private List<Camera.Size> mSupportedSizePicture;
private View mCameraView;
public CameraPreview(Context context, Camera camera, View cameraView) {
super(context);
// Capture the context
mCameraView = cameraView;
mContext = context;
setCamera(camera);
// Install a SurfaceHolder.Callback so we get notified when the
// underlying surface is created and destroyed.
mHolder = getHolder();
mHolder.addCallback(this);
mHolder.setKeepScreenOn(true);
// deprecated setting, but required on Android versions prior to 3.0
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
mCamera.setPreviewCallback(new Camera.PreviewCallback() {
public void onPreviewFrame(byte[] data, Camera camera) {
if (activeFrameCapture && imagesFrame.size() <= 5) {
Camera.Parameters parameters = camera.getParameters();
Camera.Size size = parameters.getPreviewSize();
YuvImage im = new YuvImage(data, ImageFormat.NV21, size.width,size.height, null);
Rect r = new Rect(0,0,size.width,size.height);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
im.compressToJpeg(r, parameters.getJpegQuality(), baos);
try{
FileOutputStream output = new FileOutputStream(String.format(
"/sdcard/%s_%d.jpg", "test", System.currentTimeMillis()));
output.write(baos.toByteArray());
output.flush();
output.close();
}catch(FileNotFoundException e)
{
e.printStackTrace();
}catch(IOException e){
e.printStackTrace();
}
imagesFrame.add(data);
}
}
});
}
public void startCameraPreview()
{
try{
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
}
catch(Exception e){
e.printStackTrace();
}
}
private void setCamera(Camera camera)
{
mCamera = camera;
mSupportedPreviewSizes = mCamera.getParameters().getSupportedPreviewSizes();
mSupportedFlashModes = mCamera.getParameters().getSupportedFlashModes();
mSupportedSizePicture = mCamera.getParameters().getSupportedPictureSizes();
Camera.Parameters parameters = mCamera.getParameters();
// Set the camera to Auto Flash mode.
if (mSupportedFlashModes != null && mSupportedFlashModes.contains(Camera.Parameters.FLASH_MODE_AUTO))
parameters.setFlashMode(Camera.Parameters.FLASH_MODE_AUTO);
mCamera.setParameters(parameters);
requestLayout();
}
public void surfaceCreated(SurfaceHolder holder) {
try {
mCamera.setPreviewDisplay(holder);
} catch (IOException e) {
e.printStackTrace();
}
}
public void surfaceDestroyed(SurfaceHolder holder) {
if (mCamera != null){
mCamera.setPreviewCallback(null);
mCamera.stopPreview();
mCamera.release();
}
}
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 {
Camera.Parameters parameters = mCamera.getParameters();
// Set the auto-focus mode to "continuous"
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
// Preview size must exist.
if(mPreviewSize != null) {
// 0 = landscape
// 90 = portrait
int rotation = getActivity().getWindowManager().getDefaultDisplay().getRotation();
int degrees = 0;
switch (rotation) {
case Surface.ROTATION_0: degrees = 90; break;
case Surface.ROTATION_90: degrees = 0; break;
}
mCamera.setDisplayOrientation(degrees);
if(degrees == 0)
parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
else
parameters.setPreviewSize(mPreviewSize.height, mPreviewSize.width);
}
mCamera.setParameters(parameters);
mCamera.startPreview();
} catch (Exception e){
e.printStackTrace();
}
}
/**
* Calculate the measurements of the layout
* #param widthMeasureSpec
* #param heightMeasureSpec
*/
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
// Source: http://stackoverflow.com/questions/7942378/android-camera-will-not-work-startpreview-fails
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 left, int top, int right, int bottom)
{
// Source: http://stackoverflow.com/questions/7942378/android-camera-will-not-work-startpreview-fails
if (changed) {
final int width = right - left;
final int height = bottom - top;
int previewWidth = width;
int previewHeight = height;
if (mPreviewSize != null){
Display display = ((WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
switch (display.getRotation())
{
case Surface.ROTATION_0:
previewWidth = mPreviewSize.height;
previewHeight = mPreviewSize.width;
mCamera.setDisplayOrientation(90);
break;
case Surface.ROTATION_90:
previewWidth = mPreviewSize.width;
previewHeight = mPreviewSize.height;
break;
case Surface.ROTATION_180:
previewWidth = mPreviewSize.height;
previewHeight = mPreviewSize.width;
break;
case Surface.ROTATION_270:
previewWidth = mPreviewSize.width;
previewHeight = mPreviewSize.height;
mCamera.setDisplayOrientation(180);
break;
}
}
final int scaledChildHeight = previewHeight * width / previewWidth;
mCameraView.layout(0, height - scaledChildHeight, width, height);
}
}
private Camera.Size getOptimalPreviewSize(List<Camera.Size> sizes, int width, int height)
{
// Source: http://stackoverflow.com/questions/7942378/android-camera-will-not-work-startpreview-fails
Camera.Size optimalSize = null;
final double ASPECT_TOLERANCE = 0.1;
double targetRatio = (double) height / width;
// Try to find a size match which suits the whole screen minus the menu on the left.
for (Camera.Size size : sizes){
if (size.height != width) continue;
double ratio = (double) size.width / size.height;
if (ratio <= targetRatio + ASPECT_TOLERANCE && ratio >= targetRatio - ASPECT_TOLERANCE){
optimalSize = size;
}
}
// If we cannot find the one that matches the aspect ratio, ignore the requirement.
if (optimalSize == null) {
// TODO : Backup in case we don't get a size.
}
return optimalSize;
}
}
}
The layout of my fragment :
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<FrameLayout
android:id="#+id/camera_preview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1"
/>
<RelativeLayout
android:id="#+id/innerRelativeLayout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true" >
<Button
android:id="#+id/button_capture"
android:text="Capture"
android:layout_width="fill_parent"
android:layout_height="50dp"
android:layout_margin="10dp"
android:layout_gravity="bottom"
/>
</RelativeLayout>
</RelativeLayout>
My project configuration :
apply plugin: 'com.android.application'
android {
compileSdkVersion 21
buildToolsVersion "21.1.2"
defaultConfig {
applicationId "rocketweb.com.videocatcher"
minSdkVersion 15
targetSdkVersion 21
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
packagingOptions {
exclude 'META-INF/DEPENDENCIES.txt'
exclude 'META-INF/NOTICE.txt'
exclude 'META-INF/LICENSE.txt'
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:21.0.3'
compile 'com.google.code.gson:gson:2.3.1'
compile "org.apache.httpcomponents:httpmime:4.2.3"
}
End an exemple of image result :
DropBox link to pictures
I can upload android studio project if needed.
Thank you in advance for your help
I think your problem might be when you try to setPreviewSize() according to the rotation of the camera. Please make sure that you set it to a supported preview size contained in parameters.getSupportedPreviewSizes() without swapping the dimensions.
I suspect your problem is that you are trying to swap a supported (width,height) pair and setting it to the camera and it's being rejected as a capture parameter, but it still being improperly used when telling the new YuvImage(...) constructor how to interpret the image byte array.
I am developing a camera app and the problem is that the camera i am making shows a distorted preview.
The picture it takes is clear but the preview is messed up.
Complete camera preview code is below just in case:
import java.io.IOException;
import java.util.List;
import com.glass.cuxtomcam.constants.CuxtomIntent.CAMERA_MODE;
import android.content.Context;
import android.content.res.Configuration;
import android.hardware.Camera;
import android.hardware.Camera.CameraInfo;
import android.hardware.Camera.OnZoomChangeListener;
import android.hardware.Camera.Parameters;
import android.util.Log;
import android.view.OrientationEventListener;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.widget.Toast;
public class CameraPreview extends SurfaceView implements
SurfaceHolder.Callback, OnZoomChangeListener {
private SurfaceHolder mHolder;
private Camera mCamera;
private Context mContext;
private static String TAG = "CAMERA PREVIEW";
private int zoomOffset;
private CameraListener mCallback;
private int cameraMode;
public CameraPreview(Context context, Camera camera, int cameraMode) {
super(context);
mContext = context;
mCamera = camera;
mHolder = getHolder();
this.cameraMode = cameraMode;
mHolder.addCallback(this);
mHolder.setKeepScreenOn(true);
}
public void setCameraListener(CameraListener listener) {
mCallback = listener;
}
#Override
public synchronized void surfaceChanged(SurfaceHolder holder, int format,
int width, int height) {
// 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;
}
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
if (mCamera != null) {
try {
mCamera.stopPreview();
if (mCamera.getParameters().isZoomSupported()) {
mCamera.setZoomChangeListener(this);
zoomOffset = mCamera.getParameters().getMaxZoom() / 5;
}
mCamera.setPreviewDisplay(holder);
mCamera.startPreview();
mCamera.lock();
} catch (IOException e) {
Log.e("Error starting preview", e.getMessage());
}
}
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
if (mCamera != null) {
mCamera.stopPreview();
// release the camera
mCamera.release();
// unbind the camera from this object
mCamera = null;
}
}
public synchronized void zoomIn() {
if (mCamera != null && mCamera.getParameters().isZoomSupported()
&& mCamera.getParameters().isSmoothZoomSupported()) {
int zoomvalue = mCamera.getParameters().getZoom() + zoomOffset;
if (zoomvalue <= mCamera.getParameters().getMaxZoom()) {
mCamera.startSmoothZoom(zoomvalue);
}
} else {
Toast.makeText(mContext, "Zoom In is not supported",
Toast.LENGTH_LONG).show();
}
}
public synchronized void zoomOut() {
if (mCamera != null && mCamera.getParameters().isZoomSupported()
&& mCamera.getParameters().isSmoothZoomSupported()) {
int zoomvalue = mCamera.getParameters().getZoom() - zoomOffset;
if (zoomvalue >= 0) {
mCamera.startSmoothZoom(zoomvalue);
}
} else {
Toast.makeText(mContext, "Zoom Out is not supported",
Toast.LENGTH_LONG).show();
}
}
#Override
public void onZoomChange(int zoomValue, boolean stopped, Camera camera) {
// Log.i("Camera Zoom Value", zoomValue + "");
}
}
Can anyone guide me on why is this happening?
Not sure if it is still relevant (after 2 months without an answer). But this is a solution I used when my camera was like you showed.
Camera.Parameters parameters = camera.getParameters();
parameters.setPreviewFpsRange(30000, 30000);
parameters.setPreviewSize(640,360);
camera.setParameters(parameters);
It sets the frames per second to 30fps, the problem you are experiencing is a too high framerate (most likely)
I'm developing a face recognition app.I need to display a small dotted circle on my camera interface to place the face of the person so that user can train the app well than taking pictures with different scales.
I followed "This link" but I don't know how to do it on camera interface. so can anyone please upload a sample project or give me something to move on with my project? thanks in advance..
Edit-2013-02-14
ok that code is working. but i got another 2 problems.
i can draw the circle. but it's always not in the same position. when the screen size changes, it's position is always changing. I tried with getWidht() and getHeight() methods but i couldn't draw the circle in the center of the screen.do you have any idea about that?
according to your answer i have to create all the views programatically. so now i need to add a capture button to my interface. can you please explain it with your answer?
EDIT :
Code edited to draw circle at center and add capture image button on surface view.
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 java.util.List;
import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.DashPathEffect;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.Point;
import android.hardware.Camera;
import android.hardware.Camera.PictureCallback;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.Display;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewGroup.LayoutParams;
import android.view.Window;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.Toast;
public class TestActivity extends Activity {
/** Called when the activity is first created. */
Camera mCamera = null;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.camera_layout);
mCamera = getCameraInstance();
Preview mPreview = new Preview(this, mCamera);
FrameLayout preview = (FrameLayout) findViewById(R.id.camera_preview);
preview.addView(mPreview);
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
int screenCenterX = (size.x /2);
int screenCenterY = (size.y/2) ;
DrawOnTop mDraw = new DrawOnTop(this,screenCenterX,screenCenterY);
addContentView(mDraw, new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
//Adding listener
Button captureButton = (Button) findViewById(R.id.button_capture);
captureButton.setOnClickListener(
new View.OnClickListener() {
#Override
public void onClick(View v) {
mCamera.takePicture(null, null, mPicture);
}
});
}
/**
* Helper method to access the camera returns null if
* it cannot get the camera or does not exist
* #return
*/
private Camera getCameraInstance() {
Camera camera = null;
try {
camera = Camera.open();
} catch (Exception e) {
// cannot get camera or does not exist
}
return camera;
}
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(data);
fos.close();
Toast.makeText(TestActivity.this, "Photo saved to folder \"Pictures\\MyCameraApp\"", Toast.LENGTH_SHORT).show();
} catch (FileNotFoundException e) {
} catch (IOException e) {
}
}
};
private static File getOutputMediaFile(){
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");
return mediaFile;
}
}
class DrawOnTop extends View {
int screenCenterX = 0;
int screenCenterY = 0;
final int radius = 50;
public DrawOnTop(Context context, int screenCenterX, int screenCenterY) {
super(context);
this.screenCenterX = screenCenterX;
this.screenCenterY = screenCenterY;
}
#Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
Paint p = new Paint();
p.setColor(Color.RED);
DashPathEffect dashPath = new DashPathEffect(new float[]{5,5}, (float)1.0);
p.setPathEffect(dashPath);
p.setStyle(Style.STROKE);
canvas.drawCircle(screenCenterX, screenCenterY, radius, p);
invalidate();
super.onDraw(canvas);
}
}
//----------------------------------------------------------------------
class Preview extends SurfaceView implements SurfaceHolder.Callback {
SurfaceHolder mHolder;
Camera mCamera;
Preview(Context context, Camera camera) {
super(context);
// Install a SurfaceHolder.Callback so we get notified when
this.mCamera = camera;
// underlying surface is created and destroyed.
mHolder = getHolder();
mHolder.addCallback(this);
//this is a deprecated method, is not required after 3.0
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
public void surfaceCreated(SurfaceHolder holder) {
// The Surface has been created, acquire the camera and tell
// to draw.
try {
mCamera.setPreviewDisplay(holder);
mCamera.startPreview();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void surfaceDestroyed(SurfaceHolder holder) {
// Surface will be destroyed when we return, so stop the
// Because the CameraDevice object is not a shared resource,
// important to release it when the activity is paused.
mCamera.stopPreview();
mCamera.release();
mCamera = null;
}
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
// Now that the size is known, set up the camera parameters
// the preview.
Camera.Parameters parameters = mCamera.getParameters();
List<Camera.Size> previewSizes = parameters.getSupportedPreviewSizes();
// You need to choose the most appropriate previewSize for your app
Camera.Size previewSize = previewSizes.get(0);
parameters.setPreviewSize(previewSize.width, previewSize.height);
mCamera.setParameters(parameters);
mCamera.startPreview();
}
}
camera_layout.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<FrameLayout
android:id="#+id/camera_preview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1"
/>
<Button
android:id="#+id/button_capture"
android:text="Capture"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
/>
</LinearLayout>
Don't forget to add permission:
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" />
New permission added:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />