gmusic.api
gmusic.api copied to clipboard
Authentication Question
I'm integrating your library with my current app which already uses the Android AccountManager for authentication with an App Engine (GAE) server.
The authtoken obtained for the GAE is fetched as follows
accountManager.getAuthToken(account, "ah", false, new GetAuthTokenCallback(), null);
Where "ah" is the authTokenType for App Engine. Other types are "youtube", "finance" etc for the different apis.
So here's my question... Is it possible to obtain a token this way for gmusic.api and avoid the need to user to enter their password? If so, what authTokenType should be used?
You can obtain auth Token so:
accountManager.getAuthToken(account, "sj", null, this, new AccountManagerCallback() {
@Override
public void run(AccountManagerFuture result) {
// Get the result of the operation from the AccountManagerFuture.
Bundle bundle;
try {
bundle = result.getResult();
// The token is a named value in the bundle. The name of the value
// is stored in the constant AccountManager.KEY_AUTHTOKEN.
Token=bundle.getString(AccountManager.KEY_AUTHTOKEN);
Perfect! I will try it later - many thx.
Awesome - please post a fully example using both the Account Manager and use of the Google Music API
I can confirm it works and will post example when the day job is done
Any progress on the example by any chance?
@milleph would you be kind enough to post it?
It's very easy with Google Play services , you must only add google-play-services.jar and use this code :
token = GoogleAuthUtil.getToken( mActivity, mEmail, "sj");
it's only supported to real devices , no emulator
The two examples posted by @dommy1985 show you how to get the token. By far, the simplest way is by using the Google Play Services jar in his second example. In either case, there are some traps that are best handled in the implementing application, instead of within the gm library. Be sure to read up on using the Play Services jar here:
http://android-developers.blogspot.com/2012/09/google-play-services-and-oauth-identity.html
Google has not yet exposed the Music service through the Google Oauth API, so you can't use the Oauth examples in the article, but the details (responses and handling) are still helpful.
For now, I'll modify the android.gm library so you can pass the token to it and login with it.
Here is an example of how to use the new login method.
In your application, extend AsyncTask to get the token and pass it to the new gm library login method:
public class GoogleAuthTask extends AsyncTask<String, Void, Boolean> {
private Activity mActivity;
public GoogleAuthTask(Activity activity) {
mActivity = activity;
}
@Override
protected Boolean doInBackground(String... params) {
boolean success = false;
try {
String authToken = GoogleAuthUtil.getToken(mActivity, params[0],
"sj");
if (!TextUtils.isEmpty(authToken)) {
GoogleMusicApi.createInstance(mActivity);
success = GoogleMusicApi.login(mActivity, authToken);
if (!success)
GoogleAuthUtil.invalidateToken(mActivity, authToken);
}
} catch (UserRecoverableAuthException e) {
mActivity.startActivityForResult(e.getIntent(), 1001);
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (GoogleAuthException e) {
e.printStackTrace();
}
return success;
}
}
Also in your application/activity, execute the above task where necessary, like this:
GoogleAuthTask task = new GoogleAuthTask(this) {
@Override
protected void onPostExecute(Boolean success) {
Toast.makeText(MainActivity.this, String.valueOf(success),
Toast.LENGTH_LONG).show();
}
};
task.execute([your_email_address]);
// there must be a google account on the device that uses this same email address.
Great @bkhall , You must also make this:
//if GoogleMusicApi.login(mActivity, authToken); return Error 401
GoogleAuthUtil.invalidateToken(mActivity, token);
this is necessary to invalidate the old token is being assigned a new token
Great comment. Updated the example...
@dommy1985 How do I check if 401 is returned? GoogleMusicApi.login() seems to always return true, if the token isn't empty.
You’ll have to build out your own class/method to do that from the source code in the project. At the time, all I cared about was whether or not the login succeeded.
At the point where the request returns an HttpResponse call the httpResponse.getStatusLine().getStatusCode() method. That’ll give you what you’re looking for. If the statusCode == HttpStatus.SC_OK, then continue. You could wrap the cases in a switch-case block to handle the different statusCodes.
From: cypressious [mailto:[email protected]] Sent: Saturday, October 26, 2013 10:04 AM To: jkiddo/gmusic.api Cc: Baron Hall Subject: Re: [gmusic.api] Authentication Question (#5)
@dommy1985 https://github.com/dommy1985 How do I check if 401 is returned? GoogleMusicApi.login() seems to always return true, if the token isn't empty.
— Reply to this email directly or view it on GitHub https://github.com/jkiddo/gmusic.api/issues/5#issuecomment-27148057 . https://github.com/notifications/beacon/ydqSPYcpm3TVNpQocQzaUqVIlTOmhEt-V9_ohJ8yTLoUDJWJf8v3PhRuineGu9UF.gif
Thanks for responding. I modified the login() method to look like this:
public static final boolean login(final Context context,
final String authToken) {
if (!TextUtils.isEmpty(authToken)) {
final SimpleForm form = new SimpleForm().close();
GoogleMusicApi.setAuthorizationHeader(authToken);
mHttpClient.post(context,
"https://play.google.com/music/listen?hl=en&u=0",
new ByteArrayEntity(form.toString().getBytes()),
form.getContentType());
return mHttpClient.getResponseCode() == HttpStatus.SC_OK;
} else {
return false;
}
}
Its a matter of code style - the desktop API version implements the login method as void - and throws exceptions for anything else than OK. And btw - the desktop API version also works on android
I tried to login using following method but the response code given was 200 :
public static final boolean login(final Context context, final String authToken) { if (!TextUtils.isEmpty(authToken)) {
final SimpleForm form = new SimpleForm().close();
GoogleMusicApi.setAuthorizationHeader(authToken);
String response = mHttpClient.post(context, "https://play.google.com/music/listen?hl=en&u=0", new ByteArrayEntity(form.toString().getBytes()), form.getContentType());
Log.d(TAG, "response = " + response);
Log.d(TAG, "mHttpClient.getResponseCode() " + mHttpClient.getResponseCode());
return mHttpClient.getResponseCode() == HttpStatus.SC_OK;
} else {
return false;
}
}
and I got response like this :
12-11 17:55:03.785: D/com.android.gm.api.GoogleMusicApi(24744): response = Google Play Music#gb{font:13px/27px Arial,sans-serif;height:30px}#gbz,#gbg{position:absolute;white-space:nowrap;top:0;height:30px;z-index:1000}#gbz{left:0;padding-left:4px}#gbg{right:0;padding-right:5px}#gbs{background:transparent;position:absolute;top:-999px;visibility:hidden;z-index:998;right:0}.gbto #gbs{background:#fff}#gbx3,#gbx4{background-color:#2d2d2d;background-image:none;background-image:none;background-position:0 -138px;background-repeat:repeat-x;border-bottom:1px solid #000;font-size:24px;height:29px;height:30px;opacity:1;filter:alpha(opacity=100);position:absolute;top:0;width:100%;z-index:990}#gbx3{left:0}#gbx4{right:0}#gbb{position:relative}#gbbw{left:0;position:absolute;top:30px;width:100%}.gbtcb{position:absolute;visibility:hidden}#gbz .gbtcb{right:0}#gbg .gbtcb{left:0}.gbxx{display:none !important}.gbxo{opacity:0 !important;filter:alpha(opacity=0) !important}.gbm{position:absolute;z-index:999;top:-999px;visibility:hidden;text-align:left;border:1px solid #bebebe;background:#fff;-moz-box-shadow:-1px 1px 1px rgba(0,0,0,.2);-webkit-box-shadow:0 2px 4px rgba(0,0,0,.2);box-shadow:0 2px 4px rgba(0,0,0,.2)}.gbrtl .gbm{-moz-box-shadow:1px 1px 1px rgba(0,0,0,.2)}.gbto .gbm,.gbto #gbs{top:29px;visibility:visible}#gbz .gbm{left:0}#gbg .gbm{right:0}.gbxms{background-color:#ccc;display:block;position:absolute;z-index:1;top:-1px;left:-2px;right:-2px;bottom:-2px;opacity:.4;-moz-border-radius:3px;filter:progid:DXImageTransform.Microsoft.Blur(pixelradius=5);opacity:1;top:-2px;left:-5px;right:5px;bottom:4px;-ms-filter:"progid:DXImageTransform.Microsoft.Blur(pixelradius=5)";opacity:1\0/;top:-4px\0/;left:-6px\0/;right:5px\0/;bottom:4px\0/}.gbma{position:relative;top:-1px;border-style:solid dashed dashed;border-color:transparent;border-top-color:#c0c0c0;display:-moz-inline-box;display:inline-block;font-size:0;height:0;line-height:0;width:0;border-width:3px 3px 0;padding-top:1px;left:4px}#gbztms1,#gbi4m1,#gbi4s,#gbi4t{zoom:1}.gbtc,.gbmc,.gbmcc{display:block;list-style:none;margin:0;padding:0}.gbmc{background:#fff;padding:10px 0;position:relative;z-index:2;zoom:1}.gbt{position:relative;display:-moz-inline-box;display:inline-block;line-height:27px;padding:0;vertical-align:top}.gbt{display:inline}.gbto{box-shadow:0 2px 4px rgba(0,0,0,.2);-moz-box-shadow:0 2px 4px rgba(0,0,0,.2);-webkit-box-shadow:0 2px 4px rgba(0,0,0,.2)}.gbzt,.gbgt{cursor:pointer;display:block;text-decoration:none !important}span#gbg6,span#gbg4{cursor:default}.gbts{border-left:1px solid transparent;border-right:1px solid transparent;display:block;display:inline-block;padding:0 5px;position:relative;z-index:1000}.gbts{display:inline}.gbzt .gbts{display:inline;zoom:1}.gbto .gbts{background:#fff;border-color:#bebebe;color:#36c;padding-bottom:1px;padding-top:2px}.gbz0l .gbts{color:#fff;font-weight:bold}.gbtsa{padding-right:9px}#gbz .gbzt,#gbz .gbgt,#gbg .gbgt{color:#ccc!important}.gbtb2{display:block;border-top:2px solid transparent}.gbto .gbzt .gbtb2,.gbto .gbgt .gbtb2{border-top-width:0}.gbtb .gbts{background:url(//ssl.gstatic.com/gb/images/b_8d5afc09.png);_background:url(//ssl.g
how to resolve this issue?
The Android variant has been removed. Is there any way to login with a token?
Is this part of what needs to be implemented (cf. Readme)?
@geecko86 - the Android variant was more like a 'feature' branch. What kind of token do you mean? AFAIK, you can only login to the service using either regular password or the app specific 2-factor auth password. Currently, I think that the only part that works is actually login - everything else pretty much returns 404 - and I can't even say for how long it hasn't worked - probably as long back as 3 months
And, for reference, the current API also works on Android, that is - until it the URL's were changed, which might be around July, 2014
The feature I'm interested in (getAllSongs()) still works once logged in.
I'm talking about the type of authTokens referenced just above. The current API works on Android, yes, but the former Android variant featured a login(Context context, String token) method, which is why I was asking if it was still possible to login with a token and not just a password. You're saying it's not. Unless you have any objection I'll put it back in the code.
I'll also check out commits around July 2014 on Simon's repo. :)
It should still be possible...
If you login once with the username/password method, then cache the token securely somewhere, you can use that token here later, until it expires or it's revoked. In which case you'll have to go through the username/password login again.
However, if you have two-factor authentication turned on, the username/password login will fail. You'll either have to turn it off or create an application specific login in your Google account for Google Music.
Just Google around if you don't know how to do that.
I should also point out that this token is a web token. It's not the same token you get back if you're using Oauth for example, so don't bother with that. It simply won't work. On Mar 8, 2015 9:24 AM, "Guillaume" [email protected] wrote:
The feature I'm interested in (getAllSongs()) still works once logged in.
I'm talking about the type of authTokens https://github.com/jkiddo/gmusic.api/issues/5#issuecomment-12950840 referenced just above. The current API works on Android, yes, but it featured a login(Context context, String token) https://github.com/jkiddo/gmusic.api/blob/0323358eae008159690e47746a1a1d1aaa967947/android.gmusic.api/src/com/android/gm/api/GoogleMusicApi.java#L68 method, which is why I was asking if it was still possible to login with a token and not just a password. You're saying it's not. Unless you have any objection I'll put it back in the code.
I'll also check out commit around July 2014. :)
— Reply to this email directly or view it on GitHub https://github.com/jkiddo/gmusic.api/issues/5#issuecomment-77751553.
You're welcome to introduce the dependency to Android again including the login, but as @bkhall says, its a web token.
@geecko86 - I did some digging yesterday, and I don't think that the URL's have changed. I more seems like that the HTTP requests does not contain all the cookies that Google Music responds with. This is pretty clear if you use the Apache HTTP client instead of the HttpUrl client. @geecko86 Would you care to look into this?
Even though I support the project and would like to see it flourish, I ended up finding a much more efficient way to list all the tracks from Google Play Music on Android.
On top of that, I'm afraid I'm not really qualified when it comes to network stuff... Sorry.
@geecko86 Could you share your "much more efficient way to list all the tracks from Google Play Music on Android"? I am not into cookies and http clients either :)