I am having an issue, I have never had problem opening files via ACTION_VIEW the next way:
File file = new File(getActivity().getFilesDir(), TEMP_FILE_NAME);
String dataType = "image/*";
if (file.exists()) {
Intent fileIntent = new Intent(Intent.ACTION_VIEW);
fileIntent.setDataAndType(Uri.fromFile(file), dataType);
fileIntent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
Intent intent = Intent.createChooser(fileIntent, "Open file");
try {
startActivity(intent);
} catch (ActivityNotFoundException e) {
e.printStackTrace();
Log.e(TAG, "There is a problem when opening the file");
}
} else {
Toast.makeText(getContext(), "Invalido", Toast.LENGTH_LONG).show();
}
The problem I am having right now is that even though the file exists when I choose the app to open the file it immediately closes and tells me Not found. I have put the image I am loading in an image view and there is no problem, so the file is valid but for some reason it has conflicts when I am opening it via intent.
I am aware that it may have something to do with the way I am creating the file, I am retrieving it from Google drive so I am writing the file using the Apache Commons library the next way:
DriveContents contents = result.getDriveContents();
InputStream inputStream = contents.getInputStream();
File file = new File(getActivity().getFilesDir(), TEMP_FILE_NAME);
try {
OutputStream outputStream = new FileOutputStream(file);
IOUtils.copy(inputStream, outputStream);
IOUtils.closeQuietly(inputStream);
IOUtils.closeQuietly(outputStream);
} catch (IOException e) {
e.printStackTrace();
}
What is it I am doing wrong? I am not totally sure if the problem has to do with the copy method executing asynchronously or something like that.
Thanks in advance.
I have never had problem opening files via ACTION_VIEW the next way
That code will never work, as third-party apps have no rights to work with files on getFilesDir() of your app.
What is it I am doing wrong?
You are attempting to serve an inaccessible file to third-party programs. Use FileProvider to serve the file, using FileProvider.getUriForFile() to get the Uri to use in your ACTION_VIEW Intent.
Related
I am used to opening my files in my apps using the next code:
public void openFile(#NonNull String uri) {
checkNotNull(uri);
File file = new File(uri);
String dataType = null;
if (ContentTypeUtils.isPdf(uri)) dataType = "application/pdf";
else if (ContentTypeUtils.isImage(uri)) dataType = "image/*";
if (file.exists() && dataType != null) {
Intent target = new Intent(Intent.ACTION_VIEW);
target.setDataAndType(Uri.fromFile(file), dataType);
target.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
Intent intent = Intent.createChooser(target, "Open file");
try {
startActivity(intent);
} catch (ActivityNotFoundException e) {
e.printStackTrace();
Log.e(TAG, "There is a problem when opening the file :(");
}
} else {
Toast.makeText(getContext(), "Invalido", Toast.LENGTH_LONG).show();
}
}
I had always used static files so this was enough, but now I am using the Google Drive SDK for Android. I possess the driveId of the file I want to open but the problem is I cannot find a clean way to open the file contents I obtain by doing this:
Drive.DriveApi.fetchDriveId(mGoogleApiClient, documentFile.getDriveId())
.setResultCallback(driveIdResult -> {
PendingResult<DriveApi.DriveContentsResult> open =
driveIdResult.getDriveId().asDriveFile().open(
mGoogleApiClient,
DriveFile.MODE_READ_ONLY,
null);
open.setResultCallback(result -> {
DriveContents contents = result.getDriveContents();
InputStream inputStream = contents.getInputStream();
// I know I can get the input stream, and use it to write a new file.
});
});
So the only thing that comes to my mind is creating a static route to create a file every time I have to open it, and erasing it every time I have to open a new file.
What I have understood up until now is that the Google Drive API for Android already saves an instance of the file so what I have in mind sounds unnecessary, I would like to know if there is a better way to achieve this. Is there a way I can open the file and do something similar to what I do with the Intent.ACTION_VIEW in a cleaner way?
Thanks in advance.
Well since it seems this will not be answered I will post what I did. All I did was create a temp file where I put my contents to be read. I still don't know if it was the best choice so this question will still be opened for a better answer.
open.setResultCallback(result -> {
DriveContents contents = result.getDriveContents();
InputStream inputStream = contents.getInputStream();
writeTempFile(inputStream);
});
And here the implementation of the `writeTempFile`:
private synchronized File writeTempFile(#NonNull InputStream inputStream) {
checkNotNull(inputStream);
File filePath = new File(mActivity.getFilesDir(), "TempFiles");
if (!filePath.exists()) filePath.mkdirs();
File file = new File(filePath, TEMP_FILE);
try {
OutputStream outputStream = new FileOutputStream(file);
IOUtils.copyLarge(inputStream, outputStream);
IOUtils.closeQuietly(inputStream);
IOUtils.closeQuietly(outputStream);
} catch (IOException e) {
e.printStackTrace();
}
return file;
}
I have a string (called comments) that contains some text that I want to display using an external app. I initially create the file like so:
String end = "rtf";
FileOutputStream outputStream;
try {
outputStream = openFileOutput("document." + end, Context.MODE_PRIVATE);
outputStream.write(comments.getBytes());
outputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
However I am unable to open the file with an external application when I try the following:
String type = "text/rtf";
Intent intent = new Intent (Intent.ACTION_VIEW);
File file = new File(getFilesDir() + "/document." + end);
Uri fileUri = Uri.fromFile(file);
intent.setDataAndType(fileUri,type);
startActivityForResult(intent, Intent.FLAG_GRANT_READ_URI_PERMISSION);
The message that I receive when I open try to the document with the external app is:
"open failed: EACCESS (Permission denied)."
Please advise. Thanks.
However I am unable to open the file with an external application when I try the following:
Correct. Intent.FLAG_GRANT_READ_URI_PERMISSION is for use with a ContentProvider, not for bare file:// Uri values, such as you are using. Use FileProvider to add such a ContentProvider to your app. See also the "Sharing Files" training module and this sample app.
Bear in mind that there's a good chance that your next problem will be an ActivityNotFoundException, as relatively few Android devices will have an app that will support the text/rtf MIME type.
I'm programming an app that receives all kind of documents as base64 strings. I've been searching all morning, and I didn't find a way to display the documents properly without storing them. As an alternative I wrote this:
private void createReadableFile(DocumentBinary document) {
try {
byte[] bytes = Base64.decode(document.getDocument(), 0);
FileOutputStream os = openFileOutput(document.getSuggestedFileName(), MODE_PRIVATE);
os.write(bytes);
os.flush();
os.close();
openFile(document);
} catch (Exception e) {
Ln.e(e, "Error while parsing document");
}
}
And I do this with the created file:
private void openFile(File file, String mimeType) {
Intent viewIntent = new Intent();
viewIntent.setAction(Intent.ACTION_VIEW);
viewIntent.setDataAndType(Uri.fromFile(file), mimeType);
viewIntent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
startActivity(viewIntent);
}
But it doesn't start anything. It calls onPause and onResume but nothing happens. I know that if I change MODE_PRIVATE to MODE_WORLD_READABLE it would work, but MODE_WORLD_READABLE is deprecated. Do you know a better way to do it or what to use instead of MODE_PRIVATE?
Save the file to external storage, or
Use FileProvider to create a ContentProvider that serves the file from internal storage, or
Create your own ContentProvider that implements openFile() and serves up a stream of content from some other source
hi i am new to android development. i manually kept a pdf file in emulator sdcard through ddms, and i also installed "adobe reader" in emulator when i tried to read the pdf file in emulator
with the following code
File file =
new File(Environment.getExternalStorageDirectory().getAbsolutePath()+"/iTunes Connect.pdf");
Uri path = Uri.fromFile(file);
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.setDataAndType(path,"application/pdf");
try
{
startActivity(intent);
}
catch (ActivityNotFoundException e)
{
Toast.makeText(xv.this,
getString(R.string.app_name),
Toast.LENGTH_SHORT).show();
}
i am getting the file path is not valid error.
can any one help me in this.
use %20(for white space) in between iTunes and 20Connect.pdf.
File file = new File(Environment.getExternalStorageDirectory().getAbsolutePath()+"/iTunes%20Connect.pdf");
I think this will solve your problem
try out this path
File file=new File("/sdcard/iTunes Connect.pdf");
I think this will work for u
I think you should not use hard coded file paths.
The framework will give you the base path of the area you want to save files to.
For SD card you should, use Environment.getExternalStorageDirectory()
local files you should, use Context.getFilesDir() (or Context.openFileOutput(String name, int mode), etc)
local cache you should, use Context.getCacheDir()
For emulator you can try File file=new File("mnt/sdcard/iTunes Connect.pdf");
I think that your emulator have not adob reader install please check first it is install or not
File file = new File(Environment.getExternalStorageDirectory().getAbsolutePath() +"/"+ filename);
Intent target = new Intent(Intent.ACTION_VIEW);
target.setDataAndType(Uri.fromFile(file),"application/pdf");
target.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
Intent intent = Intent.createChooser(target, "Open File");
try {
startActivity(intent);
} catch (ActivityNotFoundException e) {
// Instruct the user to install a PDF reader here, or something
} `enter code here`
I have made an app which downloads the pdf from the server and stores it in
/data/data/<package_name>files
using this code:
FileOutputStream fos = openFileOutput(pdfFileName, Context.MODE_WORLD_READABLE);
fos.write(pdfAsBytes);
fos.close();
But when reading these file from the pdf reader app which I already have on the device is sometimes showing black screen and sometimes displays the file with annoying fonts. The code I am using is:
File file = new File("/data/data/<package_Name>/files/pdffile");
Uri path = Uri.fromFile(file);
Intent pdfIntent = new Intent(Intent.ACTION_VIEW);
pdfIntent.setDataAndType(path, "application/pdf");
pdfIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
try
{
startActivity(pdfIntent);
}
catch(Exception e)
{
Log.e("Activity Not Found Exception",e.toString());
}
I have tried the same code with the same files at other path(in sdcard) they work fine.
Please help me and tell me what should have gone wrong.
What should be a possible way to correct it?
You should use method
android.content.Context.getFilesDir().
Returns the absolute path to the directory on the filesystem where files created with openFileOutput(String, int) are stored.
This code works for me:
File file = new File(this.getFilesDir(), pdfFileName);
Uri path = Uri.fromFile(file);
Intent pdfIntent = new Intent(Intent.ACTION_VIEW);
pdfIntent.setDataAndType(path, "application/pdf");
pdfIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
try {
startActivity(pdfIntent);
} catch(ActivityNotFoundException e) {
Log.e("Activity Not Found Exception",e.toString());
}
There are only 2 methods to achieve what you want:
1) Using SDCARD
You save downloaded pdf somewhere SDCARD. Something like this:
Instead of creating a file:
File pdfFile = new File(Environment.getExternalStorageDirectory(), "pdffile");
FileOutputStream fos = new FileOutputStream(pdfFile);
fos.write(pdfAsBytes);
fos.close();
...
And you use pdfFile when creating an Intent.
2) Using custom ContentProvider
The second method can be used if you still do not want to use your SDCARD storage. You can use your app's CacheDir (you will download your file there). This involves creating your own ContentProvider, and after that you will be able to pass corresponding URI to the pdfreader app.
Details on how to do this all are here.
There is no known other methods to open any downloaded file in 3rd party app in Android.