Image and file operations on Android - java

I get pictures url from gallery or camera on android but I can't convert them to file. When i developing an app with Java in android, sometimes I need to get pictures from gallery and camera to my application. But when i try to do this I'm getting errors.
Isn't there a standard here? The code works at one api level and does not works another one. Or when I take the URI of some images and convert it to file, I get an error regardless of the api level. I wonder if there is a fundamental solution to this problem?
I am starting intent with this
Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(intent,IMAGE_RESULT);
And then I'm catching data with this code:
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == Activity.RESULT_OK) {
if (requestCode == IMAGE_RESULT) {
String filePath = ImageFilePath.getPath(OwnProfileActivity.this, data.getData());
selectedFile = new File(filePath);
showProgressDialog();
Handler handler = new Handler();
handler.postDelayed(this::chaneProfileImage, 1000);
}
}
}

May I suggest something like this, but of course this is if you have a bitmap:
private fun getImageUriFromBitmap(image: Bitmap): Uri? {
val bytes = ByteArrayOutputStream()
image.compress(Bitmap.CompressFormat.PNG, 100, bytes)
val relativeLocation = Environment.DIRECTORY_PICTURES + File.pathSeparator + "NotifyMe"
val contentValues = ContentValues().apply {
put(MediaStore.MediaColumns.DISPLAY_NAME, "notifyMe_${System.currentTimeMillis()}")
put(MediaStore.MediaColumns.MIME_TYPE, "image/png")
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
put(MediaStore.MediaColumns.RELATIVE_PATH, relativeLocation)
put(MediaStore.MediaColumns.IS_PENDING, 1)
}
}
return context?.contentResolver?.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues)
}
Then you can create the file with the uri
val file = File(uri.path)
source: https://gist.github.com/franciscobarrios/9f6634c87ca6e56ed70cd96807dd1dcb

Related

Get real path of a file from URI? [duplicate]

I am trying to fetch a file this way:
final Intent chooseFileIntent = new Intent(Intent.ACTION_GET_CONTENT);
String[] mimetypes = {"application/pdf"};
chooseFileIntent.setType("*/*");
chooseFileIntent.addCategory(Intent.CATEGORY_OPENABLE);
if (chooseFileIntent.resolveActivity(activity
.getApplicationContext().getPackageManager()) != null) {
chooseFileIntent.putExtra(Intent.EXTRA_MIME_TYPES, mimetypes);
activity.startActivityForResult(chooseFileIntent, Uploader.PDF);
}
Then in onActivityResult :
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
}
According to many threads I'm supposed to fetch the file name from the intent with data.getData().getPath(), the file name I'm expecting is my_file.pdf, but instead I'm getting this :
/document/acc=1;doc=28
So what to do? Thanks for your help.
I am trying to fetch a file
Not with that code. That code is asking the user to pick a piece of content. This may or may not be a file.
According to many threads I'm supposed to fetch the file name from the intent with data.getData().getPath()
That was never correct, though it tended to work on older versions of Android.
So what to do?
Well, that depends.
If you wish to only accept files, integrate a file chooser library instead of using ACTION_GET_CONTENT. (UPDATE 2019-04-06: since Android Q is banning most filesystem access, this solution is no longer practical)
If you are willing to allow the user to pick a piece of content using ACTION_GET_CONTENT, please understand that it does not have to be a file and it does not have to have something that resembles a filename. The closest that you will get:
If getScheme() of the Uri returns file, your original algorithm will work
If getScheme() of the Uri returns content, use DocumentFile.fromSingleUri() to create a DocumentFile, then call getName() on that DocumentFile — this should return a "display name" which should be recognizable to the user
To get the real name and to avoid getting a name that looks like "image: 4431" or even just a number, you can write code as recommended by CommonsWare.
The following is an example of a code that selects a single pdf file, prints its name and path to the log, and then sends the file by email using its uri.
private static final int FILEPICKER_RESULT_CODE = 1;
private static final int SEND_EMAIL_RESULT_CODE = 2;
private Uri fileUri;
private void chooseFile() {
Intent fileChooser = new Intent(Intent.ACTION_GET_CONTENT);
fileChooser.setType("application/pdf");
startActivityForResult(Intent.createChooser(fileChooser, "Choose one pdf file"), FILEPICKER_RESULT_CODE);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, #Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == FILEPICKER_RESULT_CODE) {
if (resultCode == RESULT_OK) {
fileUri = data != null ? data.getData() : null;
if (fileUri != null) {
DocumentFile d = DocumentFile.fromSingleUri(this, fileUri);
if (d != null) {
Log.d("TAG", "file name: " + d.getName());
Log.d("TAG", "file path: " + d.getUri().getPath());
sendEmail(fileUri);
}
}
}
}
}
private void sendEmail(Uri path) {
String email = "example#gmail.com";
Intent intent = new Intent(android.content.Intent.ACTION_SEND);
intent.setType("application/octet-stream");
intent.putExtra(android.content.Intent.EXTRA_SUBJECT, "PDF file");
String[] to = { email };
intent.putExtra(Intent.EXTRA_EMAIL, to);
intent.putExtra(Intent.EXTRA_TEXT, "This is the pdf file...");
intent.putExtra(Intent.EXTRA_STREAM, path);
startActivityForResult(Intent.createChooser(intent, "Send mail..."), SEND_EMAIL_RESULT_CODE);
}
hope it helps.

selecting photos from google photos crushes my app

i'm writing an android app on java and need to let my users select and crop images from the gallery.
There is no problem when choosing an image from any native gallery, but when a user chooses to eater crop or choose an image from google photos app the app crushes.
I cannot figure out what is the source of the problem so any answer will be helpful
this is the code i'm using
class fields:
private Uri imageUri;
opening the camera:
private void camOpen() {
Intent i = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
File f = new File(Environment.getExternalStorageDirectory(), "file" + String.valueOf(System.currentTimeMillis()) + ".png");
StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
StrictMode.setVmPolicy(builder.build());
imageUri = Uri.fromFile(f);
i.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
i.putExtra("return-data", true);
startActivityForResult(i, CAMERA_CODE);
}
opening the gallery:
private void galleryOpen() {
Intent i = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(Intent.createChooser(i, "select file"), SELECT_PHOTO_CODE);
}
cropping the image:
private void cropImage() {
try {
Intent cropIntent = new Intent("com.android.camera.action.CROP");
cropIntent.setDataAndType(imageUri, "image/*");
cropIntent.putExtra("crop", true);
cropIntent.putExtra("aspectX", 1);
cropIntent.putExtra("aspectY", 1);
cropIntent.putExtra("return-data", true);
startActivityForResult(cropIntent, CROP_CODE);
} catch (Exception e) {}
}
the result handler:
#Override
protected void onActivityResult(int requestCode, int resultCode, #Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == CAMERA_CODE && resultCode == Activity.RESULT_OK) {
cropImage();
} else if (requestCode == SELECT_PHOTO_CODE && resultCode == Activity.RESULT_OK) {
if (data != null) {
imageUri = data.getData();
cropImage();
}
} else if (requestCode == CROP_CODE && resultCode == Activity.RESULT_OK) {
Bundle bundle = data.getExtras();
Bitmap b = bundle.getParcelable("data");
hasImageChanged=true;
ivProfilePic.setImageBitmap(b);
capturedImage = b;
}
}
thank you for any useful help...
Android does not support crop intent because croping is not part of android api.
So i recommend you for Using library
the issue was with the crop intent. I ended up using the uCrop library and it fixed the problem.

Open file from documents on Android Nougat

I'm using file helper class from this post https://stackoverflow.com/a/20559175/2281821 but it doesn't working properly in each case. I'm using Intent chooseIntent = new Intent(Intent.ACTION_OPEN_DOCUMENT); to start file picker. I have Android Nougat and I'm receiving from onActivityResult uri: content://com.android.externalstorage.documents/document/home%3Aimage.png
What does this home: means? How can I get access to this file? I was trying with Environment.getExternalStorageDirectory() and System.getenv("EXTERNAL_STORAGE") but I can't get acess.
Following code can be used to get document path:
Intent galleryIntent = new Intent();
galleryIntent .setType("image/*");
galleryIntent .setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(galleryIntent , getString(R.string.app_name)),REQUEST_CODE);
OnActivityResult():
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK) {
if (requestCode == REQUEST_CODE) {
Uri uri = data.getData();
}
}
}
You can use "uri" variable value to get bitmap. If you want to open document other image also then remove following line:
galleryIntent .setType("image/*");
You get access to a content scheme by opening for instance an InputStream on the uri.
InputStream is = getContentResolver().openInputStream(uri);
BitmapFactory.decodeFromStream(is) will happily read from your stream.

Saving an image into my Gallery

I'm making an Android application in Android studio where the user can take a photo and save it into a new folder in their gallery. Currently the application takes the pictures fine but doesn't save the image into the new "SOC" folder in my gallery. I'm not getting any errors and I have no idea why it's not saving the image. Any help would be appreciated.
My code is as fallows
static final int REQUEST_IMAGE_CAPTURE = 1;
private static final int CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE = 0;
public void onClickbtnCamera(View v)
{
Intent imageIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
Uri uriSavedImage=Uri.fromFile(new File("/storage/emulated/0/DCIM/SOC","QR_"+timeStamp+ ".png"));
imageIntent.putExtra(MediaStore.EXTRA_OUTPUT, uriSavedImage);
startActivityForResult(imageIntent, 1);
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 1) {
//Check for succesful result code
if (resultCode == -1) {
//Show your Toast when the result is a success.
Toast toast = Toast.makeText(getApplicationContext(),
"Picture is saved in your SOC gallery", Toast.LENGTH_SHORT);
toast.setGravity(Gravity.TOP | Gravity.CENTER_HORIZONTAL, 100, 0);
toast.show();
}
}
}
I think you must manually add your new photo Uri to Media Content Provider.
take a look here
Call this method in your Activity for result
protected void addPhotoToGallery() {
Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
File f = new File(getCurrentPhotoPath());
Uri contentUri = Uri.fromFile(f);
mediaScanIntent.setData(contentUri);
this.getActivity().sendBroadcast(mediaScanIntent);
}
you should save the photo path before launching the intent and then getCurrentPhotoPath() must get that path

Android application: how to use the camera and grab the image bytes?

I'm trying to create a small app for Android that takes a picture using the device's camera and put's a PNG frame on top of it. This way the final saved picture will have a beach on top of it, or hats, or anything. Does anyone have any sample programs with this behavior?
Have a look at the SDK documentation on using the image capture intent here.
I start my image capture intent like this:
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(intent, CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE);
CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE is a private member in my activity:
private static final int CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE = 100;
Then get the byte array back from the camera by using the following onActivityResult handler:
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE) {
if (resultCode == Activity.RESULT_OK) {
Bitmap bmp = (Bitmap) data.getExtras().get("data");
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bmp.compress(Bitmap.CompressFormat.PNG, 100, stream);
byte[] byteArray = stream.toByteArray();
AddImage(byteArray);
} else if (resultCode == Activity.RESULT_CANCELED) {
// User cancelled the image capture
} else {
// Image capture failed, advise user
}
}
}
After that you can do all the processing you want on the image.

Categories