I was looking at the code for JumpNotes and there was one thing I just could not figure out.
JumpNotes: AccountList.java
public static final String[] GOOGLE_ACCOUNT_REQUIRED_SYNCABILITY_FEATURES =
new String[]{ "service_ah" };
This is used to get google accounts like so:
mAccountManager.getAccountsByTypeAndFeatures(SyncAdapter.GOOGLE_ACCOUNT_TYPE,
SyncAdapter.GOOGLE_ACCOUNT_REQUIRED_SYNCABILITY_FEATURES,
What is this feature "service_ah"? What does it mean?
Is there any way I can get the source for the authenticator service for google accounts on Android?
From Android Documentation:
Account features are authenticator-specific string tokens identifying
boolean account properties. For example, features are used to tell
whether Google accounts have a particular service (such as Google
Calendar or Google Talk) enabled. The feature names and their meanings
are published somewhere associated with the authenticator in question.
I didn't found any official documentation, but it seems that each feature is of the form service_code where code stands for a Google service.
From this (outdated) list of services, "ah" stands apparently for "Google Mashups Editor & Google App Engine"
This python Google account authentication example is not really helpful for you,but we can learn two things as below:
First, the connection on a google account is handled by GAE in two steps.
> This takes two calls, one to the ClientLogin service of Google Accounts,
and then a second to the login frontend of App Engine.
Second, We can find on line 101 the token "_ah", which means in this case that we enable cookies for automatic auth with the service next time he wants to auth (user data are stored into cookies to skip the first auth call).
So in your case "service_ah" means that you want the user to authenticate one time and then the authentication process should be automatically handled by the AccountManager.
Related
Many Google Applications allow you to switch between Google Accounts and show you the currently connected account.
For example Google Fit, Gmail, Google+, etc...
From the perspective of the code I call .connect() on the Google Client and enter a loop of
connection failed
launch automatic resolution
get activity result
retry connect
until I finally connect.
This is documented in many places, here for example: https://developers.google.com/android/guides/api-client
On the UX side what happens is that the user is presented with multiple dialogs asking every time something different.
One of the dialog ask to chose an Account between the ones available on the phone (it probably automatically resolve without user interaction if there's only one account configured).
How do you query the Google Client to know which account is currently connected?
I found no documentation about it anywhere.
The closest thing I found is this:
https://developers.google.com/android/reference/com/google/android/gms/common/AccountPicker
but I do not create the picker, it's something completely handled by the Play Services in the procedure I described above.
You have to request the Account resource with Google Plus API.
Add the following permission in the manifest:
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
Then use this API to get the account that is logged in currently.
EDIT (addressing the comment):
In .builder add login scope as shown in the example and initiate the G+ Api as well. Since you do not need social scopes, this scope will give you access to currently authenticated user's information.
Once you setAccountName through the builder, you can access the Account resource for this user which you can get at anytime through getAccountName.
EDIT 2:
So apologies for not addressing the G+ context with last edit.
Here's a class in simple Google Sign In (Identity platform) which give you access to account resource.
More information in the official documentation.
I want to use Google Drive for cloud sync purposes.
Is it possbile using Google Drive API for Android to connect to a specific account that will act as a cloud storage server ?
How can I set the user account and password when I try to connect with that specified Google account ?
So far I'm using:
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addApi(Drive.API)
.addScope(Drive.SCOPE_FILE)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
But this provides the user with a login dialog to select its own local account which is not what I'm intending to do. Thanks.
This is an excerpt from this answer I gave on a similar question:
There are two main items you need to make a request to a Google API:
refresh_token - Used to get more access_tokens and never expires
access_token - Used to send API calls (example: upload a file) and expires every 60 minutes.
In order to get either of these you have to follow certain steps.
Obtain a OAuth 2.0 client ID through the Google Developers Console
Obtain an access token from the Google Authorization Server
Send the access token to an API
Refresh the access token, if necessary
More specific information about this "general" process can be found here.
The tricky step is getting the refresh token because once you have that stored in a secure location, you can do anything with simple httpRequests.
To get a refresh token, a user has to agree to give your project access to certain features. This is called scopes in Google language. You can do this in many different ways (according to Google):
There are several ways to make this request, and they vary based on
the type of application you are building. For example, a JavaScript
application might request an access token using a browser redirect to
Google, while an application installed on a device that has no browser
uses web service requests.
The one thing they don't tell you is that, in your case, it doesn't matter what medium you use to get the refresh_token because you are only using one account. The Google Drive API isn't really designed to be used like a server. It is designed to be used by a developer that wants to store information on each of its user's accounts. Like if you had a picture app, you could have a feature that stores edited picture on someone's personal Google Drive account.
What you (and many others who have recently asked about) want to do is essentially use a Drive account as a server. That means that the medium through which you get your refresh_token does not have to be related to the medium in which you are using the Drive Account.
For example in my specific case, I wanted a way to store user pictures on a server for free for an android app. I am using this free service called Parse to act as my database server, but they give you very limited file storage in their free tier.
Because of this, I decided to try and figure out how to use Google drive accounts to expand my storage. I created a generic gmail account something like "hostingaccount#gmail.com" to be the host of the files (15g for free).
To get my refresh_token, I setup a php server to authenticate that one account. When someone goes to the page I setup, they are prompted to login and then grant access to my project to use their Google Drive account (Specific scope: https://www.googleapis.com/auth/drive). I then setup the script to print the refresh_token for that account on the screen. I copied that string an put it into my server when now I can easily send httpRequests to:
https://www.googleapis.com/oauth2/v3/token/ to get an access token and to:
https://www.googleapis.com/upload/drive/v2/files to upload files.
I link it at the top of this edit, but this answer shows you how to get a refresh token using my php method. I never spent the time to try an figure out how to get a refresh token any other way, but if you read my whole long answer I think I mention that I believe that this can also be done with the Android Google Drive API.
I have tried to help so many people with this problem, maybe I should just start a blog and make a tutorial about it ;)
I am facing a problem with in app purchases/subscriptions:
If there are multiple accounts on the device, I can't get the purchases, which were made with the second account.
This can sometimes be temporarily fixed, by installing the app from the Google Play web interface, but after a while, the purchases won't appear in the query, forcing the user to reinstall.
I am using the IabHelper classes from this sample.
Doing some Google searches, I found that this bug exists since a while, but unfortunately I couldn't find out if the error is in the IabHelper classes or on Google's side.
I'd like to draw attention to Google, so they provide a proper fix for this, either in the IabHelper classes or in the Play Services or to provide information, how this should be handled.
I am using the code in an app with (at the time of writing) 900.000 active user installs and I have to trigger quite a lot of refunds, due to this.
If there is a fix for this, which I missed, please let me know.
Edit:
Sometimes it's not possible at all to retrieve the purchases, even if there is only one account on the phone.
It seems like there isn't a one way road to solve this, but let's try do this.
When the user first install the app get his/her primary email or all accounts on the device
Ask the user what email will they be using for future payment/ or which account is active for google play.
you can use this code to get the account
Pattern emailPattern = Patterns.EMAIL_ADDRESS; // API level 8+
Account[] accounts = AccountManager.get(context).getAccounts();
for (Account account : accounts) {
if (emailPattern.matcher(account.name).matches()) {
String possibleEmail = account.name;
...
}
}
Don't forget to ask for permission
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
After the user selects the email, you can send a link via email to confirm this email address
Lead all the payment to that specific email.
Method 2
Use the new "Send & Receive money using Gmail" future
Create a email intent and send specific data to the email intent and make payments.
Upon success, send a code to the user email
Use the code to activate whatever purchased they make.
Method 3
Use another payment library or gateway for your in app purchase instead of Google play.
As others have noted, this is a bug with the Google Play Billing Library. If it affects you, star this issue on https://issuetracker.google.com/issues/139597485 so Google can notice it (really?) and start working on a fix.
It is sure a bug in the in-app billing service apis. This is a similar question and as mentioned in one of the answers, may be you need to introduce login mechanism and store the purchases made from an account to your server or locally on the device in an encrypted file or something similar.
I had ran into same problem couple of months later.
After hours of finding solutions and all i came up with a work around something like this,
You can use OAuth 2.0.
But you also have to manage it from your backend.
I am not a backend developer so i didnt know how exactly it does in backend but at app side i have done something like this,
You can use the first Google account allowing authentication on your serve side. OAuth 2.0 is a tool that simplifies and get developers an easy way to allow users to access your application. The OAuthHmacSigner class does manages the authentication.
signer = new OAuthHmacSigner();
signer.clientSharedSecret = Constants.CONSUMER_SECRET;
Then the Android activity uses the following code to launch the OAuth flow :
launchOauth.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
startActivity(new Intent().setClass(v.getContext(),
PrepareRequestTokenActivity.class));
}
});
In order to get an OAuth 2.0 access token, you simply need to call:
AccountManager.getAuthToken()
I Hope this might help :)
I have two accounts, but one does not work. What I did is I went into android's settings, and then went into account preferences. I changed my main account from the one that does not work to the working one. Then I assigned the new account to be the main one for all of my applications, including google play. That worked for me. Sometimes, if it does not work for some reason, you can also go online and access the Google Play store from the internet.
Try to get dup...duplicate dot with file signature ending in .apk or .xcode
I'm not sure if this is the answer you're searching for, but perhaps setting up a shared Google Play Family Library would suffice. It works for up to 5 users sharing the same purchases (app, music, movies, etc), if desired.
(See: https://support.google.com/googleplay/answer/7007852?hl=en)
I am implementing a sync adapter for my app to sync with an appengine backend. On appengine I am using the built in User api for authentication. There is a post HERE that tells how to do it, however the app is listed under the gmail account. Ideally my app would be listed in the accounts. I don't want to ask the user for username and password, just use the existing google account for authentication. Has anyone done this before??
Update:
I've been working on this and it looks like I could implement the AuthenticationService and store the users account name and leave the password as an empty string. In the getAuthToken() methods I should be able to simple return the google auth token. Will post once I get further along...
Perhaps you have misunderstood the Android account system. When you go to Settings -> Accounts & Sync and add a new account what you see then is a list of account types. Often there is a relationship between account types and apps, for example Facebook accounts are used together with Facebook. Normally you would add a new account type if you have a different backend system for handling authentication etc.
If I understand you correctly, you use Google accounts but want it to appear as your own account type. That sounds wrong to me. You'll end up reimplementing the Google account handling, with little value. I believe it is simpler for users if you simply piggyback on what Google provides you with. Your app / service / content provider can be seen when clicking on the account. For example, after installing "Tasks" by "Team Task" (disclaimer: I'm not affiliated with that company) they add "Sync Tasks" to the list of data & sync options.
But if you really want to create your own account type, follow the sample Sample Sync Adapter. Look for the Authenticator code and related resources (e.g., manifest, activity layout, etc.).
This is indeed possible and I have implemented this with success but be warned it is a bit of a headache.
There is an excellent tutorial available called writing-an-android-sync-provider-part-1
... don't forget to check the follow up in part 2
Beyond this there is also an example in the Android SDK samples called SampleSyncAdapter which was invaluable in my development.
With a little hard work and a lot of coffee you should be able to get this working ;)
I need some help understanding what the account manager offers us. I have a web service which requires a token for use. For example, if a developer wants to use my api, they would use a url like:
http://myservice.com/addfriend?name=john&token=abc
The token "abc" is retrieved by the developer using oauth. So now any developer that releases an app which uses my API will have to get their users to go through the oauth flow to get their own token for their app.
Does the android account manager solve any of this? Can developers query the account manager to see if the user has already auth'd in the past, and reuse whatever token is in that central location? I don't see how this would work, take Facebook as an example. They've created their own single-sign-on module. And they probably want to give each third party app that uses them a different token for tracking. And each third party app requests a different set of permissions. I don't know that the android account manager supports any of that.
So I'm curious why facebook would create their own sso support instead of using AccountManager to handle this. Also not sure if I have use cases for AccountManager correct here, maybe it has a totally different use case.
Thank you
May have changed since I last saw this, but
AccountManager am = AccountManager.get(this);
Account[] accounts = am.getAccountsByType("com.facebook.auth.login");
am.getAuthToken
AccountManager is the way to go for registering your account apis through there. The accounts will then show up in "Accounts & Sync" in the menu. You would use
am.addAccount(String accountType, String authTokenType, String[] requiredFeatures,
Bundle addAccountOptions, Activity activity,
AccountManagerCallback<Bundle> callback, Handler handler);
AndDev link: http://developer.android.com/reference/android/accounts/AccountManager.html