Sharing data between 2 Android applications - android

I have gone through a lot of similar answers, but since a lot of things have changed recently, I wanted to ask it again.
I have an application A that stores data in Shared Preferences. I want application B to be able to access the data stored in the Shared Preferences by application A.
Findings so far -
We can't use WORLD_READABLE for Shared Preferences, since it has
been deprecated.
We can't use sharedUserId to share data since it has been
deprecated.
I also read that apps signed with the same key can access each
other's code and data. But can we access the data just by doing that?
(Or do we need to do something else also along with the signing
process?). If yes, how?
One of the solutions is to share the data using Content Providers (data source being the Shared Preferences).
Are there any other ways to share the data as well?

I also read that apps signed with the same key can access each other's code and data
Only via sharedUserId.
Are there any other ways to share the data as well?
You could:
Have one app expose a service that the other app starts and passes the data via Intent extras
Have one app expose a service that the other app binds to and passes the data via AIDL parameters
Have one app send an explicit broadcast Intent to the other app with the data included in Intent extras
Have one app start an activity in the other app with the data included in Intent extras
Those options, as with the ContentProvider solution, can be secured by Android's permission system. If you carefully set up a custom permission, with a protectionLevel of signature, those apps will be able to communicate with each other, but other apps will not be able to hack into those communication channels.
And, of course, another option is to just have one app.

Related

Sharing and persisting data between multiple Android applications

I'm developing a group of complex Android applications that need to share common state and configuration settings.
For example, see this picture explaining my scenario:
I want that APP 1, APP 2 and APP 3 be able to access (read/write) data to the common storage area. Additionally, I need uninstall protection i.e. I don't want the data to be removed when the user uninstalls any of the apps.
I've already read about SQLite databases, ContentProviders and writing on Internal and External storage, but each of the above mentioned methods have disadvantages as listed below:
SQLite database: DB is deleted on app uninstall and is private to each app
ContentProvider: The data is removed when the app with the ContentProvider is removed
Internal storage: Is private to each app and data is deleted on app uninstall (http://developer.android.com/training/basics/data-storage/files.html#InternalVsExternalStorage)
External storage: Is unreliable (user may remove SD card)
Store on server: Not possible, user may not have reliable internet connection
EDIT:
I don't want any dependencies on Google Play Services because I will be distributing the apps via Play Store and as 3rd party downloads.
Please help me out.
Google Drive sort of does this for you. You basically get granted permission to a local filesystem that is backed by a remote one. On most phones this is getting preinstalled so the uninstall issue you are worried about is less of an issue.
You could create a folder for your apps that you can then read/write.
https://developers.google.com/drive/android/
You can use the shared preferences object to read and write preferences data from a file. Most important is to use MODE_MULTI_PROCESS. The bit MODE_MULTI_PROCESS is used if multiple processes are mutating the same SharedPreferences file.
Use the following code:
SharedPreferences shPrefernces = context.getSharedPreferences("filename", MODE_MULTI_PROCESS);
String s1 = shPrefernces.getString("keytosearch1", "");
String pass = shPrefernces.getString("keytosearch2", "");
I agree that Shared Preferences with world_readable will not sufficient for you or sharing across internet is not possible, but still you can do one thing.
Using Broadcast receivers and Custom Broadcasts.
with redundant common data across all apps with shared preferences.
Who updates the data will send a broadcast to system.
All the apps implement broadcast receiver. when ever a new broadcast received they update the data in shared preferences.
App A -> sends broadcast when data is updated.
If App B is installed already App B also receives broadcast and save the data from that intent.
if App B updates new data.
APP B -> sends broadcast for the common data
Other Apps will update data.
Only common data will be lost when all apps are removed. If at least one app is installed data persists.
Preference data will always be stored inside each applications own context. Use sharedUserId and have a new preference file created in all the apps. On opening each app, the app has to check for the preference value from all other applications context and should write into its preference based on last updated time value available in the preference to find the latest updated one.
Whenever any app is opened, the latest data will be stored in its local. if any of the app is installed or uninstalled, this should work fine.

How to access one App's Database to another Application using Sqlite?

I have two applications which resulting to use database.
Application A which creates database name DB1. This database I wanted to access in
application B. The applications are in different packages.
How can I do this ?
Application are not allowed to read private data of another application (you can do this only on rooted devices). The easiest way is to store database in some public location, but that is not recommend because any app on device will have access to database file...
Here is what you can do. You can create BroadcastReceiver-s from both sides and implement your communication protocol using message passing. Application B will broadcast requests, application A will handle that request and send result back to the application B. The only problem is that application A code must be updated to. For more info on how to use message passing, check this article
you need to have both applications installed using same user id. Add this to both manifests:
android:sharedUserId="com.abc.xyz"

How to share data across a group of applications in Android

Consider the following scenario. A company releases many apps. And they want some data to be shared across all these apps. Any of these app can create or read these data, just like a common database. So company decided to create an android library which does this purpose. I searched for a few days and my analysis are given below.
SharedPreferences- not recommended and is deprecated. It does not serve the purpose too. All other apps need to know the package name of the app that created the data to create PackageContext. Here this is impractical as any app can create/update/read data and it is not possible to say who is who.
ContentProviders - This does not work for me. The reason being ContentProviders has to be present in each app. There can not be 2 content providers with same name in a device. In addition to that, ContentProviders are basically meant for one app creates data and other apps subscribe to it using Content_Uri.
Network connection - We do not want to do store data in any server.
External storage - This is the only option remaining. Should I go for this?
And interestingly the data has to be secured as well which is nowhere supported in any of the storage options.
Note: For iOS, we use keychain to implement the same functionality
Understanding the problem on Android
Ironically, due to the intense sandboxing on iOS, there's a straightforward way to make this happen there (App Groups) provided the apps that need to share data are all by the same developer. Likely because Android is more flexible on security, this actually ends up being a more difficult problem there. The Android team have so far not seen fit to provide a convenient and secure way to specifically share this kind of data because there's a low security workaround.
That said, there are plenty of ways to share data between applications without involving the cloud.
SharedPreferences
The original question states that SharedPreferences are deprecated. This isn't true, as far as I can tell, however the MODE_WORLD_READABLE and MODE_WORLD_WRITABLE contexts are deprecated which makes this approach subject to not working in the future. The mode has been deprecated for quite some time, though - since Android 4.2 (2012). There's no threat in the current Android docs to suggest they're actually phasing it out (sometimes deprecation just means "this isn't a great idea" not "this is going to be removed"). I suspect the lack of a more secure OS-level direct alternative for application data sharing at the settings level is probably the reason for preserving it in a state of deprecation for the last 5 years.
File Access
The simplest and most common way I'm aware of to implement data sharing between applications on Android is to simply request file access on the device and create a shared location on external storage for this data. (Don't be confused by the "external storage" designation - this is just how Android refers to shared data. It doesn't necessarily refer to an SD card.) You give the file a unique name, and you store it somewhere that your apps know where to look for it. Best way to get that path is something like:
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS)
The obvious problem with this is security. While not deprecated by the OS, it introduces the same problem that the Android docs list as the reason for deprecating MODE_WORLD_* - it's inherently insecure and opens up potential exploits in your application.
You're placing your information where everything has ready access to
it.
You're asking for permissions that your app may not otherwise need.
You're reading files that you can't verify the origin of.
If your application isn't handling any sensitive data, maybe this doesn't matter to you (it might to your users). If you're planning to read data from those files, you should ensure you're providing maximum validation for that data before parsing. Check the size of the file, validate the formatting, etc.
Creating your own service
You could always create a Service or an IntentService. (There are subtle differences between the two, but IntentService is a subclass of Service that runs in a Worker thread while Service interrupts the main thread. IntentService also implements Intent support which provides the most straightforward interapplication communication on Android).
This service has its own private storage, for which it has full read/write access, but nothing else does. This service then provides an interface to receive Intents from other apps, and to return results (as Intents) to those apps. This is an extremely friendly way to implement interapplication data while maximizing data privacy and security of that data. If outlying apps mostly need to request very basic information from a central application, this is your entry-level option.
Implementing a BroadcastReceiver
Along the same lines is the BroadcastReceiver class. Depending on what sort of data you're intending to share between applications, and how familiar those applications may be with your specific approach, this another possibility. Again, you'll be managing the shared data under one application's private storage. Communication is done by Intents, so it's similar to an IntentService - except that applications may communicate with a BroadcastReceiver by issuing systemwide events (that is, they don't need to be explicitly communicating with your app or service - they're shouting out the world for a piece of info, and expecting an answer.)
Creating a ContentProvider
The Original Post seems to misunderstand what a ContentProvider is and how it works. You have to think of this type of item like you would a cloud solution - even though it's local to your device. Every app doesn't need a ContentProvider - they all need to communicate with a ContentProvider, and that ContentProvider maintains, updates and returns data.
This is probably the most "Android-y" solution for this particular usecase and offers the greatest expandability. You implement an independent process that handles data storage and responds to other applications. It is, however, a more evolved solution - and as such may be more a more challenging endeavor. If you need a real database service, rather than a fairly simple request/response type service, ContentProvider seems to be the best choice.
Seems like what you need is shared user id.
It allows application sandbox to be shared across multiple android applications if they are all signed by the same signature.
But, watch out for gotchas!
Yes. Probably using same path in external storage for all applications is the best way. A common portion of code could be used to know whether database there exists or not and therefore open or create new one. For security I recommend always to use 'user' and 'password' when connecting to DB, but if you think it is not sufficient I advise you to see this: http://www.hwaci.com/sw/sqlite/see.html

Confusion on Activity Lifecycle

I have one app which authenticate user to access internal activity, App is having several activity which gets data from previous activity
So I am bit confused on activity life cycle
I read Bundle data into local variable in activity OnCreate and reading DB in async task based on that data. this DB data is displayed on my app.
Now if I switch to another app, will my app have that local variable/Static variable data (read from DB data) with them,
I have SingleInstance class which keeps user ticket etc informations, Is that variable keeps in memory of app if we got phone call in between.
I am bit confused on this part.
As document suggest that you need to store unsaved data in shared preferences.
It would be good if someone highlight on that..
Well, first of all you need to make sure you understand the difference between a new app and a new activity according to the sentence:
Now if I switch to another app, will my app have that DB data with them after switching back to my app
If you actually mean different apps, the answer is "NO in another app(in case is your app too)" you cannot have access to another application DB (at least not directly), the only way is if that application implemented a content provider to share its data with another application, by default android applications are like sandbox and do not share any information with other apps unless specifically declared, there's another rules between two apps signed with same key but that's a different story and a huge advance topic not related to this question...
In case that you " mean go to another app (not mine) and then try to use it from MY app again " the answer is "YES", the information in the database is accessible among all the building components like "activity, service" that belong to the same application, information in database is persisted even after closing completely the app (and so is shared preference), but there's a huge different between shared preference and DB, and knowing when to use one or another differentiates between good and excellent developers, golden rule (but not the only or the best) is that, DB is used for complex queries and relational data that needs some sort of preprocessing or postprocessing to get the proper values, mean while shared preference is just a "key/value" map that persist in the application context
Hope this Helps.
Regards!

Sharing data between apps with same library

Is there anyway I can do something like this
all data I/O functions are written in a library package
data can only be shared between apps with this library (optional)
every apps with this library can initiate the "DB" at first time, and later-installed apps can access the same "DB"
I thought ContentProvider is a perfect solution for me, but it seems that condition 3 is impossible.
any suggestion plz?
all data I/O functions are written in a library package
OK.
data can only be shared between apps with this library (optional)
Perfectly fine with the proper permissions for your provider (signature).
every apps with this library can initiate the "DB" at first time, and later-installed apps can access the same "DB"
I thought ContentProvider is a perfect solution for me, but it seems that condition 3 is impossible.
It's up to you to code the underlying structure of your data. Since you already assumed that the provider will belong in a dedicated library package, a possible solution is:
Implement your provider in package com.mysuite.library.
Publish this app in the Play Store.
Make client apps A, B and C.
Publish them in the Play Store.
Require your users to download this library package whenever apps A, B or C can't find com.mysuite.library installed.
However, if you don't want to provide a central package, I believe you will need to serve a provider in each of your own apps, with different authorities (to avoid CONFLICTING_PROVIDER error). Upon initializing each client, you first check if there is another provider in your namespace (com.mysuite.provider*), assuming you either know all possible authorities you are going to create and/or iterate among them when searching (com.mysuite.provider1, 2 etc.).
However, this proposition may create problems with custom backups (say, if only one of the clients is backed up), which will force the re-creation of data. It certainly has caveats and is definitely more complex (ugly, IMHO), but it can be made to work.
Personally, I'd stick with option 1 (library package). I don't see users complaining when downloading required library packages for apps.
It's just an architectural decision, really.
There are only four ways to maintain shared data:
You have a single APK that stores the data and makes it available to other apps. If this app is uninstalled the data is gone.
Every app maintains its own copy of the data but synchronizes changes to the others.
The data is stored on the SD card. This is generally a poor solution though several apps do it.
The data is stored on a server and is only accessible when the device has a network connection.
Once you've chosen where you want your data to reside, you can transfer it around by any number of mechanisms.
ContentProvider is a good choice if you are not storing the data on SD card or on a server, but you want to be able to transfer the data to apps that don't know it exists using content: URI's.
If you have no need to ever share any of this data with anyone outside your particular suite of apps, and your data is not structured as a database, you may prefer a simpler transport.

Categories

Resources