I am trying to launch the Android camaera via an intent, take a picture and have returned the URI. Should be quite simple right, after all there are loads and loads of posts on how to do this on SO.
However, I am using a galaxy S3 with ICS, and find that when I call the camera intent it takes me to the gallery not the camera.
Here is the code I have tried.
Firstly a simple one:
public static final int REQUEST_CODE_CAMERA = 1337;
.
.
.
Intent intent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(intent, REQUEST_CODE_CAMERA);
This did not work. SoI tried the example from Vogella.com
private static final int REQUEST_CODE = 1;
Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
startActivityForResult(intent, REQUEST_CODE);
I have also read people suggesting different request codes such as 1888, 1337 and 2500. Is there not a universal request code or framework based static int I can use? Or are these code one of the many SO red herrings, and therefore one can use any code?
BTW I am aware of the bug in which the S3 does not work with the MediaStore.EXTRA_OUTPUT. It's not help with this that I need. I already know how to overcome that hurdle.
[EDIT]
**PLEASE NOTE
For those reading this orientation can be a serious problem that needs to be taken care of when using the Camera intent. Although the activity launching the camera has it's orientation locked in the manifest. When the device was in portrait mode it would call OnCreate before and after OnActivityResult; thus class global variables are wiped. The solution was to save all the class global variables via the *onSaveInstanceStat*e method, and in the OnCreate use these to reload and display the images in the view. From the information gleaned from SO not all devices will do this but it tends to be consistent per device. My guess is memory management of activities is dependant on available hardware and Android platform. I really wish this was not the case, but Android is Android.
[/EDIT]
MainActivity.java
public class MainActivity extends Activity {
private static final int CAMERA_REQUEST = 1888;
private ImageView imageView;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
this.imageView = (ImageView)this.findViewById(R.id.imageView1);
Button photoButton = (Button) this.findViewById(R.id.button1);
photoButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(cameraIntent, CAMERA_REQUEST);
File imagesFolder = new File(Environment.getExternalStorageDirectory(), "MyCameraImages");
imagesFolder.mkdirs();
File image = new File(imagesFolder, "image.jpg");
Uri uriSavedImage = Uri.fromFile(image);
cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, uriSavedImage);
}
});
}
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == CAMERA_REQUEST && resultCode == RESULT_OK) {
Bitmap photo = (Bitmap) data.getExtras().get("data");
imageView.setImageBitmap(photo);
}
}
}
activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity" >
<ImageView
android:id="@+id/imageView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:layout_marginBottom="79dp" />
<Button
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginBottom="26dp"
android:text="StartCamera" />
</RelativeLayout>
Snap Shot of image saved in Gallery
For using the camera I use the following intent:
Intent intent = new Intent("android.media.action.IMAGE_CAPTURE");
android.media.action.IMAGE_CAPTURE
and
android.provider.MediaStore.ACTION_IMAGE_CAPTURE
are one and the same thing. the variable android.provider.MediaStore.ACTION_IMAGE_CAPTURE
refers to the string above.the reason to refer to the variable instead of the string is to be sure that there is no change in string .in case the string changes the android people shall also change the constant and you shall be able to know that you are referring to the wrong constant but for a string no error will come while compiling.
i hope it clears.
Code for choose photo from gallery and take a new picture also supported in SDK 24 or later
Activity
private File filePathImageCamera;
private Uri imagePath;
private static final int IMAGE_GALLERY_REQUEST = 2;
private static final int IMAGE_CAMERA_REQUEST = 3;
private String imageFilePath;
private void selectImage() {
final CharSequence[] options = {"Take Photo", "Choose from Gallery", "Cancel"};
AlertDialog.Builder builder = new AlertDialog.Builder(DocumentActivity.this);
builder.setTitle("Upload Photo!");
builder.setItems(options, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int item) {
if (options[item].equals("Take Photo")) {
photoCameraIntent();
} else if (options[item].equals("Choose from Gallery")) {
photoGalleryIntent();
} else if (options[item].equals("Cancel")) {
dialog.dismiss();
}
}
});
builder.show();
}
private void photoCameraIntent() {
Intent pictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
Uri uri = null;
try {
filePathImageCamera = createImageFile();
} catch (IOException ex) {
// Error occurred while creating the File
}
if (pictureIntent.resolveActivity(getPackageManager()) != null) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
//Create a file to store the image
if (filePathImageCamera != null) {
Uri photoURI = FileProvider.getUriForFile(this, BuildConfig.APPLICATION_ID + ".provider", filePathImageCamera);
pictureIntent.putExtra(MediaStore.EXTRA_OUTPUT,
photoURI);
startActivityForResult(pictureIntent,
IMAGE_CAMERA_REQUEST);
}
} else {
if (filePathImageCamera != null) {
uri = Uri.fromFile(filePathImageCamera);
pictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
startActivityForResult(pictureIntent, IMAGE_CAMERA_REQUEST);
}
}
}
}
private File createImageFile() throws IOException {
String timeStamp =
new SimpleDateFormat("yyyyMMdd_HHmmss",
Locale.getDefault()).format(new Date());
String imageFileName = "IMG_" + timeStamp + "_";
File storageDir =
getExternalFilesDir(Environment.DIRECTORY_PICTURES);
// Create the storage directory if it does not exist
if (!storageDir.exists() && !storageDir.mkdirs()){
Log.d("error", "failed to create directory");
}
File image = File.createTempFile(
imageFileName, /* prefix */
".jpg", /* suffix */
storageDir /* directory */
);
imageFilePath = image.getAbsolutePath();
return image;
}
private void photoGalleryIntent() {
Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(intent, "Get Image From"), IMAGE_GALLERY_REQUEST);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == IMAGE_GALLERY_REQUEST) {
if (resultCode == RESULT_OK) {
imagePath = data.getData();
Glide.with(MainActivity.this).load(imagePath).into(imageview);
}
} else if (requestCode == IMAGE_CAMERA_REQUEST) {
if (resultCode == RESULT_OK) {
if (filePathImageCamera != null && filePathImageCamera.exists()) {
imagePath = Uri.fromFile(filePathImageCamera);
Glide.with(MainActivity.this).load(imagePath).into(imageview);
}
}
}
}
Manifest
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<application>
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="${applicationId}.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths" />
</provider>
</application>
create new file provider_paths.xml in res/xml directory
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="my_images"
path="Android/data/your_package_name/files/Pictures" />
</paths>
Note - Application permission required