How to get Exif data from an InputStream rather than a File? - android

The reason why I am asking this is because the callback of the file chooser Intent returns an Uri.
Open file chooser via Intent:
Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(intent, "Select Picture"), CHOOSE_IMAGE_REQUEST);
Callback:
#Override
public void onActivityResult(int requestCode, int resultCode, final Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == CHOOSE_IMAGE_REQUEST && resultCode == Activity.RESULT_OK) {
if (data == null) {
// Error
return;
}
Uri fileUri = data.getData();
InputStream in = getContentResolver().openInputStream(fileUri);
// How to determine image orientation through Exif data here?
}
}
One way would be to write the InputStream to an actual File, but this seems like a bad workaround for me.

After the 25.1.0 support library was introduced, now is possible to read exif data from URI contents (content:// or file://) through an InputStream.
Example:
First add this line to your gradle file:
compile 'com.android.support:exifinterface:25.1.0'
Uri uri; // the URI you've received from the other app
InputStream in;
try {
in = getContentResolver().openInputStream(uri);
ExifInterface exifInterface = new ExifInterface(in);
// Now you can extract any Exif tag you want
// Assuming the image is a JPEG or supported raw format
} catch (IOException e) {
// Handle any errors
} finally {
if (in != null) {
try {
in.close();
} catch (IOException ignored) {}
}
}
For more information check: Introducing the ExifInterface Support Library, ExifInterface.

Related

I want take uri from selected file

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();
}
}
this code lead me to select file and i want take uri of selected file,
Hi once you get your image you need to trigger and retrieve image data using onActivityResult like this, have a dedicated result code for this operation. rough example below to give u idea
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data)
{
if (resultCode == Activity.RESULT_OK) {
Uri uri = data.getData(); // ur raw file data convert to anything u want
try {
//for images
Bitmap bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), uri);
imageView.set(bitmap) //example , you can choose what you want to with bitmap
//for files
InputStream inputStream;
File file = null;
try {
inputStream = getContentResolver().openInputStream(Uri.parse(your URI));
file = new File(String.valueOf(inputStream));
}catch (Exception e){
}
}catch (IOException e) {
e.printStackTrace();
}

Android storage access framework returning "raw" path

Trying to use the Storage access framework to select a file from the device (an html file that I wan't to parse) but it returns a file path that doesn't appear to be a content URI (/document/raw:/storage/emulated/0/Download/test.html) and that errors when I use it with the content resolver.
Intent to fetch file:
boolean alreadyHasReadPermissions = hasPermission(Manifest.permission.READ_EXTERNAL_STORAGE);
if (alreadyHasReadPermissions) {
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("text/html");
try {
activity.startActivityForResult(intent, fileChooserResultCode);
}catch(ActivityNotFoundException e){
Toast.makeText(activity, R.string.unable_to_open_file_picker, Toast.LENGTH_LONG).show();
}
}
Code to read a file:
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode==fileChooserResultCode){
if(resultCode == Activity.RESULT_OK && data.getData()!=null) {
String contentUriString = data.getData().getPath();
try {
Uri contentUri = Uri.parse(contentUriString);
InputStream inputStream = getContentResolver().openInputStream(contentUri); // <<< Errors with FileNotFoundException
BufferedReader bf = new BufferedReader(new InputStreamReader(inputStream));
...
}catch (NullPointerException | IOException e){
Toast.makeText(this, R.string.unable_to_open_file, Toast.LENGTH_LONG).show();
}
}
}
}
Delete:
String contentUriString = data.getData().getPath();
and delete:
Uri contentUri = Uri.parse(contentUriString);
And change:
InputStream inputStream = getContentResolver().openInputStream(contentUri);
to:
InputStream inputStream = getContentResolver().openInputStream(data.getData());
IOW, do not call getPath() on a Uri.

SAF - ACTION_CREATE_DOCUMENT - after I save the file on Drive the file is empty

I am a beginner in SAF. What I'm trying to do is super simple to save a config. Let's say the file is .conf.
I copy .conf to conf.txt and I save it on Drive.
Here is my code:
tools.deleteFile(dst); // delete conf.txt if it exists
int res = tools.copyFile(src,dst); // copy .conf to conf.txt
if(res == -1) return;
tools.viewFile(dst);
// verify in Log info that the content of cnf.txt is correct
Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("text/plain");
intent.putExtra(Intent.EXTRA_TITLE, dst);
startActivity(intent);
I do a save in Drive. The file appears on my pc but when I open it, it's empty.
When I do the inverse: ACTION_OPEN_DOCUMENT
public void onActivityResult(int requestCode, int resultCode,
Intent resultData) {
Uri uri;
if (resultCode == Activity.RESULT_OK){
if (requestCode == 30){
if (resultData != null) {
uri = resultData.getData();
try {
String content =
readFile(uri);
} catch (IOException e) {
e.printStackTrace();
}
The function readFile opens the file and stops while reading because there is no data.
What did I do wrong?
The Intent(Intent.ACTION_CREATE_DOCUMENT) is for CREATING text file, and use onActivityResult() to get the uri (location) from the file, THEN you use OutputStream to WRITE data (byte[]) to the file.
private void createAndSaveFile() {
Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("text/plain");
intent.putExtra(Intent.EXTRA_TITLE, "testFileSam.txt");
startActivityForResult(intent, 1);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, #Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 1) {
if (resultCode == RESULT_OK) {
try {
Uri uri = data.getData();
OutputStream outputStream = getContentResolver().openOutputStream(uri);
outputStream.write("Hi, welcome to Sam's Android classroom! Have a good day!".getBytes());
outputStream.close();
Toast.makeText(this, "Write file successfully", Toast.LENGTH_SHORT).show();
} catch (IOException e) {
Toast.makeText(this, "Fail to write file", Toast.LENGTH_SHORT).show();
}
} else {
Toast.makeText(this, "File not saved", Toast.LENGTH_SHORT).show();
}
}
}
You are just creating the document but not writing it.
Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("text/plain");
intent.putExtra(Intent.EXTRA_TITLE, dst);
startActivity(intent);
this will create document and return the uri of the document to your app.
Now you need to write something to this uri that you will get in onActivityResult
#Override
protected void onActivityResult(int requestCode, int resultCode, #Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 1) {
if (resultCode == RESULT_OK) {
try {
Uri uri = data.getData();
OutputStream outputStream = getContentResolver().openOutputStream(uri);
outputStream.write("Hi, welcome to Sam's Android classroom! Have a good day!".getBytes());
outputStream.close(); // very important
} catch (IOException e) {
e.printStackTrace();
}
}
}
}

Choose a pdf from sdcard and convert it to byte array in android studio

I need to choose a pdf from sdcard and convert it to byte array. I don't want to show it . I searched a lot but there was no answer to this question.
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == SELECT_MAGAZINE_FILE && resultCode == RESULT_OK && data != null) {
// Let's read picked image data - its URI
Uri uri = data.getData();
System.out.println(uri);
System.out.println(uri.getPath());
File file = new File(uri.getPath());
//init array with file length
byte[] bytesArray = new byte[(int) file.length()];
FileInputStream fis = null;
try {
fis = new FileInputStream(file);
fis.read(bytesArray); //read file into bytes[]
fis.close();
System.out.println(bytesArray);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
and I got this error :
java.io.FileNotFoundException: /document/primary:myfile.pdf: open failed: ENOENT (No such file or directory)
At best, your code will only work if the Uri being delivered to onActivityResult() happens to have a file scheme. Yours does not. It has a content scheme. Your code will also fail a lot due to an OutOfMemoryError, because your code fails to allocate the byte[]. PDF files can be rather large.
So, your first task is to find some other solution instead of reading the entire PDF file into a byte[], as this will be unreliable, and there is nothing that you can do to fix that, other than by not doing it.
Eventually, to get an InputStream on the content identified by the Uri, use a ContentResolver and openInputStream().
And, in the long term, you need to move this I/O to a background thread, as right now you will freeze your UI for the time that it takes you to read in the data.
Note that the use of ContentResolver for Uri values, and the use of threads, is covered in any decent book or course on Android app development.
Thanks https://stackoverflow.com/users/115145/commonsware for your help.
I changed my code to this and it works. It is better to do it with AsyncTask.
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == SELECT_MAGAZINE_FILE && resultCode == RESULT_OK && data != null) {
// Let's read picked image data - its URI
Uri uri = data.getData();
File file = new File(uri.getPath());
try {
InputStream is = getActivity().getContentResolver().openInputStream(uri);
byte[] bytesArray = new byte[is.available()];
is.read(bytesArray);
//write to sdcard
/*
File myPdf=new File(Environment.getExternalStorageDirectory(), "myPdf.pdf");
FileOutputStream fos=new FileOutputStream(myPdf.getPath());
fos.write(bytesArray);
fos.close();*/
System.out.println(fileString);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == RESULT_LOAD_IMAGE && resultCode == RESULT_OK) {
Bundle extras = data.getExtras();
Bitmap imageBitmap = (Bitmap) extras.get("data");
Log.d("++++++++++", "++++ data log +++" + imageBitmap);
}
}

Retrieving a photo from photo gallery

I have found this code and trying to implement in my application, it open the gallery, let's me select a photo, then the applications stops working and closes.
It's my first time trying to upload an image to mysql, and i'm stuck at the very beginning.
buttonChoose.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v)
{
showFileChooser();
}
});
private void showFileChooser() {
Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(intent, "Select Picture"), PICK_IMAGE_REQUEST);
}
#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 filePath = data.getData();
try
{
bitmap = MediaStore.Images.Media.getBitmap(MainActivity.this.getContentResolver(), filePath);
} catch (IOException e) {
e.printStackTrace();
}
imageView.setImageBitmap(bitmap);
}
}
Uri filePath = data.getData();
This will be meaningless for most Uri values.
The best solution to populate an ImageView from a Uri is by using a third-party image loading library, such as Picasso.
If you insist upon doing this yourself, you will need to fork a background thread, use a ContentResolver and openInputStream() to get an InputStream on the content backed by the Uri, use BitmapFactory and decodeStream() to get a Bitmap, then (on the main application thread) update the ImageView with the Bitmap.

Categories

Resources