I am trying to integrate taking a picture in Android. While running the application I am getting and error "Unfortunately, Camera has stopped", but my application didn't crash. I found this issue in Android "KITKAT". Here is the sample code I am using to take picture,
Using this function I am taking a picture,
private void take_picture_intent() {
Intent takePictureIntent = (Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT)
? new Intent(MediaStore.ACTION_IMAGE_CAPTURE_SECURE)
: new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (takePictureIntent.resolveActivity(this.getActivity().getPackageManager()) != null) {
File photoFile = null;
try {
photoFile = createImageFile();
} catch (IOException e) {
e.printStackTrace();
}
if (photoFile != null) {
photoURI = FileProvider.getUriForFile(this.getActivity(), "com.android.myapplication.fileprovider", photoFile);
Log.e(TAG, "photoFile: "+photoFile+" ,URI : "+photoURI.getPath());
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
getActivity().startActivityForResult(takePictureIntent, SelectMedia.IMAGE_CAPTURE_AT_THE_DOOR);
}
}
}
This function is used to generate Image path,
private File createImageFile() throws IOException {
// Create an image file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = "JPEG_" + timeStamp + "_";
File storageDir = getActivity().getExternalFilesDir(Environment.DIRECTORY_PICTURES);
if (!storageDir.exists())
storageDir.mkdirs();
File image = File.createTempFile(
imageFileName, /* prefix */
".jpg", /* suffix */
storageDir /* directory */
);
// Save a file: path for use with ACTION_VIEW intents
mCurrentPhotoPath = image.getAbsolutePath();
return image;
}
Here is the Log,
10-11 12:35:12.691 18815-18815/? E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.sec.android.app.camera, PID: 18815
java.lang.SecurityException: Permission Denial: opening provider android.support.v4.content.FileProvider from
ProcessRecord{42d78c60 18815:com.sec.android.app.camera/u0a84} (pid=18815, uid=10084) that is not exported from uid 10786
at android.os.Parcel.readException(Parcel.java:1472)
at android.os.Parcel.readException(Parcel.java:1426)
at android.app.ActivityManagerProxy.getContentProvider(ActivityManagerNative.java:3201)
at android.app.ActivityThread.acquireProvider(ActivityThread.java:4824)
at android.app.ContextImpl$ApplicationContentResolver.acquireUnstableProvider(ContextImpl.java:2532)
at android.content.ContentResolver.acquireUnstableProvider(ContentResolver.java:1425)
at android.content.ContentResolver.openAssetFileDescriptor(ContentResolver.java:906)
at android.content.ContentResolver.openOutputStream(ContentResolver.java:669)
at android.content.ContentResolver.openOutputStream(ContentResolver.java:645)
at com.sec.android.app.camera.Camera$LastContentUriCallback.onCompleted(Camera.java:21369)
at com.sec.android.app.camera.Camera.onLaunchGalleryForImage(Camera.java:12409)
at com.sec.android.app.camera.Camera.onImageStoringCompleted(Camera.java:11140)
at com.sec.android.app.camera.CommonEngine.imageStoringCompleted(CommonEngine.java:6954)
at com.sec.android.app.camera.CeStateInitialized.handleMessage(CeStateInitialized.java:47)
at com.sec.android.app.camera.CommonEngine$StateMessageHandler.handleMessage(CommonEngine.java:957)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5590)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1268)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1084)
at dalvik.system.NativeStart.main(Native Method)
10-11 12:35:13.021 600-19132/? E/android.os.Debug: !#Dumpstate > sdumpstate -k -t -z -d -m 18815 -o /data/log/dumpstate_app_error
I found this issue is due to conversion of URI. I have resolved this issue by replacing
FileProvider.getUriForFile(getApplicationContext(), "com.android.myapplication.fileprovider", photoFile);
By Adding a condition,
if ((Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT))
photoURI = FileProvider.getUriForFile(getApplicationContext(), "com.android.myapplication.fileprovider", photoFile);
else
photoURI = Uri.fromFile(photoFile);
on take_picture_intent() function.
Also In my Manifest I am have removed permission,
<uses-permission android:name="android.permission.CAMERA" />
Add the permission for pre-lollipop versions of specific package name, after that you can able to access it.
getApplicationContext().grantUriPermission(getCallingPackage(),
contentUri, Intent.FLAG_GRANT_READ_URI_PERMISSION);
Related
Google introduced Scoped Storage on Android 10, according to the document, we can write to the public directories without requesting permission by using MediaStore API.
Before Android 10, when we need to take a photo and save it to Pictures, code is like below:
private void dispatchTakePictureIntent() {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
// Ensure that there's a camera activity to handle the intent
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
// Create the File where the photo should go
File photoFile = null;
try {
photoFile = createImageFile();
} catch (IOException ex) {
// Error occurred while creating the File
...
}
// Continue only if the File was successfully created
if (photoFile != null) {
Uri photoURI = FileProvider.getUriForFile(this,
"com.example.android.fileprovider",
photoFile);
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
startActivityForResult(takePictureIntent, REQUEST_TAKE_PHOTO);
}
}
}
String currentPhotoPath;
private File createImageFile() throws IOException {
// Create an image file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = "JPEG_" + timeStamp + "_";
File storageDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
File image = File.createTempFile(
imageFileName, /* prefix */
".jpg", /* suffix */
storageDir /* directory */
);
// Save a file: path for use with ACTION_VIEW intents
currentPhotoPath = image.getAbsolutePath();
return image;
}
We create the file directly in the Pictures, and put the file uri into the takePhotoIntent extra, while we start the intent and take a photo, original-size photo will be saved into the Pictures directory.
But now we are targeting android 10, according to the doc, it is not nessasary to request the WRITE_EXTERNAL_STORAGE permission to save a photo into the Pictures directory.
Without the permission, we can't create the file and then get the uri of the file, put it into the intent extra. So how can we save the original-size photo?
I am new to Android development and are a bit stuck trying to save a image to the gallery. I have followed the guidelines on https://developer.android.com/training/camera/photobasics, and it works fine until I try to save the image to the gallery on the phone using getExternalStoragePublicDirectory.
When I use the getExternalFilesDir() all works, but when i try to use getExternalStoragePublicDirectory to get the picture to the gallery Ii got a NullPointerException.
I have added the WRITE_EXTERNAL_STORAGE permission to the manifest.
I have tried to read other posts about this, but havent found any soulutions to this problem.
Heres my code. If annyone culd help me finding out whats cousing the NullPointerException I would be thankful.
private File createImageFile() throws IOException {
// Create an image file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = "JPEG_" + timeStamp + "_";
File storageDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
File image = File.createTempFile(
imageFileName, /* prefix */
".jpg", /* suffix */
storageDir /* directory */
);
// Save a file: path for use with ACTION_VIEW intents
mCurrentPhotoPath = image.getAbsolutePath();
return image;
}
private void dispatchTakePictureIntent() {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
// Ensure that there's a camera activity to handle the intent
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
// Create the File where the photo should go
File photoFile = null;
try {
photoFile = createImageFile();
} catch (IOException ex) {
// Error occurred while creating the File
}
// Continue only if the File was successfully created
if (photoFile != null) {
Uri photoURI = FileProvider.getUriForFile(this,
"com.example.android.fileprovider",
photoFile);
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
startActivityForResult(takePictureIntent, REQUEST_TAKE_PHOTO);
}
}
}
private void galleryAddPic() {
Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
File f = new File(mCurrentPhotoPath);
Uri contentUri = Uri.fromFile(f);
mediaScanIntent.setData(contentUri);
this.sendBroadcast(mediaScanIntent);
}
And heres my error in Logcat:
08-02 20:04:12.920 17455-17455/com.example.android.fishlist E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.android.fishlist, PID: 17455
java.lang.NullPointerException
at java.io.File.<init>(File.java:282)
at com.example.android.fishlist.NewCatch.galleryAddPic(NewCatch.java:192)
at com.example.android.fishlist.NewCatch.access$200(NewCatch.java:45)
at com.example.android.fishlist.NewCatch$2.onClick(NewCatch.java:101)
at android.view.View.performClick(View.java:6891)
at android.widget.TextView.performClick(TextView.java:12651)
at android.view.View$PerformClick.run(View.java:26083)
at android.os.Handler.handleCallback(Handler.java:789)
at android.os.Handler.dispatchMessage(Handler.java:98)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6938)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:327)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1374)
I'm trying to do a picture from my application. I can launch the camera and do the picture, but when has finish to do the picture my app crash. I can see in my screen that my gallery is stopped and this is the error in my log:
I've tried to find something but haven't found anything.
FATAL EXCEPTION: main
android.content.ActivityNotFoundException: No Activity found to handle Intent { act=com.android.camera.action.CROP dat=file:///data/data/com.android.gallery3d/files/crop-temp (has extras) }
at android.app.Instrumentation.checkStartActivityResult(Instrumentation.java:1628)
at android.app.Instrumentation.execStartActivity(Instrumentation.java:1423)
at android.app.Activity.startActivityForResult(Activity.java:3388)
at android.app.Activity.startActivityForResult(Activity.java:3349)
at com.android.camera.actor.PhotoActor.doAttach(PhotoActor.java:1125)
at com.android.camera.actor.PhotoActor.access$500(PhotoActor.java:62)
at com.android.camera.actor.PhotoActor$2.onClick(PhotoActor.java:210)
at android.view.View.performClick(View.java:4209)
at android.view.View$PerformClick.run(View.java:17431)
at android.os.Handler.handleCallback(Handler.java:725)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:153)
at android.app.ActivityThread.main(ActivityThread.java:5297)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:833)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:600)
at dalvik.system.NativeStart.main(Native Method)
This is my code:
#Override
public void onButton1Click(int ref) {
try {
currentRef = ref;
Intent mIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
Uri fileUri = FileProvider.getUriForFile(getActivity(), BuildConfig.APPLICATION_ID + ".provider", createImageFile());
mIntent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri); // set the image file name
mIntent.putExtra("crop", "true");
startActivityForResult(mIntent, REQUEST_TAKE_PHOTO);
}catch (IOException ex) {
ex.printStackTrace();
}
}
private File createImageFile() throws IOException {
// Create an image file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = "JPEG_" + timeStamp + "_";
File storageDir = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_DCIM), "Camera");
File image = File.createTempFile(
imageFileName, /* prefix */
".jpg", /* suffix */
storageDir /* directory */
);
// Save a file: path for use with ACTION_VIEW intents
mCurrentPhotoPath = "file:" + image.getAbsolutePath();
return image;
}
No, Android Does Not Have a Crop Intent
Many developers are calling startActivity() on an Intent with an action of com.android.camera.action.CROP. They are doing this to crop an image.
This is a really bad idea.
Source here - CommonsBlog
Model: Samsung SM-G900F (Android 5.0)
Code to launch camera:
File file = new File(getExternalFilesDir(null),"video.mp4");
Uri uri = FileProvider.getUriForFile(this, "example.com.myapplication.fileprovider", file);
final Intent takePictureIntent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
takePictureIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION| Intent.FLAG_GRANT_READ_URI_PERMISSION);
} else {
final List<ResolveInfo> resInfoList =
getPackageManager()
.queryIntentActivities(takePictureIntent, PackageManager.MATCH_DEFAULT_ONLY);
for (final ResolveInfo resolveInfo : resInfoList) {
final String packageName = resolveInfo.activityInfo.packageName;
grantUriPermission(packageName, uri,
Intent.FLAG_GRANT_WRITE_URI_PERMISSION |
Intent.FLAG_GRANT_READ_URI_PERMISSION);
}
}
startActivityForResult(takePictureIntent, 42);
Log:
11-03 11:40:00.073 30377-30377/? E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.sec.android.app.camera, PID: 30377
java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=2002, result=-1, data=Intent { act=inline-data dat=content://example.com.myapplication.fileprovider/external/Android/data/example.com.myapplication/files/video.mp4 (has extras) }} to activity {com.sec.android.app.camera/com.sec.android.app.camera.Camcorder}: java.lang.IllegalStateException: Couldn't read row 0, col -1 from CursorWindow. Make sure the Cursor is initialized correctly before accessing data from it.
at android.app.ActivityThread.deliverResults(ActivityThread.java:3974)
at android.app.ActivityThread.handleSendResult(ActivityThread.java:4017)
at android.app.ActivityThread.access$1400(ActivityThread.java:172)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1471)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:145)
at android.app.ActivityThread.main(ActivityThread.java:5832)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1399)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1194)
Caused by: java.lang.IllegalStateException: Couldn't read row 0, col -1 from CursorWindow. Make sure the Cursor is initialized correctly before accessing data from it.
at android.database.CursorWindow.nativeGetLong(Native Method)
at android.database.CursorWindow.getLong(CursorWindow.java:524)
at android.database.AbstractWindowedCursor.getLong(AbstractWindowedCursor.java:75)
at android.database.CursorWrapper.getLong(CursorWrapper.java:106)
at com.sec.android.app.camera.Camera.onActivityResult(Camera.java:6956)
at android.app.Activity.dispatchActivityResult(Activity.java:6475)
at android.app.ActivityThread.deliverResults(ActivityThread.java:3970)
at android.app.ActivityThread.handleSendResult(ActivityThread.java:4017)
at android.app.ActivityThread.access$1400(ActivityThread.java:172)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1471)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:145)
at android.app.ActivityThread.main(ActivityThread.java:5832)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1399)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1194)
Looks like video capturing works only with file uri and doesn't work with content uri.
Do you have the same issues? Could you suggest some general solution?
This helped me:
Uri uri;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
uri = FileProvider.getUriForFile(context, context.getApplicationContext().getPackageName() + ".provider", f);
} else {
uri = Uri.fromFile(f);
}
intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
This is working for me.
private void launchCamera() {
Intent captureVideoIntent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
if (captureVideoIntent.resolveActivity(getPackageManager()) != null)
{
Uri videoUri = null;
try {
videoUri = getOutputMediaFileUri();
} catch (Exception ex) {
// Error occurred while creating the File
ex.printStackTrace();
}
// Continue only if the File was successfully created
if (videoUri != null) {
captureVideoIntent.putExtra(MediaStore.EXTRA_OUTPUT, videoUri);
startActivityForResult(captureVideoIntent, REQUEST_CAMERA);
}
}
}
/**
* Creating file uri to store image/video
*/
private Uri getOutputMediaFileUri() {
if(Build.VERSION.SDK_INT >= 24) {
// For android N you need to use the file provider
return FileProvider.getUriForFile(this, getResources().getString(R.string.file_provider_name), getOutputMediaFile());
} else {
return Uri.fromFile(getOutputMediaFile());
}
}
/**
* returning file to store image / video
*/
private File getOutputMediaFile() {
// External sdcard location
File mediaStorageDir = new File(
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
"DirectoryNameWhereYouWantToStore");
// Create the storage directory if it does not exist
if (!mediaStorageDir.exists()) {
if (!mediaStorageDir.mkdirs()) {
Log.d(TAG, "Oops! Failed to create directory");
return null;
}
}
// Create a media file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(new Date());
return new File(mediaStorageDir.getPath() + File.separator + "IMG_" + timeStamp + ".mp4");
}
I am developing a simple gallery app in which I search for folders which contains images and then show images of that particular folder. First I am using Environment.getExternalStorageDirectory() and then recursively search for folders having images. It is working fine simulator and devices. When my client installed app on Nexus 4, nothing is being loaded. I have seen some posts which says that Nexus series don't have any external SD slot. I don't have Nexus 4 for debugging and client is also non-technical. He can troubleshoot on his own to find the cause of problem. Can anybody help in this regard? I think the problem is in Environment.getExternalStorageDirectory() call which is not applicable in Nexus. Any idea how I can tackle this issue?
Here is the code snipped I am using:
private File createImageFile() throws IOException {
// Create an image file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = "JPEG_" + timeStamp + "_";
File cacheDir = null;
if (android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED)) {
cacheDir=new File(android.os.Environment.getExternalStorageDirectory().getAbsolutePath(), "MyImages");
}
else {
cacheDir = getCacheDir();
}
if(!cacheDir.exists()) {
cacheDir.mkdir();
}
// File storageDir = Environment.getExternalStoragePublicDirectory(
// Environment.DIRECTORY_PICTURES);
File image = File.createTempFile(
imageFileName, /* prefix */
".jpg", /* suffix */
cacheDir /* directory */
);
// Save a file: path for use with ACTION_VIEW intents
mCurrentPhotoPath = "" + image.getAbsolutePath();
return image;
}
public void dispatchTakePictureIntent() {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
// Ensure that there's a camera activity to handle the intent
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
// Create the File where the photo should go
File photoFile = null;
try {
photoFile = createImageFile();
} catch (IOException ex) {
// Error occurred while creating the File
ex.printStackTrace();
}
// Continue only if the File was successfully created
if (photoFile != null) {
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT,
Uri.fromFile(photoFile));
startActivityForResult(takePictureIntent, REQUEST_TAKE_PHOTO);
}
}
}
And here the permissions I have added manifest:
<uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="18" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-feature
android:name="android.hardware.camera"
android:required="true" />
Thanks!
I think you should give a try to the MediaStore.Images component. Load the images using a cursor. See documentation: http://developer.android.com/reference/android/provider/MediaStore.html