I am a beginner in Android development, and I have to continue a project started by a former fellow worker.
In this application we have customers files, with personal information, and there is a button allowing us to take pictures.
But here is the problem : This works fine on HTC Desire and other Android phones, but not on Galaxy S and Galaxy S II.
The algorithm used is basic : When we touch the screen or the center pad, we use the autoFocus method from the "camera" class. Then, we display the picture just taken, and when we push the menu button or the "back" button, a dialog is displayed, asking us if we want to save the picture or not.
Here is the "CameraView.java" code :
public class CameraView extends Activity implements Callback, AutoFocusCallback
{
private Camera camera;
private FrameLayout layout;
private SurfaceView surface;
private String idPatient;
private boolean start;
private int click;
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setBackgroundDrawable(null);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
layout = new FrameLayout(this);
surface = new SurfaceView(this);
surface.getHolder().addCallback(this);
surface.getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
layout.addView(surface);
setContentView(layout);
idPatient = (String) this.getIntent().getStringExtra("lePatient");
start = false;
click = 0;
}
#Override
public boolean onKeyDown(int keyCode, KeyEvent event){
if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER )
{
click++;
if((!start)&&(click==1))
{
camera.autoFocus(this);
return true;
}
}
if (keyCode == KeyEvent.KEYCODE_BACK )
{
finish();
}
return false;
}
#Override
public boolean onTouchEvent(MotionEvent event)
{
if(event.getAction() == MotionEvent.ACTION_DOWN)
{
click++;
if((!start)&&(click==1))
{
camera.autoFocus(this);
return true;
}
}
return false;
}
public void onAutoFocus(boolean success, Camera camera)
{
start = true;
PictureCallback picture = new PictureCallback()
{
#Override
public void onPictureTaken(byte[] data, Camera camera)
{
Intent intentPhoto = new Intent(CameraView.this, PhotoView.class);
intentPhoto.putExtra("lePatient", idPatient);
intentPhoto.putExtra("laPhoto", data);
CameraView.this.startActivityForResult(intentPhoto, 101);
camera.startPreview();
start = false;
click = 0;
}
};
camera.takePicture(null, null, picture);
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height)
{
Camera.Parameters params = camera.getParameters();
params.setPictureFormat(PixelFormat.JPEG);
params.setPreviewSize(width, height);
camera.setParameters(params);
camera.startPreview();
}
#Override
public void surfaceCreated(SurfaceHolder holder)
{
try
{
camera = Camera.open();
camera.setPreviewDisplay(holder);
}
catch (Exception e) {
e.printStackTrace();
}
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
camera.stopPreview();
camera.release();
camera = null;
}
/**
* Fermeture de l'activity
*/
protected void onDestroy()
{
super.onDestroy();
}
}
And the "photoView.java" class :
public class PhotoView extends Activity
{
private static final int DIALOG_ENREGISTRER = 10;
private ImageView photo;
private byte[] data;
private String idPatient;
private DBAdapter db;
/**
* Creation de l'activity
*/
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setBackgroundDrawable(null);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.photoview);
db = new DBAdapter(this);
db.open();
idPatient = (String) this.getIntent().getStringExtra("lePatient");
data = (byte[]) this.getIntent().getByteArrayExtra("laPhoto");
photo = (ImageView) this.findViewById(R.id.photo);
Bitmap bmp = BitmapFactory.decodeByteArray(data, 0, data.length);
int w = bmp.getWidth();
int h = bmp.getHeight();
Matrix mtx = new Matrix();
mtx.postRotate(90);
Bitmap rotatedBMP = Bitmap.createBitmap(bmp, 0, 0, w, h, mtx, true);
WindowManager manager = (WindowManager) this.getSystemService(Context.WINDOW_SERVICE);
Display display = manager.getDefaultDisplay();
int height= display.getHeight();
int width= display.getWidth();
Bitmap bmpFullScreen = Bitmap.createScaledBitmap(rotatedBMP, width, height, true);
photo.setImageBitmap(bmpFullScreen);
}
/**
* Permet de récuperer un évènement de click de touche
*/
public boolean onKeyUp(int keyCode, KeyEvent event) {
if((keyCode==KeyEvent.KEYCODE_BACK) ||(keyCode==KeyEvent.KEYCODE_MENU))// zoom in
{
showDialog(DIALOG_ENREGISTRER);
}
//return super.onKeyUp(keyCode, event);
return false;
}
/**
* Permet de créer des boites de dialog
*/
protected Dialog onCreateDialog(int id)
{
switch (id)
{
case DIALOG_ENREGISTRER:
return new AlertDialog.Builder(PhotoView.this)
.setIcon(android.R.drawable.ic_menu_info_details)
.setTitle("Enregistrer ?")
.setPositiveButton("OUI", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton)
{
String title = PhotoView.this.savePhotoDB();
PhotoView.this.savePhotoFS(title);
finish();
}
})
.setNegativeButton("NON", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton)
{
finish();
}
})
.create();
}
return null;
}
/**
* Permet de sauvegarder une photo dans la base de données
* #param title
*/
private String savePhotoDB()
{
Log.i("","idPatient : " +idPatient);
String comment = "Note : ";
Log.i("","comment : " + comment);
Date maintenant = new Date(System.currentTimeMillis());
SimpleDateFormat formatDateJour = new SimpleDateFormat("yyyyddMM");
String date = formatDateJour.format(maintenant);
Log.i("","Date formatée : " + date);
SimpleDateFormat formatHeure = new SimpleDateFormat("mmss");
String heure = formatHeure.format(maintenant);
Log.i("","Heure formatée : " + heure);
String fileName = "photo"+date+heure+".jpeg";
Log.i("","fileName : " + fileName);
String title = "photo"+date+heure+".jpeg";
Log.i("","title : " + title);
String userDefined = "1";
Log.i("","userDefined : " + userDefined);
db.insererPhoto(idPatient, comment, date, fileName, title, userDefined);
return title;
}
/**
* Permet de sauvegarder une photo sur le file system
* #param title
*/
private void savePhotoFS(String title) {
try
{
File fs = new File(PhotoView.this.getFilesDir()+"/"+title);
FileOutputStream fos = new FileOutputStream(fs);
fos.write(data);
fos.flush();
fos.close();
//Toast.makeText(PhotoView.this, ""+fs.getAbsolutePath(), Toast.LENGTH_LONG).show();
}
catch (Exception e)
{
e.printStackTrace();
}
}
/**
* Fermeture de l'activity
*/
protected void onDestroy()
{
db.close();
super.onDestroy();
}
}
Can anyone help me please ?
Thanks for reading :)
thank you for your answer.
Problem solved !
Here is the answer for anyone who have the same problem :
In these lines :
Intent intentPhoto = new Intent(CameraView.this, PhotoView.class);
intentPhoto.putExtra("lePatient", idPatient);
intentPhoto.putExtra("laPhoto", data);
startActivityForResult(intentPhoto, 101);
The "intentPhoto.putExtra("laPhoto", data)" method can't be executed because the "data" size is too big. "data" contains the picture taken, and on Galaxy SII, the picture resolution is very big, so this method can't send data (because it's size limited).
So I just used the setPictureSize(width, height) method (Camera.Parameters) on surfaceChanged method to define my own resolution (1024x768), and now it's works fine !
Careful : Before define your own resolution, you HAVE TO verify that it's accepted by your device by using getSupportedPictureSizes() method
Hope this could help someone
Below is the code I used to do the same thing you are trying to do. It creates a SurfaceView and starts the camera preview. Upon tapping anywhere on the screen it takes a picture, shows it and displays two buttons - save and retry (see the onPictureTaken method). The user can click Save, and return the data back to the app, or retry (which from what I can tell I did not finish the retry functionality - it just calls finish()). Hope this helps.
public class SnapShot extends Activity implements OnClickListener,
SurfaceHolder.Callback, Camera.PictureCallback {
SurfaceView cameraView;
SurfaceHolder surfaceHolder;
Camera camera;
LayoutInflater inflater;
Uri imageFileUri;
Button save;
Button retry;
View viewControl;
LayoutParams layoutParamsControl;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.view_camera);
cameraView = (SurfaceView) this.findViewById(R.id.CameraView);
surfaceHolder = cameraView.getHolder();
surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
surfaceHolder.addCallback(this);
cameraView.setFocusable(true);
cameraView.setFocusableInTouchMode(true);
cameraView.setClickable(true);
cameraView.setOnClickListener(this);
inflater = LayoutInflater.from(getBaseContext());
viewControl = inflater.inflate(R.layout.camera_control, null);
save = (Button) viewControl.findViewById(R.id.vc_btn_keep);
retry = (Button)viewControl.findViewById(R.id.vc_btn_discard);
layoutParamsControl = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);
}
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
camera.startPreview();
}
public void surfaceCreated(SurfaceHolder holder) {
camera = Camera.open();
try {
Camera.Parameters parameters = camera.getParameters();
if (this.getResources().getConfiguration().orientation != Configuration.ORIENTATION_LANDSCAPE) {
// This is an undocumented although widely known feature
parameters.set("orientation", "portrait");
// For Android 2.2 and above
camera.setDisplayOrientation(90);
// Uncomment for Android 2.0 and above
// parameters.setRotation(90);
} else {
// This is an undocumented although widely known feature
parameters.set("orientation", "landscape");
// For Android 2.2 and above
camera.setDisplayOrientation(0);
// Uncomment for Android 2.0 and above
// parameters.setRotation(0);
}
camera.setParameters(parameters);
camera.setPreviewDisplay(holder);
} catch (IOException exception) {
camera.release();
Log.v("surfaceCreated", exception.getMessage());
}
camera.startPreview();
}
public void surfaceDestroyed(SurfaceHolder holder) {
camera.stopPreview();
camera.release();
}
#Override
public void onPictureTaken(final byte[] data, Camera camera) {
this.addContentView(viewControl, layoutParamsControl);
save.setOnClickListener(new Button.OnClickListener() {
#Override
public void onClick(View v) {
insertImage(data);
Intent i = new Intent();
i.putExtra("data", imageFileUri.toString());
setResult(-1, i);
finish();
}});
retry.setOnClickListener(new Button.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
finish();
}});
}
public void insertImage(byte[] data)
{
Bitmap b = null;
try {
b = GeneralUtils.decodeFile(data, this);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
ByteArrayOutputStream bos = new ByteArrayOutputStream();
b.compress(Bitmap.CompressFormat.JPEG, 80, bos);
//b = null;
Bitmap bitmap = BitmapFactory.decodeByteArray(bos.toByteArray(), 0, bos.size());
Matrix m = new Matrix();
if (b.getWidth() > b.getHeight())
{
m.postRotate(90);
bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), m, true);
}
String result = MediaStore.Images.Media.insertImage(getContentResolver(), bitmap, "", "");
b.recycle();
data = null;
b = null;
m = null;
imageFileUri = Uri.parse(result);
}
#Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
camera.takePicture(null, null, null, this);
}
}
Related
I am building a camera app using surface view. The app loads the camera properly and image is captured. There are two scenarios in image capture:
The image is captured and nothing i.e bytes array is sent to the preview activity. It works fine here.
The image is captured and the byte array from picture callback is sent to the preview activity.
In the second scenario, the app shows a dark screen and becomes unresponsive. I don't believe I know the cause of this as I have checked with many tutorials and seen the same code.
Here's my code so far:
public class ImageActivity extends AppCompatActivity implements SurfaceHolder.Callback {
private static final String TAG = ImageActivity.class.getSimpleName();
private ImageButton closeIV;
private ImageView flipCameraIV;
private FloatingActionButton fab_capture;
private LinearLayout galleryLayout;
private Camera camera;
private Camera.PictureCallback jpegCallback;
private SurfaceView surfaceView;
private SurfaceHolder holder;
private int currCamId = 0;
private boolean isGalleryImg = false;
private boolean isCameraImg = false;
private byte[] camBytes = null;
private static final int GAL_REQ_CODE = 240;
private static final int CAM_PERM_CODE = 242;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.activity_image);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
getWindow().setStatusBarColor(getResources().getColor(R.color.black));
}
init();
holder = surfaceView.getHolder();
holder.addCallback(this);
holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
currCamId = Camera.CameraInfo.CAMERA_FACING_BACK;
}
private void handleClicks() {
closeIV.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
finish();
}
});
flipCameraIV.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Log.d(TAG, "Flip Clicked");
switchCamera();
}
});
galleryLayout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
isGalleryImg = true;
Log.d(TAG, "Gallery Button Clicked");
Intent galleryIntent = new Intent(Intent.ACTION_GET_CONTENT);
galleryIntent.setType("image/*");
startActivityForResult(galleryIntent, GAL_REQ_CODE);
}
});
fab_capture.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
captureImage();
}
});
jpegCallback = new Camera.PictureCallback() {
#Override
public void onPictureTaken(byte[] bytes, Camera camera) {
assert bytes != null;
Log.d(TAG, "Camera Bytes Array Length:\t" + bytes.length);
isCameraImg = true;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
Intent intent = new Intent(ImageActivity.this, PreviewActivity.class);
intent.putExtra("camera_bytes", bytes);
intent.putExtra("fromCamera", isCameraImg);
startActivity(intent);
return;
//refreshCamera();
}
};
}
private void captureImage() {
camera.takePicture(null, null, jpegCallback);
}
public void refreshCamera() {
if (holder.getSurface() == null) {
return; // preview surface is empty
}
// stop preview, then make changes
try {
camera.stopPreview();
} catch (Exception ex) {
ex.printStackTrace();
}
try {
camera.setPreviewDisplay(holder);
camera.startPreview();
} catch (IOException e) {
e.printStackTrace();
}
}
private void init() {
closeIV = findViewById(R.id.closeIV);
fab_capture = findViewById(R.id.fab_capture);
galleryLayout = findViewById(R.id.galleryLayout);
flipCameraIV = findViewById(R.id.flipCameraIV);
surfaceView = findViewById(R.id.surfaceView);
handleClicks();
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == GAL_REQ_CODE && resultCode == RESULT_OK) {
Uri imgUri = data.getData();
Intent intent = new Intent(ImageActivity.this, PreviewActivity.class);
intent.putExtra("fromGallery", isGalleryImg);
intent.putExtra("gallery_image", imgUri.toString());
startActivity(intent);
}
}
#TargetApi(Build.VERSION_CODES.M)
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
for (int mResults : grantResults) {
if (mResults == PackageManager.PERMISSION_DENIED) {
requestPermissions(new String[]{Manifest.permission.CAMERA,
Manifest.permission.WRITE_EXTERNAL_STORAGE},
CAM_PERM_CODE);
} else {
Toast.makeText(ImageActivity.this, "Permission Already Granted", Toast.LENGTH_SHORT).show();
}
}
}
#Override
public void surfaceCreated(SurfaceHolder surfaceHolder) {
openCamera();
}
private void openCamera() {
try {
camera = Camera.open(currCamId);
} catch (RuntimeException rex) {
rex.printStackTrace();
}
Camera.Parameters parameters = camera.getParameters();
parameters.setPreviewFrameRate(20);
parameters.setPreviewSize(352, 288);
camera.setDisplayOrientation(90);
camera.setParameters(parameters);
try {
camera.setPreviewDisplay(holder);
} catch (IOException e) {
e.printStackTrace();
}
camera.startPreview();
}
#Override
public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {
refreshCamera();
}
#Override
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
camera.stopPreview();
camera.release();
camera = null;
}
#Override
protected void onPause() {
super.onPause();
camera.stopPreview();
}
#Override
protected void onDestroy() {
super.onDestroy();
if (camera != null){
camera.stopPreview();
camera.release();
camera = null;
}
}
}
Also, I have tried switching to the front camera and back again using this snippet but doesn't work.
private void switchCamera() {
// code I tried to switch camera with but not working
if (currCamId == Camera.CameraInfo.CAMERA_FACING_BACK){
currCamId = Camera.CameraInfo.CAMERA_FACING_FRONT;
} else {
currCamId = Camera.CameraInfo.CAMERA_FACING_BACK;
}
camera = Camera.open(currCamId);
Camera.CameraInfo info = new Camera.CameraInfo();
Camera.getCameraInfo(Camera.CameraInfo.CAMERA_FACING_FRONT, info);
int rotation = this.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 rotate = (info.orientation - degrees + 360) % 360;
Camera.Parameters parameters = camera.getParameters();
parameters.setRotation(rotate);
try {
camera.setPreviewDisplay(surfaceView.getHolder());
} catch (IOException e) {
e.printStackTrace();
}
camera.setParameters(parameters);
camera.setDisplayOrientation(90);
camera.startPreview();
//openCamera();
}
I need help in solving this. Thanks.
As i see you're trying to send picture as byte array which is not possible. Because there is a restriction for intent sizes since api23. When sending extras, you must think about the sizes of extras, it really destroys user experience and causes slow load for new activities.
Anyway, your byte array is sooo big with all that picture data and i think this causing an anr. What must you do? You must save that byte array as a jpeg file first, then just add filepath into your intent. Take a look to this solution
Oh and also, just a friendly advice based on experience, it's better to use a good camera library instead of android-sdk's classic usage. As i can say, worst part of android development is anything about medias, specially camera api. It's shaming when compared with ios and google is not doing any development about this lack, since 2015.
I have tried lots of camera examples for android, but this (http://androideity.com/2011/10/08/hello-camera/) is the firs I get to save images and view it on the gallery. But what I want to know is how to change the folder I save the images. I think actually it saves them on sdcard0/DCIM.
Here is the main activity:
public class Foto extends Activity implements SurfaceHolder.Callback{
private LayoutInflater myInflater = null;
Camera myCamera;
byte[] tempdata;
boolean myPreviewRunning = false;
private SurfaceHolder mySurfaceHolder;
private SurfaceView mySurfaceView;
ImageButton takePicture;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().setFormat(PixelFormat.TRANSLUCENT);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.foto);
mySurfaceView = (SurfaceView) findViewById(R.id.surface);
mySurfaceHolder = mySurfaceView.getHolder();
mySurfaceHolder.addCallback(this);
mySurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
myInflater = LayoutInflater.from(this);
View overView = myInflater.inflate(R.layout.segundacapa,null);
this.addContentView(overView, new LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.FILL_PARENT));
takePicture = (ImageButton) findViewById(R.id.button);
takePicture.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
myCamera.takePicture(myShutterCallback, myPictureCallback, myJpeg);
}
});
}
ShutterCallback myShutterCallback = new ShutterCallback() {
#Override
public void onShutter() {
}
};
PictureCallback myPictureCallback = new PictureCallback() {
#Override
public void onPictureTaken(byte[] data, Camera myCamera) {
// TODO Auto-generated method stub
}
};
PictureCallback myJpeg = new PictureCallback() {
#Override
public void onPictureTaken(byte[] data, Camera myCamera) {
// TODO Auto-generated method stub
if(data != null){
tempdata = data;
done();
}
}
};
void done(){
Bitmap bm = BitmapFactory.decodeByteArray(tempdata, 0, tempdata.length);
String url = Images.Media.insertImage(getContentResolver(), bm, null, null);
bm.recycle();
Bundle bundle = new Bundle();
if(url != null){
bundle.putString("url",url);
Intent mIntent = new Intent();
mIntent.putExtras(bundle);
setResult(RESULT_OK, mIntent);
Toast.makeText(this, "Picture saved on" + url, Toast.LENGTH_SHORT).show();
}
else{
Toast.makeText(this, "Picture can not be saved", Toast.LENGTH_SHORT).show();
}
finish();
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
// TODO Auto-generated method stub
try{
if(myPreviewRunning){
myCamera.stopPreview();
myPreviewRunning = false;
}
Camera.Parameters p = myCamera.getParameters();
p.setPreviewSize(width,height);
myCamera.setParameters(p);
myCamera.setPreviewDisplay(holder);
myCamera.startPreview();
myPreviewRunning = true;
}catch(Exception e){}
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
// TODO Auto-generated method stub
myCamera = Camera.open();
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
myCamera.stopPreview();
myPreviewRunning = false;
myCamera.release();
myCamera = null;
}
}
There is also an XML layout with a SurfaceView (called foto.xml) and another called segundacapa.xmlwith a button.
Thank you very much!!
Instead of using Images.Media to store the image on disk (which uses default location), you can use another flavour of insertImage(), which takes your file path. You should write the file before. You don't need to convert the onPictureTaken()->data to Bitmap; you simply write the byte[] to a Jpeg file.
FileOutputStream fos = openFileOutput("saved.jpg", Context.MODE_PRIVATE);
fos.write(data);
fos.close();
You can choose the file name as you wish; you can save the file with other parameters (see more about Context.openFileOutput(). You can open the wile on /sdcard if you wish, e.g.
FileOutputStream fos = new FileOutputStream("/sdcard/saved.jpg");
Note that you need to request permission to write to the SD Card; check that the following line appears in AndroidManifest.xml:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
I am working on an android tablet application. I want to change camera from front to back and back to front on button. How can I achieve this ? I have tried several example but not getting proper response.
I am adding code also.
public class PhotoPreview extends Activity implements SurfaceHolder.Callback {
private Camera camera;
private ImageButton cameraClick;
private ImageButton cameraSwap;
SurfaceView surfaceView;
private SurfaceHolder mHolder;
boolean previewing = false;
String path = "";
LayoutInflater controlInflater = null;
Bitmap bmp;
Button cameraCancel;
private SharedPreferences myPrefs;
private int camId;
/** Called when the activity is first created. */
#SuppressWarnings("deprecation")
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
System.out.println("Photo preview Called $$$$$$$$$$$$$$$$$$ ");
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.photo_preview);
myPrefs = this.getSharedPreferences("myPrefs", MODE_PRIVATE);
camId = myPrefs.getInt("camId",1);
System.out.println("CAM ID $$$$$$$$$$$$$$$$$$ "+camId);
getWindow().setFormat(PixelFormat.UNKNOWN);
surfaceView = (SurfaceView) findViewById(R.id.camerapreview);
mHolder = surfaceView.getHolder();
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
mHolder.addCallback(this);
controlInflater = LayoutInflater.from(getBaseContext());
View viewControl = controlInflater.inflate(R.layout.control, null);
LayoutParams layoutParamsControl = new LayoutParams(
LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
this.addContentView(viewControl, layoutParamsControl);
cameraClick = (ImageButton) findViewById(R.id.cameraClick);
cameraClick.setOnClickListener(cameraClickListener);
cameraCancel = (Button) findViewById(R.id.cameraCancel);
cameraCancel.setOnClickListener(cameraCancelClickListener);
cameraSwap = (ImageButton) findViewById(R.id.cameraSwap);
cameraSwap.setOnClickListener(swapCameraClickListener);
}
/*
* This is click event of Photo capture button
*/
private OnClickListener cameraClickListener = new OnClickListener() {
#Override
public void onClick(final View v) {
if (camera != null) {
camera.takePicture(shutterCallback, rawCallback, jpegCallback);
}
}
};
/*
* This is click event of camera cancel button
*/
private OnClickListener cameraCancelClickListener = new OnClickListener() {
#Override
public void onClick(final View v) {
Intent intent = new Intent(PhotoPreview.this,
MainScreenActivity.class);
startActivity(intent);
}
};
/*
* This is click event of camera cancel button
*/
private OnClickListener swapCameraClickListener = new OnClickListener() {
#Override
public void onClick(final View v) {
if (camId == 0) {
SharedPreferences.Editor prefsEditor = myPrefs.edit();
prefsEditor.putInt("camId", 1);
prefsEditor.commit();
} else {
SharedPreferences.Editor prefsEditor = myPrefs.edit();
prefsEditor.putInt("camId", 0);
prefsEditor.commit();
}
System.out.println("CAM ID ^^^^^^^^^^^^^^^^^^^^ "+camId);
Intent intent = new Intent(PhotoPreview.this, PhotoPreview.class);
startActivity(intent);
}
};
// Handles when shutter open
ShutterCallback shutterCallback = new ShutterCallback() {
public void onShutter() {
}
};
/** Handles data for raw picture */
PictureCallback rawCallback = new PictureCallback() {
public void onPictureTaken(byte[] data, Camera camera) {
}
};
/** Handles data for jpeg picture */
PictureCallback jpegCallback = new PictureCallback() {
public void onPictureTaken(byte[] data, Camera camera) {
bmp = BitmapFactory.decodeByteArray(data, 0, data.length);
String root = Environment.getExternalStorageDirectory().toString();
File myDir = new File(root + "/Easy_Measurement_images");
myDir.mkdirs();
Random generator = new Random();
int n = 10000;
n = generator.nextInt(n);
String fname = "Image-" + n + ".jpg";
File file = new File(myDir, fname);
if (file.exists())
file.delete();
try {
FileOutputStream out = new FileOutputStream(file);
bmp.compress(Bitmap.CompressFormat.PNG, 90, out);
out.flush();
out.close();
} catch (Exception e) {
e.printStackTrace();
}
Intent intent = new Intent(PhotoPreview.this,
VerticalAdjustmentActivity.class);
startActivity(intent);
}
};
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
// Set camera preview size,orientation,rotation using parameters
if (camera != null) {
Camera.Parameters parameters = camera.getParameters();
parameters.set("orientation", "portrait");
camera.setParameters(parameters);
camera.startPreview();
}
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
System.out.println("CAM ID %%%%%%%%%%%%%%$$$$$$$$$$$$$$$$$$ "+camId);
camera = Camera.open(camId);
if (camera != null) {
try {
camera.setPreviewDisplay(holder);
} catch (IOException e) {
e.printStackTrace();
}
}
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
System.out.println("Surface destroyed ***************");
if (camera != null) {
camera.stopPreview();
camera.release();
camera = null;
}
}
}
you can open a camera using Camera.open(int i). you can use only one camera at a time. So release one and then open another. For example
public void onClick(View v) {
camera.stopPreview();
camera.release();
if(currentCameraId == Camera.CameraInfo.CAMERA_FACING_BACK){
currentCameraId = Camera.CameraInfo.CAMERA_FACING_FRONT;
}
else {
currentCameraId = Camera.CameraInfo.CAMERA_FACING_BACK;
}
camera = Camera.open(currentCameraId);
setCameraDisplayOrientation(CameraActivity.this, currentCameraId, camera);
try {
camera.setPreviewDisplay(previewHolder);
} catch (IOException e) {
e.printStackTrace();
}
camera.startPreview();
}
I am using custom camera and surface view for capturing image but the problem is the camera orientation is not proper, following is my code and sorry for my bad English communication.
public class Camera_Activity extends Activity implements
SurfaceHolder.Callback {
private Camera camera = null;
private SurfaceView cameraSurfaceView = null;
private SurfaceHolder cameraSurfaceHolder = null;
private boolean previewing = false;
private Display display = null;
private static int wid = 0, hgt = 0;
private LayoutInflater layoutInflater = null;
private View cameraViewControl = null;
private LayoutParams layoutParamsControl = null;
private Button btnCapture = null;
ImageView mImgView1;
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
display = getWindowManager().getDefaultDisplay();
wid = display.getWidth();
hgt = display.getHeight();
getWindow().setFormat(PixelFormat.TRANSLUCENT);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.camera);
mImgView1 = (ImageView) findViewById(R.id.mImgView1);
mImgView1.setImageResource(R.drawable.first_leg);
cameraSurfaceView = (SurfaceView) findViewById(R.id.cameraSurfaceView);
cameraSurfaceHolder = cameraSurfaceView.getHolder();
cameraSurfaceHolder.addCallback(this);
cameraSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
layoutInflater = LayoutInflater.from(getBaseContext());
layoutParamsControl = new LayoutParams(LayoutParams.FILL_PARENT,
LayoutParams.FILL_PARENT);
cameraViewControl = layoutInflater.inflate(R.layout.cambutton, null);
this.addContentView(cameraViewControl, layoutParamsControl);
cameraViewControl = layoutInflater.inflate(R.layout.vampireimage, null);
this.addContentView(cameraViewControl, layoutParamsControl);
btnCapture = (Button) findViewById(R.id.btnCapture);
btnCapture.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
camera.takePicture(cameraShutterCallback,
cameraPictureCallbackRaw, cameraPictureCallbackJpeg);
}
});
}
ShutterCallback cameraShutterCallback = new ShutterCallback() {
#Override
public void onShutter() {
// TODO Auto-generated method stub
System.out.println("Hello Shutter");
}
};
PictureCallback cameraPictureCallbackRaw = new PictureCallback() {
#Override
public void onPictureTaken(byte[] data, Camera camera) {
// TODO Auto-generated method stub
System.out.println("Hello Picture");
}
};
PictureCallback cameraPictureCallbackJpeg = new PictureCallback() {
#Override
public void onPictureTaken(byte[] data, Camera camera) {
// TODO Auto-generated method stub
Bitmap cameraBitmap = BitmapFactory.decodeByteArray(data, 0,
data.length);
wid = cameraBitmap.getWidth();
hgt = cameraBitmap.getHeight();
Bitmap newImage = Bitmap.createBitmap(wid, hgt,
Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(newImage);
canvas.drawBitmap(cameraBitmap, 0f, 0f, null);
Constants.mImageBitmap.clear();
Constants.mImageBitmap.add(cameraBitmap);
File storagePath = new File(
Environment.getExternalStorageDirectory() + "/Photos/");
storagePath.mkdirs();
File myImage = new File(storagePath, "1.jpg");
try {
FileOutputStream out = new FileOutputStream(myImage);
newImage.compress(Bitmap.CompressFormat.JPEG, 80, out);
out.flush();
out.close();
} catch (FileNotFoundException e) {
Log.d("In Saving File", e + "");
} catch (IOException e) {
Log.d("In Saving File", e + "");
}
camera.startPreview();
newImage.recycle();
newImage = null;
// cameraBitmap.recycle();
// cameraBitmap = null;
Intent mInPreview = new Intent(Camera_Activity.this,
Preview_Activity.class);
mInPreview.putExtra("Value", "First");
startActivity(mInPreview);
finish();
}
};
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
// TODO Auto-generated method stub
if (previewing) {
camera.stopPreview();
previewing = false;
System.out.println("Hello 2");
}
try {
Camera.Parameters parameters = camera.getParameters();
Display display = ((WindowManager) getSystemService(WINDOW_SERVICE))
.getDefaultDisplay();
if (display.getRotation() == Surface.ROTATION_0) {
parameters.setPreviewSize(height, width);
camera.setDisplayOrientation(90);
}
if (display.getRotation() == Surface.ROTATION_90) {
parameters.setPreviewSize(width, height);
}
if (display.getRotation() == Surface.ROTATION_180) {
parameters.setPreviewSize(height, width);
}
if (display.getRotation() == Surface.ROTATION_270) {
parameters.setPreviewSize(width, height);
camera.setDisplayOrientation(180);
}
camera.setParameters(parameters);
camera.setPreviewDisplay(cameraSurfaceHolder);
camera.startPreview();
previewing = true;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
// TODO Auto-generated method stub
try {
camera = Camera.open();
} catch (RuntimeException e) {
Toast.makeText(
getApplicationContext(),
"Device camera is not working properly, please try after sometime.",
Toast.LENGTH_LONG).show();
}
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
System.out.println("Hello 3");
camera.stopPreview();
camera.release();
camera = null;
previewing = false;
}
#Override
public void onBackPressed() {
// TODO Auto-generated method stub
super.onBackPressed();
AlertDialog.Builder alert = new AlertDialog.Builder(this);
alert.setTitle("3DSoles");
alert.setMessage("Do U Want to Exit?");
alert.setNegativeButton("No", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
}
});
alert.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
finish();
}
});
}
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
// TODO Auto-generated method stub
if (keyCode == KeyEvent.KEYCODE_BACK) {
AlertDialog.Builder alert = new AlertDialog.Builder(this);
alert.setTitle("3DSoles");
alert.setMessage("Do U Want to Exit?");
alert.setNegativeButton("No",
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
}
});
alert.setPositiveButton("Yes",
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
finish();
}
});
}
return super.onKeyDown(keyCode, event);
}
}
Camera class is not expected to support setPreview(height, width)
see http://developer.android.com/reference/android/hardware/Camera.html#setDisplayOrientation%28int%29 for the official way to choose Camera.setDisplayOrientation()
Starting from API 14 (ICS and higher), camera is expected to support setDisplayOrientation() without
interrupting preview.
For older platforms, I would recommend to disable change of orientation while the camera preview is active; reset of camera (stopPreview() + startPreview) may take too long for UX to be freiendly. Often, preview activities either work with fixed orientation or "simulate" in software orientation change in response to accelerometer events.
I am developing a custom camera application and testing on two galaxy tablets.. one 7inch and one 10inch.. the 10 inch works great but on the 7inch, when i take a picture, it freezes the camera preview and the logCat stops at CAMERA SNAP, CLICKED log in my btn_snap_pic on click in my customcamera class with no error. the app doesn't crash just hangs.. and if i back out of it and open the app again i get a "fail to connect to camera" i assume that this error is because when my app froze and i backed out, the camera never got released.. anyway, below is my both my CustomCamera class and my CamLayer which is my preview..
public class CustomCamera extends Activity{
String camFace ="back";
FrameLayout frame;
RelativeLayout rel;
CamLayer camPreview;
ImageView btn_snap_pic;
ImageView btn_switch_cam;
String TAG = "custom cam";
public void onCreate(Bundle savedInstanceState)
{
Bitmap btnSwitch = BitmapFactory.decodeResource(this.getResources(),
R.drawable.btn_switch_camera);
Bitmap btnSnap = BitmapFactory.decodeResource(this.getResources(),
R.drawable.btn_take_picture);
super.onCreate(savedInstanceState);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
//Set Screen Orientation
this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
RelativeLayout.LayoutParams buttonS = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
RelativeLayout.LayoutParams buttonT = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
RelativeLayout.LayoutParams cam = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
cam.addRule(RelativeLayout.BELOW);
buttonS.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
buttonT.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
buttonT.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
try{
//Create Intance of Camera
camPreview = new CamLayer(this.getApplicationContext(),camFace);
//Relative view for everything
rel = new RelativeLayout(this);
// set as main view
setContentView(rel);
//FrameLayOut for camera
frame = new FrameLayout(this);
// add Camera to view
frame.setLayoutParams(cam);
frame.addView(camPreview);
rel.addView(frame);
btn_switch_cam = new ImageView (this);
btn_switch_cam.setImageBitmap(btnSwitch);
btn_switch_cam.setLayoutParams(buttonS);
buttonS.rightMargin = 25;
buttonS.topMargin = 25;
rel.addView(btn_switch_cam);
btn_switch_cam.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
Log.v("CAMERA Switch", "CLICKED");
//frame.removeView(camPreview);
if(camFace.equals("front")){
camFace = "back";
}else{
camFace = "front";
}
//camPreview.stopCamera();
frame.removeView(camPreview);
restartCam();
//camPreview.switchCam(camFace);
}
});
btn_snap_pic = new ImageView(this);
btn_snap_pic.setImageBitmap(btnSnap);
btn_snap_pic.setLayoutParams(buttonT);
buttonT.rightMargin = 25;
buttonT.bottomMargin = 25;
rel.addView(btn_snap_pic);
btn_snap_pic.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
Log.v("CAMERA Snap", "CLICKED");
camPreview.camera.takePicture(shutterCallback, rawCallback,
jpegCallback);
}
});
} catch(Exception e){}
}
public void restartCam(){
camPreview = new CamLayer(this.getApplicationContext(),camFace);
frame.addView(camPreview);
}
ShutterCallback shutterCallback = new ShutterCallback() {
public void onShutter() {
Log.d(TAG, "onShutter'd");
}
};
/** Handles data for raw picture */
PictureCallback rawCallback = new PictureCallback() {
public void onPictureTaken(byte[] data, android.hardware.Camera camera) {
Log.d(TAG, "onPictureTaken - raw");
}
};
/** Handles data for jpeg picture */
PictureCallback jpegCallback = new PictureCallback() {
public void onPictureTaken(byte[] data, android.hardware.Camera camera) {
FileOutputStream outStream = null;
try {
outStream = new FileOutputStream(String.format(
"/sdcard/LC/images/%d.jpg", System.currentTimeMillis()));
outStream.write(data);
outStream.close();
Log.d(TAG, "onPictureTaken - wrote bytes: " + data.length);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
}
Log.d(TAG, "onPictureTaken - jpeg");
}
};
}
AND THE CAMLAYER:
public class CamLayer extends SurfaceView implements SurfaceHolder.Callback {
Camera camera;
SurfaceHolder previewHolder;
String camID;
private static final String TAG = "Cam Preview";
public CamLayer(Context context, String facing)
{
super(context);
camID = facing;
previewHolder = this.getHolder();
previewHolder.addCallback(this);
previewHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
public void surfaceCreated(SurfaceHolder holder) {
startCamera();
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height)
{
Parameters params = camera.getParameters();
//params.setPreviewSize(width, height);
//params.setPictureFormat(PixelFormat.JPEG);
camera.setParameters(params);
camera.startPreview();
}
public void surfaceDestroyed(SurfaceHolder arg0)
{
//camera.stopPreview();
//camera.release();
stopCamera();
}
public void onResume() {
//camera.startPreview();
startCamera();
}
public void onPause() {
// TODO Auto-generated method stub
//camera.stopPreview();
stopCamera();
}
public void switchCam(String newCamId) {
/*camera.stopPreview();
//camera.release();
if(camID.equals("front")){
camera.open(Camera.CameraInfo.CAMERA_FACING_FRONT);
}else{
camera.open(Camera.CameraInfo.CAMERA_FACING_BACK);
}*/
//camera.startPreview();
//camera=Camera.open(Camera.CameraInfo.CAMERA_FACING_BACK);
stopCamera();
camID = newCamId;
startCamera();
}
public void stopCamera(){
System.out.println("stopCamera method");
if (camera != null){
camera.stopPreview();
camera.setPreviewCallback(null);
camera.release();
camera = null;
previewHolder.removeCallback(this);
previewHolder = null;
}
}
private void startCamera(){
if(camID.equals("front")){
camera=Camera.open(Camera.CameraInfo.CAMERA_FACING_FRONT);
}else{
camera=Camera.open(Camera.CameraInfo.CAMERA_FACING_BACK);
}
try {
camera.setPreviewDisplay(previewHolder);
camera.setPreviewCallback(new PreviewCallback() {
public void onPreviewFrame(byte[] data, Camera arg1) {
//FileOutputStream outStream = null;
/*try {
//outStream = new FileOutputStream(String.format(
//"/sdcard/%d.jpg", System.currentTimeMillis()));
//outStream.write(data);
//outStream.close();
Log.d(TAG, "onPreviewFrame - wrote bytes: "
+ data.length);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
}*/
//CamLayer.this.invalidate();
}
});
}
catch (Throwable e){ Log.w("TAG,", "failed create surface !?!?"); }
}
public void draw(Canvas canvas) {
super.draw(canvas);
Paint p = new Paint(Color.RED);
Log.d(TAG, "draw");
canvas.drawText("PREVIEW", canvas.getWidth() / 2,
canvas.getHeight() / 2, p);
}
}
This thread says raw is not supported
https://groups.google.com/forum/?fromgroups#!topic/android-developers/D43AdrbP9oE
A raw image would consume too much memory is my guess. Other than that, I'm also disappointed its not supported.