I have studied google plus login from https://developers.google.com/+/mobile/android/getting-started
When I launch my app there is a toast message "User is connected!" and then I press G+ Sign in button my app force close.
This is the message form logcat
04-08 18:31:21.680 24231-24231/app.umitems.test.testgoogleplus1.app D/﹕ onClick()
04-08 18:31:21.680 24231-24231/app.umitems.test.testgoogleplus1.app D/AndroidRuntime﹕ Shutting down VM
04-08 18:31:21.680 24231-24231/app.umitems.test.testgoogleplus1.app W/dalvikvm﹕ threadid=1: thread exiting with uncaught exception (group=0x41f99ce0)
04-08 18:31:21.685 24231-24231/app.umitems.test.testgoogleplus1.app E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: app.umitems.test.testgoogleplus1.app, PID: 24231
java.lang.NullPointerException
at app.umitems.test.testgoogleplus1.app.ExampleActivity.resolveSignInError(ExampleActivity.java:68)
at app.umitems.test.testgoogleplus1.app.ExampleActivity.onClick(ExampleActivity.java:166)
at com.google.android.gms.common.SignInButton.onClick(Unknown Source)
at android.view.View.performClick(View.java:4445)
at android.view.View$PerformClick.run(View.java:18446)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5081)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:791)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:607)
at dalvik.system.NativeStart.main(Native Method)
Here is my code
package app.umitems.test.testgoogleplus1.app;
import android.app.Activity;
import android.content.Intent;
import android.content.IntentSender;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Toast;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesClient.ConnectionCallbacks;
import com.google.android.gms.common.GooglePlayServicesClient.OnConnectionFailedListener;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.plus.Plus;
public class ExampleActivity extends Activity implements
ConnectionCallbacks,
OnConnectionFailedListener,
GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener,
View.OnClickListener {
/* Request code used to invoke sign in user interactions. */
private static final int RC_SIGN_IN = 0;
/* Client used to interact with Google APIs. */
private GoogleApiClient mGoogleApiClient;
/* A flag indicating that a PendingIntent is in progress and prevents
* us from starting further intents.
*/
private boolean mIntentInProgress;
/* Track whether the sign-in button has been clicked so that we know to resolve
* all issues preventing sign-in without waiting.
*/
private boolean mSignInClicked;
/* Store the connection result from onConnectionFailed callbacks so that we can
* resolve them when the user clicks sign-in.
*/
private ConnectionResult mConnectionResult;
View btn;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_example);
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(Plus.API, null)
//.addScope(Plus.SCOPE_PLUS_LOGIN)
.build();
btn = findViewById(R.id.sign_in_button);
btn.setOnClickListener(this);
}
protected void onStart() {
super.onStart();
mGoogleApiClient.connect();
}
/* A helper method to resolve the current ConnectionResult error. */
public void resolveSignInError() {
Log.d("","resolveSignInError()");
if (mConnectionResult.hasResolution()) {
Log.d("","resolveSignInError() mConnectionResult.hasResolution()");
try {
mIntentInProgress = true;
/*startIntentSenderForResult(mConnectionResult.getIntentSender(),
RC_SIGN_IN, null, 0, 0, 0);*/
mConnectionResult.startResolutionForResult(this, // your activity
RC_SIGN_IN);
} 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.
Log.d("","resolveSignInError() mConnectionResult.hasResolution() catch");
mIntentInProgress = false;
mGoogleApiClient.connect();
}
}
}
protected void onStop() {
super.onStop();
if (mGoogleApiClient.isConnected()) {
mGoogleApiClient.disconnect();
}
}
@Override public void onConnected(Bundle bundle){
// We've resolved any connection errors. mGoogleApiClient can be used to
// access Google APIs on behalf of the user.
mSignInClicked = false;
Toast.makeText(this, "User is connected!", Toast.LENGTH_LONG).show();
}
@Override public void onConnectionSuspended(int i){
mGoogleApiClient.connect();
}
@Override public void onDisconnected(){
}
@Override
public void onConnectionFailed(ConnectionResult result) {
if (!mIntentInProgress) {
// Store the ConnectionResult so that we can use it later when the user clicks
// 'sign-in'.
mConnectionResult = result;
if (mSignInClicked) {
// The user has already clicked 'sign-in' so we attempt to resolve all
// errors until the user is signed in, or they cancel.
resolveSignInError();
}
}
}
/*@Override
public void onConnectionFailed(ConnectionResult result){
if (!mIntentInProgress && result.hasResolution()) {
try {
mIntentInProgress = true;*//*
startIntentSenderForResult(result.getIntentSender(),
RC_SIGN_IN, null, 0, 0, 0);*//*
result.startResolutionForResult(this, // your activity
RC_SIGN_IN);
} 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.
mIntentInProgress = false;
mGoogleApiClient.connect();
}
}
}*/
protected void onActivityResult(int requestCode, int responseCode, Intent intent) {
if (requestCode == RC_SIGN_IN) {
if (responseCode != RESULT_OK) {
mSignInClicked = false;
}
mIntentInProgress = false;
if (!mGoogleApiClient.isConnecting()) {
mGoogleApiClient.connect();
}
}
}
@Override public void onClick(View view){
Log.d("","onClick()");
if (view.getId() == R.id.sign_in_button
&& !mGoogleApiClient.isConnecting()) {
mSignInClicked = true;
resolveSignInError();
}
}
}
I just found that the app will automatically connected to Google+ without ask any permission. I don't need to press sign in button but I can post via my account. Is this a bug about privacy?
OK! So that toast is because you have signed in, and when you click you are trying to sign in again: because you don't have a connection result with an error to resolve, you get the NPE.
This is how it works:
So, if you get onConnected you should hide the sign in button - the user has signed in!
Now, perhaps for whatever reason you want the user to have to click the button to get started. That's fine too. In the onClick, you just need to test whether mPlusClient isConnected. If it is, go straight to whatever you wanted to do post sign in. If not, then resolve the connection result.