GoogleAuthUtil.getToken gives com.google.android.gms.auth.GoogleAuthException: Unknown - android

My goal is getting user's basic profile information (first name, last name etc) without any server-side work. And I don't want to use a Google+ sign-in button on the UI.
I could get user's email without any problems. So the next step is to get an access token to fetch the profile, here is my code
String token = null;
try {
token = GoogleAuthUtil.getToken(getApplicationContext(), email, SCOPE);
} catch (final UserRecoverableAuthException e) {
startActivityForResult(e.getIntent(), REQUEST_CODE_AUTH_GOOGLE_ACCOUNT);
} catch (IOException e) {
Log.e(TAG, e.toString());
} catch (GoogleAuthException e) {
Log.e(TAG, e.toString());
}
and I've defined SCOPE
private static final String SCOPE = "oauth2:https://www.googleapis.com/auth/userinfo.profile";
When I run my app, I got "com.google.android.gms.auth.GoogleAuthException: Unknown" exception. I've also tried other scopes like Scope.PLUS_LOGIN, Scope.PLUG_PROFILE. But all of them gave me the same exception.
Btw, in Google API Console, I've already setup a client ID.
I've been stuck on this for 2 days. Any help would be really appreciated.

I think you are doing it wrong. That's the way I do it:
scopes.add(AnalyticsScopes.ANALYTICS_READONLY);
credential = GoogleAccountCredential.usingOAuth2(this, scopes);
if (TextUtils.isEmpty(appPreferences.getUserName()))
{
try
{
startActivityForResult(credential.newChooseAccountIntent(), REQUEST_ACCOUNT_PICKER);
}
catch (ActivityNotFoundException e)
{
Toast.makeText(this, getString(R.string.gps_missing), Toast.LENGTH_LONG).show();
return;
}
}
Take a look at the my source file here:
https://github.com/madhur/GAnalytics/blob/develop/src/in/co/madhur/ganalyticsdashclock/MainActivity.java

Related

Is there any way to get Google Auth Token, without taking user's permission android

I want to take out the GoogleAuthToken, of the user using following method:
private class RetrieveTokenTask extends AsyncTask {
#Override
protected String doInBackground(String... params) {
String accountName = params[0];
String scopes = "oauth2:openid";
String token = null;
try {
token = GoogleAuthUtil.getToken(getApplicationContext(), accountName, scopes);
} catch (IOException e) {
Log.e(TAG, e.getMessage());
} catch (UserRecoverableAuthException e) {
Log.e(TAG, e.getMessage());
startActivityForResult(e.getIntent(), REQ_SIGN_IN_REQUIRED);
} catch (GoogleAuthException e) {
Log.e(TAG, e.getMessage());
}
return token;
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
if (s != null) {
Log.e("AccessToken", s);
preferences.edit().putString(PreferencesConstants.GOOGLE_AUTH_TOKEN, s).commit();
}
}
}
Note: This method successfully gives me the token, BUT THE PROBLEM IS: It asks for user's permission with Allow and Deny for the first time. (which I dont want). Is there any way I can take out the token, without user's permission. ?
This is due to API access given to the application. For each developer machine SHA1 should be given to API and create separate Android API key for the each SHA1.
Go to console.developers.google.com -> select your project
API & AUTH -> credentials.
Create new client Key (though it has other client keys).
select installed app -> android.
Give your package name and SHA1 correctly select OK.

Stripe payment gateway in android

I am integrating Stripe in my android application.
I have found two issues and I am stuck.
First (and major) issue is -
I have got token key from the card information. But when I tried to make my first charge, it shows error in following line.
Stripe.apiKey = "sk_test_0000000000000";
I have googled also but couldn't find any solution.
Creating Stripe Customer - cannot resolve symbol apiKey
I have even seen this kind of question too. But I failed to understand its solution.
Following is my code for making charge:
final String publishableApiKey = BuildConfig.DEBUG ?
"pk_test_000000000000000000" :
//"sk_test_00000000000000000000000" :
getString(R.string.com_stripe_publishable_key);
final TextView cardNumberField = (TextView) findViewById(R.id.cardNumber);
final TextView monthField = (TextView) findViewById(R.id.month);
final TextView yearField = (TextView) findViewById(R.id.year);
TextView cvcField = (TextView) findViewById(R.id.cvc);
Card card = new Card(cardNumberField.getText().toString(),
Integer.valueOf(monthField.getText().toString()),
Integer.valueOf(yearField.getText().toString()),
cvcField.getText().toString());
Stripe stripe = new Stripe();
stripe.createToken(card, publishableApiKey, new TokenCallback() {
public void onSuccess(Token token) {
// TODO: Send Token information to your backend to initiate a charge
Toast.makeText(
getApplicationContext(),
"Charge Token created: " + token.getId(),
Toast.LENGTH_LONG).show();
/*make a charge starts*/
// Set your secret key: remember to change this to your live secret key in production
// Create the charge on Stripe's servers - this will charge the user's card
Stripe.apiKey = "sk_test_0000000000000000000000";
try {
Map<String, Object> chargeParams = new HashMap<String, Object>();
chargeParams.put("amount", 100); // amount in cents, again
chargeParams.put("currency", "usd");
chargeParams.put("source", token.getId());
chargeParams.put("description", "Example charge");
Charge charge = Charge.create(chargeParams);
System.out.println("Charge Log :" + charge);
} catch (CardException e) {
// The card has been declined
} catch (APIException e) {
e.printStackTrace();
} catch (AuthenticationException e) {
e.printStackTrace();
} catch (InvalidRequestException e) {
e.printStackTrace();
} catch (APIConnectionException e) {
e.printStackTrace();
}
/*charge ends*/
}
I have tried these code from different examples. I followed Stripe doc too.
But I got this error:
com.stripe.exception.AuthenticationException: No API key provided. (HINT: set your API key using 'Stripe.apiKey = '.
Second Issue is - about validation.
If I am entering my own card details, and if I write wrong cvv number. It still generates token key.
I have already implemented validation of fields using Stripe's official doc. I don't know how to validate it with real time data.
Solution for the First Issue:
com.stripe.Stripe.apiKey = "sk_test_xxxxxxxxxxxxxxxxxxx";
try {
final Map<String, Object> chargeParams = new HashMap<String, Object>();
chargeParams.put("amount", 500); // amount in cents, again
chargeParams.put("currency", "usd");
chargeParams.put("source", token.getId());
chargeParams.put("description", "Example charge");
new Thread(new Runnable() {
#Override
public void run() {
Charge charge = null;
try {
charge = Charge.create(chargeParams);
} catch (AuthenticationException e) {
e.printStackTrace();
} catch (InvalidRequestException e) {
e.printStackTrace();
} catch (APIConnectionException e) {
e.printStackTrace();
} catch (CardException e) {
e.printStackTrace();
} catch (APIException e) {
e.printStackTrace();
}
System.out.println("Charge Log :" + charge);
}
}).start();
} catch (Exception e) {
e.printStackTrace();
}
Stripe's Android bindings only let you tokenize card information. Once the token has been created, it must be sent to an external server where you can use it in API requests.
You cannot use the token directly from the app as the app must never have access to your secret key, where it could easily be extracted by an attacker who would then have access to your account.
Re. your second question, the card isn't validated with the bank when the token is created (there are still some basic sanity checks, such as checking the number of digits, the fact that the expiry date is in the future, etc.). It is only when you use the token in a server-side API request that the card will be checked with the bank.

How to get refresh token for google plus in android?

I am using following code to get the access token for google plus. Is there a way to get the refresh token so that I can access the google API offline from the web server.
String accountName = params[0];
String scopes = "oauth2:profile email";
String token = null;
try {
token = GoogleAuthUtil.getToken(getApplicationContext(), accountName, scopes);
} catch (IOException e) {
Log.e(TAG, e.getMessage());
} catch (UserRecoverableAuthException e) {
startActivityForResult(e.getIntent(), REQ_SIGN_IN_REQUIRED);
} catch (GoogleAuthException e) {
Log.e(TAG, e.getMessage());
}
This link very clearly explains the api you need to hit to get token and referesh token for your server side polling.
you would receive a response like so.
{
"access_token" : "ya29.AHES6ZSuY8f6WFLswSv0HELP2J4cCvFSj-8GiZM0Pr6cgXU",
"token_type" : "Bearer",
"expires_in" : 3600,
"refresh_token" : "1/551G1yXUqgkDGnkfFk6ZbjMLMDIMxo3JFc8lY8CAR-Q"
}
you would do well to read this guide when playing around with tokens in cross platform scenario.

Ad SDKs can't seem to get the Advertising info from the device

This is what we see from Mopub and other ad networks:
java.io.IOException: Connection failure
com.google.android.gms.ads.identifier.AdvertisingIdClient.g(Unknown
Source)
com.google.android.gms.ads.identifier.AdvertisingIdClient.getAdvertisingIdInfo(Unknown
Source)
They all seem to have the same problem.
The weird thing is that we have no problem getting the advertising id from our app whatsoever with the following source. We get the right advertising id and we have no error logs.
All the SDKs are hitting the same issue (Connection failure).
Any help appreciated.
private void getAdvertisingId(AdvertisingIdHolder receiver) {
AdvertisingIdClient.Info adInfo = null;
String id = null;
boolean isLAT = false;
try {
adInfo = AdvertisingIdClient.getAdvertisingIdInfo(App.getCtx());
id = adInfo.getId();
isLAT = adInfo.isLimitAdTrackingEnabled();
} catch (IOException e) {
SLog.e("error", e);
// Unrecoverable error connecting to Google Play services (e.g.,
// the old version of the service doesn't support getting AdvertisingId).
} catch (GooglePlayServicesNotAvailableException e) {
SLog.e("error", e);
// Google Play services is not available entirely.
} catch (GooglePlayServicesRepairableException e) {
e.printStackTrace();
}
receiver.receive(id, isLAT);
}
I went through trials and errors these days on getting advertising id. Finally I got it!
The connection error can be solved if we pass in getApplicationContext() instead of the context of current activity. Below is my working code:
private void getGaid() {
new Thread(new Runnable() {
#Override
public void run() {
try {
String gaid = AdvertisingIdClient.getAdvertisingIdInfo(
getApplicationContext()).getId();
if (gaid != null) {
Log.d("DEBUG", gaid);
// gaid get!
}
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (GooglePlayServicesRepairableException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (GooglePlayServicesNotAvailableException e) {
e.printStackTrace();
}
}
}).start();
}
getGaid() can be put in onCreate(), onResume(), or onClick() of a view, as long as the thread is called by the main ui thread.
Another thing you may need is to update google play services library to latest version. As the official document here mentioned, IOException is probably caused because the old version of the service doesn't support getting AdvertisingId.
Feel free to comment if there is any other questions.

Google coordinate authentication

When I try to connect to Google coordinate, I always get an exception GoogleAuthException.
I have a Google Maps Coordinate license.
I did create my client Id in google console with my package application name and my SHA1.
I added the permissions to my manifest file:
<uses-permission android:name="android.permission.GET_ACCOUNTS"/>
<uses-permission android:name="android.permission.NETWORK"/>
<uses-permission android:name="android.permission.USE_CREDENTIALS"/>
<uses-permission android:name="android.permission.INTERNET"/>
I use this code:
final String SCOPE = "oauth2:https://www.googleapis.com/auth/coordinate";
try {
mGoogleCoordinatetoken = GoogleAuthUtil.getToken(activity, email, SCOPE);
Log.e(getClass().getSimpleName(), "token ="+mGoogleCoordinatetoken);
} catch (GooglePlayServicesAvailabilityException playEx) {
Log.e(getClass().getSimpleName(), "GooglePlayServicesAvailabilityException "+playEx.getMessage());
} catch (UserRecoverableAuthException userAuthEx) {
// Start the user recoverable action using the intent returned by
// getIntent()
Log.e(getClass().getSimpleName(), "UserRecoverableAuthException "+userAuthEx.getMessage());
} catch (IOException transientEx) {
// network or server error, the call is expected to succeed if you try again later.
// Don't attempt to call again immediately - the request is likely to
// fail, you'll hit quotas or back-off.
Log.e(getClass().getSimpleName(), "IOException "+transientEx.getMessage());
} catch (GoogleAuthException authEx) {
// Failure. The call is not expected to ever succeed so it should not be
// retried.
Log.e(getClass().getSimpleName(), "GoogleAuthException "+authEx.getMessage());
}
Any idea how I can fix this exception?
Exception:
01-30 22:24:53.968: E/getAccessToken()(24800): [ERROR] GoogleAuthException: com.google.android.gms.auth.GoogleAuthException: Unknown
01-30 22:24:53.998: E/AccessTokenTask(24800): mGoogleCoordinatetoken =null
String WEB_APPLICATION_CLIENT_ID = "656631023202-9jsg9faqe87n1uo7f5g6iupti1jl2nps.apps.googleusercontent.com";
String scopes = String.format("audience:server:client_id:" + WEB_APPLICATION_CLIENT_ID );
Log.e(getClass().getSimpleName(), "email ="+email);
String code = null;
try {
code = GoogleAuthUtil.getToken(
LoginActivity.this, // Context context
email, // String accountName
scopes
);
mGoogleCoordinatetoken = code;
} catch (IOException transientEx) {
// network or server error, the call is expected to succeed if you try again later.
// Don't attempt to call again immediately - the request is likely to
// fail, you'll hit quotas or back-off.
Log.e("getAccessToken()", "[ERROR] IOException: " + transientEx);
} catch (UserRecoverableAuthException e) {
// Recover
Log.e("getAccessToken()", "[ERROR] UserRecoverableAuthException: " + e);
code = null;
} catch (GoogleAuthException authEx) {
// Failure. The call is not expected to ever succeed so it should not be
// retried.
Log.e("getAccessToken()", "[ERROR] GoogleAuthException: " + authEx);
} catch (Exception e) {
Log.e("getAccessToken()", "[ERROR] Exception: " + e);
throw new RuntimeException(e);
}
I had the exact same problem and resolved by modifying the scope to :
"oauth2:https://www.googleapis.com/auth/[API YOU WANT]"
(the beggining is very important !)
Hope it will help someone :)
The question is why do you need to get a token. As you commented in my question, you should be fine with GoogleAccountCredential object. Once you have the credential object, you can make calls to Google APIs
credential = GoogleAccountCredential.usingOAuth2(this, scopes);
if (TextUtils.isEmpty(appPreferences.getUserName()))
{
try
{
startActivityForResult(credential.newChooseAccountIntent(), REQUEST_ACCOUNT_PICKER);
}
catch (ActivityNotFoundException e)
{
Toast.makeText(this, getString(R.string.gps_missing), Toast.LENGTH_LONG).show();
return;
}
}

Categories

Resources