Android API Google Drive "connection failed" - android

I try to work with the API Google Drive on Android, first using the demo:
https://github.com/googledrive/android-quickstart
However, I have this error that I can not solve .
GoogleApiClient connection failed:
ConnectionResult{statusCode=SIGN_IN_REQUIRED,
resolution=PendingIntent{421d40e8: android.os.BinderProxy#42137f78}}
#Override
public void onConnectionFailed(ConnectionResult result) {
// Called whenever the API client fails to connect.
Log.i(TAG, "GoogleApiClient connection failed: " + result.toString());
if (!result.hasResolution()) {
// show the localized error dialog.
GooglePlayServicesUtil.getErrorDialog(result.getErrorCode(), this, 0).show();
return;
}
// The failure has a resolution. Resolve it.
// Called typically when the app is not yet authorized, and an
// authorization
// dialog is displayed to the user.
try {
result.startResolutionForResult(this, REQUEST_CODE_RESOLUTION);
} catch (SendIntentException e) {
Log.e(TAG, "Exception while starting resolution activity", e);
// There was an error with the resolution intent. Try again.
mGoogleApiClient.connect();
}
}
#Override
protected void onActivityResult(final int requestCode, final int resultCode, final Intent data) {
if (requestCode == REQUEST_CODE_RESOLUTION) {
if (resultCode == RESULT_OK) {
Log.i(TAG, "Error resolution success.");
// Make sure the app is not already connected or attempting to connect
if (!mGoogleApiClient.isConnecting() &&
!mGoogleApiClient.isConnected()) {
mGoogleApiClient.connect();
}
} else {
GooglePlayServicesUtil.getErrorDialog(requestCode, this, 0).show();
}
break;
}
}

This may be due to negligence on developer's part (as it happened with me) - the SHA1 details you provide on the console are that of production key and you are testing on Debug mode (the SHA1 details would be different). The error message google drive API, gives could have been better, though!

Here is the info for the error you are receiving. I assume you are, but you need to be signed in to access Drive. When I run the sample app, at the very beginning it asks me to choose an account. Perhaps you do not have an account synced with the device you are using? There is an option to "add account", but maybe the behaviour is different when you have zero accounts. The documentation suggests that you either continue without using the API (simply because you cannot unless you sign in) or call startResolutionForResult(Activity, int) to prompt the user to sign in, but it would probably be easiest to just add the account to your device.

You can refer my answer here https://stackoverflow.com/a/41658044/4448757 to connect with google account, this works perfectly only in signed apk
then after you can go for google drive
IntentSender intentSender = Drive.DriveApi
.newOpenFileActivityBuilder()
.build(mGoogleApiClient);
try {
startIntentSenderForResult(intentSender, DRIVE_CHOOSER_REQUEST, null, 0, 0, 0);
} catch (IntentSender.SendIntentException e) {
e.printStackTrace();
}

Not sure if somebody still needs this, but in my case I had two google accounts so I first need to choose which account I want to use. I used this code in the onConnectionFailed
if (!connectionResult.hasResolution())
{
// show the localized error dialog.
GooglePlayServicesUtil.getErrorDialog(connectionResult.getErrorCode(), mContext, 0).show();
return;
}
try
{
connectionResult.startResolutionForResult(mContext, 1);
} catch (IntentSender.SendIntentException e)
{
e.printStackTrace();
}

Related

In-app updates not working. Unable to bind the service error

I am trying to setup the in-app updates dialog in Android but it's not working from the example provided in the docs
I have tried the examples available in the docs which ask you to do this.
appUpdateManager
.getAppUpdateInfo()
.addOnSuccessListener(
new OnSuccessListener<AppUpdateInfo>() {
#Override
public void onSuccess(AppUpdateInfo appUpdateInfo) {
if (appUpdateInfo.updateAvailability() == UpdateAvailability.DEVELOPER_TRIGGERED_UPDATE_IN_PROGRESS) {
// If an in-app update is already running, resume the update.
try {
appUpdateManager.startUpdateFlowForResult(
appUpdateInfo,
IMMEDIATE,
MainActivity.this,
MY_REQUEST_CODE);
} catch (IntentSender.SendIntentException e) {
e.printStackTrace();
}
}
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(Exception e) {
Log.e(TAG, "onFailure: onResume" + e.getMessage() );
}
});
Expected a result that tells gives me some option where it tells me that an updates is actually available. But it directly gives me the error unable to bind to the service.
There seems to be an issue with Google Play Core library with Android Virtual Devices. please use the Real Device
I have disabled the google play store application, and I am getting the same error after this every time I am opening the app on which I am performing this In-App update testing. A very weird implementation has been provided by Google.

Sign in to Google account with old password - how to redirect to blue Google Sign-In page?

I’ve implemented the Google Sign-In SDK into my application and it works fine.
When I click on the sign-in button, a window opens displaying the already stored accounts. Selecting one of those accounts successfully ends the sign-in process.
The one use case that does not pass is when the user gets to the sign-in dialog and clicks on an account that has an invalid password. I’m not sure how to solve this issue.
I followed with Google instruction "implement Sign-in SDK" and after calling those lines:
Task<GoogleSignInAccount> task = GoogleSignIn.getSignedInAccountFromIntent(data);
GoogleSignInAccount googleSignInAccount = task.getResult(ApiException.class);
I catch exception with status code 12501 SIGN_IN_CANCELLED.
As I said before, it happens because one of the stored accounts has invalid password.
Here are the steps to reproduce:
user logged in once
dialog stored his credentials
meanwhile user changed his account's password on www
user selects saved credentials
unrelated error code occurs).
How could I make user to redirect to this blue Google Sign-In page and keep the current flow?
For example, AliExpress somehow can handle this and redirects user to blue page with asking user to sign in again.
My code is not much different than in Google's instruction. This is my code flow. All start from onClick():
In onClick() method:
// Logout before all operations
GoogleSignInAccount account = GoogleSignIn.getLastSignedInAccount(this);
if (account != null) {
mGoogleSignInClient.signOut();
}
// Call to sign in
Intent signInIntent = mGoogleSignInClient.getSignInIntent();
startActivityForResult(signInIntent, RequestCodes.RC_GOOGLE_SIGN_IN);
In onActivityResult section:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
Log.d(TAG, "onActivityResult() called with: requestCode = [" + requestCode + "], resultCode = [" + resultCode + "], data = [" + data + "]");
if (requestCode == RequestCodes.RC_GOOGLE_SIGN_IN) {
try {
// Call to take account data
Task<GoogleSignInAccount> task = GoogleSignIn.getSignedInAccountFromIntent(data);
// Fetch account data
GoogleSignInAccount googleSignInAccount = task.getResult(ApiException.class);
Account account = googleSignInAccount.getAccount();
// Calling to get short lived token
String shortLivedToken = GoogleAuthUtil.getToken(mContext, account, "oauth2:" + Scopes.PROFILE + " " + Scopes.EMAIL);
// Further calls here...
} catch (ApiException e) {
//https://developers.google.com/android/reference/com/google/android/gms/auth/api/signin/GoogleSignInStatusCodes
if (e.getStatusCode() == 12501) {
Log.e(TAG, "SIGN_IN_CANCELLED");
} else if (e.getStatusCode() == 12502) {
Log.e(TAG, "SIGN_IN_CURRENTLY_IN_PROGRESS");
} else if (e.getStatusCode() == 12500) {
Log.e(TAG, "SIGN_IN_FAILED");
} else {
e.printStackTrace();
}
} catch (GoogleAuthException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
} else {
super.onActivityResult(requestCode, resultCode, data);
}
}
Disclaimer
I am not a Google employee. Everything I say below are my conclusions from investigating similar issues.
Short answer
You are doing everything right. It is the recommended way of logging into google account.
Unfortunately there is no actual callback in this mechanism to specify what actually went wrong in your case. The way Google Play Services handles it is by notifying user that his credentials became obsolete by notificaion you can see below (right after the password was changed).
I would recommend filing a bug for adding extra result codes for your case on https://issuetracker.google.com as it seems like a sensible improvement.
Long answer
Google uses Android account API just like everybody else (you can try it yourself).
Behind the scenes it's just a oauth token retrieval and storage mechanism.
When the password was changed, the token is no longer valid and you get errors trying to use it.
The way it works is the way Google Play Services developers chose to implement it (hence I recommend you to file a bug).
For example, AliExpress somehow can handle this and redirects user to
blue page with asking user to sign in again.
Aliexpress uses the deprecated API. As you can see the dialog for picking account has different color and no avatars. The API is is still usable, but may be shut down anytime (or not). I do not recommend you to use this, but here is how it works:
import com.google.android.gms.common.AccountPicker;
import com.google.android.gms.auth.GoogleAuthUtil;
import com.google.android.gms.auth.UserRecoverableAuthException;
void chooseAccount() {
Intent signInIntent = AccountPicker.newChooseAccountIntent(null, null, new String[]{GoogleAuthUtil.GOOGLE_ACCOUNT_TYPE}, true, null, null, null, null);
startActivityForResult(signInIntent, REQ_CHOOSE_ACCOUNT);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQ_CHOOSE_ACCOUNT) {
String email = data.getExtras().getString("authAccount");
// better do this in background thread
try {
GoogleAuthUtil.getToken(this, new Account(email, GoogleAuthUtil.GOOGLE_ACCOUNT_TYPE), "oauth2:https://www.googleapis.com/auth/userinfo.profile");
} catch (UserRecoverableAuthException recEx) {
Intent recoverIntent = recEx.getIntent();
// Will redirect to login activity
startActivityForResult(recoverIntent, REQ_RECOVER);
} catch (Exception e) {
Log.d(TAG, "caught exception", e);
}
}
}
Hope it helps!
UPD: new Google Play APIs have ResolvableApiException, which extends ApiException you are catching. It has method startResolutionForResult() similar to the one used in older APIs. But the Bundle you receive contains no resolution info.
Bundle[{googleSignInStatus=Status{statusCode=unknown status code: 12501, resolution=null}}]
If you will file a bug, post it here, we will star it)
You can also show the "Choose account" dialog using default Android API (min API 23)
The code below may be sued to show a "choose account dialog" using default Android Account Management APIs. This is new and (hopefully) not going to be deprecated for a while.
import android.accounts.Account;
import android.accounts.AccountManager;
// Unfortunately can be used only on API 23 and higher
Intent signInIntent = AccountManager.newChooseAccountIntent(
null,
null,
new String[] { "com.google" },
"Please select your account",
null,
null,
new Bundle());
startActivityForResult(signInIntent, REQ_SELECT_ACCOUNT);
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQ_SELECT_ACCOUNT) {
String accountName = data.getExtras().getString(AccountManager.KEY_ACCOUNT_NAME);
String accountType = data.getExtras().getString(AccountManager.KEY_ACCOUNT_TYPE);
// now you can call GoogleAuthUtil as in example above
}
}
You can also get list of Google accounts, visible to your app
Account becomes visible to your app after user have tried to sign in with that kind of account into your app, using one of the methods above. Event if sign in was not successful (e.g. password is expired), you will see this account in the list (won't be able to distinguish which one in case of multiple accounts though). So this may be used as workaround, but in a limited way.
import android.accounts.Account;
import android.accounts.AccountManager;
try {
// requires android.permission.GET_ACCOUNTS
Account[] accounts = AccountManager.get(this).getAccountsByType("com.google");
for (Account account : accounts) {
Log.d(TAG, "account: " + account.name);
}
} catch (Exception e) {
Log.i("Exception", "Exception:" + e);
}
Conclusion
Unfortunately I've found no other ways to access google account data to work around your case using modern Google Sign-In APIs. All advanced AccountManager APIs require you to have the same signature as account owner app (GMS - Google Mobile Services) which is not the case. So we can only request this from Google and hope for it to be implemented :(

Can not connect to Google Game services [duplicate]

I am developing an Android application where I want to use the Google API. For that I have imported the google-play-service-lib project.
I am following this link to initialize GoogleApiClient object.
My code:
1) In the onCreate() method I am building the GoogleApiClient object:
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(Plus.API, null)
.addScope(Plus.SCOPE_PLUS_LOGIN)
.build();
2) In onStart(), I call mGoogleApiClient.connect().
3) My activity implements
ConnectionCallbacks and OnConnectionFailedListener.
4) My onConnectionFailed() method looks like:
public void onConnectionFailed(ConnectionResult result) {
//in dubug result looks like : ConnectionResult{
//statusCode=SIGN_IN_REQUIRED, resolution=PendingIntent
// {41f8ca70: android.os.BinderProxy#41f8ca10}}
try {
if(!mIntentInProgress && result.hasResolution())
{
mIntentInProgress=true;
result.startResolutionForResult(mActivity, RC_SIGN_IN);
}
} catch (SendIntentException e) {
e.printStackTrace();
}
}
5) My onActivityResult() method contains:
if (requestCode == RC_SIGN_IN) {
if (!mGoogleApiClient.isConnecting()) {
mGoogleApiClient.connect();
}
}
When I run my app I get a Toast that says that an internal error popped up. I did create the project in the Google console.
I had the same problem.
From documentation:
The client may choose to continue without using the API or it may call startResolutionForResult(Activity, int) to prompt the user to sign in.
So you should try to sign in by using startResolutionForResult() function
#Override
public void onConnectionFailed(ConnectionResult result) {
if (result.hasResolution()) {
try {
// !!!
result.startResolutionForResult(this, REQUEST_CODE_RESOLVE_ERR);
} catch (SendIntentException e) {
mPlusClient.connect();
}
}
mConnectionResult = result;
}
Just follow google's instructionss
AND CAUTION
Since you are still in development mode, check if you have added your testing email address in the GAME DETAILS center before publishing the game.
Check that you are signing the app with a keystore that is in the apk uploaded to Google Play Developer's Console (if testing, you can upload as alpha and publish while keeping it private).
If not this, it could be other things. Make sure your account's email address is listed in testers in the Account details page (on the settings menu with a gear icon), and the licensed response is set to LICENSED, NOT to RESPOND_NORMALLY
This error indicates that the user needs to authorize your app. There's a full workflow for this, following the tutorial at https://developers.google.com/+/mobile/android/getting-started look for "onConnectionFailed"
Drive api should be enabled from the console page.
Not sure if this is the best answer but it worked for me. I copied onConnectionFailed() from the BasicSamples TakeANumber MainActivity. It calls BaseGameUtils to resolve. Of course that implies you have the BaseGameUtils library included in your project and that's another can of worms. But maybe you can get by with the one method so I copied it below.
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
logger.info( "onConnectionFailed() *play* : attempting to resolve");
if (mResolvingConnectionFailure) {
logger.info( "onConnectionFailed(): already resolving");
return;
}
if (mSignInClicked || mAutoStartSignInFlow) {
mAutoStartSignInFlow = false;
mSignInClicked = false;
mResolvingConnectionFailure = true;
if (!BaseGameUtils.resolveConnectionFailure(this, mGoogleApiClient, connectionResult,
RC_SIGN_IN, getString(R.string.signin_other_error))) {
mResolvingConnectionFailure = false;
}
}
}
From Google BasicSamples BaseGameUtils.java:
public static boolean resolveConnectionFailure(Activity activity,
GoogleApiClient client, ConnectionResult result, int requestCode,
String fallbackErrorMessage) {
if (result.hasResolution()) {
try {
result.startResolutionForResult(activity, requestCode);
return true;
} catch (IntentSender.SendIntentException e) {
// The intent was canceled before it was sent. Return to the default
// state and attempt to connect to get an updated ConnectionResult.
client.connect();
return false;
}
} else {
// not resolvable... so show an error message
int errorCode = result.getErrorCode();
Dialog dialog = GooglePlayServicesUtil.getErrorDialog(errorCode,
activity, requestCode);
if (dialog != null) {
dialog.show();
} else {
// no built-in dialog: show the fallback error message
showAlert(activity, fallbackErrorMessage);
}
return false;
}
}
if you are not using debug keys, push app to google play as alpha, add yourself as a tester and MOST important - follow the "Opt-in" link on Aplha page and CONFIRM that you are the tester.
I'd like to share my experience with this. My case was when using Google Play Services for Google Play Games. I was also getting the onConnectionFailed giving SIGN_IN_REQUIRED error. Finally I realize I had not "Published" my Game settings in the developer console. Not to be mistaken for publishing an "alpha" or "beta" version of your apk. I mean the actual Google Play Games "Game" you create and link to the game's APK.
I had Same problem and solved with this solution ,
I actually had very old version google play-services library so I updated It with latest google play-service library to compile 'com.google.android.gms:play-services:11.0.4' from my previous version library to support your android SDK and maintain compileSDKVersion and targetSDKVersion in gradle:app.
add google drive enabled API_KEY in manifest.and try again
In my case the problem was in sensitive scopes added and not verified:
https://console.developers.google.com/apis/credentials
Credentials -> OAuth consent screen -> Scopes for Google APIs
Make sure you have no unverified scopes.
for my cause i wrongly used release SHA1 key to generate API in developer console.
Then created SHA1 key with debug.keystore and updated in my api credentials.
Its started working.
keytool -list -v -keystore "C:\Users\<user>n\.android\debug.keystore" -alias androiddebugkey -storepass andro
id -keypass android

onConnectionFailed giving SIGN_IN_REQUIRED(4)

I am developing an Android application where I want to use the Google API. For that I have imported the google-play-service-lib project.
I am following this link to initialize GoogleApiClient object.
My code:
1) In the onCreate() method I am building the GoogleApiClient object:
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(Plus.API, null)
.addScope(Plus.SCOPE_PLUS_LOGIN)
.build();
2) In onStart(), I call mGoogleApiClient.connect().
3) My activity implements
ConnectionCallbacks and OnConnectionFailedListener.
4) My onConnectionFailed() method looks like:
public void onConnectionFailed(ConnectionResult result) {
//in dubug result looks like : ConnectionResult{
//statusCode=SIGN_IN_REQUIRED, resolution=PendingIntent
// {41f8ca70: android.os.BinderProxy#41f8ca10}}
try {
if(!mIntentInProgress && result.hasResolution())
{
mIntentInProgress=true;
result.startResolutionForResult(mActivity, RC_SIGN_IN);
}
} catch (SendIntentException e) {
e.printStackTrace();
}
}
5) My onActivityResult() method contains:
if (requestCode == RC_SIGN_IN) {
if (!mGoogleApiClient.isConnecting()) {
mGoogleApiClient.connect();
}
}
When I run my app I get a Toast that says that an internal error popped up. I did create the project in the Google console.
I had the same problem.
From documentation:
The client may choose to continue without using the API or it may call startResolutionForResult(Activity, int) to prompt the user to sign in.
So you should try to sign in by using startResolutionForResult() function
#Override
public void onConnectionFailed(ConnectionResult result) {
if (result.hasResolution()) {
try {
// !!!
result.startResolutionForResult(this, REQUEST_CODE_RESOLVE_ERR);
} catch (SendIntentException e) {
mPlusClient.connect();
}
}
mConnectionResult = result;
}
Just follow google's instructionss
AND CAUTION
Since you are still in development mode, check if you have added your testing email address in the GAME DETAILS center before publishing the game.
Check that you are signing the app with a keystore that is in the apk uploaded to Google Play Developer's Console (if testing, you can upload as alpha and publish while keeping it private).
If not this, it could be other things. Make sure your account's email address is listed in testers in the Account details page (on the settings menu with a gear icon), and the licensed response is set to LICENSED, NOT to RESPOND_NORMALLY
This error indicates that the user needs to authorize your app. There's a full workflow for this, following the tutorial at https://developers.google.com/+/mobile/android/getting-started look for "onConnectionFailed"
Drive api should be enabled from the console page.
Not sure if this is the best answer but it worked for me. I copied onConnectionFailed() from the BasicSamples TakeANumber MainActivity. It calls BaseGameUtils to resolve. Of course that implies you have the BaseGameUtils library included in your project and that's another can of worms. But maybe you can get by with the one method so I copied it below.
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
logger.info( "onConnectionFailed() *play* : attempting to resolve");
if (mResolvingConnectionFailure) {
logger.info( "onConnectionFailed(): already resolving");
return;
}
if (mSignInClicked || mAutoStartSignInFlow) {
mAutoStartSignInFlow = false;
mSignInClicked = false;
mResolvingConnectionFailure = true;
if (!BaseGameUtils.resolveConnectionFailure(this, mGoogleApiClient, connectionResult,
RC_SIGN_IN, getString(R.string.signin_other_error))) {
mResolvingConnectionFailure = false;
}
}
}
From Google BasicSamples BaseGameUtils.java:
public static boolean resolveConnectionFailure(Activity activity,
GoogleApiClient client, ConnectionResult result, int requestCode,
String fallbackErrorMessage) {
if (result.hasResolution()) {
try {
result.startResolutionForResult(activity, requestCode);
return true;
} catch (IntentSender.SendIntentException e) {
// The intent was canceled before it was sent. Return to the default
// state and attempt to connect to get an updated ConnectionResult.
client.connect();
return false;
}
} else {
// not resolvable... so show an error message
int errorCode = result.getErrorCode();
Dialog dialog = GooglePlayServicesUtil.getErrorDialog(errorCode,
activity, requestCode);
if (dialog != null) {
dialog.show();
} else {
// no built-in dialog: show the fallback error message
showAlert(activity, fallbackErrorMessage);
}
return false;
}
}
if you are not using debug keys, push app to google play as alpha, add yourself as a tester and MOST important - follow the "Opt-in" link on Aplha page and CONFIRM that you are the tester.
I'd like to share my experience with this. My case was when using Google Play Services for Google Play Games. I was also getting the onConnectionFailed giving SIGN_IN_REQUIRED error. Finally I realize I had not "Published" my Game settings in the developer console. Not to be mistaken for publishing an "alpha" or "beta" version of your apk. I mean the actual Google Play Games "Game" you create and link to the game's APK.
I had Same problem and solved with this solution ,
I actually had very old version google play-services library so I updated It with latest google play-service library to compile 'com.google.android.gms:play-services:11.0.4' from my previous version library to support your android SDK and maintain compileSDKVersion and targetSDKVersion in gradle:app.
add google drive enabled API_KEY in manifest.and try again
In my case the problem was in sensitive scopes added and not verified:
https://console.developers.google.com/apis/credentials
Credentials -> OAuth consent screen -> Scopes for Google APIs
Make sure you have no unverified scopes.
for my cause i wrongly used release SHA1 key to generate API in developer console.
Then created SHA1 key with debug.keystore and updated in my api credentials.
Its started working.
keytool -list -v -keystore "C:\Users\<user>n\.android\debug.keystore" -alias androiddebugkey -storepass andro
id -keypass android

Error : ConnectionResult{statusCode=INTERNAL_ERROR, resolution=null}

I am developing the application where I am integrating the Google Drive in my App. Below is my code which is I simply copied from the sample code but I am getting exception when connecting with Google Drive.
Exception : ConnectionResult{statusCode=INTERNAL_ERROR, resolution=null} in the onConnectionFailed() method.
Please guys share your views.
public class MainActivity extends Activity implements ConnectionCallbacks,
OnConnectionFailedListener {
private static final String TAG = "android-drive-quickstart";
private static final int REQUEST_CODE_CAPTURE_IMAGE = 1;
private static final int REQUEST_CODE_CREATOR = 2;
private static final int REQUEST_CODE_RESOLUTION = 3;
private GoogleApiClient mGoogleApiClient;
private Bitmap mBitmapToSave;
/**
* Create a new file and save it to Drive.
*/
private void saveFileToDrive() {
// Start by creating a new contents, and setting a callback.
Log.i(TAG, "Creating new contents.");
final Bitmap image = mBitmapToSave;
Drive.DriveApi.newContents(mGoogleApiClient).addResultCallback(new OnNewContentsCallback() {
#Override
public void onNewContents(ContentsResult result) {
// If the operation was not successful, we cannot do anything
// and must
// fail.
if (!result.getStatus().isSuccess()) {
Log.i(TAG, "Failed to create new contents.");
return;
}
// Otherwise, we can write our data to the new contents.
Log.i(TAG, "New contents created.");
// Get an output stream for the contents.
OutputStream outputStream = result.getContents().getOutputStream();
// Write the bitmap data from it.
ByteArrayOutputStream bitmapStream = new ByteArrayOutputStream();
image.compress(Bitmap.CompressFormat.PNG, 100, bitmapStream);
try {
outputStream.write(bitmapStream.toByteArray());
} catch (IOException e1) {
Log.i(TAG, "Unable to write file contents.");
}
// Create the initial metadata - MIME type and title.
// Note that the user will be able to change the title later.
MetadataChangeSet metadataChangeSet = new MetadataChangeSet.Builder()
.setMimeType("image/jpeg").setTitle("Android Photo.png").build();
// Create an intent for the file chooser, and start it.
IntentSender intentSender = Drive.DriveApi
.newCreateFileActivityBuilder()
.setInitialMetadata(metadataChangeSet)
.setInitialContents(result.getContents())
.build(mGoogleApiClient);
try {
startIntentSenderForResult(
intentSender, REQUEST_CODE_CREATOR, null, 0, 0, 0);
} catch (SendIntentException e) {
Log.i(TAG, "Failed to launch file chooser.");
}
}
});
}
#Override
protected void onResume() {
super.onResume();
if (mGoogleApiClient == null) {
// Create the API client and bind it to an instance variable.
// We use this instance as the callback for connection and connection
// failures.
// Since no account name is passed, the user is prompted to choose.
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addApi(Drive.API)
.addScope(Drive.SCOPE_FILE)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
}
// Connect the client. Once connected, the camera is launched.
mGoogleApiClient.connect();
}
#Override
protected void onPause() {
if (mGoogleApiClient != null) {
mGoogleApiClient.disconnect();
}
super.onPause();
}
#Override
protected void onActivityResult(final int requestCode, final int resultCode, final Intent data) {
switch (requestCode) {
case REQUEST_CODE_CAPTURE_IMAGE:
// Called after a photo has been taken.
if (resultCode == Activity.RESULT_OK) {
// Store the image data as a bitmap for writing later.
mBitmapToSave = (Bitmap) data.getExtras().get("data");
}
break;
case REQUEST_CODE_CREATOR:
// Called after a file is saved to Drive.
if (resultCode == RESULT_OK) {
Log.i(TAG, "Image successfully saved.");
mBitmapToSave = null;
// Just start the camera again for another photo.
startActivityForResult(new Intent(MediaStore.ACTION_IMAGE_CAPTURE),
REQUEST_CODE_CAPTURE_IMAGE);
}
break;
}
}
#Override
public void onConnectionFailed(ConnectionResult result) {
// Called whenever the API client fails to connect.
Log.i(TAG, "GoogleApiClient connection failed: " + result.toString());
if (!result.hasResolution()) {
// show the localized error dialog.
GooglePlayServicesUtil.getErrorDialog(result.getErrorCode(), this, 0).show();
return;
}
// The failure has a resolution. Resolve it.
// Called typically when the app is not yet authorized, and an
// authorization
// dialog is displayed to the user.
try {
result.startResolutionForResult(this, REQUEST_CODE_RESOLUTION);
} catch (SendIntentException e) {
Log.e(TAG, "Exception while starting resolution activity", e);
}
}
#Override
public void onConnected(Bundle connectionHint) {
Log.i(TAG, "API client connected.");
if (mBitmapToSave == null) {
// This activity has no UI of its own. Just start the camera.
startActivityForResult(new Intent(MediaStore.ACTION_IMAGE_CAPTURE),
REQUEST_CODE_CAPTURE_IMAGE);
return;
}
saveFileToDrive();
}
#Override
public void onDisconnected() {
Log.i(TAG, "API client disconnected.");
}
}
Heads up! There's a problem in the Developers Console.
If you are getting this bug even after 1) making sure that you have registered the package name with its corresponding certificate fingerprint, and 2) are (re)using an already existing project, then you should check that this project has an product name and an email address (double check that one specially) associated with it, both to be found in the "consent screen" section.
Very old projects may not have these two fields populated. Newer projects have these fields filled out with some default values.
Took me a day to find this...
I resolve this issue by signing my Google Drive application on API console following these steps
Go to the Google Developers Console.
Select a project, or create a new one.
In the sidebar on the left, expand APIs & auth. Next, click APIs.
In the list of APIs, make sure the status is ON for the Drive API.
In the sidebar on the left, select Credentials.
If your application needs to submit authorized requests:
Under OAuth, click Create new Client ID.
Select Installed application and Android.
In the Package name field, enter your Android app's package name.
Paste the SHA1 fingerprint into the form where requested.
Click Create Client ID.
I solved the issue from register the application and generate signing certificate fingerprint.
https://developers.google.com/drive/android/auth#generate_the_signing_certificate_fingerprint_and_register_your_application
I followed above links and It solved my problem.
For me the problem was that when in the example there was :
.addApi(Drive.API)
And I didn't added the drive api in the console
this error message helped me to figure out the issue
com.google.android.gms.drive.auth.c: Authorization failed: server
returned error: Access Not Configured. The API is not enabled for your
project, or there is a per-IP or per-Referer restriction configured on
your API key and the request does not match these restrictions. Please
use the Google Developers Console to update your configuration.. See
https://developers.google.com/drive/handle-errors for details.
Don't forget the permissions:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
Do you have any error messages in logcat? The most likely cause of a failed connection is that you haven't properly setup an app in the cloud console.
See the instructions here: https://developers.google.com/drive/android/auth
In my case, I had to change the Client ID to use the exact package name of the activity class building the GoogleApiClient object, not a higher-level package.
I was also getting the same error.
For my project, Drive API was not enabled under API & auth -> APIs.
After enabling this Drive API, this problem was resolved.
I solved adding this line to gradle:
compile 'com.google.android.gms:play-services-identity:8.1.0'
You need to have two separate Client IDs, one for debug, the other one for release.
Sometimes we miss the obvious.
In Android Studio go to
Tool-> Android-SDK Manager -> Google Play Service
Update the Google Play Service..I am sure it will work
I got the same problem as above, when I moved an existing application from Eclipse to Android studio. My problem was that I named applicationId different from the package id. Changing applicationId to be the same as the package name solved the problem.
I got the same issue. My sign-in was working but it stopped working all of sudden. I tried all the solutions mentioned here. But didn't solve my problem. However, upon disabling the google sign in and enabling it solved my problem. So just go to the firebase console, select Authentication > Sign-in Methods > google > click Edit > disable and enable.

Categories

Resources