I'm building an Android app which syncs data to Google Fit and uses the Google Fit SDK to achieve that - but I'm pretty sure my question also applies when you are using the REST API.
Within my app users can also change data inserted to Google Fit. The Google Fit SDK has two distinct functions to handle those kind of things: insertData() and updateData().
Now, I don't want to keep track of whether a user changed an already synced data point vs whether it is an entirely new datapoint. I just want to have a simple Boolean flag which indicates whether a data point has already been uploaded to Google Fit or not - that's to keep things simple and reliable on the app's side.
So when a user creates a new data point in my app, I set a syncedToGoogleFit flag for that data point in my DB to 0. When the data point has been synced to Google Fit I set it to 1. When the user later changes the data point in my app I set it to 0 again and so on.
However, the Google Fit SDK distinguishes between inserting and updating which means a simple Boolean wouldn't be enough to track changes on my end as insertData() will fail if there already is a data point for a given timestamp. Is it possible to always call updateData() even if I am actually inserting new data and that way get by with just the Boolean flag on my end?
Looking at the documentation it should be okay, but I would feel safer if someone could confirm that. Also I'd like to know whether there are any potential performance implications of the approach outlined above, but I guess this is just something the SDK devs can answer.
I've played around quite a bit with the SDK now and from what I am seeing I can say, that using updateData() seems to work just fine.
Related
I am trying to create an experiment using Firebase remote config.
The criteria is as follows:
It should target only new users who have not used the app ( opening the app for the first time)
Now on further research I found that there is a user property as below:
However, this is not available in the experiment window or a similar property that fulfils the above criteria in the Firebase console as seen below:
I can only see the user properties set by my code. One way I can think of is to use one of my custom user property which is not yet set (but set to a value like null), but I don't know how I can do this.
References
https://support.google.com/firebase/answer/6317486?hl=en
https://firebase.googleblog.com/2016/10/better-user-targeting-with-firebase.html
I will share our experience with experiments for new users and how the different combinations of targeting work because we worked with it a lot already. You can skip the investigation part if you're not interested and just check the solution that we use now.
Our Investigations Part:
Firstly, when we integrated Firebase, we were afraid that Audiences won't work properly for experiments targeting cuz all current users will be treated as new ones after integration, so we checked several approaches and went with an approach of creating specific User Properties that we specified on the client side differently for old/new users. For instance, we created a User Property called adv_experiment_enrolled and specified on client side values 'enrolled'/'not_enrolled', so all new users after installation of this version became 'enrolled' and old ones after updating the version just became 'not_enrolled'. And we just used that User Property as targeting in an experiment. That worked well, but it wasn't a general approach that we could use easily for all experiments and we needed to create User Properties for each new experiment.
So we've tried the Audiences approach after few months of integration that was what #jackes described here with First Open Time user property:
https://stackoverflow.com/a/50075684/2723437
And we've got several problems, first of all, seems they had some troubles with populating of that kind of audience and just ~3-5% of new users were getting there. We also created an Audience depending on First Open event itself and used it too, it was populating better and was close to the real number of installs that we had. But we've noticed problems with this approach as well and the biggest one was that an experiment had only 20-30% of users from that Audience. We tested it and noticed by some of our metrics that seems users are not enrolled in this experiment in their first session cuz 1) Firebase takes some time to enroll a user in the Audience and 2) Remote Config has 12h cache by default, so it wasn't really a data for most of the new installations.
A solution that seems to work well for now:
We were surprised with that Firebase does have User Property for First Open Time, but doesn't allow to use this as the targeting for experiments (It would be very helpful to solve this problem tbh), so we just decided to try our good experience with User Property targeting and apply the general approach First Open Time user property, so we've created our own custom_first_open_time especially to target installations after some specific time (we just used current timestamps for platforms in seconds).
Important notes:
- You have to set up user properties before loading a remote config.
- You have to keep this first open time on the client side persistently once you generated it (usually you use NSUserDefaults/SharedPreferences for iOS/Android for that)
Sample of experiment configuration:
Didn't tried, but it should work. Create an Audience in Firebase Console with following condition: First Open Time is greater than or equal to some date. Where the date should be the next day after you starting an experiment.
I am newbie to contentful and I have written an android application which uses content delivery API to fetch the content from my space.
I have used Vault and normal API (without vault) to fetch the content.
I observe that there is always a 3-5 seconds of delay in fetching the delta changes (new and update content).
My requirement is to give a real time data sync.
Is this an issue with my implementation or its an expected behaviour from contentful.
Sample code:
1. Using Vault
Vault.with(App.getInstance(), SampleSpace.class).requestSync(
SyncConfig.builder()
.setClient(ClientProvider.get())
.setInvalidate(false)
.build());
List<SampleTable> appointments = Vault.with(App.getInstance(), SampleSpace.class)
.fetch(SampleTable.class)
.where(SampleTable$Fields.DATE+"=?", mDateToCheck)
.all();
Normal API
private final CDAClient client = CDAClient.builder().setToken(CDA_TOKEN).setSpace(SPACE_ID).build();
client.observe(CDAEntry.class).all()
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
.subscribe(new Action1<CDAArray>() {
#Override
public void call(CDAArray entries) {
//business logic here
}});
Thanks for your time and help!!
I'm a maintainer of the Java and Android SDKs in Contentful.
There could be some reasons for the slowdown:
1) You are syncing a lot of data
This would mean, that a lot of data, potentially even different pages have to be fetched from Contentful, parsed, serialised and put into the database in the Vault case.
In this case taking a look at fetching the entries by id and not using sync might be an idea. Sadly you would loose the niceness of Vault model classes and would need to implement the mapping from Contentful models to your custom models yourself.
2) ClassLoader.getResources
In your code snippet, you are recreating a CDAClient or Vault with every sync call. This has a known issue on Android and we are currently working on fixing it.
For now, till an update is out, the recommendation is to try and see if storing Vault and/or the CDAClient in a field might be helpful for subsequent calls.
3) The network is slow
Sadly this would mean, there is nothing we can do from our side ... ;)
I hope this gives you some pointers, on a solution, please feel free to report back with any progress you encounter.
The only solution I find to this issue is to use Contentful Preview API.
So when some object is modified/deleted/created, the response speed will be the same. That being said, the user can get every update in one second or less in the app/web.
The problem is the app will be showing entries that are published or not (draft),so it depends on the project requierements.
In case the user needs to use this solution, he must use the Content Preview API - access token which is in APIs top panel section in Contentful. I hope it helps!
I am creating one Google Fit compatible App. My objective is to store Google Fit data using HistoryApi, and provide kind of Back Up- Restore functionality to user. If user buys new Android devices then he/she should be able to BackUp(sync) old data using his/her account.
I need to use Custom Data Type, as Public Data Types doesn't meet my requirements.
Everything works perfect, I am able to insert data and read data using History Api.
But When I try to read data from Another Android device using same Google Account then data is not available to read there.
My problem seems similar to this Custom DataTypes not synching between devices
This statement from Google Fit Document is not clear to me.
Custom data types are not available to use in other apps. Only the app
that creates a custom fitness data type can use it
source : CustomDataType
Q-1) What does it really means ? If I have an app GoogleFitDemo installed on multiple Android devices, then is it possible to sync data between this same app between multiple Android devices ?
Q-2)Is it improper way to store and backup data using Google fit ?
Update:
Finally, I found that Custom Data Type can also be synced normally, same as other Public Data Types. I had the sync issue as mentioned by #Ifor. Sync functionality is still buggy. In some scenarios sync stops working, and sometimes synced data is inconsistent across multiple devices.
1). My understanding is that same app same account but different devices it should work. Having said that sync is notoriously slow (hours days...) and has been buggy so it may be hard to tell if you have it right or not.
2) There are better backup methods... But if the data fits in with the rest of the stuff Google Fit is about and is not too big then it's probably ok.
I'm using Google Analytics SDK to collect statistics from my Android application. I want to be able to create a chart showing which language are users using.
To do so, I'm creating a visitor scope custom variable like this:
tracker.setCustomVar(1, "Language", language, 1);
The problem is I'm afraid that this approach isn't correct. I want to create a pie chart in Home -> Dashboards in google analytics, so I choose Add widget -> Pie -> "Unique Visitors" grouped by "Custom Variable (Value 01)".
Pie chart created like above shows invalid results. The goal is to get last variable value for each user and then display the number of users for each value. What it actually does is it takes all variable values and for each value it shows the number of visitors that ever had this value.
This means that if someone switched between languages, he will appear in both languages in the chart. Not the one that he is actually using.
So my question is - how to do it correctly? Should I change something in the code, perhaps use something other than variables? Or maybe it's possible to fix it just via google analytics website?
Thanks
There's no way to achieve what you want.
If the same visitor changes it's language it will have that language from now on, but he'll still show up as the old value on the days before. It happens because in GA history is never rewritten, data is processed by session(visit) and the data that goes in is static and can't be removed or changed. If the visitor was reported only on the new value it means that the visits before would have been changed. This is just against the design.
You may find other ways to remedy that and understand better people that are changing their languages on the application. You may fire an event when Language is changed for example and understand the impact of new languages being added to your application.
There's only one place in GA where you have a better view on multiple sessions. and that's the multichannel funnels, but they only work for Goal Completions reporting on different Traffic Sources. The reports you see there are processed by a separate system inside Google Analytics and can break some of the rules about how Google Analytics processes and stores data. Because of that they can tie the visit back together and understand the progression of changes that happend on the traffic sources dimension and lead to a goal completion.
I'm sorry it doesn't solve your problem. But unfortunately it's just not possible by design.
You don't need to set the user's language yourself, go to your Google Analytics webpage > Audience > Demographics > Language.
This will show you everything you need to know about your users' selected languages.
EDIT:
For a custom app value (like a setting value), in my experience the best approach is to set up a daily/weekly ping of that value as an event, so you'll get a daily pie chart of all your active users selected language.
you can set up such a ping using the AlarmManager
i'm looking for a way to sync items stored in a database among users
so anyone of those users changes anything from his phone , the change will be reflected in the database and SYNC with all users related to him in real time
what's the best way to achieve the real time sync ? push notification ? is Urban airship what i'm looking for ?
Syncing data well is often specific to your application and your data. It's beyond the scope of an SO question but here's some thoughts if you implement your own ...
Some of the interesting design points are:
Reliably getting a delta
Dealing with conflicts
How real time is real time?
For reliably getting a delta, be careful about relying on date time for distributed machines. This post discussed some of those challenges and some alternatives.
Can I Rely on the iOS Device Clock Being Correct?
Merging new entities is easy but if multiple folks are editing the same entity, you need to decide how to merge. For conflicts, you can in order of preference (1) auto merge - come up with an algorithm that automatically merges the content without user intervention and ideally with no data loss (2) rely on the user to merge with an interface and (3) a form of auto-merge: last write wins. There's also variations where you interleave the revisions - it's a form of last write wins but the revisions are maintained . You can also auto merge at a field level of an entity if that's appropriate. My post to the question above covers interleaving but it depends on what your data is.
How real is real time? When syncing occasionally connected devices, the devices will getting farther and farther out of date and it takes time to catch up. Consider batching sets of changes in the communication pattern to optimize but it will still not be real time. Embrace that in the design - does the user see data animate into there current views as data is synchronized?
Architecturally, you'll likely want to expose your data in the cloud through REST services or SOAP web services since it's cross platform. For multiple devices platforms, you'll likely end up porting the sync algorithm. The best you could hope for is using something like Sqlite so you can share your devices database schema code and sql statements.
I would start with Dan Grover's presentation, "Cross-Platform Data Synchronization": http://iphone2009.crowdvine.com/talk/presentation_file/5104/Grover_Syncing.pdf