How to access to internal storage in Android - android

I want to store .docx files generated and modified through an Android app into the internal storage of android phones (all the same model of phone if that helps). I've got the loading of the template (located into the app) and the modifying of the fields working, but I'm blocked on how to save the files.
I am using docx4j which has a method for saving :
private void writeDocxToStream(WordprocessingMLPackage template,
String target) throws IOException, Docx4JException {
File f = new File(target);
template.save(f);
}
I have tried other more "manual" ways, but I always have the same problem :
what should be the input for the target directory?
It seems easy to do it for external storage, but concerning internal storage it's something else.
When I simply try to output a String in a test.txt then get the String in it back, with the classical BufferedReader, InputStreamReader, FileInputStream way of doing, I can't get this information whatsoever.
Information on this topic is super scattered, I've passed the afternoon reading about thousands of ways to achieve storage, but none corresponds to my problem.
I have set <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> in my Manifest just to be sure but it doesn't change anything.
Moreover, and maybe it has to do with the issue, I can't access files (from device or from computer) on my testing device (a Samsung Galaxy 5S which can run the app), I seem to have quite all folders but not any files in them, apart from a few xml and txt files... (However, I still get nothing when doing the : write in EditText - store in File - save File in .txt - retrieve String - view String in textView).
This is super important as I have to retrieve the .docx files for further use, after them being created.
Thank you for your answers and let me know if I can provide any more information, I know my problem is quite unclear.

It seems easy to do it for external storage, but concerning internal storage it's something else.
To write to external storage, you use the two-parameter File constructor, where you provide a File object pointing to some root location on external storage, such as:
new File(getExternalFilesDir(null), target);
To write to internal storage, you use the two-parameter File constructor, where you provide a File object pointing to some root location on internal storage, such as:
new File(getFilesDir(), target);

You don't have to hold the permission android.permission.WRITE_EXTERNAL_STORAGE if you write your file to the app's private internal storage.
In your code, with the call
context.getDir("testfile", Context.MODE_WORLD_READABLE)).getPath().toString()+"/test.docx";
the file will write to the path
/data/data/com.yourpackage.name/app_testfile/test.docx
If the write operate successfully, you can read and retrieve the content of the file by using the path above.

Related

Android: Storage Access Framework - Just need to copy a file to extSD

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 ;-)

Get internal as well as external storage file path

In my app, i need to read external as well as internal filepath. In other words, the user can select a file from internal storage if he desires or from sdcard if he so desires.
I found this while searching in SO:
Use getExternalStorageDirectory() to get access to external storage.
Use getFilesDir() to get at your app's portion of internal storage.
But how would i know whether the user has chosen a file from external or internal directory?
Here is a sample method that reads an image from internal storage;
public Bitmap readFromInternalStorage(String filename){
try {
File filePath = this.getFileStreamPath(filename);
FileInputStream fi = new FileInputStream(filePath);
return BitmapFactory.decodeStream(fi);
} catch (Exception ex) { /* handle exception like a king here */}
return null;
}
Now, what you could do from here is to see if the value is null and if so, then try to use a corresponding method to read from External Storage!
Of course, you can also have class variables to keep track of which source the image/file came from (internal or external) and update them accordingly depending on which method was called!
I hope this helps you solve this issue! Good luck.
But how would i know whether the user has chosen a file from external or internal directory?
That is up to you in your user interface. You are the one who is building the file-browsing UI, and so you know what root directory you used in your file-browsing UI.
Of course, there will not be any files in any of those locations, most likely.
getFilesDir() is part of internal storage, and the only files that will be in there will be ones that you place there yourself.
getExternalFilesDir() is part of external storage. In theory, the user could put files in this directory using other tools, like a desktop OS. In practice, the user is unlikely to do this, and nothing else is going to put files in that directory other than your code.
You are certainly welcome to write a file-browsing UI that uses other external storage locations, such as Environment.getExternalStoragePublicDirectory(), that are more likely to actually contain files.

When using emulators, how to interpret the output path when calling Context.getFilesDir()?

Inside onCreate() I have this line:
File aux = context.getFilesDir();
which outputs this:
/data/user/0/com.example.tirengarfio.myapplication/files
but.. where is this path exactly insde Linux filesystem? or is it taking as reference the Android Studio Project root directory? os should I create it somewhere?
EDIT:
As I said to #Simas, but by the moment Im not connecting any smartphone. Im just using emulators on Linux. My intention is just reading a file using
FileOutputStream fos = openFileInput(FILENAME, Context.MODE_PRIVATE);.
So, where should I place the file inside the Linux filesystem?
This is the path of your app's local data folder. It can either be in the memory card or the device storage.
There's no easy way to access it if your device is not rooted but here's a starter:How to access data/data folder in Android device?
Let us see what the doc says :
Returns the absolute path to the directory on the filesystem where files created with openFileOutput(String, int) are stored.
No permissions are required to read or write to the returned path, since this path is internal storage.
So actually the files you will find are those which were saved with the very same function openFileOutput(String,int) by your/other applications.
So basically if you want to test some functionality (which I suppose) write a unit test that uses this API openFileOutput(String,int) to store some mockup data and then get it again with Context.getFilesDir() and some code for file processing.

Using a file located in either the raw or assets folder

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://.

Is it possible to reference a strings.xml file that is not saved in your res folder?

I am creating an app that could potentially be used in multiple educational establishments across a variety of courses with tutors who will want to be able to update some of the information within the app themselves on an ad hoc basis. I originally thought that the best way to do this would be to have the application download a new strings.xml file to the res/values folder, though I have read that you cannot update this folder/file whilst the app is packaged and running. I think a good work around for this would be to be able to save another strings.xml file elsewhere
My questions are:
Is this at all possible?
Where would I go about saving the strings.xml so that it is not
packaged when I export the app?
note: The file will not be called string.xml so there will be no confusion etc. with the actual strings.xml.
There is no "rule" of where you should put the file (minus, of couse system and other private folders you can't access). However, the logical and most common place to put a non-packaged resource that your app downloads would either be in your own applications data folder (located on the internal storage of the device) or on the external storage of the device (SD card).
To write your file to the internal storage you will need to use the context's openFileOutput(..) method. This stores the file within your apps private data directory. Use openFileInput(..) to read your stored file
To write to external storage you will need to add the WRITE_EXTERNAL_STORAGE permission to your manifest. After doing that, you can use FileOutputStream to write your files data when downloading. InputStream for reading (look up which input stream type would be most suitable)
Obviously, the examples I'm giving aren't fully detailed or have code but they will guide you in the right direction for storing files on your device.
Files under the res folder are used by the compiler to autogenerate the R class that contains the ids of the strings,layouts,drawables etc...
Of course you can download a custom resource from your server and stored it in the SD as #dymmeh points. And is the most reasonable way of to achieve modification of literals but be aware, you will not be able to use the #string/string_id in your layout's xml and you will have to parse the downloaded file yourself.

Categories

Resources