4.2 Jellybean now supports multiple users. However as per the docs, all calls to all the APIs to get storage location return locations private to the current user (eg: getExternalStorageDirectory()).
I cache plenty of content from servers and store this to external storage, but with a multi user enviornment, this data will need to be duplicated for all users. This is wasting a lot of space.
Is there any way to store files to a common area for all users to make use of?
Apparently not, according to the release notes:
No matter which of these APIs you use to save data for a given user,
the data will not be accessible while running as a different user.
From your app’s point of view, each user is running on a completely
separate device.
I hope I'm wrong because I have the same problem as you.
I appreciate that it would have been a potential security hole, but if I saved files in the folder returned by getExternalStoragePublicDirectory, I would have only myself to blame.
Related
After analyzing my Android application with a security tool, it has detected a high level vulnerability "File unsafe delete check". I have investigated about this, and it seems that the problem is that the application uses "file.delete()".
That function is considered unsafe because data could theoretically be retrieved with a tool that scans all the storage device. So, if that way of deleting is "unsafe"... what is the "safe" way to delete files in Android? (to avoid getting that "security error" that is supposedly a "high level" one). What is the proper way to delete files in Android Development?
I am getting the same security warning in 2 different applications, one made with native Java and the other one with Xamarin Forms. Thank you very much!
what is the "safe" way to delete files in Android?
There is none for the vast majority of Android devices. You use delete() on File.
That function is considered unsafe because data could theoretically be retrieved with a tool that scans all the storage device
If the Android device happens to use a classic hard drive (spinning magnetic media), you can overwrite the data before deleting it. On any sort of flash media, that will be ineffective, as the physical location where the data is written can vary with each write operation ("wear leveling").
So, this really boils down to your objective:
If you feel that the user will be harmed if this data is available to be read, store it encrypted with a user-supplied passphrase.
If you are simply trying to avoid this warning, ask the developers of this "security tool" what they are expecting you to do. Or, find a better tool.
This is not an Android specific issue.
It has to do with how file systems work, and the physical storage media it self.
When you delete a file, regardless of API, what is actually deleted is the record in the files table.
The actual data on disk or flash storage remains.
There is a method for secure deletion:
Before deleting the file, overwrite its contents with garbage or zeros several times.
But, this method only works for magnetic media such as hard disks.
Android devices use NAND flash for storage.
Because the number of writes a NAND chip can take before it fails is a lot less than that of magnetic memory, these chips usually come with a mechanism that spreads out the write commands.
What this means is that even if you try to write random data or zeros over your file, there is no guarantee the actual data will be overwritten.
The writes may go to a different sector to avoid wear.
So, on one hand, for flash storage it is enough to overwrite the file once, but on the other hand, it is impossible to do correctly at application level.
If you want to make your application secure, you must make sure to store sensitive data encrypted.
Then, even if someone tries to read the raw storage, they wouldn't be able to recover the data.
Don't store user credentials (like passwords) in regular files on Android.
Use Android accounts API and let the OS manage security.
If you still need file storage but want to protect the data, encrypt it in memory and then write to file.
As said by the other answers the first thing to consider under a theoretical point of view is if there is really a need to store any sensitive information in files to be kept on customer side
If this is really the case, encryption is the real way to guarantee proper security. Files would be protected not only against the recovery after deletion but also during their known life on the device
That said, in the case of a vulnerability assessment - i.e. a static analysis of the code - it would not be immediate to detect that you are calling for a deletion [via file.delete()] of encrypted files. Or maybe you are just calling the deletion of files with nothing to hide
In both these cases the found vulnerability would just be a false positive. Which is part of the game because you can guess that it's quite complicated for an automated tool to understand if something really "deserves" protection or not
What you can do to get rid of the vulnerability is adding the logic to empty the files before calling file.delete(). You have a sample here for this purpose. This will solve the vulnerability detection you are experiencing
My app are sometime needed syncing with web servers and pull the data in mobile sqlite database for offline usages, so database size is keep growing exponentially.
I want to know how the professional app like whatsapp,hike,evernote etc manage their offline sqlite database.
Please suggest me the steps to solve this problem.
PS: I am asking about offline database (i.e growing in the size after syncing) management do not confuse with database syncing with web servers.
I do not know how large is your data size is. However, I think it should not be a problem storing reasonably large data into the internal memory of an application. The internal memory is shared among all applications and hence it can grow until the storage getting filled.
In my opinion, the main problem here is the query time if you do not have the proper indexing to your database tables. Otherwise, keeping the databases in your internal storage is completely fine and I think you do not have to be worried about the amount of data which can be stored in the internal storage of an application as the newer Android devices provide better storage capability.
Hence, if your database is really big, which does not fit into the internal memory, you might consider having the data only which is being used frequently and delete otherwise. This highly depends on the use case of your application.
In one of the applications that I developed, I stored some large databases in the external memory and copied them into the internal memory whenever it was necessary. Copying the database from external storage into internal storage took some time (few seconds) though. However, once the database got copied I could run queries efficiently.
Let me know if you need any help or clarification for some points. I hope that helps you.
For max size databases. AFAIK You don't want to loose what's on the device and force a reload.
Ensure you don't drop the database with each new release of your app when a simple alter table add column will work.
What you do archive and remove from the device give the user a way to load it in the background.
There might be some Apps / databases where you can find a documentation, but probably this case is limited and an exception.
So to know exactly what's going on you need to create some snapshots of the databases. You can start with that of one app only, or do it directly with several, but without analyzing you won't get a reliable statement.
The reasons might be even different for each app as databases and app-features differ naturally too.
Faster growth in size than amount of incoming content might be related to cache-tables or indexing for searches, but perhaps there exist other reasons too. Without verification and some important basic-info about it, it's impossible to tell you a detailed reason.
It's possible that table-names of a database give already some hints, but if tablenames or even fields just use meaningless strings, then you've to analyze the data inside including the changes between snapshots.
The following link will help in understanding what exactly Whatsapp is using,
https://www.quora.com/How-is-the-Whatsapp-database-structured
Not really sure if you have to keep all the data all the time stored on the device, but if you have a choice you can always use cloud services (like FCM, AWS) to store or backup most of the data. If you need to keep all the data on the device, then perhaps one way is to use Caching mechanisms in your app.
For Example - Using LRU (Least Recently Used) to cache/store the data that you need on the device, while storing the rest on the cloud, and deleting whats unneeded from the device. If needed you can always retrieve the data on demand (i.e. if the user tries to pull to refresh or on a different action) and delete it whenever its not being used.
I am building an android app which requires to have >300 images and ca. 100 audio files for an apk size of around 50mb (after webp compression and proguard).
It is not huge and I could probably live with that. But since I am planning to add other features the size will get bigger and bigger.
I am still interested though, since I'm quite new to android development, if there is a better way to store all this files, perhaps remotely and access them when required.
When the app starts I would have to load all the images into a list and once an element of the list is tapped I would need to open a separate activity and load the sound. So there is no upload from the App, just a resource gathering.
I do not know if it is more efficient this way or to store all the files locally.
Either way I would like to know what my options are. what are the pros and cons of a server (and if it would be a viable solution for me at all) and what is the advantage of storing them locally instead.
Please keep in mind that I working by myself and haven't got money to invest on premium servers or stuff like that.
FILE STORAGE will be best for you. Performance depends on the type and amount of data you are using. You do not need too much of data manipulation so go for file storage if privacy is not your concern for the data as it will be available for all the applications.
Use SQLite Database if the files needs to be protected from other applications.
Use File Storage(internal/external memory) if other applications can also access your files.
Avoid Fetching data from server using JSON parsing/Http requests it will make your app rely on the internet all the time. Unless you are using it to update your database or file storage.
Within my Android app that is available via Google Play, I want to offer additional items that can be bought via in-app billing.
The kind of items I want to offer is media content such as graphics and sounds, which would normally go into the res folder of the app.
The problem is that these resources must be protected, of course. In its documentation, Google suggests not to store the content inside of the application package but to obtain a key after the item was bought and then send the key to a remote server where the key is checked and, if successful, the graphics/sounds offered for download to the app.
This sounds good, from the security perspective. But if I do this, I can't use the content as easily as resources can be accessed normally. If the user can get additional background PNGs, for example, I can't use R.drawable.new_background but have to decode the bitmap programatically, right?
So are there any alternatives or best practices for downloading additional media content via in-app billing?
I would say, as everyone who is determined enough can reverse-engineer the code, anyway, why not just store the content inside of the app but do strong checks if the user might use that content at all.
The answer depends somewhat on your specific concerns, which, from your question, might be either 1 or 2 below:
1) I'm concerned that someone will be able to use my resource within my app without paying, or
2) I'm concerned that a user (either one who has paid, or one who has not paid) will remove my resources and use them outside my app.
Another possibility, that does not seem to be indicated by your question (but which others have attempted to address) would be:
3) I'm concerned about my initial APK download being too large due to downloading a large number of resources, only some of which they user will decide to use.
If your only concern is item 1, then you can just store your resources as you normally would, but inside your app, refuse to load / use any resource for which you have not yet received an in-app payment. This is certainly the simplest approach.
If your concern is item 2, then you can just include with your APK an encrypted binary archive in the raw folder, and decode a specific resource from it whenever that resource is authorized (e.g., by payment) for use by the app. As others have noted, this is not really a big deal in terms of processor load, and it does provide some protection from casual theft. Of course, there is always copyright law if you're dealing with one of those "creative plagiarist" oxymorons who breaks your encryption and steals your resources anyway.
If your concern is item 3, then you'll need an external server from which your items can be retrieved.
Google App Engine is a popular choice for hosting when implementing this kind of storage outside the app. You would want to just cache any purchased /downloaded resources in an encrypted archive in your app's own external files folder (as returned by getExternalFilesDir()), then read and decrypt it as in item 2, above. Such files will be automatically deleted when your app is uninstalled.
One of obvious reasons for not storing additional content in the app is your app's app download size. If you are offering audio as additional content it can drammatically increase the size of your application. And users care about it. Besides it makes it easier to publish additional content, since you can do it via your server side/developer console without the need to publish app update. Moreover, if you want to provide high quality graphics, you will be able to serve appropriate version of the image directly to the device without the need of storing all density/screen size versions.
If you are concerned about security you can always use encryption and signatures to access resources and make attackers life much harder by properly obfuscating your code (or even moving security/decryption related code to native side, which will make it faster as well).
Yes, that would create a drawback that you will have to decode them programmatically and there is nothing to do about it. I honestly don't see why it is so big of a deal, on contrary, I think it's quite convenient that you will have more data driven access to resources.
As a summary I dont really think there are any standards for doing this and it depends on your app and content type. If you offer a fixed amout of 5-10 images, then there it is perfectly fine to keep them locally, if it is richer content, more items, heavier resources, then client-server would suit you more.
One solution would definitely be the following approach featuring two apps that share the same user ID. But this is not as elegant as in-app purchases and a bit hacky, obviously.
Create two apps with the same android:sharedUserId in AndroidManifest.xml
Store the paid content in the second app, that is a library app from now on and only contains those images (apart from necessary folders and manifest)
Sign both APKs with the same key
Offer the first app for free, as usual, and make the second app a paid one
In the free app, use the PackageManager to check if the second APK is installed
If yes, use createPackageContext() to create a Context for the second app which is then used to access the second app's resources from the first app
Google Play offers extension packs that can be purchased. These are large extensions that can be downloaded if purchased, and are separate from your app. This is one possibility.
http://developer.android.com/google/play/expansion-files.html
Depending on how secure you want it, and the size of the media, you can encrypt the media with a key, and store it with your app. It will be downloaded and installed with the app, but inaccessible. When the in-app purchase is complete, you can decrypt the contents and offer it to the user. You can either store the key in the source code with the app to decrypt it, or you can verify the purchase on your own server and retrieve the key from your server.
I want to maintain data on an android device even if my app is uninstalled.
I want to maintain the data (some key) in android device even when the app is uninstalled or removed i want to retain this data when my app is re-installed in the same device.
A similar question passed by on Google Groups quite a while ago and as far as I understood, there's not a single method that will fully prevent a user from deleting the data stored. If you think about it, it actually wouldn't make sense to provide a way to fill up a device's (internal) storage without the user being able to free up that space again.
That being said, your options for storing semi-persistant data that does not get wiped out when an app is being uninstalled seem to be limited to either the SD card, some web-based location or a seperate content provider - each with its own limitations.
You might also want to read through Google's documentation on this.
You can save it to a folder and if app is reinstalled, load it from there.