Currently I am able to download a file off the internet and store on the SD card, then use the file from there. However that makes the file (with proprietary data) available to be seen. I would prefer to use the file from somewhere like raw or assets folder.
I will skip the downloading code, but my code to use the file is this
File myFile = new File (android.os.Environment.getExternalStorageDirectory() + "/folder/filename.xml");
Intent myIntent = new Intent(Intent.ACTION_VIEW);
myIntent.setData(Uri.fromFile(myFile));
Android opens the file with the default application and all is good.
I have found similar Q/A's that revolve around using code like
Uri.parse("android.resource://com.projectname.testing/raw/filename");
and
InputStream ins = getResources().openRawResource(R.raw.filename);
but I can't work out how to get either of those two back into a 'file' format to be used with my .setData code
I would like to solve my problem by simply accessing the file as a file. However since it is being used by an external application I have read I might need to make a temporary copy of the file with mode_world_readable then delete it after the application closes. This sounds like a lot of extra work, especially since my code above does work for a file stored on the SD card.
Does anyone have any ideas?
Thanks
I would prefer to use the file from somewhere like raw or assets folder.
Note that these too can be "seen".
but I can't work out how to get either of those two back into a 'file' format to be used with my .setData code
setData() does not take a File. It takes a Uri. Use Uri.parse() to parse other types of Uri values -- you already have this code shown above.
However since it is being used by an external application I have read I might need to make a temporary copy of the file with mode_world_readable then delete it after the application closes.
It definitely will need to be world-readable. Also, not all apps support all schemes, so apps that support file:// or http:// might not support android.resource://.
Related
I'd like to write an app that crops/resizes photos and writes them back to shared storage in their new size but everything I've read about how SAF and mediastore works suggests that at best I'd only be able to write the file back with a new name. And at worst I might not be able to open the files at all if I'm not the original creator. A solution that involves triggering a SAF dialog to open the file is reasonable though I'd like to be able to just batch change all the files (photos) in a folder (say dcim). But if I have to also trigger a SAF dialog to write the file back out that's pretty yucky.
Obviously if I were to target pre-10 versions of android this could still be done, but then I'd be blocked from the playstore, and I don't really want to write apps that only I can use.
everything I've read about how SAF and mediastore works suggests that at best I'd only be able to write the file back with a new name
Use ACTION_OPEN_DOCUMENT (or ActivityResultContracts.OpenDocument). You have full read-write access to the content identified by the Uri that you receive.
A solution that involves triggering a SAF dialog to open the file is reasonable though I'd like to be able to just batch change all the files (photos) in a folder (say dcim)
Use ACTION_OPEN_DOCUMENT_TREE (or ActivityResultContracts.OpenDocumentTree). You have full read-write access to all of the documents inside of that tree.
Existing Xamarin Forms app on Android.
New feature request from the bosses: To copy some updated documents from a USB FlashDrive to a known directory on the extSD already in the tablet.
Seems like that shouldn't require a PhD. Everything we've done to date has been on the internal storage so typical System.IO calls work fine. But Android has this whole Storage Access Framework stuff in place for things like the external SD, or Google Drive or where ever.
Every question and tutorial I see are all for the same thing: How to open a document browser to the SD card, or how to create a new CREATE DOCUMENT INTENT.
I'm not looking to do any of that. Don't need a UI. Not making a new text file from scratch.
I just want to copy a file from the flashdrive to the extSD. Everything else is in place to do this to internal storage. Easy-Peezy.
Its a single line when copying from the flashdrive to the internal SD.
FileInfo.CopyTo(targetAddress, true);
How do I copy a file to the extSD? Do I really need 200 lines of overhead making a DOCUMENTPROVIDER, and CONTRACT and 20 other things just to copy a file? All I get is "ACCESS TO extSD 1234-5678 is denied". Seems like it should be fairly simple to get permission to the card then just copy a file or make a new folder. But I swear everything I read for SAF makes it sound like you have to make 10 classes and a manager for them all first.
Anyone got a simple example of the minimalist way to get write permission to the extSD and copy from A to B?
If it is copying only one file them its pretty simple. Let the user select the fle with ACTION_OPEN_DOCUMENT. You get an uri for the file. Now let the user create a file at the right place using ACTION_CREATE_DOCUMENT. You got another uri. Now open an InputStream and an OutputStream for those uries. Then read bytes from input and write to output. Less then 200 lines ;-)
I have a doubt I read these tutorials just to get the clear understanding of the SAF introduced in kitkat in higher version of android How to use the new SD card access API presented for Android 5.0 (Lollipop)?
How to persist permission in android API 19 (KitKat)?
Android API below 19 equivalent for ContentResolver takePersistableUriPermission
Android Gallery on KitKat returns different Uri for Intent.ACTION_GET_CONTENT
Now i have a question when the intent is fired and i get select the sd card to get the uritree from the intent which i am getting but is the root tree I will have to iterate through the uri to get the specific file uri.
Now the question is I have mp3 files in my phone and I want to edit that specific file which is selected so how can i get that selected files uri from the tree and edit it?I tried editing directly using file but it makes my mp3 file disappear and i dont want to fire SAF intent again n again so how to check is user has given permission to sd card or not?
P.S. I am using jaudio tagger for editing the tags of mp3 files.
THANK YOU!!
I have got answers of almost everything in this question Now the issue if I am using jaudio tagger library for tagging mp3 files which takes File as a objects but android 4.4 and above wont let u modify File objects so I just want to knw the alternative how can i edit File objects in 4.4 above?
This is how I did it,
first copy the file from the sdcard to the phone memory and then do the desired changes and cut and paste the file again at its original place.
Example is here where I am editing the tag of mp3 file which is in the sdcard:-
https://github.com/reyanshmishra/Rey-MusicPlayer/tree/master/app/src/main/java/com/boom/music/player/TagEditor
The library you refer to is called JaudioTagger, and it does not and most probably will never accept DocumentFile. The Storage Access Framework is Google's invention and far from any standard. And JaudioTagger is written for portability.
However, I finally managed to get JaudioTagger mostly running with SAF, but had to substantially modify it, even to rewrite some functions. Basically I replaced all File and RandomAccessFile with my own classes, and additionally the handling of temporary files and renaming must be rewritten (e.g. the scheme: copy original file, change copy, remove original file, rename copy to original name).
In fact it might be easier to use the native TagLib instead, because that already accepts a special C++ class as input. All I did was to create such C++ class whose basis is a file descriptor derived from ParcelFileDescriptor derived from Uri derived from DocumentFile.
Finally one might come to the conclusion that the Storage Access Framework is somewhat suboptimal.
I'm very new to android. I would like to create a package that upon install would put files in the app folder (/data/data/my.app/...) of the android file system.
I would like to do this, so I could access the files using standard java File methods (in order to reuse my own code), and not have to use the android resource accessing methods.
The only way I thought might achieve something in this direction, is to put the files in the /res folder, and copy them to the file system in runtime (on first run, for example). This has the disadvantage of having two copies of each file for no reason.
Another way could be to get my app to download these files from a server (saw this option in another answer as well). This is possible, but I would wish to avoid having to put up a file server for such a simple task...
To my understanding, DDMS will not help here, as it only allows me to access the folder manually, after the application is installed.
My question is: Is there a different way to achieve my original goal (accessing files using standard java methods)? If not, is there a cleaner way to put files on the file system?
Thanks!
There are 3 methods I can think of that avoid duplication:
As you mentioned using the res/raw folder. You can avoid duplication if your existing code uses can use InputStream instead of File and use Resources.openRawResource().
Use the assets folder and access the file using file using AssetManager.openNotAssetFd(). Again this would require the use of Streams not File class. This can get a bit messy if your file is compressed because assets are memory mapped.
If you code is really tied to File (doesn't just use it to open an InputStream). To avoid duplication you could download the file from the web on the first time it is run and store it into the external storage.
You can put your files on under /res/raw and then use:
Resources res = context.getResources();
InputStream in_s = res.openRawResource(R.raw.myfile);
Or if you want the File object
File f = new File(context.getResources().openRawResource(R.raw.myfile));
Then you can use normal Java apis to work with your files.
I am trying to load an xml file located in the /assets folder of an android project by name using this method:
getAssets().openXmlResourceParser("thefilename.xml");
However, executing this code always throws a "FileNotFound" exception, even though the file is located in the /assets folder and is with the correct file name.
Now, I have not put the file in the /res/xml folder because I really need to be able to 1. edit the file right on the device itself and most importantly 2. add new xml files to the application without issuing an update, to allow for easy user modifications.
Thanks in advance.
I think what you are looking for is either getAssets().open("thefilename.xml") or getAssets().openFd("thefilename.xml") depending on what the end use of the file is. You can see from Dianne's response in this post awhile back that openXmlResourceParser() is not really usable just to gain access to files in the assets/ directory: http://goo.gl/2KfgT
From there you will have a stream that you could feed into a SAXParser or do whatever else you choose.
Side Note: On the points you mentioned you really can't edit files directly in assets/ or add new files to assets/ at runtime. You will need to work with files on either internal or external storage to do those things. You probably already knew that, but I thought I'd mention it.
Hope that Helps!