I am writing an SDK for Android that will be used by many different apps. Each app needs to know if there is a previous installation of another app that uses the SDK; the first one will create a random id (a cookie) and store it, all later apps have to read it and reuse it. Note that the cookie will be created anew for every device.
I have searched for a long time for the answer; please read thoroughly before answering because I have read lots of different StackOverflow answers and have scoured the internet reading random blogs; I have tried a lot of things but none worked (I will save you the links).
A ContentProvider is definitely overkill. Also it needs to intrude an app's AndroidManifest.xml, something I am trying to avoid.
Likewise for a service: needs to be defined in the AndroidManifest.xml, which I do not control and do not want to require changes to.
Using external storage would perhaps be an option, but I don't want to require additional permissions.
Using SharedPreferences directly with getSharedPreferences() does not work because apps can only access their own preferences.
I can get a common preferences object using createPackageContext(package, MODE).getSharedPreferences(). This would work beautifully if I had a main package and many clients of the data, but in fact I don't know the package of the app that will be installed first -- it can be any of them. I don't even have a list of package names to search. Passing a package name which has not been installed fails.
Following the approach above, I have tried to piggyback on some standard Android app which I can count on, and store my preferences there -- say:
createPackageContext(
"com.android.browser",
Context.CONTEXT_RESTRICTED)
.getSharedPreferences(
"GLOBAL_PREFS",
Context.MODE_WORLD_READABLE);
but it does not work: the error reads
Couldn't create directory for SharedPreferences file
/data/data/com.android.browser/shared_prefs/GLOBAL_PREFS.xml
So, to recap: I need to store a piece of data (a short string) in some standard location, so that any other app can go there and read it if present, and it should work if at all possible without doing any magic in the AndroidManifest.xml or requesting any permissions.
There probably isn't any perfect answer, so perhaps the best solution is to write to external storage; then so be it. To put things into context, apparently it is trivial to do this on iOS using a keychain, designed to store secure data.
Unfortunately there really isn't a great answer for this that I know of. You've come up with a pretty good outline of your options and the best way may well be with external storage.
Just to throw something out there, I suppose it's possible you could use a flat file with a fixed name and world readable (and possibly writable) permissions. You'd have to then iterate through all applications' directories and check for this known-named file in each folder and attempt to open it.
While this might work theoretically, consider the case where the app that contains the "cookie" is uninstalled. Then you're left cookie-less. You might want to create the cookie in every app, copying over the value of the previous cookies to new cookies.
I haven't actually tried this, but I imagine it should work.
Related
Here the problem: my app will generate some files, and I want to give to the users the opportunity to exchange these files between them.
This requires 3 steps:
Saving the data: easily done in Storage implementing the
functions required by the Externalizable class;
Sharing the data: done (probably, right now it's impossible to check if the
result is correct because the missing step 3) with the sharing
methods offered by the framework, as soon as I understood I needed
to use as mimetype "application/octect-stream";
importing the downloaded data (shared by another user): this one I can't manage to
find a way to make it work. Loading the files from the app's Storage
is easy, but accessing to the folders out of the app's Storage is
something I can't manage to do.
I used FileSystemStorage in the hope of gaining access at least to the Download folder that (mostly) every phone has, but apparently I can't manage to accomplish the task
Using the FileSystemStorage on Android, for example, I have access to
/storage/emulated/0
/storage/emulated/legacy
file:///system
The first two being related to the Storage of the app.
Acceding to file:/// I obtain a long list of folders, a partial list including
media
logs
sdcard
Removable
...
root
...
But when I try to access some of these, they all appear to be empty. Either I make some mistake or the app can't see their content.
So I wonder if there is a way to accomplish the task, namely to have access to the files (probably in the Download folder) the user has downloaded, to import them.
Phone apps live in isolation within the phone. Android literally creates a separate Linux user for every app so they don't step on each other and damage the phone. iOS does similar tricks.
As a result apps can't just write a file to downloads and can't just list all the files there. This would violate the users privacy. So the native API to share a file is usually separate from the files API. We do have a share API in the CN class which lets you share images etc. to an arbitrary OS app. See isNativeShareSupported and share.
Ok, maybe I found a solution for reading the files from the Download folder in an extension of CodenameOne called FileChooser.
According to this blog post it should give access to, between the others, the Download folder (at least in Android).
I'm going to try it and, when everything is ready and tested, edit this reply to say how it worked out for me.
I need to save some URL that could change later in my app. I want that no-one can see them and find these URLs.
I tried SharedPrefences and database but they are easily accessible by any one who has a rooted phone.
Is there anyway to encode this data and save them in SharedPrefences so that I can decrypt it in the app?
encrypted-userprefs is a good library that allows you to encrypt the saved preferences. However, keep in mind that through reverse engineering, it might still be possible to retrieve the encryption keys from your APK and since you're using a URL, your app is likely to request it at some point where a network tool such as WireShark can observe it.
You can make it difficult, but you can't make it impossible.
Think about it: you want the information to be accessible to your app (you didn't say that, but I'm assuming it), but inaccessible to everyone else. That means your app has to have more information than anyone else, even a human who has root access to the phone.
Anyone who has that level of access to your phone has access to the app's bytecode. They can use this to see what your app does, down to the finest detail. In other words, what information does your app have that a human can't gain access to? None. Anything your app can do, a determined human with root access can also do.
Sensitive information should always be stored server-side. Even then, anyone with root access to your server can get at that information (for the same reasons as above); but the idea is that everyone and their mother can download the app, but people you trust (employees, etc) can get at the server.
I recently found that the databases of Android apps are totally exposed. That said, my configuration is exposed, I save there passwords.
So, now my doubt resumes on java code.
String value = "example";
This could be an example where I store a password to pass by reference to webservice.
People, with some kind of software (like this example Is there a way to get the source code from an APK file?) could be able to get all the code? (I tried to follow the steps without success)
I read about http://developer.android.com/tools/help/proguard.html, how do I know that it's already implemented in my project?
When you create an Android project, a proguard.cfg file is
automatically generated in the root directory of the project.
I checked my root directory and I don't have that file.
Thank you guys.
Obfuscation does not guarantee that your code won't be de-compiled. people who get your apk will still be able to review the code (although the flow of the app will be significantly more difficult to understand). Function names, variables and class names are changed but the code is still viewable.
password and other sensitive information should be kept in Android's keychain , where it's protected. never save passwords in a configuration file (preferences file).
You can look into encrypting your local database with sqlcipher. Proguard obfuscates code but will not hide your passwords if you have them hardcoded anywhere, it is not a tool to be used for security[reference]. Also all of your network traffic is vulnerable unless you use some sort of TLS.
As you describe your app now it is trivial to get the passwords in your app.
You can use char[ ] instead of string data type for storing sensitive values like password. This will make it difficult to recover if someone takes memory dump as value is not present string literal pool if used char[] data type.
I am building an application where in i want to know which all applications present on the android device have opened/accessed a given file. Can any one help me on this. I have used FileObservor, but it just tells me which all files are opened or accessed. I want to know which application has accessed it.
First, there is no logging, so you would have to catch things as they are happening, before they are finished.
On an ordinary linux you would be able to use the file observer like (inotify) mechanism to find out when a file is accessed, and then go trolling through through /proc/whatever/fd to try to find who is accessing it, if you can do that while they still have it open. But android runs each application as its own userid (excepting allied packages which share), meaning that you lack permission to access this information from another app.
You might be able to accomplish something by holding the data in a content provider rather than putting it in a simple file, as then any access to it would be mediated by your code.
I've only just started to write in Java on Android, so please bear with me.
I have some settings I want to hold in my app, normally I would have used an xml file. Trouble is i'm not sure how to load it into the xml parser to read it.
I thought I might be able to drop it into /res/values/Info.xml and open it from there but it does'nt find the file.
I have also read that people are starting to use a SQLite database to hold information in, is this more the standard way to go?
thanks a lot
Luke
It sounds like what you want are Shared Preferences. Its a simple way of storing key value pairs, along with a UI for letting the user change them.
You could try storing to External Files (that way they can save settings on an SD card if they have 2.2). You wouldn't be able to modify the files in the res folder like you tried because these files get compiled into the app package. You could also try Internal Files found on the same page. SQLite might be a bit much for config settings.