I met a problem in my project.
I want to use "Google API" to log in in my LoginActivity. And Log out from another Activity(named WelcomeActivity)
LoginActivity:
(code is here)
public class LoginActivity extends AppCompatActivity implements
GoogleApiClient.OnConnectionFailedListener,
View.OnClickListener {
// Configuration of Google API - Step 1/3
private static final String TAG = "LoginActivity";
private static final int RC_SIGN_IN = 9001;
public static GoogleApiClient mGoogleApiClient;
private ProgressDialog mProgressDialog;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
GoogleAPI();
}
public void GoogleAPI(){
// Button listeners
findViewById(R.id.sign_in_button).setOnClickListener(this);
GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestEmail()
.build();
mGoogleApiClient = new GoogleApiClient.Builder(this)
.enableAutoManage(this /* FragmentActivity */, this /* OnConnectionFailedListener */)
.addApi(Auth.GOOGLE_SIGN_IN_API, gso)
.build();
}
#Override
public void onStart() {
super.onStart();
....
}
// [START onActivityResult]
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
// Result returned from launching the Intent from GoogleSignInApi.getSignInIntent(...);
if (requestCode == RC_SIGN_IN) {
GoogleSignInResult result = Auth.GoogleSignInApi.getSignInResultFromIntent(data);
handleSignInResult(result);
}
}
// [END onActivityResult]
// [START handleSignInResult]
private void handleSignInResult(GoogleSignInResult result) {
if (result.isSuccess()) {
// Signed in successfully, show authenticated UI.
CustomApplication app = (CustomApplication)getApplication();
GoogleSignInAccount acct = result.getSignInAccount();
Intent i = new Intent(LoginActivity.this, WelcomePage.class);
i.putExtra("Username", acct.getDisplayName());
startActivity(i);
}
}
// [END handleSignInResult]
// [START signIn]
private void signIn() {
Intent signInIntent = Auth.GoogleSignInApi.getSignInIntent(mGoogleApiClient);
startActivityForResult(signInIntent, RC_SIGN_IN);
}
// [END signIn]
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
...
}
private void showProgressDialog() {
...
}
private void hideProgressDialog() {
...
}
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.sign_in_button:
signIn();
break;
….
}
}
}
And I want to use Sign_out Method in my Welcome activity,
private void signOut() {
// Auth.GoogleSignInApi.signOut(mGoogleApiClient).setResultCallback(
// new ResultCallback<Status>() {
// #Override
// public void onResult(Status status) {
// // [START_EXCLUDE]
//// updateUI(false);
// // [END_EXCLUDE]
// }
// });
// }
In order to solve this problem, i try 2 methods:
make mGoogleApiClient as a global variable(extends Application or Singleton), i try it, but failed, in Welcome page, mGoogleApiClient is not null, but error is: mGoogleApiClient is not connected yet.
i call LoginActivity.getMGoogleApiClient(static variable), but also failed, same error: mGoogleApiClient is not connected yet.
I already search this problem for days, but nothing useful to solve it, please help me ..
When you enableAutoManage, then the googleApiClient gets connected onStart and gets disconnected onStop and is handled automatically by the library. What you could is, logout the user in the other activity, whatever your code is to logout the user from your backend, except don't sign out from google yet.
Pseudo code:
private void logOut(){
//your logout code in the log out activity
setCurrentUser(null);
}
And in the activity with the googleApiClient, you could check if the user is logged-in in onConnected callback of googleApiClient. If the current user is not logged in, sign out the user from Google.
#Override
public void onConnected(Bundle connectionHint) {
if (getCurrentUser() == null){
signOut();
}
}
private void signOut() {
Auth.GoogleSignInApi.signOut(mGoogleApiClientPlus).setResultCallback(
new ResultCallback<Status>() {
#Override
public void onResult(Status status) {
//signed out.
}
});
}
If you don't use enableAutoManage and don't disconnect the client in onStop (which I don't know if it's recommended), you could use your 2 methods but I won't recommend using static fields for googleApiClient object.
One solution is to do your normal logout flow (ignore mGoogleApiClient). The next time the user opens your app to the login screen and hits google login, you log them out first, then do the google login
e.g.:
private void googleLogin() {
googleLogout();
Intent signInIntent = Auth.GoogleSignInApi.getSignInIntent(mGoogleApiClient);
startActivityForResult(signInIntent, RC_SIGN_IN);
}
private void googleLogout() {
if (mGoogleApiClient.isConnected()) {
Auth.GoogleSignInApi.signOut(mGoogleApiClient);
}
}
Related
I am using google+ login in my android app google+ login is working but want to navigate on my custom made homepage my google+ login code is on MainActivity.java.
How do I navigate to my homepage(i.e Main_tab.java) after login.
Here is my code for MainActivity
public class MainActivity extends AppCompatActivity implements
GoogleApiClient.OnConnectionFailedListener, View.OnClickListener {
private static final String TAG = "SignInActivity";
private static final int RC_SIGN_IN = 9001;
private GoogleApiClient mGoogleApiClient;
private TextView mStatusTextView;
private ProgressDialog mProgressDialog;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Views
mStatusTextView = (TextView) findViewById(R.id.status);
// Button listeners
findViewById(R.id.sign_in_button).setOnClickListener(this);
findViewById(R.id.sign_out_button).setOnClickListener(this);
findViewById(R.id.disconnect_button).setOnClickListener(this);
// [START configure_signin]
// Configure sign-in to request the user's ID, email address, and basic
// profile. ID and basic profile are included in DEFAULT_SIGN_IN.
GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestEmail()
.build();
// [END configure_signin]
// [START build_client]
// Build a GoogleApiClient with access to the Google Sign-In API and the
// options specified by gso.
mGoogleApiClient = new GoogleApiClient.Builder(this)
.enableAutoManage(this /* FragmentActivity */, this /* OnConnectionFailedListener */)
.addApi(Auth.GOOGLE_SIGN_IN_API, gso)
.build();
// [END build_client]
// [START customize_button]
// Set the dimensions of the sign-in button.
SignInButton signInButton = (SignInButton) findViewById(R.id.sign_in_button);
signInButton.setSize(SignInButton.SIZE_STANDARD);
// [END customize_button]
}
#Override
public void onStart() {
super.onStart();
OptionalPendingResult<GoogleSignInResult> opr = Auth.GoogleSignInApi.silentSignIn(mGoogleApiClient);
if (opr.isDone()) {
// If the user's cached credentials are valid, the OptionalPendingResult will be "done"
// and the GoogleSignInResult will be available instantly.
Log.d(TAG, "Got cached sign-in");
GoogleSignInResult result = opr.get();
handleSignInResult(result);
} else {
// If the user has not previously signed in on this device or the sign-in has expired,
// this asynchronous branch will attempt to sign in the user silently. Cross-device
// single sign-on will occur in this branch.
showProgressDialog();
opr.setResultCallback(new ResultCallback<GoogleSignInResult>() {
#Override
public void onResult(GoogleSignInResult googleSignInResult) {
hideProgressDialog();
handleSignInResult(googleSignInResult);
}
});
}
}
// [START onActivityResult]
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
// Result returned from launching the Intent from GoogleSignInApi.getSignInIntent(...);
if (requestCode == RC_SIGN_IN) {
}
GoogleSignInResult result = Auth.GoogleSignInApi.getSignInResultFromIntent(data);
handleSignInResult(result);
}
// [END onActivityResult]
// [START handleSignInResult]
private void handleSignInResult(GoogleSignInResult result) {
Log.d(TAG, "handleSignInResult:" + result.isSuccess());
if (result.isSuccess()) {
// Signed in successfully, show authenticated UI.
GoogleSignInAccount acct = result.getSignInAccount();
mStatusTextView.setText(getString(R.string.signed_in_fmt, acct.getDisplayName()));
updateUI(true);
} else {
// Signed out, show unauthenticated UI.
updateUI(false);
}
}
// [END handleSignInResult]
// [START signIn]
private void signIn() {
Intent signInIntent = Auth.GoogleSignInApi.getSignInIntent(mGoogleApiClient);
startActivityForResult(signInIntent, RC_SIGN_IN);
}
// [END signIn]
// [START signOut]
private void signOut() {
Auth.GoogleSignInApi.signOut(mGoogleApiClient).setResultCallback(
new ResultCallback<Status>() {
#Override
public void onResult(Status status) {
// [START_EXCLUDE]
updateUI(false);
// [END_EXCLUDE]
}
});
}
// [END signOut]
// [START revokeAccess]
private void revokeAccess() {
Auth.GoogleSignInApi.revokeAccess(mGoogleApiClient).setResultCallback(
new ResultCallback<Status>() {
#Override
public void onResult(Status status) {
// [START_EXCLUDE]
updateUI(false);
// [END_EXCLUDE]
}
});
}
// [END revokeAccess]
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
// An unresolvable error has occurred and Google APIs (including Sign-In) will not
// be available.
Log.d(TAG, "onConnectionFailed:" + connectionResult);
}
private void showProgressDialog() {
if (mProgressDialog == null) {
mProgressDialog = new ProgressDialog(this);
mProgressDialog.setMessage(getString(R.string.loading));
mProgressDialog.setIndeterminate(true);
}
mProgressDialog.show();
}
private void hideProgressDialog() {
if (mProgressDialog != null && mProgressDialog.isShowing()) {
mProgressDialog.hide();
}
}
private void updateUI(boolean signedIn) {
if (signedIn) {
findViewById(R.id.sign_in_button).setVisibility(View.GONE);
findViewById(R.id.sign_out_and_disconnect).setVisibility(View.VISIBLE);
} else {
mStatusTextView.setText(R.string.signed_out);
findViewById(R.id.sign_in_button).setVisibility(View.VISIBLE);
findViewById(R.id.sign_out_and_disconnect).setVisibility(View.GONE);
}
}
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.sign_in_button:
signIn();
break;
case R.id.sign_out_button:
signOut();
break;
case R.id.disconnect_button:
revokeAccess();
break;
}
}
}
When the sign in is successful, open your desired activity by using Explicit intent from Android doc code and Vogella tutorials
Learn about intents in Android and some basic concepts if you don't know, it will help you since they are the basics.
I tried to implement google sign in api, but every time I opened the app, even I didnt click sign in button, button click is called in the code and throw exception that in if (result.isSuccess()) that result is null, anyone knows why?
public class Login extends FragmentActivity {
private static final int RC_SIGN_IN = 2222;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestEmail()
.build();
mGoogleApiClient = new GoogleApiClient.Builder(getApplicationContext())
.enableAutoManage(this /* FragmentActivity */, this /* OnConnectionFailedListener */)
.addApi(Auth.GOOGLE_SIGN_IN_API, gso)
.build();
google_Button = (SignInButton) findViewById(R.id.sign_in_button);
google_Button.setOnClickListener(this);
}
public void onClick(View v) {
switch (v.getId()) {
case R.id.sign_in_button:
Log.d("Result: ","click google");
signIn();
break;
}
}
private void signIn() {
Intent signInIntent = Auth.GoogleSignInApi.getSignInIntent(mGoogleApiClient);
startActivityForResult(signInIntent, RC_SIGN_IN);
}
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode == RC_SIGN_IN) {
Log.d("Result: ","google sign in");
GoogleSignInResult result = Auth.GoogleSignInApi.getSignInResultFromIntent(data);
handleSignInResult(result);
}
}
private void handleSignInResult(GoogleSignInResult result) {
if (result.isSuccess()) {
GoogleSignInAccount acct = result.getSignInAccount();
Log.d("Google token: ",result.getSignInAccount().getEmail());
} else {
Log.d("Google","fail");
}
}
In your onDestroy() or onStop() method call this :
if (mGoogleApiClient.isConnected()) {
mGoogleApiClient.disconnect();
}
This is because sometimes the api client is not destroyed and the session has still not finished.
If you want to logout then use the following code on click of your logout button.
if (mGoogleApiClient.isConnected()) {
Plus.AccountApi.clearDefaultAccount(mGoogleApiClient);
Plus.AccountApi.revokeAccessAndDisconnect(mGoogleApiClient)
.setResultCallback(new ResultCallback<Status>() {
#Override
public void onResult(Status status) {
}
});
mGoogleApiClient.disconnect();
}
I am trying to integrate Facebook and Google authentication for my mobile application. I have followed Google and Facebook tutorials on how to do it and both projects work fine when they are separated. In my current solution signing in with Google works ok but Facebook gives me following error msg:
Permission Denial: get/set setting for user asks to run as user -2 but is calling from user 0; this requires android.permission.INTERACT_ACROSS_USERS_FULL
E/Parcel: Class not found when unmarshalling: com.facebook.login.LoginClient$Request
Caused by: java.lang.NoClassDefFoundError: com/facebook/login/LoginClient$Request
Caused by: java.lang.ClassNotFoundException: Didn't find class "com.facebook.login.LoginClient$Request" on path
Here is my LoginAvtivity class I use for authentication:
public class ActivityLogin extends AppCompatActivity implements GoogleApiClient.OnConnectionFailedListener, View.OnClickListener {
private static final String TAG = "SignInActivity";
private static final int RC_SIGN_IN = 9001;
private GoogleApiClient mGoogleApiClient;
private ProgressDialog mProgressDialog;
private LoginButton facebookButton;
private CallbackManager facebookCallbackManager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
FacebookSdk.sdkInitialize(getApplicationContext());
facebookCallbackManager = CallbackManager.Factory.create();
setContentView(R.layout.activity_login);
// Button listeners
findViewById(R.id.google_button).setOnClickListener(this);
facebookButton = (LoginButton)findViewById(R.id.facebook_button);
// [START configure_signin]
// Configure sign-in to request the user's ID, email address, and basic
// profile. ID and basic profile are included in DEFAULT_SIGN_IN.
GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestEmail()
.requestIdToken(getString(R.string.server_client_id))
.build();
// [START build_client]
// Build a GoogleApiClient with access to the Google Sign-In API and the
// options specified by gso.
mGoogleApiClient = new GoogleApiClient.Builder(this)
.enableAutoManage(this /* FragmentActivity */, this /* OnConnectionFailedListener */)
.addApi(Auth.GOOGLE_SIGN_IN_API, gso)
.build();
// [START customize_button]
// Customize sign-in button. The sign-in button can be displayed in
// multiple sizes and color schemes. It can also be contextually
// rendered based on the requested scopes. For example. a red button may
// be displayed when Google+ scopes are requested, but a white button
// may be displayed when only basic profile is requested. Try adding the
// Scopes.PLUS_LOGIN scope to the GoogleSignInOptions to see the
// difference.
SignInButton signInButton = (SignInButton) findViewById(R.id.google_button);
signInButton.setSize(SignInButton.SIZE_STANDARD);
signInButton.setScopes(gso.getScopeArray());
setGooglePlusButtonText(signInButton, "Sign in with Google");
facebookButton.registerCallback(facebookCallbackManager, new FacebookCallback<LoginResult>() {
#Override
public void onSuccess(LoginResult loginResult) {
Intent intent = new Intent(ActivityLogin.this, MainActivity.class);
startActivity(intent);
}
#Override
public void onCancel() {
Log.d("TOKEN", "Canceled!!!!!!!!!!");
}
#Override
public void onError(FacebookException error) {
Log.d("TOKEN", "CHUUUUUUJ WIELKI!!!!!!!!!!!!");
}
});
}
#Override
public void onStart() {
super.onStart();
OptionalPendingResult<GoogleSignInResult> opr = Auth.GoogleSignInApi.silentSignIn(mGoogleApiClient);
if (opr.isDone()) {
// If the user's cached credentials are valid, the OptionalPendingResult will be "done"
// and the GoogleSignInResult will be available instantly.
Log.d(TAG, "Got cached sign-in");
GoogleSignInResult result = opr.get();
handleSignInResult(result);
} else {
// If the user has not previously signed in on this device or the sign-in has expired,
// this asynchronous branch will attempt to sign in the user silently. Cross-device
// single sign-on will occur in this branch.
showProgressDialog();
opr.setResultCallback(new ResultCallback<GoogleSignInResult>() {
#Override
public void onResult(GoogleSignInResult googleSignInResult) {
hideProgressDialog();
handleSignInResult(googleSignInResult);
}
});
}
}
// [START onActivityResult]
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
// Result returned from launching the Intent from GoogleSignInApi.getSignInIntent(...);
if (requestCode == RC_SIGN_IN) {
GoogleSignInResult result = Auth.GoogleSignInApi.getSignInResultFromIntent(data);
handleSignInResult(result);
}
}
// [END onActivityResult]
// [START handleSignInResult]
private void handleSignInResult(GoogleSignInResult result) {
Log.d(TAG, "handleSignInResult:" + result.isSuccess());
if (result.isSuccess()) {
// Signed in successfully, show authenticated UI.
GoogleSignInAccount acct = result.getSignInAccount();
//mStatusTextView.setText(getString(R.string.signed_in_fmt, acct.getDisplayName()));
//updateUI(true);
Intent intent = new Intent(ActivityLogin.this, MainActivity.class);
startActivity(intent);
String idToken = acct.getIdToken();
if (idToken != null) {
Log.d("TOKEN", idToken);
//sendEmail(idToken);
} else {
Log.d("TOKEN", "CHUUUUUUJ WIELKI!");
}
} else {
// Signed out, show unauthenticated UI.
//updateUI(false);
}
}
// [END handleSignInResult]
// [START signIn]
private void signIn() {
Intent signInIntent = Auth.GoogleSignInApi.getSignInIntent(mGoogleApiClient);
startActivityForResult(signInIntent, RC_SIGN_IN);
}
// [END signIn]
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
// An unresolvable error has occurred and Google APIs (including Sign-In) will not
// be available.
Log.d(TAG, "onConnectionFailed:" + connectionResult);
}
private void showProgressDialog() {
if (mProgressDialog == null) {
mProgressDialog = new ProgressDialog(this);
mProgressDialog.setMessage(getString(R.string.loading));
mProgressDialog.setIndeterminate(true);
}
mProgressDialog.show();
}
private void hideProgressDialog() {
if (mProgressDialog != null && mProgressDialog.isShowing()) {
mProgressDialog.hide();
}
}
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.google_button:
signIn();
break;
case R.id.tutorial:
Intent intent = new Intent(this, TutorialActivity.class);
startActivity(intent);
break;
// case R.id.disconnect_button:
// revokeAccess();
// break;
}
}
protected void setGooglePlusButtonText(SignInButton signInButton, String buttonText) {
// Find the TextView that is inside of the SignInButton and set its text
for (int i = 0; i < signInButton.getChildCount(); i++) {
View v = signInButton.getChildAt(i);
if (v instanceof TextView) {
TextView tv = (TextView) v;
tv.setText(buttonText);
return;
}
}
}
}
And here is the xml layout for this class:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context=".ActivityLogin"
android:background="#drawable/background_gradient">
<com.facebook.login.widget.LoginButton
android:id="#+id/facebook_button"
android:layout_width="200dp"
android:layout_height="40dp"
android:layout_above="#+id/google_button"
android:layout_centerHorizontal="true"
android:layout_marginBottom="20dp" />
<com.google.android.gms.common.SignInButton
android:id="#+id/google_button"
android:layout_width="200dp"
android:layout_height="40dp"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginBottom="60dp"
/>
It seems that I am missing something imporant here but I cannot find what it is. The first error message says that I am missing permissions but according to both google and facebook tutorials this particular permission is not required.
You are not handling the Facebook result in your onActivityResult() method.
Add this to your method -
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
// Result returned from launching the Intent from GoogleSignInApi.getSignInIntent(...);
if (requestCode == RC_SIGN_IN) {
GoogleSignInResult result = Auth.GoogleSignInApi.getSignInResultFromIntent(data);
handleSignInResult(result);
}
else{
//Add this to handle Facebook result
facebookCallbackManager.onActivityResult(requestCode, resultCode, data);
}
}
I tried the google developer documentation and tried sign-in for my app.
The code is copied from the git with added codes from the documentation.
and defined in LoginActivity as
Public class LoginActivity extends AppCompatActivity implements
GoogleApiClient.OnConnectionFailedListener,
View.OnClickListener {
private static final String TAG = "* * SignIn * *";
private static final int RC_SIGN_IN = 9001;
private GoogleApiClient mGoogleApiClient;
private ProgressDialog mProgressDialog;
Bundle userData = new Bundle();
Intent newIntent;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.login);
findViewById(R.id.sign_in_button).setOnClickListener(this);
// [START configure_signin]
// Configure sign-in to request the user's ID, email address, and basic
// profile. ID and basic profile are included in DEFAULT_SIGN_IN.
GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestEmail()
.build();
// [END configure_signin]
// [START build_client]
mGoogleApiClient = new GoogleApiClient.Builder(this)
.enableAutoManage(this /* FragmentActivity */, this /* OnConnectionFailedListener */)
.addApi(Auth.GOOGLE_SIGN_IN_API, gso)
.build();
// [END build_client]
// [START customize_button]
SignInButton signInButton = (SignInButton) findViewById(R.id.sign_in_button);
signInButton.setSize(SignInButton.SIZE_STANDARD);
signInButton.setScopes(gso.getScopeArray());
// [END customize_button]
}
#Override
public void onStart() {
super.onStart();
OptionalPendingResult<GoogleSignInResult> opr = Auth.GoogleSignInApi.silentSignIn(mGoogleApiClient);
if (opr.isDone()) {
Log.d(TAG, "Got cached sign-in");
GoogleSignInResult result = opr.get();
handleSignInResult(result);
} else {
showProgressDialog();
opr.setResultCallback(new ResultCallback<GoogleSignInResult>() {
#Override
public void onResult(GoogleSignInResult googleSignInResult) {
hideProgressDialog();
handleSignInResult(googleSignInResult);
}
});
}
}
// [START onActivityResult]
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
// Result returned from launching the Intent from GoogleSignInApi.getSignInIntent(...);
if (requestCode == RC_SIGN_IN) {
GoogleSignInResult result = Auth.GoogleSignInApi.getSignInResultFromIntent(data);
handleSignInResult(result);
}
}
// [END onActivityResult]
// [START handleSignInResult]
private void handleSignInResult(GoogleSignInResult result) {
Log.d(TAG, "handleSignInResult:" + result.isSuccess());
if (result.isSuccess()) {
// Signed in successfully, show authenticated UI.
GoogleSignInAccount acct = result.getSignInAccount();
userData.putString("Username", acct.getDisplayName());
userData.putString("Email",acct.getEmail());
newIntent = new Intent(LoginActivity.this, MainActivity.class);
newIntent.putExtras(userData);
startActivity(newIntent);
finish();
} else {
userData.putString("Username", "Anonymous");
userData.putString("Email","www.example.com");
newIntent = new Intent(LoginActivity.this, MainActivity.class);
newIntent.putExtras(userData);
startActivity(newIntent);
finish();
}
}
// [END handleSignInResult]
// [START signIn]
private void signIn() {
Intent signInIntent = Auth.GoogleSignInApi.getSignInIntent(mGoogleApiClient);
startActivityForResult(signInIntent, RC_SIGN_IN);
}
// [END signIn]
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
Log.d(TAG, "onConnectionFailed:" + connectionResult);
}
private void showProgressDialog() {
if (mProgressDialog == null) {
mProgressDialog = new ProgressDialog(this);
mProgressDialog.setMessage("Please wait");
mProgressDialog.setIndeterminate(true);
}
mProgressDialog.show();
}
private void hideProgressDialog() {
if (mProgressDialog != null && mProgressDialog.isShowing()) {
mProgressDialog.hide();
}
}
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.sign_in_button:
signIn();
break;
}
}
}
But I get following error log.
as
12-16 23:02:44.074 5545-5545/com.example.www.newapp E/AndroidRuntime: java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=40962, result=-1, data=Intent { (has extras) }}
to activity {com.example.www.newapp/com.google.android.gms.auth.api.signin.internal.SignInHubActivity}:
java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.Class java.lang.Object.getClass()' on a null object reference
My MainActivity code is as
public class MainActivity extends AppCompatActivity
implements NavigationView.OnNavigationItemSelectedListener, View.OnClickListener {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
View header = navigationView.getHeaderView(0);
userName = (TextView) header.findViewById(R.id.userName);
userName.setText(user);//Username recieved through intent
}}
While running it in emulator it shows update your play service, is it a problem?
The Error occurred only in emulator in when compiling with new play service 8.3
While testing in actual hardware doesn't show any problem. It is due to the mismatch in the play service versions in emulator and the API.
Hope they upgrade the Google API SDK with latest play service and release some notice about it.
I wanted to implement a Google signin activity which on success opens my next activity. If the user logs out from the next activity, I want to go back to Google signin activity and signout. However when I call signout in onActivityResult I get the following exception
Caused by: java.lang.IllegalStateException: GoogleApiClient is not connected yet.
Here's the relevant code
public class LoginActivity extends AppCompatActivity implements
GoogleApiClient.OnConnectionFailedListener,
View.OnClickListener {
private static final String TAG = "LoginActivity";
private static final int RC_SIGN_IN = 9001;
private GoogleApiClient mGoogleApiClient;
private GoogleSignInOptions gso;
private TextView mStatusTextView;
private ProgressDialog mProgressDialog;
#Override
protected void onCreate(Bundle savedInstanceState) {
Log.d(TAG, "onCreate()");
super.onCreate(savedInstanceState);
setContentView(R.layout.signin_activity);
// Views
mStatusTextView = (TextView) findViewById(R.id.status);
// Button listeners
findViewById(R.id.sign_in_button).setOnClickListener(this);
findViewById(R.id.sign_out_button).setOnClickListener(this);
findViewById(R.id.disconnect_button).setOnClickListener(this);
// [START configure_signin]
// Configure sign-in to request the user's ID, email address, and basic
// profile. ID and basic profile are included in DEFAULT_SIGN_IN.
gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestEmail()
.build();
// [END configure_signin]
// [START build_client]
// Build a GoogleApiClient with access to the Google Sign-In API and the
// options specified by gso.
mGoogleApiClient = new GoogleApiClient.Builder(this)
.enableAutoManage(this /* FragmentActivity */, this /* OnConnectionFailedListener */)
.addApi(Auth.GOOGLE_SIGN_IN_API, gso)
.build();
// [END build_client]
SignInButton signInButton = (SignInButton) findViewById(R.id.sign_in_button);
signInButton.setSize(SignInButton.SIZE_STANDARD);
signInButton.setScopes(gso.getScopeArray());
// [END customize_button]
}
#Override
public void onStart() {
Log.d(TAG, "onStart()");
super.onStart();
OptionalPendingResult<GoogleSignInResult> opr = Auth.GoogleSignInApi.silentSignIn(mGoogleApiClient);
if (opr.isDone()) {
// If the user's cached credentials are valid, the OptionalPendingResult will be "done"
// and the GoogleSignInResult will be available instantly.
Log.d(TAG, "Got cached sign-in");
GoogleSignInResult result = opr.get();
handleSignInResult(result);
} else {
// If the user has not previously signed in on this device or the sign-in has
// expired,
// this asynchronous branch will attempt to sign in the user silently. Cross-device
// single sign-on will occur in this branch.
showProgressDialog();
opr.setResultCallback(new ResultCallback<GoogleSignInResult>() {
#Override
public void onResult(GoogleSignInResult googleSignInResult) {
hideProgressDialog();
handleSignInResult(googleSignInResult);
}
});
}
}
// [START onActivityResult]
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
Log.d(TAG, "onActivityResult()");
super.onActivityResult(requestCode, resultCode, data);
// Result returned from launching the Intent from GoogleSignInApi.getSignInIntent(...);
if (requestCode == RC_SIGN_IN) {
GoogleSignInResult result = Auth.GoogleSignInApi.getSignInResultFromIntent(data);
handleSignInResult(result);
}
else if (requestCode == Constants.MAPS_ACTIVITY_FINISHED) {
if (resultCode == Constants.SIGNOUT) {
signOut();
}
}
}
// [END onActivityResult]
// [START handleSignInResult]
private void handleSignInResult(GoogleSignInResult result) {
Log.d(TAG, "handleSignInResult:" + result.isSuccess());
if (result.isSuccess()) {
// Signed in successfully, show authenticated UI.
GoogleSignInAccount acct = result.getSignInAccount();
mStatusTextView.setText(getString(R.string.signed_in_fmt, acct.getDisplayName()));
updateUI(true);
Intent intent = new Intent(this, MapsActivity.class);
startActivityForResult(intent, Constants.MAPS_ACTIVITY_FINISHED);
} else {
// Signed out, show unauthenticated UI.
updateUI(false);
}
}
// [END handleSignInResult]
// [START signIn]
private void signIn() {
Log.d(TAG, "signin()");
Intent signInIntent = Auth.GoogleSignInApi.getSignInIntent(mGoogleApiClient);
startActivityForResult(signInIntent, RC_SIGN_IN);
}
// [END signIn]
// [START signOut]
private void signOut() {
Log.d(TAG, "signout()");
Auth.GoogleSignInApi.signOut(mGoogleApiClient).setResultCallback(
new ResultCallback<Status>() {
#Override
public void onResult(Status status) {
// [START_EXCLUDE]
updateUI(false);
// [END_EXCLUDE]
}
});
}
// [END signOut]
}
According to the Javadoc:
1) signOut:
public abstract PendingResult<Status> signOut (GoogleApiClient client)
Parameters
client The connected GoogleApiClient to service the call.
2) getSignInIntent
public abstract Intent getSignInIntent (GoogleApiClient client)
Parameters
client The GoogleApiClient to service the call.
signOut call requires a connected GoogleApiClient; while getSignInIntent() doesn't. In Google's sample, sign-out button is only enabled after signing-in, which can guarantee a connected GoogleApiClient. However, in your case, you will need to explicitly listen to onConnected before calling signOut. You can use GoogleApiClient.Builder.addConnectionCallbacks to register an onConnected listener, and making sure you queue the signOut request until onConnected is called back.
(Since you used autoManage, GoogleApiClient internal will auto-connect in onStart() and auto-disconnect in onStop)
Your exception tells you what the problem is: your client is not connected. First of all I suggest that you check out this guide about Google API Client.
Anyway, what you should do is add the following code somewhere to your app:
mGoogleApiClient.connect();
This code will send a connection request, and if everything is fine, your client will get connected. After that, before you use it, you should check if the client is connected to avoid this error in future:
if (mGoogleApiClient.isConnected()) {
// do your stuff with Google Api Client
}