I have a simple question but can't seem to find the answer anywhere I look online.
I have an activity A that downloads files from the internet and puts them to a local folder obtained by getApplicationContext().getFilesDir().getPath() which points to: "/data/data/com.myapp.android/files"
Now when the user selects a file I want to show its content and for that I do the following:
File file = new File(filePath);
Uri uri = Uri.fromFile(file);
MimeTypeMap mime = MimeTypeMap.getSingleton();
String type = mime.getMimeTypeFromExtension(fileExtension);
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setAction(android.content.Intent.ACTION_VIEW);
intent.setDataAndType(uri, type);
Intent intentChooser = Intent.createChooser(intent, "Open File");
startActivity(intentChooser);
When this executes the user is presented with the Open File dialog and after they select "Gallery" the Gallery activity appears with nothing on it.
Looking at logcat I see the following:
E/PanoMetadata(17732): Could not read file: /data/data/com.myapp.android/files/downloads/Splash.png
E/PanoMetadata(17732): java.io.FileNotFoundException: /data/data/com.myapp.android/files/downloads/Splash.png: open failed: EACCES (Permission denied)
E/PanoMetadata(17732): at libcore.io.IoBridge.open(IoBridge.java:409)
E/PanoMetadata(17732): at java.io.FileInputStream.<init>(FileInputStream.java:78)
Note the "open failed: EACCES (Permission denied)"
But the file is really there and I can display it using my activity A without a problem.
The problem seems to be that the other activity which starts using ACTION_VIEW (in this case Gallery) seems to run under different process/user so it does not have read access to my file.
My 3 questions are:
Is it possible to get the ACTION_VIEW activity to run within my process and user context (of activity A)?
How do I share files between activities? (I do not like to copy the file under /sdcard/... but if that is the only option than it will have to be.)
Is there a way to pass the file content (not file pointer) from my activity to the Gallery activity or other activities?
Regards!
Is it possible to get the ACTION_VIEW activity to run within my process and user context (of activity A)?
No, nor would you want it to, for security reasons.
How do I share files between activities?
This question is the same as your next one, as far as I can tell.
Is there a way to pass the file content (not file pointer) from my activity to the Gallery activity or other activities?
The best solution is to use a ContentProvider. The simplest solution is to use FileProvider, which you can just add to your manifest and configure to serve up your files, without any need to create a subclass. See also: http://developer.android.com/training/secure-file-sharing/index.html
An app can't acces the private data of another app. Being that way, "Gallery" can't reach "data/data/com.myapp.android/files". You need to put the shared files directory in the external storage.
Related
DONT mark this as duplicate, before reading what I need.
I have seen many similar topics, but in none of them I've found solution.
I need the simplest thing: In my application I have button "View Media Files". After clicking that button, i need to be opened (with built-in File Explorer) this directory - SD_CARD/my_folder where are media files (and I want to click any of them and they should be opened in default Media player)..
I have used all suggested answers on SO , like this:
Intent intent = new Intent(Intent.ACTION_VIEW);
Uri mydir = Uri.parse("/sdcard/Recorder_Videos");
intent.setDataAndType(mydir, "*/*");
startActivity(intent);
but all they do: after clicking button, it opens "Choose File" menu:
(Where I cant still play media files when clicking)
The solution (not complete) I have found, was that I was missing file:// prefix. Here is my solution (however, it shows all kinds of applications on first view):
public void openFolder(String location)
{
// location = "/sdcard/my_folder";
Intent intent = new Intent(Intent.ACTION_VIEW);
Uri mydir = Uri.parse("file://"+location);
intent.setDataAndType(mydir,"application/*"); // or use */*
startActivity(intent);
}
p.s. Strange and surprising, but there doesnt exist the standard definition of "File Browser" in stock Android systems (unless you install 3rd party "File Explorer")..
That's why "resource/folder" mime-type doesnt work by default..
However, let's say a simple truth. File-Browser is a SIMPLE and ESSENTIAL part of any OS system. And it's quite disrespectful from Android, saying that it's not their job, and throwing the responsiblity to 3rd party apps.
You can use type DocumentsContract.Document.MIME_TYPE_DIR which works on several devices and launches File Explorer. You can refer this SO for more details.
I'm working on a functionality for an Android-Application, which downloads a file from a local server using the Android Download-Manager. Up to now I easily download the file to the downloads directory by using
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS,filename);
Now I would like to let the user choose the target including the filename. Therefore I use the ACTION_CREATE_DOCUMENTIntent:
void pickTargetFile() {
Intent intent = new Intent()
.setAction(Intent.ACTION_CREATE_DOCUMENT)
.setType("image/jpeg");
startActivityForResult(Intent.createChooser(intent, "Select a target to save the file"), SAVE_FILE_CODE);
}
But when I now use the resulting path in the download-manager it doesn't write the data in the created file but creates a new one named e.g. filename-1.jpeg when filename.jpeg was created by the File-Create-Dialog.
Either I would like the download-manager to write into the previously created file or use another dialog to choose a target for the download-manager but not creating the file by the dialog.
Does someone know an easy way to archive this?
I am making an app that downloads a file. After the file finishes downloading, the user can press a button that will open the file location in their default file manager.
I don't want to use intents as it causes the file manager to act like a file chooser! I do NOT want a file picker. My app should get lost after the user clicks on the button after showing him the downloaded location. I will figure out destroying my app later but first I want to fire up the default file manager and point it to the downloaded location. Let me know how to do this.
I used this code but it acts like a file picker.
Intent intent = new Intent(Intent.ACTION_GET_CONTENT); //tried ACTION_VIEW but it says no apps that can perform this action!
Uri uri = Uri.fromFile(mDownloadDir); //mDownloadDir is file object
intent.setDataAndType(uri, "resource/folder");
mContext.startActivity(Intent.createChooser(intent, "Open folder"));
I am experimenting with Android development. I am making an app that will allow the user to browse files in a web service and view them. These files could be anything: text, pdf, pictures, etc.
Previously, I would download the file to external storage and then call Intent.SetDataAndType() and pass it the URL to the file. That would cause the Android device to bring up an app picker and let the user choose the appropriate method to look at the file.
But since I do not want the user to edit the file, only to look at it, it seemed silly to download a file to storage; a file that I didn't want to hang around. Since the file can be obtained by a URL, why don't I pass that as a parameter to the Intent.SetDataAndType()?
I tried that. The first problem was that the file name was assumed to be the name of the web service call, and that seemed to be more important than the mime-type. I changed the web service to be the same name as whatever file was attempting to be downloaded. That solved that issue.
So now, the file is being opened. But it is always being opened in a web browser. I get to choose the web browser, but I would rather have another app open it.
My code looks like this:
Intent i = new Intent(Intent.ActionView);
i.SetDataAndType(Android.Net.Uri.Parse(GetUrlToFile(fileref, fileName)), mimeType);
i.SetFlags(ActivityFlags.GrantReadUriPermission);
i.SetFlags(ActivityFlags.NewTask);
i.SetFlags(ActivityFlags.ClearWhenTaskReset); // so if the app is relaunched, we don't show the display application.
StartActivity(i);
The code is in C# because I'm using Xamarin, but I don't believe that should make a difference.
I tried using StartActivity(Intent.CreateChooser(i, "Open me")); but that didn't give me any more options for choosing.
Does anyone have any ideas as to how to do this?
I have not found a way to do this yet, so I have gone through a workaround.
Instead of using a URL, I changed my app to be a Content Provider as well. Now, when I want the file opened, I create a URI that refers to the file within my app and pass that off to an Intent. When my app is contacted by this Intent, I download the file locally to my cache directory and return that.
My code has changed to this:
Intent i = new Intent(Intent.ActionView);
i.SetDataAndType(Android.Net.Uri.Parse("content://com.sample.erik.provider/files/" + id), mimeType);
i.SetFlags(ActivityFlags.GrantReadUriPermission);
i.SetFlags(ActivityFlags.NewTask);
i.SetFlags(ActivityFlags.ClearWhenTaskReset); // so if the app is relaunched, we don't show the display application.
StartActivity(i);
Then, I have my own content provider which does most of the work in OpenFile()
public override ParcelFileDescriptor OpenFile(Android.Net.Uri uri, string mode)
{
switch (sUriMatcher.Match(uri))
{
case FILE_ID:
if (mode != "r")
throw new Java.Lang.UnsupportedOperationException("Do not support write access: " + uri);
String id = uri.LastPathSegment;
Java.IO.File file = new Java.IO.File(Application.Context.CacheDir, id);
DownloadToFile(file, id);
return ParcelFileDescriptor.Open(file, ParcelFileMode.ReadOnly);
default:
throw new Java.Lang.IllegalArgumentException("Unknown Uri: " + uri);
}
}
It is not my original plan, but this way seems to work quite well and meets my needs.
I am currently trying to create an app which when taking a picture using the camera, when saving the image, it saves to a specific folder location and if the folder doesn't currently exist on the phone, it creates the folder and saves the file to that location. My code does not currently work, although I have tried. Could you please look at my code and advise me on what I need to do.
Here is the code:
else if(v==camera){
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
File newDirectory = new File(Environment.getExternalStorageDirectory() + "App_Pictures/");
String filename = new String("image1.jpeg");
File outputFile = new File(newDirectory, filename);
outputFile.mkdirs();
startActivity(intent);
}
It looks like you're trying to get an external app to take a picture for you. If this is the case, you need to use startActivityForResult, not startActivity, because you want to receive the resulting photo. Then you will receive the result in the onActivityResult method of your activity. This process is described in detail here.
If you actually want your own app to take the picture, instead of an external app, you'll need to use a completely different approach. Here is an app that starts recording a video right when it is launched, and saves it to a directory on the SD card, so perhaps it's a useful starting point if you want to do it this way.