What is the difference between getFilesDir() and getFileAbsolutePath() - android

When I use either of them, I get the same result. It's just that to use getFileAbsolutePath, I use a file object.
Log.v("getFilesDir", "" + getFilesDir().toString());
file = getFilesDir();
Log.v("file.getAbsolutePath",""+file.getAbsolutePath());
Result:
V/getFilesDir﹕ /data/data/com.kingbell.interprocesscommunication_simple/files
V/file.getAbsolutePath﹕/data/data/com.kingbell.interprocesscommunication_simple/files

As explained in android docs.
getFilesDir()
Returns the absolute path to the directory on the filesystem where files created with openFileOutput(String, int) are stored.
This means that it returns a File Object, A File could represent files or directories, in this case a directory. you can check it by calling the isDirectory() method.
getAbsolutePath()
Returns the absolute path of this file.
This is the path of this file, but rememeber that directories are represented with the same file objects just like a real file. you can verify it by checking the isDirectory() or isFile() method.
So, in your case they point to the same place.
You called getFilesDir(), so your context give you a directory represented in an instance of the File class. In that file object you call getAbsolutePath() so they represent the same thing, since this is an actual directory.
Clear?

Maybe it will be more clear with the source code.
getAbsolutePath()
package java.io.file
public class File {
public String getAbsolutePath() {
return fs.resolve(this);
}
}
and getFilesDir()
package android.content
public abstract class Context {
public abstract File getFilesDir();
}
and for a specific Context(typically is an activity), the return value for the getFilesDir() call is fixed and should be always same, it tells you a location you can use to save your file.
At the same time, you can call getAbsolutePath() on any File object to get a full file path, either the file created by you or the file carried in an URI sent to you.
That is why these two calls are in the different packages.
Hope the explanation helps.

Related

Rename Realm DB file name in Android

I have a Realm DB file, with name "abc.realm". How to change this name to something else? Should I just replace the file name using IO operations or can I do it with migrations? Not able to find any satisfactory answer neither on the web nor on StackOverflow.
Realm stores 2 files, the realm itself and a .lock file. So if you call your realm "abc.realm", then next to this file there is also "abc.realm.lock".
The way to go about renaming your realm file is,
Make sure you find the location of both files
Rename both files with the same name but keeping the ".lock" extension on the lock file
Modify the path to the realm that you pass to the RealmConfigurationBase inheritor
Clearly before doing any of this, make sure to backup your database, just in case.
I don't know what programming language you're writing your android application in, so I'll go with a skeleton in pseudocode
private void BackupRealmFile(string realmLocation, string saveLocation)
{
// make a copy of the file and store it somewhere
}
void YourMainMethod()
{
BackupRealmFile("some/path", "your/backup/path");
IOLib.RenameFile("some/path/abc.realm", "some/path/newName.realm");
IOLib.RenameFile("some/path/abc.realm.lock", "some/path/newName.realm.lock");
var config = new RealmConfiguration("some/path/newName.realm");
// maybe some more settings on your conf
var realm = Realm.GetInstance(config);
}
I hope this helps.

Android/Kotlin - Accessing assets folder from a top-level function

In my app, I put helper methods in the top level, not contained in any class, so I can call any of them from anywhere. And I have an assets folder (app/src/main/assets) with text files in it.
I get access to this folder inside Main Activity using this code
val file: String = applicationContext.assets.open("folderInAssets/filename.txt").bufferedReader().use {
it.readText()
}
However, it seems that I cannot access the assets folder from outside activities or classes. applicationContext is not defined, and I cannot have access to a Context. I also tried
Application().assets.open(...)
but it gives me the error: java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.res.AssetManager android.content.Context.getAssets()' on a null object reference
My Question: How can I get access to the folder from a top-level function in Kotlin? And is there a preferable "Kotlinic" way to define helper methods in an app?
Thanks in Advance.

java.lang.FileNotFoundException in Android/Kotlin even though file is present

I have a data class called Contact which has a companion object property 'allContacts: List' which returns contacts after parsing them from a JSON file.
Relevant code:
val allContacts: List<Contact>
get() {
val json = JSONObject(File("app/src/main/res/data/contacts.json").readText()).getJSONArray("contacts")
val contacts = mutableListOf<Contact>()
...
I do indeed have a contacts.json in res/data package. (data package created manually).
Here's the proof:
Why is this happening? Is the contacts.json file not included in the final .apk?
I have tried logging the current path of the app using
Log.i('.MainActivity', System.getProperty('user.dir'))
But always get . in Logcat.
EDIT: I decompiled the apk in Android Studio and found no traces of contacts.json
Your file doesn't exist in the same project directory you expect it to.
You have to create a resource directory raw and paste your file in there.
Then, you can reference your file as R.raw.contacts wherever you need to reference the file.
Reading the file is another story.
I found it best to create a separate top-level extension function for reading and returning the file contents
fun Activity.readFile(fileID: Int): String {
val inputStream = this.resources.openRawResources(fileID)
return inputStream.use{it.readText()} // Returns entirety of file contents as string.
}

RealmConfiguration.Builder with DocumentFile

I'm struggling with storing a realm db on the sd card. The point is that I have to use DocumentFile instead of simple File object to have write access. Another words:
Uri uri = getUriInstanceToSaveDB(); // my inner method
new File(uri.getPath()).canWrite() == false
DocumentFile.fromTreeUri(getActivity(), uri).canWrite() == true
Therefore I can't just store data using RealmConfiguration.Builder() (cause it uses File object as storing mechanism). Of course, I've also tried to use simple String there instead of File object - no result.
Real doesn't support DocumentFile at this point in time, so I'm afraid you are currently out of luck unless you can find a way to map a DocumentFile to a local File reference.
Also one of the problems with DocumentFile is that it might reference a file that doesn't exist locally, which would prevent Realm from using it. So it is unclear if Realm could ever support this.

How to write to DocumentFile in Android programmatically?

Android API has DocumentFile class. This class has canWrite() method.
Suppose I called this method and it returned true. Also suppose this object was representing "raw" file.
Now how can I do what it said I can?
Namely, how to write "Hello world" text into that file?
Thanks.
Namely, how to write "Hello world" text into that file?
It is not necessarily a file.
To write to the document identified by that DocumentFile, call getUri() on that DocumentFile to get the Uri to the document. Pass that to openOutputStream() on a ContentResolver. Then, write to the stream, flush() the stream, and close() the stream. Basically, once you get the OutputStream, from there ordinary Java I/O takes over.

Categories

Resources