I have this code:
(This is code that call the video intent)
Intent videoIntent = new Intent(android.provider.MediaStore.ACTION_VIDEO_CAPTURE);
videoIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(getOutputMediaFile()));
videoIntent.putExtra(MediaStore.EXTRA_DURATION_LIMIT , 5);
videoIntent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 0);
startActivityForResult(videoIntent, VIDEO_REQUEST);
(Rest of code)
private static final int VIDEO_REQUEST = 2888;
public static File getOutputMediaFile(){
File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES), "FolderApp");
if (! mediaStorageDir.exists()){
if (! mediaStorageDir.mkdirs()){
//Cant create folder!!
return null;
}
}
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
File mediaFile mediaFile = new File(mediaStorageDir.getPath() + "_VID_" + timeStamp + ".3gp");
} else {
return null;
}
return mediaFile;
}
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == VIDEO_REQUEST && resultCode == Activity.RESULT_OK) {
//OK!! but not create a video file returned in getOutputMediaFile()
}
}
The video is not saving it to desired location similar thing I did try with Image capture and it worked.
The video is not saving it to desired location
There is no requirement that a camera app follow the rules of ACTION_IMAGE_CAPTURE or ACTION_VIDEO_CAPTURE. Some will honor a specific requested output location. Some will not, and will return where they chose to store the image/video in the Uri contained in the result Intent delivered on onActivityResult(). Some may be completely broken and not tell you anything about where the image/video was stored, even if there was one stored.
I did try with Image capture and it worked
My guess is that you did not try it on the hundreds of camera applications that come pre-installed on devices or are available on the Play Store, Amazon AppStore for Android, BlackBerry World, the Nokia X Store, the Yandex store, etc.
If you wish to rely upon third-party camera apps, your best course of action is:
Specify a desired output location
In onActivityResult(), see if the output was written where you requested, and if so, use it
Otherwise, in onActivityResult(), obtain the Uri from the Intent, and if it is not null, use it
Otherwise, tell the user to download a better camera app, perhaps linking them to one that you know works well with your app
Your code looks ok. Maybe you can try:
Environment.DIRECTORY_MOVIES
instead of
Environment.DIRECTORY_PICTURES
for your video location... but it's just a guess
The way that always works for me:
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if(data == null) {
//CANNOT GET URI
return;
}
File source = new File(data.getData().getPath());
File destination = new File(PATH_TO_YOUR_DESIRE_LOCATION,FILENAME);
//MOVE FILE
if(source.renameTo(destination)) {
//success
} else {
//something's wrong
}
}
Also if you set MediaStore.EXTRA_OUTPUT parameter to android.provider.MediaStore.ACTION_VIDEO_CAPTURE intent, then
getData() inside onActivityResult will always return null
Related
With all of the changes in android 10 that are related to scoped storage, how can we open the camera. I saw some tutorial that suggest using a file provider, but I don't really quite get it.
Can you provide a snippet of code to launch the camera intent, and receive the taken image ?
Edit :
In this article : https://medium.com/#arkapp/accessing-images-on-android-10-scoped-storage-bbe65160c3f4
He provided this code :
fun takePicture(context: Activity, imageName: String) {try {
val capturedImgFile = File(
context.getExternalFilesDir(Environment.DIRECTORY_PICTURES),
imageName)
captureImgUri = FileProvider.getUriForFile(
context,
context.applicationContext.packageName + ".my.package.name.provider",
capturedImgFile)val intent = Intent(MediaStore.ACTION_IMAGE_CAPTURE).also {
it.putExtra(MediaStore.EXTRA_OUTPUT, captureImgUri)
it.putExtra("return-data", true)
it.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
context.startActivityForResult(it, REQUEST_CODE_TAKE_PICTURE)
}
} catch (e: ActivityNotFoundException) {e.printStackTrace()}
}#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode != RESULT_OK) {return}
if (requestCode == REQUEST_CODE_TAKE_PICTURE) {
/*We cannot access the image directly so we again create a new File at different location and use it for futher processing.*/
Bitmap capturedBitmap = getBitmap(this, captureImgUri)
/*We are storing the above bitmap at different location where we can access it.*/ val capturedImgFile = File(
getExternalFilesDir(Environment.DIRECTORY_PICTURES),
getTimestamp() + "_capturedImg.jpg"); convertBitmaptoFile(capturedImgFile, capturedBitmap)/*We have to again create a new file where we will save the processed image.*/ val croppedImgFile = File(
getExternalFilesDir(Environment.DIRECTORY_PICTURES),
getTimestamp() + "_croppedImg.jpg"); startCrop(
this,
Uri.fromFile(capturedImgFile),
Uri.fromFile(croppedImgFile))}
super.onActivityResult(requestCode, resultCode, data)
}
I have two questions:
What does this line do :
it.putExtra("return-data", true)
in OnActivityResulty, why didn't he just use the uri directly, he first created a file and then parsed the file into an uri, what is this for ? how does it have to do android 10 scoped storage ?
What does this line do : it.putExtra("return-data", true)
Nothing, usually. It's possible that there are some camera apps that will do something when receiving this undocumented and (generally) unsupported Intent extra.
in OnActivityResulty, why didn't he just use the uri directly
He does, in earlier steps. By the end, he wants to use uCrop to allow the user to crop the image. Perhaps he wants to hold onto both the original and the cropped photo.
Sorry to bother you guys, but I am not able to get a solution where In we take picture using intents. I know the default behavior of native camera is to save the picture at default directory/place of O.S. The thing is I have some requirements where I do not want to save the picture when clicked using camera app. There has to be a solution of this issue, be it like once we take a picture we could delete it right away, or there should be an alternate by which we won't allow O.S to save Image, please help.
Here is a piece of code I tried, tried several ways by creating a directory and then deleting file, nothing works.
public void takeImageFromCamera() {
Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(cameraIntent, CAMERA_REQUEST);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// Check for the integer request code originally supplied to startResolutionForResult().
if (requestCode == CAMERA_REQUEST && resultCode == RESULT_OK) {
if (isCameraPermissionGranted()) {
bitmap= (Bitmap) data.getExtras().get("data");
// bitmap = processReuiredImage(picUri);
getProfileDetailViaFace(encodeImageBitmapToString(bitmap));
Log.d("path",String.valueOf(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES)));
// getApplicationContext().getContentResolver().delete(, "/storage/emulated/0/Pictures", null);
// mediaStorageDir.getPath().delete();
} else {
requestCameraPermission();
}
}
public void takeImageFromCamera() {
File file = getOutputMediaFile(CAMERA_FILE_TYPE);
if (Build.VERSION.SDK_INT >= 24) {
try {
Method m = StrictMode.class.getMethod("disableDeathOnFileUriExposure");
m.invoke(null);
} catch (Exception e) {
e.printStackTrace();
}
}
picUri = Uri.fromFile(file);
Intent takePictureIntent = new
Intent(MediaStore.ACTION_IMAGE_CAPTURE_SECURE);
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, picUri);
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
startActivityForResult(takePictureIntent, CAMERA_REQUEST);
}
}
private File getOutputMediaFile(int type) {
mediaStorageDir = new
File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES), "peppercard");
/**Create the storage directory if it does not exist*/
if (!mediaStorageDir.exists()) {
if (!mediaStorageDir.mkdirs()) {
return null;
}
}
/**Create a media file name*/
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
if (type == CAMERA_FILE_TYPE) {
mediaFile = new File(mediaStorageDir.getPath() + File.separator +
"IMG_" + timeStamp + ".jpeg");
} else {
return null;
}
}
return mediaFile;
}
The thing is I have some requirements where I do not want to save the picture when clicked using camera app
The decision of whether or not to save an image is up to the camera app, not you. There are hundreds of camera apps that might respond to ACTION_IMAGE_CAPTURE, and the developers of those apps can do whatever they want.
There has to be a solution of this issue, be it like once we take a picture we could delete it right away, or there should be an alternate by which we won't allow O.S to save Image,
Take the photo yourself, using the camera APIs or libraries that wrap around them (e.g., CameraKit-Android, Fotoapparat).
There has to be a solution of this issue, be it like once we take
a picture we could delete it right away
Indeed there is. You could specify a path (even using a file provider) where the camera app has to put the image in a file.
Then when the camera app is done you can get the image from that file and then delete the file.
Have a look at Intent.EXTRA_OUTPUT.
Pretty standard your question. You can find a lot of example code on this site.
Final I have found the answer after waiting from past 2 days, yay..It will not save the file as I am just deleting the file after returning from the activity.
String[] projection = { MediaStore.Images.Media.DATA };
Cursor cursor = managedQuery(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, projection, null, null, null)
int column_index_data = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToLast();
String imagePath = cursor.getString(column_index_data);
Bitmap bitmapImage = BitmapFactory.decodeFile(imagePath );
Log.d("bitmapImage", bitmapImage.toString()); /*delete file after taking picture*/
Log.d("imagePath", imagePath.toString());
File f = new File(imagePath);
if (f.exists()){
f.delete();
}
sendBroadcast(newIntent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE,Uri.fromFile(f)));
I am using SquareCamera library (https://github.com/boxme/SquareCamera) for taking square picture.The problem I am facing is that SquareCamera is creating its own folder where taken pics are getting stored. I want these pics to store in my own folder. I don't know how to achieve that. I am very new to android. Below is the code where instead of default camera I am calling its own class.
public void onLaunchCamera(View view) {
// create Intent to take a picture and return control to the calling application
Intent intent = new Intent(this,CameraActivity.class);
// Start the image capture intent to take photo
startActivityForResult(intent, CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE);
And this is the onActivityResult method
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE) {
if (resultCode == RESULT_OK) {
Uri takenPhotoUri = data.getData();
Bitmap takenImage = BitmapFactory.decodeFile(takenPhotoUri.getPath());
imageView.setImageBitmap(takenImage);
I thought about saving this bitmap into my own folder but I couldn't think how to delete the created directory of SquareCamera.
So I found the solution. I added the library as a module in my app. Referring (https://www.youtube.com/watch?v=1MyBO9z7ojk). And there I changed the source code a little bit and now it's working perfect.
I'm a bit long in the tooth at Android and am not 100% with the new Uri methods of file access enforced since KitKat. For conventional file access you can get a private writeable file using.
private static final File OUTPUT_DIR = Environment.getExternalStorageDirectory();
FileOutputStream fos;
void yourMethodBeginsHere() {
String outputPath = new File(OUTPUT_DIR, "test.png").toString();
try {
fos = new FileOutputStream(outputPath, false);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
//Work with file
}
If you need a truly external file path please refer to the excellent answer already existing at https://stackoverflow.com/a/26765884/5353361 which deals fully with the new Uri based system of permissions and the integrated file explorer.
I have been trying to create an Android camera activity to test how it works on the emulator, but I am not sure if I am doing things right.
I have added the permission to the manifest for the deprecated camera version, focus and front camera. And I have been looking up tutorials and learning the code.
I have also tried to include a frame layout preview with some custom buttons, but I really don't know how to make the buttons layout overlay the frame.
Do I need to use fragments?
Also I should mention I have read about the new "camera2" and my interest to implement it to the same activity, but maybe that would be just too much for a simple test. What are your recommendations on this?
If your search for code, try the following sample code (I have also an answer at How to move image captured with the phone camera from one activity to an image view in another activity?, you can take a look).
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
mFileUri = Uri.fromFile(getOutputMediaFile(1));
intent.putExtra(MediaStore.EXTRA_OUTPUT, mFileUri);
// start the image capture Intent
startActivityForResult(intent, 100);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent imageReturnedIntent) {
super.onActivityResult(requestCode, resultCode, imageReturnedIntent);
if (resultCode == RESULT_OK) {
if (mFileUri != null) {
// do something...
}
}
}
private static File getOutputMediaFile(int type) {
// External sdcard location
File mediaStorageDir = new File(Environment.getExternalStorageDirectory(), "DCIM/Camera");
// Create the storage directory if it does not exist
if (!mediaStorageDir.exists()) {
if (!mediaStorageDir.mkdirs()) {
return null;
}
}
// Create a media file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(new Date());
File mediaFile;
if (type == 1) { // image
mediaFile = new File(mediaStorageDir.getPath() + File.separator + "IMG_" + timeStamp + ".jpg");
} else if (type == 2) { // video
mediaFile = new File(mediaStorageDir.getPath() + File.separator + "VID_" + timeStamp + ".mp4");
} else {
return null;
}
return mediaFile;
}
If using emulator to test, make sure camera supported like this:
I do not think that I can give you a exact answer to you question since it is very brad thing to answer. But I will try to give you some high-level guidance to your approaches.
Generally using Fragments is the best way to write an Android application and now it is the recommended way.
You can make another application to work on behalf of your application using Intents in Android. Which is you can start the Camera Application installed on your device to take the images on behalf of your application.
static final int REQUEST_IMAGE_CAPTURE = 1;
private void dispatchTakePictureIntent() {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);
}
}
You can read more from here
But these camera APIs come into play if you want to write your own custom Camera API. Because there are scenarios where you actually want your own custom camera functionality for your special requirements of the application you are building.
So decide what is that you want to achieve. If you just want to get a photo and save it you can simply use Intent and request the camera application to take the photo for your application.
To get more in depth understanding on camera APIs you can start from here
Edit,
Yes you can actually do something like following
if (Build.VERSION.SDK_INT > 9) {
and have different execution paths depending on the version.
Hope someone may give some pointers (or an out right answer)...
Simple app, take an image using the built-in camera app, save the image to a separate application. Be done.
Problem: The camera application saves the image in the default app location (/mnt/sdcard/external_sd/DCIM/Camera) as well as my custom path (in code below).
Both files are exactly the same except for the file name. The external_sd file (the one I want gone) is saved with dashes (-) vs my custom file path saved with underscores. File sizes are exactly the same.
How can I stop this double image issue?
Is there an extra intent option I'm missing?
Or am I doing this completely wrong, missing something?
I'm using a Galaxy S Vibrant.
Code snippet:
private static Uri _outputFileUri;
private static File _file;
private ImageView _image;
private SimpleDateFormat _simpleDateFormat = new SimpleDateFormat("yyyy_MM_dd_HH_mm_ss");
_takePicture = (Button) findViewById(R.id.takePicture);
_takePicture.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
_intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
_file = new File(Environment.getExternalStorageDirectory() +
"/Android/data/my own folder/files/",
_simpleDateFormat.format(new Date()).toString() +
".jpg");
_outputFileUri = Uri.fromFile(_file);
_intent.putExtra(MediaStore.EXTRA_OUTPUT, _outputFileUri);
startActivityForResult(_intent, CAMERA_ACTIVITY);
}
});
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_CANCELED) {
Toast.makeText(this, "Activity cancelled", Toast.LENGTH_LONG).show();
return;
}
switch (requestCode) {
case CAMERA_ACTIVITY:
if (resultCode == RESULT_OK) {
try{
Bitmap b = MediaStore.Images.Media.getBitmap(getContentResolver(), _outputFileUri);
_image.setImageBitmap(b);
_image.invalidate();
}
catch(Exception e){
e.printStackTrace();
}
}
break;
}
}
This is device-dependent behavior. My observation is that HTC devices do not have this duplication problem, but Samsung devices do.
Please remove the following lines:
_file = new File(Environment.getExternalStorageDirectory() +
"/Android/data/my own folder/files/",
_simpleDateFormat.format(new Date()).toString() +
".jpg");
_outputFileUri = Uri.fromFile(_file);
_intent.putExtra(MediaStore.EXTRA_OUTPUT, _outputFileUri);
Also update the code to get the image from intent:
Bitmap b = (Bitmap) data.getExtras().get("data");
_image.setImageBitmap(b);
_image.invalidate();
This way picture wouldn't be saved on sd card or default location.
I had the same problem and gave up. Sometime later I found out that I was not getting it anymore and I'm not sure what change I made to my code, but I think that it was MediaStore's fault (check my unsolved question: Weird camera Intent behavior)
As you already have the image URI, why don't you use it to set the ImageViews' bitmap?
// void setImageURI(Uri uri)
_image.setImageBitmap(_outputFileUri);
I had this issue and here is how i solved it :
File createImageFile() throws IOException{
String timestamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String filename = "IMG_"+timestamp+"_";
File image = File.createTempFile(filename,".jpg",mGalleryFolder );
if (image.length() == 0 ){
boolean delete = image.delete();
}
mLocation = image.getAbsolutePath();
return image;
}
It's not exactly solving but works for me ;)