I need to share data between two android apps that are on the same phone without using the internet. The data I want to share includes a several key value pairs of different data types. The options I am aware of are:
Using intents - Send and Receive. But the typical examples
for intents do not involve these use cases. Intents seems more
suited for sharing data of a particular mime type or launch apps (or
let users choose from) to handle the data being shared.
Sharing the SharedPreferences. However the MODE_WORLD_READABLE
or MODE_WORLD_WRITEABLE flags required for this have been deprecated
post API 17.
Broadcast Receivers - But I'm not exactly listening to events.
I want to use a request/response cycle.
Content Providers. This is great except for the fact that I
need to store the data in a database in the app sharing the data. If I have key, value pairs
where the value can be of different data types, this makes the data
table a bit cumbersome. Is there a better way to do this with
content providers?
Which is the best technique to adopt?
I created a small library that makes it simple to share SharedPreferences from one app to another in a READ ONLY fashion using ContentProvider.
Described it here - https://github.com/ratpik/android-sharedpreferences-api/blob/master/README.md
You can set up Broadcast Reciever on one end to listen for particular intent type. And broadcast intents from first application with data held in extras. You can send whole objects via intent using parcerable approach.
More about parcerable approach can be found here
Related
I'm trying to send a SerializableExtra from an application to another one.
I use
resultIntent.putExtra("thing", fc);
and in the receive application :
Thing theThing = (Thing) data.getSerializableExtra("thing");
But since the applications doesn't have the same names I got the following error:
Java.lang.RuntimeException: Parcelable encountered ClassNotFoundException reading a Serializable object (name = com.test.senderapp.Thing)
And I can't modify the sender application , I need to find a way to make it works only controlling the application that receive the intent.
Thank you
Use Content Providers to achieve this.
https://developer.android.com/guide/topics/providers/content-providers.
We were discussing this issue into something pretty similar; we wanted that a keyboard could share data with another app and use it with a combination of other features.
The goal is that you define which data to expose and other apps can use that similar to what the Contact's app does; which you can access a CursorLoader to fetch all of the user's contacts.
On the other hand, as a second solution, you can make your second app receive a String and send the object as a JSON; but I'd rather prefer the first one if you're going to keep adding more objects or summing up other applications.
If I have a class that contains a static variable, say x:
class MyClass {
static boolean x = false;
// Other methods
}
Now let us say that, hypothetically, I set x = true; from my first activity. Is there any point through the rest of my app's life cycle (including various activities and threads) where this value will simple be 'reset' back to false due to how the 'Google JVM' or the android environment works? I have heard that static variables have a 'lifetime', that dies when the program dies. Do Activities count as separate 'programs'? What about services? Or even Widgets?
I am asking this because it is often difficult to share complex data structures that rely on other complex processing (like syncing data from an online database) in android due to how 'separated' activities are, and static variables are often a very quick and dirty solution to the problem. Other things I have tried include serialisation, but that doesn't really seem like a practical solution either (constantly serialising and decoding objects when the user navigates from one activity to the next seems like it would be very resource intensive).
If I am an evil person for doing this, please tell me what I am doing wrong, or even better, give me some links or examples of better ways to solve this problem.
Yes. There are times where that will reset. Primarily if the user leaves the app and starts fiddling around with other apps or if the user lets the phone go to sleep for a long period of time. The Android process could kill the actual app. Then the "state" of the app will be restored when the user comes back, however static variables will be at their defaults because the actual process was rebuilt.
Generally passing small objects between Activities and Services is done by overriding the Parcelable interface. This will allow you to save and restore objects using setOnInstanceState methods of both Activities, Views, and some adapters. They will likewise, have a restore method in which you can rebuild the object. Parcelable is preferable over Serializable.
Larger data may require a shared file or database depending on the data that you want to have synced. There is a 1 MB size limit for parcelables being passed between Activities. One common tactic is to save the information to a file and send a URI to the location of where the information can be retrieved.
Answering your question - yes, there is a situation when you set x = true and value will be 'reset' back to false. Well, not exactly reset but consider this scenario: you have an activity and a service. Service is using separate process (you can define that in AndroidManifest when you declare your service). Then those two processes (main app and service) won't share memory and setting x to true in your activity won't affect the value of MyClass.x in your service. In all other cases changing value in one place will be visible everywhere else. Hope it helps!
No, a static variable will not be changed unless you change it or the app ends, it is safe (but generally unclean) to use it. Closing the activity the variable lives in won't hurt it.
You suggest you just need to keep track of a value as you move around activities. In that case you can add the value in your Intents as what is called an 'extra'. If you need to also pass back the value after, android also has the startActivityForResult feature
Intent extras example:
x below could be any type of value including any object which implements Parcelable
Intent intent = new Intent(...);
intent.putExtra("myKey", x);
startActivity(intent);
in receiving class:
x = getIntent().getBooleanExtra("myKey");
Edit:
Given your additional comment - "lists of objects that contain yet more lists of objects" you may get a Parcel too large exception when trying to use extras, but this is an indication you have a bigger architectural problem and that there may be a better approach
Use Gson.
Gson is a Java library that can be used to convert Java Objects into their JSON representation. It can also be used to convert a JSON string to an equivalent Java object. Gson can work with arbitrary Java objects including pre-existing objects that you do not have source-code of.
You have two options. Convert to string , then put data in an intent then pass to activity. Or Convert to string with gson, save to a preference, then in the other activity, check if the preference is alive and read from it.
If you wish to be bold, you can persist to database preferably using Realm for Android or ObjectBox is a new mobile object database optimized for performance. With ObjectBox, we are bringing technology from NoSQL server databases to mobile.
I wanted to learn more about the Android Services / Broadcasts, so I started a simple project, to create a battery monitoring app. It turned out pretty good, I'm using it for a few days now, but I want to add a new function: to show since when is the phone charging/discharging.
First I thought that I would create two static fields in my BoradcastReciever extension class, where I get and publish the data about the battery, one for the actual state (charging/discharging), and one for the time, when the change in state happened. This way, I could just subtract from the current time the last change, and know exactly since when is the phone charging/discharging.
But there is a problem with this solution: It won't show the correct data at first, when a user starts the app. I wouldn't make a big deal of it, but I saw that Android tracks this data somewhere, because inside my phone settings I found this information, so why take the hard way.
So my question is: is there an easy way to get from the Android system the date/time (no matter what format) of the last charging state change?
I looked at the BatteryManager reference but there are no constants named after what I seek, and which I could use, to get the information from the Intent of my receiver.
The Android OS tracks the connect/disconnect of a power source, but does not make this data accessible to apps. You have to record this all yourself, using intent filters.
The two intent filters to use are android.intent.action.ACTION_POWER_CONNECTED and android.intent.action.ACTION_POWER_DISCONNECTED; with these, you can monitor when the power source is connected and disconnected.
You can find information about this process explained incredibly clearly here. Another blog describing the process can be found here.
I have something of an abstract question regarding managing live feeds/polling on web sites.
I am creating a web app (built on Java/Spring/Hibernate) and on the user's home page I want a live feed of the latest activity from all the members of there team, and I am trying to work out the best way to handle this query on the server side.
The brute force way would be to load the current users list of team mates, and then iterate through each of his team mates, loading their latest conversations/file uploads/etc, and then merging all this activity in to a single list sorted by timestamp and returning that (lets say for sake of example that we just return the top 10 latest activity for the feed).
However, that seems very un-performant, especially as this operation would need to be done regularly (depending on the polling interval).
I have also considered making all the potential activities (conversations/status updates/uploads) as extending an Activity class and then just having a direct SQL/JPQL query in a DAO that selects all the latest activity from a set of users to be returned, but concerned that might bypass the caching and continued access to the DB would also reduce performance.
Has anyone handled this type of problem before? any one know what a good approach is?
Thanks!
This is an old one now, but here is what i did for this:
All tasks that should appear on a live wall extend Activity (this was already the case)
Created a new Notification object, the Notification had a link to the underlying Activity and a link to a user (who was being notified).
Created a pre-persist hook for Activity that created a Notification object for the Activity being persisted - it did this for every user that was interested (all users following the user that was persisting the Activity)
For the moment, Notifications are persisted/retrieved to the DB - possibly not scalable to very high volumes, but the approach I think supports moving to a Queue based system (such as LinkedIn's Kafka queue library which is designed exactly for this purpose). As it is per-user, it also provides the option to have a read/unread notification flag for significant notifications.
When I log a user in, I pull down some user data. It's just a userid and stuff like that. A couple of strings really. The thing is I don't want to pull this down every time if it's the same user over and over and so I want to store it locally across sessions. I'm aware of SQLite but is making a table just for 1 row really the best solution? Is there not another, better way?
Check the developer.android.com site. Data Storage :
http://developer.android.com/guide/topics/data/data-storage.html#pref
The SharedPreferences class provides a general framework that allows you to save and retrieve persistent key-value pairs of primitive data types
If primitive types is all you need, and the boundary is your application (no multi process stuff), then you should be OK with just using SharedPrefs. Anything else (files,sqlLite) is overkill. SharedPrefs has a clean api that should be sufficient for your needs.
See the developer.android.com site for shared pref usage.
You could use Shared Preferences. It is meant for that.
This other question asks about storing files on the device. The recommendation is to store files on the SD card (if available) and that could be a solution to your problem.