How can I get the path from a file - android

I'm making an App where I call the file explorer, the when I choose a file i get the name with file.getName() and put it in a TextView and get the path with file..getPath() and save it in a String, this String I use it to attach the file into a mail... my problem is that when a choose a file like .PDF, .DOC, .DOCX, .MP3 I can attach it but when a select an image I get this kind of path: "/media/external/images/media/1220" and does not attach anithing, I've been serarching everywhere and use almost every option I have found with no result.
Here is my code:
private void PickFile(View v) {
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("*/*");
startActivityForResult(intent, PICKER);
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if ((resultCode == RESULT_OK) && (requestCode == PICKER)) {
String FilePath = data.getData().getPath();
File file = new File(FilePath);
}
if (txtAdjunto1.getText() == "_") {
adjunto1 = file.getPath();// I get the path to add it to the MimeBodyPart
txtAdjunto1.setText(file.getName());// I put the name in the TextView
I've been trying this:
public String getRealPathFromURI(Uri contentUri) {
Cursor cursor = null;
int column_index;
String ruta = null;
try {
String[] proj = { MediaStore.Images.Media.DATA };
cursor = getContentResolver().query(contentUri, proj, null, null, null);
if (cursor != null){
column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
ruta = cursor.getString(column_index);
}
return ruta;
} finally {
if (cursor != null) {
cursor.close();
}
}
But the app crashes when I pick the file.
Also tried this:
file = new File(file.getAbsolutePath());
But still geting this "/media/external/images/media/1220"...
Hop someone can help me with this, and thanks in advance

ACTION_GET_CONTENT and ACTION_OPEN_DOCUMENT allow the user to choose a piece of content. That content might be a local file. That content might also be:
Something on a file server on the network
Something in a cloud storage service, such as Google Drive
Something in an encrypted volume
Something that is a file, but is not a file that you can access directly
And so on
You have two main options. If you only want files, then use a third-party file chooser library to replace all of the code in your question.
Or, you can take the Uri that you get from data.getData() in onActivityResult() and do two things with it:
First, use DocumentFile.fromSingleUri() to get a DocumentFile object pointing to that Uri. You can call getName() on the DocumentFile to get a "display name" for the content, which should be something that the user will recognize.
Then, use a ContentResolver and openInputStream() to get at the content itself, similar to how you might use a FileInputStream to get at the bytes in a file.

Try this...
The following code is to select any type of file from file manager and camera then convert to byte array and attach file make edit as per your requirement
private void selectFile() {
final CharSequence[] items = {"Camera", "Choose from File Manager",
"Cancel"};
AlertDialog.Builder builder = new AlertDialog.Builder(ComposeActivity.this);
builder.setTitle("Add Attachment!");
builder.setItems(items, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int item) {
boolean result = Constant.checkPermission(ComposeActivity.this);
if (items[item].equals("Camera")) {
userChoosenTask = "Camera";//String
if (result)
cameraIntent();
} else if (items[item].equals("Choose from File Manager")) {
userChoosenTask = "Choose from File Manager";//String
if (result) {
FileManagerIntent();
}
} else if (items[item].equals("Cancel")) {
dialog.dismiss();
}
}
});
builder.show();
}
to call camera
private void cameraIntent() {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(intent, REQUEST_CAMERA);
}
file from file manager
private void FileManagerIntent() {
try {
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("*/*");
startActivityForResult(Intent.createChooser(intent, "Select File"), 111);
} catch (Exception e) {
// Handle exceptions here
e.printStackTrace();
}
}
results
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == Activity.RESULT_OK) {
if (requestCode == SELECT_FILE)
onSelectFromGalleryResult(data);
else if (requestCode == REQUEST_CAMERA)
onCaptureImageResult(data);
}
}
getting camera result and converting it to bytearray
private void onCaptureImageResult(Intent data) {
Bitmap thumbnail = (Bitmap) data.getExtras().get("data");
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
thumbnail.compress(Bitmap.CompressFormat.JPEG, 90, bytes);
File destination = new File(Environment.getExternalStorageDirectory(),
System.currentTimeMillis() + ".jpg");
Uri uri = Uri.fromFile(destination);
String uriString = uri.toString();
String path = destination.getAbsolutePath();
if (uriString.startsWith("content://")) {
Cursor cursor = null;
try {
cursor = ComposeActivity.this.getContentResolver().query(uri, null, null, null, null);
if (cursor != null && cursor.moveToFirst()) {
strFileName = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME));
}
} finally {
cursor.close();
}
} else if (uriString.startsWith("file://")) {
strFileName = destination.getName();
}
attachLayout.setVisibility(View.VISIBLE);
txtFileName.setText(strFileName);
try {
fileByteArray = bytes.toByteArray();
strFile = Base64.encodeToString(fileByteArray, Base64.DEFAULT);
Log.v("Soma", strFile);
Log.v("Byte Array * ", strFile);
} catch (Exception e) {
e.printStackTrace();
}
}
result from file manager
private void onSelectFromGalleryResult(Intent data) {
Uri uri = data.getData();
if (uri.toString().contains("video") || uri.toString().contains("audio")) {
Toast.makeText(ComposeActivity.this, "Oops! can't send video/audio file", Toast.LENGTH_SHORT).show();
} else {
String uriString = uri.toString();
File myFile = new File(uriString);
String path = myFile.getAbsolutePath();
if (uriString.startsWith("content://")) {
Cursor cursor = null;
try {
cursor = ComposeActivity.this.getContentResolver().query(uri, null, null, null, null);
if (cursor != null && cursor.moveToFirst()) {
strFileName = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME));
}
} finally {
cursor.close();
}
} else if (uriString.startsWith("file://")) {
strFileName = myFile.getName();
}
Log.v("Super DisplayName", strFileName);
attachLayout.setVisibility(View.VISIBLE);
txtFileName.setText(strFileName);
try {
InputStream iStream = getContentResolver().openInputStream(uri);
fileByteArray = getBytes(iStream);
strFile = Base64.encodeToString(fileByteArray, Base64.DEFAULT);
Log.v("Byte Array * ", strFile);
} catch (Exception e) {
e.printStackTrace();
}
}
}
file to bytearray
public byte[] getBytes(InputStream inputStream) throws IOException {
ByteArrayOutputStream byteBuffer = new ByteArrayOutputStream();
int bufferSize = 1024;
byte[] buffer = new byte[bufferSize];
int len = 0;
while ((len = inputStream.read(buffer)) != -1) {
byteBuffer.write(buffer, 0, len);
}
return byteBuffer.toByteArray();
}

Related

Android app getting crash when select image from Recent images from gallery

My app work perfectly when select image from Pictures or images categories in Gallery but app getting crash when select image from recent images
This is my intent call
galleryLayout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (EasyPermissions.hasPermissions(getActivity(), perms_gallery)) {
Intent intent = new Intent();
intent.setType("image/*");
intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(intent, "Select Picture"), SELECT_FILE);
}else {
EasyPermissions.requestPermissions(getActivity(), getString(R.string.read_file),
READ_REQUEST_CODE, perms_gallery);
}
}
});
Crash happen from here String id = wholeID.split(":")[1];
public String getPathFromUriGallery(Context context, Uri uri) {
Cursor cursor = null;
try {
String wholeID = DocumentsContract.getDocumentId(uri);
String id = wholeID.split(":")[1];
String sel = MediaStore.Images.Media._ID + "=?";
String[] filePath = {MediaStore.Images.Media.DATA};
cursor = context.getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, filePath, sel, new String[]{id}, null);
cursor.moveToFirst();
int columnIndex = cursor.getColumnIndex(filePath[0]);
return cursor.getString(columnIndex);
} finally {
if (cursor != null) {
cursor.close();
}
}
}
this my error log
Process: io.test.susitkMed.doctor, PID: 9576
java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=65537, result=-1, data=Intent { dat=content://com.google.android.apps.docs.storage/document/acc=3;doc=encoded=0ajgvv25pDn5wcNiiiv1YFYu7neaIdrulcWk/kBdEa8TqupNEKLhnLzz flg=0x1 launchParam=MultiScreenLaunchParams { mDisplayId=0 mBaseDisplayId=0 mFlags=0 } }} to activity {io.test.susitkMed.doctor/io.test.susitkMed.doctor.ui.activities.MainActivity}: java.lang.ArrayIndexOutOfBoundsException: length=1; index=1
at android.app.ActivityThread.deliverResults(ActivityThread.java:4520)
at android.app.ActivityThread.handleSendResult(ActivityThread.java:4563)
at android.app.ActivityThread.-wrap22(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1698)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6776)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1496)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1386)
Caused by: java.lang.ArrayIndexOutOfBoundsException: length=1; index=1
I found this solution from this github sample https://github.com/maayyaannkk/ImagePicker
This is the solution for above issue
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == PICK_IMAGE && resultCode == RESULT_OK
&& null != data) {
Uri selectedImage = data.getData();
String imageEncoded = getRealPathFromURI(getActivity(), selectedImageUri);
Bitmap selectedImage = BitmapFactory.decodeFile(imageString);
image.setImageBitmap(selectedImage);
}
}
These method use for get image url
public String getRealPathFromURI(Context context, Uri contentUri) {
OutputStream out;
File file = new File(getFilename(context));
try {
if (file.createNewFile()) {
InputStream iStream = context != null ? context.getContentResolver().openInputStream(contentUri) : context.getContentResolver().openInputStream(contentUri);
byte[] inputData = getBytes(iStream);
out = new FileOutputStream(file);
out.write(inputData);
out.close();
return file.getAbsolutePath();
}
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
private byte[] getBytes(InputStream inputStream) throws IOException {
ByteArrayOutputStream byteBuffer = new ByteArrayOutputStream();
int bufferSize = 1024;
byte[] buffer = new byte[bufferSize];
int len = 0;
while ((len = inputStream.read(buffer)) != -1) {
byteBuffer.write(buffer, 0, len);
}
return byteBuffer.toByteArray();
}
private String getFilename(Context context) {
File mediaStorageDir = new File(context.getExternalFilesDir(""), "patient_data");
// Create the storage directory if it does not exist
if (!mediaStorageDir.exists()) {
mediaStorageDir.mkdirs();
}
String mImageName = "IMG_" + String.valueOf(System.currentTimeMillis()) + ".png";
return mediaStorageDir.getAbsolutePath() + "/" + mImageName;
}
Use this methods instead..
public String getImagePathFromUri(Uri contentUri) {
String res = null;
String[] proj = {MediaStore.Images.Media.DATA};
Cursor cursor = getContentResolver().query(contentUri, proj, null, null, null);
if (cursor.moveToFirst()) {
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
res = cursor.getString(column_index);
}
cursor.close();
return res;
}
Use Document provider instead.
For eg:
Intent it = new Intent();
it.setAction(Intent.ACTION_GET_CONTENT);
it.setType("image/*");
startActivityForResult(it, 1000);
----------------------
#Override
protected void onActivityResult(int requestCode, int resultCode, #Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 1000) {
if (resultCode == Activity.RESULT_OK && data != null) {
try {
Bitmap bm = getBitmapFromUri(data.getData());
iv.setImageBitmap(bm);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
private Bitmap getBitmapFromUri(Uri uri) throws IOException {
ParcelFileDescriptor parcelFileDescriptor =
getContentResolver().openFileDescriptor(uri, "r");
FileDescriptor fileDescriptor = parcelFileDescriptor.getFileDescriptor();
Bitmap image = BitmapFactory.decodeFileDescriptor(fileDescriptor);
parcelFileDescriptor.close();
return image;
}
When I select the image from recent then the image is broken in android | Multiple images from recent
I have mentioned below my answer link please go there and find your solutions
You can find the full post from this link || Click link here
Also, you can find here
Sample preview
Call multiple images select
Intent i = new Intent(Intent.ACTION_GET_CONTENT);
i.addCategory(Intent.CATEGORY_OPENABLE);
i.setType("image/*");
i.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
*gallery*.launch(i);
gallery basically startActivityForResult(i,123) and OnActivityResult method is deprecated, the gallery is alternative which is defined below
ActivityResultLauncher<Intent> gallery = choosePhotoFromGallery();
and choosePhotoFromGallery() is method which is define below
private ActivityResultLauncher<Intent> choosePhotoFromGallery() {
return registerForActivityResult(
new ActivityResultContracts.StartActivityForResult(),
result -> {
try {
if (result.getResultCode() == RESULT_OK) {
if (null != result.getData()) {
if (result.getData().getClipData() != null) {
ClipData mClipData = result.getData().getClipData();
for (int i = 0; i < mClipData.getItemCount(); i++) {
ClipData.Item item = mClipData.getItemAt(i);
Uri uri = item.getUri();
String imageFilePathColumn = getPathFromURI(this, uri);
productImagesList.add(imageFilePathColumn);
}
} else {
if (result.getData().getData() != null) {
Uri mImageUri = result.getData().getData();
String imageFilePathColumn = getPathFromURI(this, mImageUri);
productImagesList.add(imageFilePathColumn);
}
}
} else {
showToast(this, "You haven't picked Image");
productImagesList.clear();
}
} else {
productImagesList.clear();
}
} catch (Exception e) {
e.printStackTrace();
showToast(this, "Something went wrong");
productImagesList.clear();
}
});
}
and getPathFromURI() is method which define below
public String getPathFromURI(Context context, Uri contentUri) {
OutputStream out;
File file = getPath();
try {
if (file.createNewFile()) {
InputStream iStream = context != null ? context.getContentResolver().openInputStream(contentUri) : context.getContentResolver().openInputStream(contentUri);
byte[] inputData = getBytes(iStream);
out = new FileOutputStream(file);
out.write(inputData);
out.close();
return file.getAbsolutePath();
}
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
private byte[] getBytes(InputStream inputStream) throws IOException {
ByteArrayOutputStream byteBuffer = new ByteArrayOutputStream();
int bufferSize = 1024;
byte[] buffer = new byte[bufferSize];
int len = 0;
while ((len = inputStream.read(buffer)) != -1) {
byteBuffer.write(buffer, 0, len);
}
return byteBuffer.toByteArray();
}
and the getPath() is
private File getPath() {
File folder = new File(Environment.getExternalStorageDirectory(), "Download");
if (!folder.exists()) {
folder.mkdir();
}
return new File(folder.getPath(), System.currentTimeMillis() + ".jpg");
}

Pick image from Gallery - File not found when running newer Android versions

I am working on a address book like Android SDK 14+ app. The users should be able to pick an image from the Gallery to add it to a contact entry.
Running the following code to pick and copy the image is no problem in API 14-20 but does not work in API 21+. The file is not found anymore:
protected void pickFoto() {
if (filePermissionsRequired()) {
askForFilePermissions(new PermissionRequestCompletionHandler() {
#Override
public void onPermissionRequestResult(boolean permissionGranted) {
if (permissionGranted)
addOrEditReceipt();
}
});
return;
}
Intent pickPhotoIntent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(pickPhotoIntent , PICK_FOTO_ACTION);
}
protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
super.onActivityResult(requestCode, resultCode, intent);
if (resultCode == Activity.RESULT_OK) {
switch (requestCode) {
...
case PICK_FOTO_ACTION: {
Uri imageUri = intent.getData();
String[] filePathColumn = {MediaStore.Images.Media.DATA};
Cursor cursor = getContentResolver().query(imageUri, filePathColumn, null, null, null);
cursor.moveToFirst();
int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
String filePath = cursor.getString(columnIndex);
cursor.close();
File imgFile = new File(filePath);
if (imgFile.exists())
// use the file...
else
Toast.makeText(this, "Image file not found", Toast.LENGTH_LONG).show();
break;
}
}
public interface PermissionRequestCompletionHandler {
void onPermissionRequestResult(boolean permissionGranted);
}
private PermissionRequestCompletionHandler permissionRequestCompletionHandler;
public boolean filePermissionsRequired() {
if (Build.VERSION.SDK_INT >= 23)
return checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED;
else
return false;
}
public boolean askForFilePermissions(PermissionRequestCompletionHandler completionHandler) {
if (Build.VERSION.SDK_INT >= 23) {
permissionRequestCompletionHandler = completionHandler;
boolean hasPermission = this.checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED;
if (!hasPermission) {
this.requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE}, 1);
return true;
}
}
permissionRequestCompletionHandler = null;
return false;
}
The app has runtime permissions to access the Gallery. So what am I doing wrong? How to access the file on newer API versions?
}
try below code to open the camera and getting result:
File file = new File(Environment.getExternalStorageDirectory() + "/DCIM/", "image" + System.currentTimeMillis() + ".png");
Uri imageUri = Uri.fromFile(file);
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
startActivityForResult(intent, PICK_FOTO_ACTION);
for getting result :
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == Activity.RESULT_OK) {
switch (requestCode) {
case PICK_FOTO_ACTION: {
Uri imageUri = imageUri;
File imgFile = new File(imageUri.getPath());
if (imgFile.exists())
// use the file...
else
Toast.makeText(this, "Image file not found", Toast.LENGTH_LONG).show();
break;
}
}
}
for getting actual path from uri :
public String getPath(Uri uri)
{
String[] projection = { MediaStore.Images.Media.DATA };
Cursor cursor = managedQuery(uri, projection, null, null, null);
if (cursor == null) return null;
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
String s=cursor.getString(column_index);
cursor.close();
return s;
}
remove unwanted uri part :
public String RemoveUnwantedString(String pathUri){
//pathUri = "content://com.google.android.apps.photos.contentprovider/-1/2/content://media/external/video/media/5213/ORIGINAL/NONE/2106970034"
String[] d1 = pathUri.split("content://");
for (String item1:d1) {
if (item1.contains("media/")) {
String[] d2 = item1.split("/ORIGINAL/");
for (String item2:d2) {
if (item2.contains("media/")) {
pathUri = "content://" + item2;
break;
}
}
break;
}
}
//pathUri = "content://media/external/video/media/5213"
return pathUri;
}
For versions 21 and higher you can do this , you need to add a condition to check the SDK version for this. Exectute this code in the API 21+ condition block.
String wholeID = DocumentsContract.getDocumentId(imageUri );
String id = wholeID.split(":")[1];
String sel = MediaStore.Images.Media._ID + "=?";
cursor =
getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
projection, sel, new String[]{ id }, null);
try
{
int column_index = cursor
.getColumnIndex(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
path = cursor.getString(column_index).toString();
cursor.close();
}
catch(NullPointerException e) {
}
Call the Gallery with belo code
public static final int SELECT_IMAGE_FROM_GALLERY_CODE = 701;
public static void callGallery(Activity activity) {
Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
activity.startActivityForResult(Intent.createChooser(intent, "Complete action using"),
SELECT_IMAGE_FROM_GALLERY_CODE);
}
In OnActivityResult, read URI and read path from uri.
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == CommonUtils.SELECT_IMAGE_FROM_GALLERY_CODE) {
if (data != null) {
Uri selectedImageUri = data.getData();
// get path from Uri
String imagepath = getPath(this, selectedImageUri);
if (null != imagepath && (!imagepath.isEmpty())) {
// if the image path is not null and not empty, copy image to sdcard
try {
copyDirectoryOrFile(new File(imagepath), new File(myTargetImageFilePath));
} catch (IOException e) {
e.printStackTrace();
}
// load the image into imageView with the help og glide.
loadImageWithGlide(myImageViewContactImage,
myTargetImageFilePath, myDefaultImagePath, myErrorImagePath, false);
} else {
Toast.makeText(this, "Error: Photo selection failed.", Toast.LENGTH_LONG).show();
}
}
}
}
public void loadImageWithGlide(ImageView theImageViewToLoadImage,
String theLoadImagePath, int theDefaultImagePath, int theErrorImagePath,
boolean theIsSkipMemoryCache) {
if (theIsSkipMemoryCache) {
Glide.with(ProfileActivity.this) //passing context
.load(theLoadImagePath) //passing your url to load image.
.placeholder(theDefaultImagePath) //this would be your default image (like default profile or logo etc). it would be loaded at initial time and it will replace with your loaded image once glide successfully load image using url.
.error(theErrorImagePath)//in case of any glide exception or not able to download then this image will be appear . if you won't mention this error() then nothing to worry placeHolder image would be remain as it is.
.diskCacheStrategy(DiskCacheStrategy.ALL) //using to load into cache then second time it will load fast.
//.animate(R.anim.fade_in) // when image (url) will be loaded by glide then this face in animation help to replace url image in the place of placeHolder (default) image.
.centerCrop()
.into(theImageViewToLoadImage); //pass imageView reference to appear the image.
} else {
Glide.with(ProfileActivity.this)
.load(theLoadImagePath)
.diskCacheStrategy(DiskCacheStrategy.NONE)
.skipMemoryCache(true)
.centerCrop()
.into(theImageViewToLoadImage);
}
}
public static String getPath(Context theCtx, Uri uri) {
try {
Cursor cursor = (theCtx).getContentResolver().query(uri, null, null, null, null);
cursor.moveToFirst();
String document_id = cursor.getString(0);
document_id = document_id.substring(document_id.lastIndexOf(":") + 1);
cursor.close();
cursor = (theCtx).getContentResolver().query(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
null, MediaStore.Images.Media._ID + " = ? ", new String[]{document_id}, null);
cursor.moveToFirst();
String path = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA));
cursor.close();
return path;
} catch (Exception e) {
return null;
}
}
public static void copyDirectoryOrFile(File sourceLocation, File targetLocation)
throws IOException {
if (sourceLocation.isDirectory()) {
if (!targetLocation.exists() && !targetLocation.mkdirs()) {
throw new IOException("Cannot create directory " + targetLocation.getAbsolutePath());
}
String[] children = sourceLocation.list();
for (int i = 0; i < children.length; i++) {
copyDirectoryOrFile(new File(sourceLocation, children[i]),
new File(targetLocation, children[i]));
}
} else {
File directory = targetLocation.getParentFile();
if (directory != null && !directory.exists() && !directory.mkdirs()) {
throw new IOException("Cannot create directory " + directory.getAbsolutePath());
}
InputStream in = new FileInputStream(sourceLocation);
OutputStream out = new FileOutputStream(targetLocation);
// Copy the bits from instream to outstream
byte[] buf = new byte[1024];
int len;
while ((len = in.read(buf)) > 0) {
out.write(buf, 0, len);
}
in.close();
if (out != null) {
try {
out.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
To load image with glide, add following dependency in app gradle file
compile 'com.github.bumptech.glide:glide:3.7.0'

Upload image from devide to FTP using android app

Hey I have a code that let the user pick an image from the gallery and after he chooses the image is shown in an image view, now when the user click a button it should upload the image to ftp server , but from some reason the app tells me that the location of the file I am giving is not found.
here is the ftp upload code (I execute it using asynctask)
public UploadImage(String host,int port,String username,String password,String imagePath) {
this.host = host;
this.port = port;
this.username = username;
this.password = password;
this.imagePath = imagePath;
}
public void uploadingFilestoFtp() throws IOException
{
FTPClient con = null;
try
{
con = new FTPClient();
con.connect(host);
if (con.login(username, password))
{
con.enterLocalPassiveMode(); // important!
con.setFileType(FTP.BINARY_FILE_TYPE);
Uri uri = Uri.parse(this.imagePath);
String data = uri.getPath();
FileInputStream in = new FileInputStream(new File(data));
boolean result = con.storeFile("/img.png", in);
in.close();
if (result) Log.v("upload result", "succeeded");
con.logout();
con.disconnect();
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
and the loading file to imageview
loadedImage = (ImageView)findViewById(R.id.upload_image1);
Drawable drawable = loadedImage.getDrawable();
if(drawable.getConstantState().equals(getResources().getDrawable(R.drawable.camera_icon).getConstantState())) {
Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(intent, "SelectPicture"), SELECT_PICTURE);
}
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK) {
if (requestCode == SELECT_PICTURE) {
selectedImageURI = data.getData();
loadedImage = (ImageView)findViewById(R.id.upload_image1);
loadedImage.setScaleType(ImageView.ScaleType.CENTER_CROP);
Glide.with(this).load(selectedImageURI)
.into((ImageView) findViewById(R.id.upload_image1));
ImageView m =(ImageView)findViewById(R.id.remove_image);
m.setFocusable(true);
m.setVisibility(View.VISIBLE);
}
}
}
The imagePath String is the image uri converted to string.
can anyone help me and tell me why isn't it finding the file?
Ask user to pick the image and use that image to imageView.. the path consist of the actual image path you can upload it..
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == PICK_IMAGE_REQUEST && resultCode == RESULT_OK && data != null && data.getData() != null) {
uri = data.getData();
if (uri != null)
{
path = uri.toString();
if (path.toLowerCase().startsWith("file://"))
{
// Selected file/directory path is below
path = (new File(URI.create(path))).getAbsolutePath();
}
else{
path = getRealPathFromUri(getApplicationContext(),uri);
}
}
try {
bitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), uri);
profileImg.setImageBitmap(bitmap);
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static String getRealPathFromUri(Context context, Uri contentUri) {
Cursor cursor = null;
try {
String[] proj = { MediaStore.Images.Media.DATA };
cursor = context.getContentResolver().query(contentUri, proj, null, null, null);
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
return cursor.getString(column_index);
} finally {
if (cursor != null) {
cursor.close();
}
}
}
Hope you are giving permission also

Not able to copy image using ACTION_GET_CONTENT

I am trying to copy image using below code:
Intent intentImage = new Intent();
intentImage.setType("image/*");
intentImage.setAction(Intent.ACTION_GET_CONTENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
startActivityForResult(intentImage, 10);
With this i am able to open all image content.
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == 10) {
if (resultCode != RESULT_OK) return;
Uri selectedImageUri = data.getData();
try {
String selectedImagePath1 = getPath(selectedImageUri);
File file = new File(selectedImagePath1);
String fna = file.getName();
String pna = file.getParent();
File fileImage = new File(pna, fna);
copyFileImage(fileImage, data.getData());
} catch (Exception e) {
}
}
}
private void copyFileImage(File src, Uri destUri) {
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
try {
bis = new BufferedInputStream(new FileInputStream(src));
bos = new BufferedOutputStream(getContentResolver().openOutputStream(destUri));
byte[] buf = new byte[1024];
bis.read(buf);
do {
bos.write(buf);
} while (bis.read(buf) != -1);
} catch (NullPointerException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (bis != null) bis.close();
if (bos != null) bos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Now i am successfully get path and name of the image .
Now when i run the above code then it gives me error of requires android.permission.MANAGE_DOCUMENTS, or grantUriPermission().
so i have put the permission in manifest :
i have also defined the permission for read and write internal/external storage.
But still i am getting this error.
How can i copy image ?
Select picture using below code
Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(intent,
"Select Picture"), 1);
this will open gallery, after selecting pic you will get selected pic uri in below code
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
switch(requestCode) {
case 1:
if(resultCode == RESULT_OK)
{
Uri selectedImageUri = data.getData();
String selectedImagePath = getPath(selectedImageUri);
File sel = new File(selectedImagePath);
Bitmap bitmap = BitmapFactory.decodeFile(sel.getAbsolutePath());
imageView1.setImageBitmap(bitmap);
Bitmap resized = Bitmap.createScaledBitmap(bitmap, 600,370, true);
ByteArrayOutputStream blob = new ByteArrayOutputStream();
resized.compress(Bitmap.CompressFormat.JPEG, 100, blob);
String StrBase64 = Base64.encodeToString(blob.toByteArray(), Base64.DEFAULT);
imageView1.setImageBitmap(resized);
// Toast.makeText(getApplicationContext(), ""+selectedImagePath, Toast.LENGTH_LONG).show();
}
break;
}
}
public String getPath(Uri uri) {
// just some safety built in
if( uri == null ) {
// TODO perform some logging or show user feedback
return null;
}
// try to retrieve the image from the media store first
// this will only work for images selected from gallery
String[] projection = { MediaStore.Images.Media.DATA };
Cursor cursor = managedQuery(uri, projection, null, null, null);
if( cursor != null ){
int column_index = cursor
.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
return cursor.getString(column_index);
}
// this is our fallback here
return uri.getPath();
}
add permission in manifest
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
this way you will get selected image in Base64 to string
Try this code-
Image will copy in SaveImage folder in sd card
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
switch(requestCode) {
case 1:
if(resultCode == RESULT_OK)
{
Uri selectedImageUri = data.getData();
String selectedImagePath = getPath(selectedImageUri);
File sel = new File(selectedImagePath);
Bitmap bitmap = BitmapFactory.decodeFile(sel.getAbsolutePath());
imageView1.setImageBitmap(bitmap);
SaveImage(bitmap);
}
break;
}
}
private void SaveImage(Bitmap finalBitmap) {
String root = Environment.getExternalStorageDirectory().toString();
File myDir = new File(root + "/SaveImage");
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);
finalBitmap.compress(Bitmap.CompressFormat.JPEG, 90, out);
out.flush();
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}

Implementing a File Picker in Android and copying the selected file to another location

I'm trying to implement a File Picker in my Android project. What I've been able to do so far is :
Intent chooseFile;
Intent intent;
chooseFile = new Intent(Intent.ACTION_GET_CONTENT);
chooseFile.setType("*/*");
intent = Intent.createChooser(chooseFile, "Choose a file");
startActivityForResult(intent, PICKFILE_RESULT_CODE);
And then in my onActivityResult()
switch(requestCode){
case PICKFILE_RESULT_CODE:
if(resultCode==-1){
Uri uri = data.getData();
String filePath = uri.getPath();
Toast.makeText(getActivity(), filePath,
Toast.LENGTH_LONG).show();
}
break;
}
This is opening a file picker, but its not what I want. For example, I want to select a file (.txt), and then get that File and then use it. With this code I thought I would get the full path but it doesn't happen; for example I get: /document/5318/. But with this path I can't get the file. I've created a method called PathToFile() that returns a File :
private File PathToFile(String path) {
File tempFileToUpload;
tempFileToUpload = new File(path);
return tempFileToUpload;
}
What I'm trying to do is let the user choose a File from anywhere means DropBox, Drive, SDCard, Mega, etc... And I don't find the way to do it correctly, I tried to get the Path then get a File by this Path... but it doesn't work, so I think it's better to get the File itself, and then with this File programmatically I Copy this or Delete.
EDIT (Current code)
My Intent
Intent chooseFile = new Intent(Intent.ACTION_GET_CONTENT);
chooseFile.addCategory(Intent.CATEGORY_OPENABLE);
chooseFile.setType("text/plain");
startActivityForResult(
Intent.createChooser(chooseFile, "Choose a file"),
PICKFILE_RESULT_CODE
);
There I've got a question because I don't know what is supported as text/plain, but I'm gonna investigate about it, but it doesn't matter at the moment.
On my onActivityResult() I've used the same as #Lukas Knuth answer, but I don't know if with it I can Copy this File to another part from my SDcard I'm waitting for his answer.
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == PICKFILE_RESULT_CODE && resultCode == Activity.RESULT_OK){
Uri content_describer = data.getData();
//get the path
Log.d("Path???", content_describer.getPath());
BufferedReader reader = null;
try {
// open the user-picked file for reading:
InputStream in = getActivity().getContentResolver().openInputStream(content_describer);
// now read the content:
reader = new BufferedReader(new InputStreamReader(in));
String line;
StringBuilder builder = new StringBuilder();
while ((line = reader.readLine()) != null){
builder.append(line);
}
// Do something with the content in
text.setText(builder.toString());
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
getPath() from #Y.S.
I'm doing this :
String[] projection = { MediaStore.Files.FileColumns.DATA };
Cursor cursor = getActivity().getContentResolver().query(content_describer, projection, null, null, null);
int column_index = cursor.getColumnIndexOrThrow(projection[0]);
cursor.moveToFirst();
cursor.close();
Log.d( "PATH-->",cursor.getString(column_index));
Is getting a NullPointerException :
java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=131073, result=-1, data=Intent { dat=file:///path typ=text/plain flg=0x3 }} to activity {info.androidhive.tabsswipe/info.androidhive.tabsswipe.MainActivity2}: java.lang.NullPointerException
EDIT with code working thanks to #Y.S., #Lukas Knuth, and #CommonsWare.
This is the Intent where I only accept files text/plain.
Intent chooseFile = new Intent(Intent.ACTION_GET_CONTENT);
chooseFile.addCategory(Intent.CATEGORY_OPENABLE);
chooseFile.setType("text/plain");
startActivityForResult(
Intent.createChooser(chooseFile, "Choose a file"),
PICKFILE_RESULT_CODE
);
On my onActivityResult() I create an URI where I get the data of the Intent, I create a File where I save the absolute path doing content_describer.getPath();, and then I keep the name of the path to use it in a TextView with content_describer.getLastPathSegment(); (that was awesome #Y.S. didn't know about that function), and I create a second File which I called destination and I send the AbsolutePath to can create this File.
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == PICKFILE_RESULT_CODE && resultCode == Activity.RESULT_OK){
Uri content_describer = data.getData();
String src = content_describer.getPath();
source = new File(src);
Log.d("src is ", source.toString());
String filename = content_describer.getLastPathSegment();
text.setText(filename);
Log.d("FileName is ",filename);
destination = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/Test/TestTest/" + filename);
Log.d("Destination is ", destination.toString());
SetToFolder.setEnabled(true);
}
}
Also I've created a function that you have to send the source file, and destination file that we have created previously to copy this to the new folder.
private void copy(File source, File destination) throws IOException {
FileChannel in = new FileInputStream(source).getChannel();
FileChannel out = new FileOutputStream(destination).getChannel();
try {
in.transferTo(0, in.size(), out);
} catch(Exception e){
Log.d("Exception", e.toString());
} finally {
if (in != null)
in.close();
if (out != null)
out.close();
}
}
Also I've created a function that says to me if this folder exist or not (I have to send the destination file, if it doesn't exist I create this folder and if it does not I do not do nothing.
private void DirectoryExist (File destination) {
if(!destination.isDirectory()) {
if(destination.mkdirs()){
Log.d("Carpeta creada","....");
}else{
Log.d("Carpeta no creada","....");
}
}
Thanks again for your help, hope you enjoy this code made with everyone of you guys :)
STEP 1 - Use an Implicit Intent:
To choose a file from the device, you should use an implicit Intent
Intent chooseFile = new Intent(Intent.ACTION_GET_CONTENT);
chooseFile.setType("*/*");
chooseFile = Intent.createChooser(chooseFile, "Choose a file");
startActivityForResult(chooseFile, PICKFILE_RESULT_CODE);
STEP 2 - Get the absolute file path:
To get the file path from a Uri, first, try using
Uri uri = data.getData();
String src = uri.getPath();
where data is the Intent returned in onActivityResult().
If that doesn't work, use the following method:
public String getPath(Uri uri) {
String path = null;
String[] projection = { MediaStore.Files.FileColumns.DATA };
Cursor cursor = getContentResolver().query(uri, projection, null, null, null);
if(cursor == null){
path = uri.getPath()
}
else{
cursor.moveToFirst();
int column_index = cursor.getColumnIndexOrThrow(projection[0]);
path = cursor.getString(column_index);
cursor.close();
}
return ((path == null || path.isEmpty()) ? (uri.getPath()) : path);
}
At least one of these two methods should get you the correct, full path.
STEP 3 - Copy the file:
What you want, I believe, is to copy a file from one location to another.
To do this, it is necessary to have the absolute file path of both the source and destination locations.
First, get the absolute file path using either my getPath() method or uri.getPath():
String src = getPath(uri); /* Method defined above. */
or
Uri uri = data.getData();
String src = uri.getPath();
Then, create two File objects as follows:
File source = new File(src);
String filename = uri.getLastPathSegment();
File destination = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/CustomFolder/" + filename);
where CustomFolder is the directory on your external drive where you want to copy the file.
Then use the following method to copy a file from one place to another:
private void copy(File source, File destination) {
FileChannel in = new FileInputStream(source).getChannel();
FileChannel out = new FileOutputStream(destination).getChannel();
try {
in.transferTo(0, in.size(), out);
} catch(Exception){
// post to log
} finally {
if (in != null)
in.close();
if (out != null)
out.close();
}
}
Try this. This should work.
Note: Vis-a-vis Lukas' answer - what he has done is use a method called openInputStream() that returns the content of a Uri, whether that Uri represents a file or a URL.
Another promising approach - the FileProvider:
There is one more way through which it is possible to get a file from another app. If an app shares its files through the FileProvider, then it is possible to get hold of a FileDescriptor object which holds specific information about this file.
To do this, use the following Intent:
Intent mRequestFileIntent = new Intent(Intent.ACTION_GET_CONTENT);
mRequestFileIntent.setType("*/*");
startActivityForResult(mRequestFileIntent, 0);
and in your onActivityResult():
#Override
public void onActivityResult(int requestCode, int resultCode,
Intent returnIntent) {
// If the selection didn't work
if (resultCode != RESULT_OK) {
// Exit without doing anything else
return;
} else {
// Get the file's content URI from the incoming Intent
Uri returnUri = returnIntent.getData();
/*
* Try to open the file for "read" access using the
* returned URI. If the file isn't found, write to the
* error log and return.
*/
try {
/*
* Get the content resolver instance for this context, and use it
* to get a ParcelFileDescriptor for the file.
*/
mInputPFD = getContentResolver().openFileDescriptor(returnUri, "r");
} catch (FileNotFoundException e) {
e.printStackTrace();
Log.e("MainActivity", "File not found.");
return;
}
// Get a regular file descriptor for the file
FileDescriptor fd = mInputPFD.getFileDescriptor();
...
}
}
where mInputPFD is a ParcelFileDescriptor.
References:
1. Common Intents - File Storage.
2. FileChannel.
3. FileProvider.
4. Requesting a Shared File.
As #CommonsWare already noted, Android returns you a Uri, which is a more abstract concept than a file-path.
It can describe a simple file-path too, but it can also describe a resource that is accessed through an application (like content://media/external/audio/media/710).
If you want your user to pick any file from the phone to read it from your application, you can do so by asking for the file (as you did correctly) and then use the ContentResolver to get an InputStream for the Uri that is returned by the picker.
Here is an example:
Intent chooseFile = new Intent(Intent.ACTION_GET_CONTENT);
// Ask specifically for something that can be opened:
chooseFile.addCategory(Intent.CATEGORY_OPENABLE);
chooseFile.setType("*/*");
startActivityForResult(
Intent.createChooser(chooseFile, "Choose a file"),
PICKFILE_REQUEST_CODE
);
// And then somewhere, in your activity:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == PICKFILE_REQUEST_CODE && resultCode == RESULT_OK){
Uri content_describer = data.getData();
BufferedReader reader = null;
try {
// open the user-picked file for reading:
InputStream in = getContentResolver().openInputStream(content_describer);
// now read the content:
reader = new BufferedReader(new InputStreamReader(in));
String line;
StringBuilder builder = new StringBuilder();
while ((line = reader.readLine()) != null){
builder.append(line);
}
// Do something with the content in
some_view.setText(builder.toString());
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
Important: Some providers (like Dropbox) store/cache their data on the external storage. You'll need to have the android.permission.READ_EXTERNAL_STORAGE-permission declared in your manifest, otherwise you'll get FileNotFoundException, even though the file is there.
Update: Yes, you can copy the file by reading it from one stream and writing it to another:
// Error handling is omitted for shorter code!
Uri content_describer = data.getData();
InputStream in = null;
OutputStream out = null;
try {
// open the user-picked file for reading:
in = getContentResolver().openInputStream(content_describer);
// open the output-file:
out = new FileOutputStream(new File("some/path/to/a/writable/file"));
// copy the content:
byte[] buffer = new byte[1024];
int len;
while ((len = in.read(buffer)) != -1) {
out.write(buffer, 0, len);
}
// Contents are copied!
} finally {
if (in != null) {
in.close();
}
if (out != null){
out.close();
}
}
Deleting the file is probably not possible, since the file doesn't belong to you, it belongs to the application that shared it with yours. Therefor, the owning application is responsible for deleting the file.
With ActivityResultLauncher it works alike this:
ActivityResultLauncher<Intent> startActivityForResult = requireActivity().registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), result -> {
if (result.getResultCode() == Activity.RESULT_OK) {
Intent data = result.getData();
Uri contentUri = data.getData();
...
}
});
Usage example:
Intent data = new Intent(Intent.ACTION_GET_CONTENT);
data.addCategory(Intent.CATEGORY_OPENABLE);
data.setType("*/*");
Intent intent = Intent.createChooser(data, "Choose a file");
startActivityForResult.launch(intent);
The following dependency is required (with or without -ktx):
implementation "androidx.activity:activity:1.5.0"
I did the same to let the user choose an image from a folder :
1) there is a button OPEN:
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_open:
myOpenImagePicker();
break;
}
}
2) the open image folder function:
#SuppressLint("InlinedApi")
public void myOpenImagePicker() {
if (Build.VERSION.SDK_INT < 19) {
Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(
Intent.createChooser(intent, "Select Picture"),
SELECT_FOLDER);
} else {
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("image/*");
startActivityForResult(intent, SELECT_FOLDER);
}
}
3) the activity result where i get the image file path and do whatever i want with the image path:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case SELECT_FOLDER:
if (resultCode == RESULT_OK && data != null) {
Uri originalUri = data.getData();
String id01 = W_ImgFilePathUtil.getPath(
getApplicationContext(), originalUri);
Bitmap unscaledBitmap = W_ImgScalingUtil.decodeResource(id01,
xdrawing.getViewWidth(), xdrawing.getViewHeight(),
ScalingLogic.FIT);
if (unscaledBitmap == null) {
zprefsutil.ShowToast("IMAGE ERROR", 1);
} else {
setExternalScaledBitmap(W_ImgScalingUtil
.createScaledBitmap(unscaledBitmap,
xdrawing.getViewWidth(),
xdrawing.getViewHeight(), ScalingLogic.FIT));
unscaledBitmap.recycle();
xdrawing.invalidate();
}
}
break;
default:
break;
}
}
4) and now the MOST IMPORTANT PART, the W_ImgFilePathUtil class, the code is not from me but it allows you to retrieve the full path of any selected file be it on sd card, google drive, ...:
public class W_ImgFilePathUtil {
/**
* Method for return file path of Gallery image
*
* #param context
* #param uri
* #return path of the selected image file from gallery
*/
#SuppressLint("NewApi")
public static String getPath(final Context context, final Uri uri) {
// check here to KITKAT or new version
final boolean isKitKatorUp = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
// DocumentProvider
if (isKitKatorUp && DocumentsContract.isDocumentUri(context, uri)) {
// ExternalStorageProvider
if (isExternalStorageDocument(uri)) {
final String docId = DocumentsContract.getDocumentId(uri);
final String[] split = docId.split(":");
final String type = split[0];
if ("primary".equalsIgnoreCase(type)) {
return Environment.getExternalStorageDirectory() + "/"
+ split[1];
}
}
// DownloadsProvider
else if (isDownloadsDocument(uri)) {
final String id = DocumentsContract.getDocumentId(uri);
final Uri contentUri = ContentUris.withAppendedId(
Uri.parse("content://downloads/public_downloads"),
Long.valueOf(id));
return getDataColumn(context, contentUri, null, null);
}
// MediaProvider
else if (isMediaDocument(uri)) {
final String docId = DocumentsContract.getDocumentId(uri);
final String[] split = docId.split(":");
final String type = split[0];
Uri contentUri = null;
if ("image".equals(type)) {
contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
} else if ("video".equals(type)) {
contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
} else if ("audio".equals(type)) {
contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
}
final String selection = "_id=?";
final String[] selectionArgs = new String[] { split[1] };
return getDataColumn(context, contentUri, selection,
selectionArgs);
}
}
// MediaStore (and general)
else if ("content".equalsIgnoreCase(uri.getScheme())) {
// Return the remote address
if (isGooglePhotosUri(uri))
return uri.getLastPathSegment();
return getDataColumn(context, uri, null, null);
}
// File
else if ("file".equalsIgnoreCase(uri.getScheme())) {
return uri.getPath();
}
return null;
}
/**
* Get the value of the data column for this Uri. This is useful for
* MediaStore Uris, and other file-based ContentProviders.
*
* #param context
* The context.
* #param uri
* The Uri to query.
* #param selection
* (Optional) Filter used in the query.
* #param selectionArgs
* (Optional) Selection arguments used in the query.
* #return The value of the _data column, which is typically a file path.
*/
public static String getDataColumn(Context context, Uri uri,
String selection, String[] selectionArgs) {
Cursor cursor = null;
final String column = "_data";
final String[] projection = { column };
try {
cursor = context.getContentResolver().query(uri, projection,
selection, selectionArgs, null);
if (cursor != null && cursor.moveToFirst()) {
final int index = cursor.getColumnIndexOrThrow(column);
return cursor.getString(index);
}
} finally {
if (cursor != null)
cursor.close();
}
return null;
}
/**
* #param uri
* The Uri to check.
* #return Whether the Uri authority is ExternalStorageProvider.
*/
public static boolean isExternalStorageDocument(Uri uri) {
return "com.android.externalstorage.documents".equals(uri
.getAuthority());
}
/**
* #param uri
* The Uri to check.
* #return Whether the Uri authority is DownloadsProvider.
*/
public static boolean isDownloadsDocument(Uri uri) {
return "com.android.providers.downloads.documents".equals(uri
.getAuthority());
}
/**
* #param uri
* The Uri to check.
* #return Whether the Uri authority is MediaProvider.
*/
public static boolean isMediaDocument(Uri uri) {
return "com.android.providers.media.documents".equals(uri
.getAuthority());
}
/**
* #param uri
* The Uri to check.
* #return Whether the Uri authority is Google Photos.
*/
public static boolean isGooglePhotosUri(Uri uri) {
return "com.google.android.apps.photos.content".equals(uri
.getAuthority());
}
}
CONCLUSION : the code works with image path but sure works with any kind of file.
Hope this helps solve your problem.
PEACE.
A Uri is not a file. A Uri is closer to a Web server URL. It is an opaque address, which only has meaning to the "server" (or in this case, the ContentProvider).
Just as you use an InputStream to read in the bytes represented by a Web URL, you use an InputStream to read in the bytes represented by the Uri. You get such a stream by calling openInputStream() on a ContentResolver.
Here is how to implement a file picker and move the selected file into another location (e.g picture).
Firstly, add a file picker with a button on click listener to your code like this:
A button to pick file:
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_choose_file:
showFileChooser();
break;
}
}
private String filePath = null;
private File sourceFile;
private static final int FILE_SELECT_CODE = 0;
private void showFileChooser() {
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("*/*");
intent.addCategory(Intent.CATEGORY_OPENABLE);
try {
startActivityForResult(
Intent.createChooser(intent, "Select a File to Copy"),
FILE_SELECT_CODE);
} catch (android.content.ActivityNotFoundException ex) {
Toast.makeText(this, "Please install a File Manager.",
Toast.LENGTH_SHORT).show();
}
}
Then handle onActivityResult like this:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case FILE_SELECT_CODE:
if (resultCode == RESULT_OK) {
// Get the Uri of the selected file
Uri uri = data.getData();
File file = new File(getCacheDir(), getFileName(uri));
int maxBufferSize = 1 * 1024 * 1024;
try {
InputStream inputStream = getContentResolver().openInputStream(uri);
Log.e("InputStream Size","Size " + inputStream);
int bytesAvailable = inputStream.available();
int bufferSize = Math.min(bytesAvailable, maxBufferSize);
final byte[] buffers = new byte[bufferSize];
FileOutputStream outputStream = new FileOutputStream(file);
int read = 0;
while ((read = inputStream.read(buffers)) != -1) {
outputStream.write(buffers, 0, read);
}
Log.e("File Size","Size " + file.length());
inputStream.close();
outputStream.close();
file.getPath();
Log.e("File Path","Path " + file.getPath());
file.length();
Log.e("File Size","Size " + file.length());
if(file.length() > 0){
sourceFile = file;
saveFile(sourceFile);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (OutOfMemoryError e) {
e.printStackTrace();
}
} else {
}
break;
}
super.onActivityResult(requestCode, resultCode, data);
}
private void saveFile (File sourceFile) {
try {
File currentFile = sourceFile;
Bitmap myBitmap = BitmapFactory.decodeFile(currentFile.getAbsolutePath());
String path = currentFile.getAbsolutePath();
String idStr = path.substring(path.lastIndexOf('/') + 1);
File filepath = Environment.getExternalStorageDirectory();
File dir = new File(filepath.getAbsolutePath() + "/" + "yourFolderName" + "/");
if (!dir.exists()) {
dir.mkdirs();
}
String fileName = currentFile.getName();
file = new File(dir, fileName);
if (file.exists()) file.delete();
FileOutputStream fos = new FileOutputStream(file);
myBitmap.compress(CompressFormat.JPEG, 65, fos);
fos.flush();
fos.close();
} catch (Exception e) {
e.printStackTrace();
}
}
Note: Don't forget to add this permission to the manifest file.
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Hope this helps.
Pass the URI returned in onActivityResult in this method
private String getPath(Uri contentURI) {
String result;
Cursor cursor = getActivity().getContentResolver().query(contentURI,
null, null, null, null);
if (cursor == null) {
result = contentURI.getPath();
} else {
cursor.moveToFirst();
int idx = cursor
.getColumnIndex(MediaStore.Images.ImageColumns.DATA);
result = cursor.getString(idx);
cursor.close();
}
return result;
}
Here's how you do it in newer Android versions:
private ActivityResultLauncher<String> filePicker;
//execute this in your AppCompatActivity onCreate
public void registerFilePicker() {
filePicker = registerForActivityResult(
new ActivityResultContracts.GetContent(),
uri -> onPickFile(uri)
);
}
//execute this to launch the picker
public void openFilePicker() {
String mimeType = "*/*";
filePicker.launch(mimeType);
}
//this gets executed when the user picks a file
public void onPickFile(Uri uri) {
try (InputStream inputStream = getContentResolver().openInputStream(uri)) {
} catch (IOException exception) {
}
}
More info: https://developer.android.com/training/basics/intents/result

Categories

Resources