I am trying to create an app using Google Fit Api and i am trying to get the total time of exercise (supposed that the exercise is walking) for the user. What i want basically is to get the value marked in below image :
Google Fit Time Screenshot
I was thinking to work with sessions (https://developers.google.com/fit/android/using-sessions) but i prefer to skip this if there is already something provided by Google. I know how to get the daily steps/calories/distance but i am not able to find anything to get the daily exercise time.
Let me describe what I found so far, but there is one issue left...
You can use the aggregate api and group by activity type. Here is an example with daily bucketing:
POST https://www.googleapis.com/fitness/v1/users/me/dataset:aggregate
{
"aggregateBy": [
{
"dataSourceId": "derived:com.google.activity.segment:com.google.android.gms:merge_activity_segments"
}
],
"endTimeMillis": "1481788800000",
"startTimeMillis": "1481702400000",
"bucketByTime": {
"period": {
"timeZoneId": "America/Los_Angeles",
"type": "day",
"value": 1
}
}
}
The call will return a number of records, each containing three values: activity type, duration in milliseconds, and number of segments. You can find the activity types at: https://developers.google.com/fit/rest/v1/reference/activity-types. You can add up the milliseconds for the activity types you are interested in.
Now, the issue - I have seen examples of mismatch of activity types between the API and Fit app. I don't know how widespread the mismatch is. See my question: Getting active time from Google Fit Rest API.
Related
Is there any way to order the subscription list of Youtube channels by recently subscribed?
youtube
.subscriptions()
.list("snippet")
.setOrder("")// relevance, unread, alphabetical
.setMaxResults((long) 1000) // it is not affecting, the max limit is 50
.setMine(true)
.execute();
According to documents, I can only get max 50 items at a time, and I have only three order type parameters relevance, unread, alphabetical.
But I need to reach the channel I subscribed lastly. I would be really appreciated it if anybody helps me to handle this.
Thanks in advance!
According to the docs, you have the following parameter at your disposal:
myRecentSubscribers (boolean)
This parameter can only be used in a properly authorized request. Set this parameter's value to true to retrieve a feed of the subscribers of the authenticated user in reverse chronological order (newest first).
Note that this parameter only supports retrieval of the most recent 1000 subscribers to the authenticated user's channel. To retrieve a complete list of subscribers, use the mySubscribers parameter. That parameter, which does not return subscribers in a particular order, does not limit the number of subscribers that can be retrieved.
That is: do insert something like .setMyRecentSubscribers(true) in the sequence of setters of your code above. (Also you may remove the setChannelId setter call, since, by requiring from you to be authorized to invoke this endpoint, the API already knows the channel to which your call is referring to.)
Note also that the parameter's maxResults maximum value is 50. To receive only the most recent subscriber have .setMaxResults(1) in the setter sequence above.
If your want to obtain the list of all your subscriptions then there's the following parameter:
mine (boolean)
This parameter can only be used in a properly authorized request. Set this parameter's value to true to retrieve a feed of the authenticated user's subscriptions.
Have .setMine(true) (without .setChannelId) in your setters sequence.
You will have to invoke repeatedly the API's endpoint to get all of your subscriptions, since this endpoint provides paginated result sets. Upon obtaining all those subscriptions, sort them by snippet.publishedAt.
If you're only interested to obtain the most recent channel to which to have subscribed, instead of the sort algorithm, is sufficient to use the max algorithm (O(n) instead of O(n log n)) on the same property.
For an example of how to implement pagination in your code, have a look at some of the sample code provided by Google itself.
As I understand from your question, you want to check if you are following a specific youtube channel with help of Youtube Data API V3.
For that it is mentioned in the document that you can use forChannelId parameter.
Also Youtube Data API has a playground to let you see the results of your query. You can simply put a channelId in forChannelId field and result will return an empty array if you are not subscribed specified channel or result will return the data of that specified channel if you are subscribed to it.
You can do a simple request from your Java app to get results. In this code example I'm checking if authorized youtube API user is subscribed to Firebase Youtube Channel or not.
SubscriptionListResponse response = request.setForChannelId("UC_x5XG1OV2P6uZZ5FSM9Ttw")
.setMine(true)
.execute();
And response will include details of specified channel in the request you will make. I also share response of the request I shared above.
{
"kind": "youtube#SubscriptionListResponse",
"etag": "zCQ7lTwIBgdyVsQmbymEu-fUgjU",
"pageInfo": {
"totalResults": 1,
"resultsPerPage": 5
},
"items": [
{
"kind": "youtube#subscription",
"etag": "A-G_B0BnSqn7XtJi7BgHJEk9L3Q",
"id": "uTEDDg6jpPBwnsim9moHkataEljshwFopudOgIy34nk",
"snippet": {
"publishedAt": "2020-07-08T14:02:43.789000Z",
"title": "Google Developers",
"description": "The Google Developers channel features talks from events, educational series, best practices, tips, and the latest updates across our products and platforms.",
"resourceId": {
"kind": "youtube#channel",
"channelId": "UC_x5XG1OV2P6uZZ5FSM9Ttw"
},
"channelId": "UCC77fYySvfP7p-6QGaa-3lw",
"thumbnails": {
"default": {
"url": "https://yt3.ggpht.com/-Fgp8KFpgQqE/AAAAAAAAAAI/AAAAAAAAAAA/Wyh1vV5Up0I/s88-c-k-no-mo-rj-c0xffffff/photo.jpg"
},
"medium": {
"url": "https://yt3.ggpht.com/-Fgp8KFpgQqE/AAAAAAAAAAI/AAAAAAAAAAA/Wyh1vV5Up0I/s240-c-k-no-mo-rj-c0xffffff/photo.jpg"
},
"high": {
"url": "https://yt3.ggpht.com/-Fgp8KFpgQqE/AAAAAAAAAAI/AAAAAAAAAAA/Wyh1vV5Up0I/s800-c-k-no-mo-rj-c0xffffff/photo.jpg"
}
}
}
}
]
}
I have an upcoming video games app. A game release can come out on multiple platforms. I heard that firestore is much more flexible than firebase real time database on how you can retrieve your data. I'm stuck on how can I check if my game release documents in my release collection contains the user chosen platforms, so the app can show the games coming out on his platforms.
This is what I currently have
platforms is a list of Integer which contains platforms ids
databaseReference.collection(getRegionNode())
.whereEqualTo("m_y", monthFilter)
.whereArrayContains("platforms", platforms)
.orderBy("date", Query.Direction.ASCENDING).get().addOnCompleteListener(listener);
Here's an example of a game release document:
1369: {
"src": "Images/dead.png",
"name": "red dead 2",
"date": 2018-10-26,
"region": worldwide,
"platforms": "[12, 13, 54]"
}
Let's say for example, user wants to only be shown platform 12 and 13 games, I want a query that checks and retrieves all releases documents where 12 and 13 are in their platforms list. Thank you!
Firestore Query's whereArrayContains(String field, Object value):
Creates and returns a new Query with the additional filter that documents must contain the specified field, the value must be an array, and that the array must contain the provided value.
According to your comments, your platforms object that is passed as the second argument to this method is of type array. What you are actually doing, you are searching in the platforms property which is of type array for an array, which is not possible since the platforms array in your database contains numbers:
"platforms": "[12, 13, 54]"
And not arrays. A query like this:
databaseReference.collection(getRegionNode())
.whereEqualTo("m_y", monthFilter)
.whereArrayContains("platforms", 12) //Passed a number as the second argument
.orderBy("date", Query.Direction.ASCENDING).get().addOnCompleteListener(listener);
Will work fine because we are searching within the platforms array for a number. Please also note, if you intend to use this king of query, an index is required. For how to create an index, please see my answer from this post.
Even if you using the above query, you can filter your items using only one whereArrayContains() method call. If you will use more than one, the following error will occur:
Caused by: java.lang.IllegalArgumentException: Invalid Query. Queries only support having a single array-contains filter.
If you need to filter on more than one platform, you'll need to change the logic of structuring your database by creating a property for each individual platform that you have and chain whereEqualTo() method calls. I know it sounds a little weird but this is how Cloud Firestore works.
Your schema should like this:
1369: {
"src": "Images/dead.png",
"name": "red dead 2",
"date": 2018-10-26,
"region": worldwide,
"platformsOne": 12,
"platformsTwo": 13,
"platformsThree": 54
}
To find all the games for platform 12, 13 and 54, you should use a query that looks like this:
FirebaseFirestore rootRef = FirebaseFirestore.getInstance();
Query query = rootRef.
.whereEqualTo("platformsOne", 12)
.whereEqualTo("platformsTwo", 13)
.whereEqualTo("platformsThree", 54);
I have a quick question about the best practices for data structure in a firebase database.
I want users of my app to be able to maintain a friends list. The firebase documentation recommends creating a schema (not sure if thats the proper word in this context) that is as flat as possible. Because of this I thought it would be a good idea to separate the friends section from the player section in the database like so:
{
"players":{
"player1id":{
"username":"john",...
},
"player2id": ...,
"player3id": ...
}
"friends": {
"player1id"{
"friends":{
"friend1Id":true,
"friend2Id":true
}
},
}
"player2id"{
"friends":{
"friend1Id":true,
"friend2Id":true
}
},
}
}
So my questions are as follows:
Is this a good design for my schema?
When pulling a friends list for one player, will the friends lists of EVERY player be pulled? and if so, can this be avoided?
Also, what would be the best way to then pull in additional information about the friends once the app has all of their IDs. e.g. getting all of their user names which will be stored as a string in their player profile.
Is this a good design for my schema?
You're already thinking in the right direction. However the "friends" node can be simplified to:
"friends": {
"player1id": {
"friend1Id":true,
"friend2Id":true
}
}
Remember that Firebase node names cannot use the character dot (.). So if your IDs are integer such as 1, 2, and 3 everything is OK, but if the IDs are username be careful (for example "super123" is OK but "super.duper" is not)
When pulling a friends list for one player, will the friends lists of EVERY player be pulled? and if so, can this be avoided?
No. If you pull /friends/1 it obviously won't pull /friends/2 etc.
Also, what would be the best way to then pull in additional information about the friends once the app has all of their IDs. e.g. getting all of their user names which will be stored as a string in their player profile.
Loop through the IDs and fetch the respective nodes from Firebase again. For example if user 1 has friends 2, 3, and 4, then using a for loop fetch /players/2, /players/3, and /players/4
Since firebase pull works asynchronously, you might need to use a counter or some other mechanism so that when the last data is pulled you can continue running the completion code.
I started developing simple app to learn Firebase, I followed cool blog post: https://firebase.googleblog.com/2013/04/denormalizing-your-data-is-normal.html
In my app, I want to store user profiles (its extension of firebase user) and relationship between users (something like friendship)
I came up with this data structure idea:
profile
profile1:
userName:"User 1",
userDescription: "User 1 description"
profile2:
userName:"User 2",
userDescription: "User 2 description"
profile3:
userName:"User 3",
userDescription: "User 3 description"
profileFriends:
profile1:
profile2: true
profile2:
profile1: true
profile3: true
profile3:
profile2: true
Of course instead of profile1 I use pushed keys.
I wonder I its okay for such a use case - I want to display all friends of profile2.
I have to get Database reference to
"profileFriends/profile2"
And then iterating childs gives me keys: profile1 and profile3 which I can then listen using reference
"profile/profile1"
"profile/profile3"
Since Im working in Android, I can wrap all this code and use Observable that emits profiles.
Question: Do I get this right? I have some SQL background and standard request-response api experience, Im just little worried if my user have 100 friends Ill need to make total 101 listeners - is it similar to make 101 requests? Is there any smarter way to solve "join" in non-joinable no-sql database?
I guess another solution is denormalization, but I'm not a big fan of updating many places to change for example profile description
I'm quite new to Android programming (very little programming experience). I want to make an app that will track Car maintenance. I would like users to be able to see their data (roughly) according to the following hierarchy:
Year (see total costs, maybe summarize categories)
--Month (month's costs)
----Maintenance Instance
------Details about the instance (what was done for what cost)
I don't have my data design finalized, but you can see the kind of data I'm trying to track. What approach would you suggest? Do I need to use SQLite? If so, would you recommend a hierarchy of tables or just one table that will be shown hierarchically through queries? Like I said, I'm new. I'd appreciate any pointers in the right direction.
In Android, you can use SharedPreferences to store simple data like global preferences (i.e. in your app you could store a currency flag as a preference to display currency as dollars or pounds) but for anything more complicated you should use SQLite. This tutorial is excellent and will get you started - http://www.vogella.com/tutorials/AndroidSQLite/article.html It seems like you could have one table with each row being a maintenance entry with columns for the date, cost and action carried out. You could then query the database by a date range to get the cost for that range or a list of action carried out in that range (e.g. per month or year). Each row would represent a separate maintenance event.
I recommend you use JSON, a very easy to use storage format. A typical JSON message you would store might look like the following:
{
"maintenance_data": [
{
"date": 1091029109,
"maintenance_details": "Drove car around while owner was gone"
},
{
"date": 1021234134,
"maintenance_details": "Ate cookies while on job"
},
{
"date": 1041023234,
"maintenance_details": "Ain't nobody got time for maintenance"
}
],
"car_id": 1234,
"owner_name": "Slick diddy"
}