I'm new to Android, but do have some expreience with Java.
For my application I have to use a text file which I have decided to acces from the internal storage using the following code:
String functFileName = "nameOfMyFile";
OutputStream output = openFileOutput(functFileName, Context.MODE_APPEND);
As far as i understood, this means that my application creates a file with the name nameOfMyFile.txt in the internal storage memory, or opens it, if it already exists.
Once the file has been created, it will remain stored until the app is deleted. (Please correct me if I got it wrong)
My question is: Is it possible, that a file with that name has already been created by another application, which in this case would ruin my programm?
In other words: Can I be sure that my app doesn't access another file, which accidentally has the same name, than creating one of itself?
Sorry if this question isn't very professional.
I'd be grateful for any help.
The openFileOutput(String name, int mode) function documentation says :
Open a private file associated with this Context's application package for writing. Creates the file if it doesn't already exist.
It clearly states that the file created with this function is private to the application that created it, so you can be sure that no other application have access to it, provided that MODE_APPEND or PRIVATE were used.
Other two modes MODE_WORLD_READABLE, MODE_WORLD_WRITEABLE are dangerous and deprecated in API 17 and make the file available for other apps.
Related
I'm currently building a .Net Maui App that is only targeting android. I need to save some data in the public external storage that I can access and copy to my PC and that persists even if I uninstall the app. I choose the Documents directory.
The following does the job:
string dir = Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryDocuments).AbsolutePath
But I get a warning from my IDE that GetExternalStoragePublicDirectory is deprecated.
I've found several postings that
Android.App.Application.Context.GetExternalFilesDir(Android.OS.Environment.DirectoryDocuments)
will also work, but that does not return the same result.
The deprecated method returns
/storage/emulated/0/Documents
while the other one returns
/storage/emulated/0/Android/data/com.companyname.myappname/files/Documents
Hence the appname is in the path, this is not persistent in case the app is uninstalled. So what is the correct way to get the public external documents directory?
I had done a sample to test the MediaStore and the Context api. According to your description, you want to save some data to the file in the Document folder.
For the Context
All the files or directories you get from it belong to the application, when user uninstall the app from the devices, all of these will be deleted from the device. So this doesn't meet the requirement.
For the MediaStore
This api can be used to create file in the public folder, but the file can just be accessed by the app which create it. When user uninstall the application, you can't access it either.
And the google suggest the developer use the ACTION_CREATE_DOCUMENT to let the user create a file by himself and then user can open it by the ACTION_OPEN_DOCUMENT.
So even though the Android.OS.Environment.GetExternalStoragePublicDirectory method has marked as deprecated, it is the easier way to get the result you want.
For more information, you can check this case and the official document.
My app (App A) need to write a textfile which will be stored under another app's(App B) internal memory. Any idea how to implement this?
I have tried the following:
Under both the AndroidManifest.xml file, I have specified the same android:sharedUserId.
From App A, I used:
filePath = getPackageManager().getPackageInfo("packagename of App B", 0).applicationInfo.dataDir;
to get the path and I have confirmed that the path is correct for App B's internal memory.
But I am getting "java.io.IOException: Permission Denied".
Any idea where I have made mistake?
According to official documentation here,
Technically, another app can read your internal files if you set the file mode to be readable. However, the other app would also need to know your app package name and file names.
It's a do-able thing.
So, create a File object with your filepath and call setReadable on it.
Also, check you're not creating the file with MODE_PRIVATE.
I have a lite version of an application that uses a SQLite database. I want to copy that database over to the full version of the application when the user installs the full version.
I have written some code to perform the file copy, but the lite database file always comes up as unreadable. The file is there and I can point to it, but I can't read it to perform the copy.
In the Android documentation, we read:
You can save files directly on the
device's internal storage. By default,
files saved to the internal storage
are private to your application and
other applications cannot access them
(nor can the user).
Note the words, "by default".
Is there a way that I can override that default and make the SQLite file readable by my other application?
Thank you.
I believe you have 2 options.
Set the sql database to be world readable on creation. You can do this by setting the appropriate mode parameter in the call to openFileOutput() or openOrCreateDatabase().
Set the sharedUserId attribute in the manifest of both of your applications so that they have the same user ID. This treats both applications as the same user, giving both applications access to the same private set of files.
The two apps have the same sharedUserId. When I use this code in app1
context.openFileOutput("/data/data/org.me.app2/files/shared-data.dat", MODE_PRIVATE)
I get an exception telling me that the file contains a path separator.
I am trying to write a file from app1 into app2's storage. (I do of course need to make sure that app2's files directory exists first)
Ideally, I would write to a user specific directory instead of an app specific directory, but I do not know if that can be done
First of all, NEVER use a full path to internal storage like /data/data. Let the operating system give you the path (for example, via Context.getFilesDir() or Environment.getExternalStorageState()). Don't make assumption on where the data is.
Secondly - you already are doing that! Unlike File, Context.openFileOutput already prepends /data/data/[package] to your path, so you don't need to specify that. Just specify the file name.
If you really feel that it's safe and necessary, and if both apps share the same user ID using android:sharedUserId in the manifest, you can get a context of the other app by using Context.createPackageContext() and use CONTEXT_RESTRICTED, then use openFileOutput with only the file name.
Open a FileOutputStream of the needed file, relative to this path:
String filePath = getPackageManager().
getPackageInfo("com.your2ndApp.package", 0).
applicationInfo.dataDir;
Since this is months old I assume you've already solved your problem, but I'll contribute anyway.
Sharing data between apps is what ContentProviders are for. Assuming that you know how to write a ContentProvider and access it, you can access files via ParcelFileDescriptor, which includes constants for the mode in which you create the files.
What you need now is to limit access so that not everybody can read the files through the content provider, and you do that via android permissions. In the manifest of one your apps, the one that will host the files and the content provider, write something like this:
<permission android:name="com.example.android.provider.ACCESS" android:protectionLevel="signature"/>
and in both apps add this:
<uses-permission android:name="com.example.android.provider.ACCESS" />
by using protectionLevel="signature", only apps signed by you can access your content provider, and thus your files.
You should not be overwriting other applications files. That said you have two solutions
Use public external storage (like the SD card) to share the file between the apps.
If the other app is not yours then you can't write to its /data directory, without root that is. Anything is possible with root, just don't expect your users to all have root access.
Edit: Developer owns both applications
Thanks for Roman Kurik for pointing this out. A link to his post on SO
From the android docs
android:sharedUserId
The name of a Linux user ID that will
be shared with other applications. By
default, Android assigns each
application its own unique user ID.
However, if this attribute is set to
the same value for two or more
applications, they will all share the
same ID — provided that they are also
signed by the same certificate.
Application with the same user ID can
access each other's data and, if
desired, run in the same process.
So this is exactly the way user id's work in linux, essentially you are the owner of both and have read/write access to both.
In one android application, I created a database file in data/data/com.rams/databases/dbfilename.
If I created a second application with the same package name (com.rams) and I access the database file created with my first application, the second application is able to access the database contents.
How can I secure the database file created with my first application?
Almost without exception, and regardless of language or platform, there will always be a way for an application running with the relevant credentials, an application running within a certain environment or a user with the relevant credentials to access and read a given file.
You should assume it will always be possible to access a given file in ways you never intended.
Instead of trying to manage access to the file, try to manage comprehension of the file contents. In other words, it won't matter if everything and everyone can access and read a file if the contents are protected such that only an allowed application can understand the contents.
Or, more simply, look into encrypting the file contents if you need to absolutely ensure that nothing other than allowed applications can make sense of what is in a given file.