4

My goal is to develop a game that allows to quiz music with friends. You can test it by yourself by registering to this Google+ community : https://plus.google.com/u/0/communities/100815426127955231967

I am testing my app on several devices :

  • Motorola Xoom, android 4.1.2, build JZO54K
  • Nexus 7 2012 Wifi "nagasi", android 5.0.2, build LRX22G
  • Nexus 5, android 5.0.1, build LRX22C

I use the same Google user on all devices. My app is registered and I included the right lines in the manifest file.

With exactly the same code, I can succesfully connect to Google Plus and Games services on Nexus 7 and Nexus 5 lollipop devices, but not on Xoom android 4 device.

Here is the code, the connection request is in the Activity onCreate :

@Override
protected void onCreate(Bundle savedInstanceState) {
if (GooglePlayServicesUtil.isGooglePlayServicesAvailable(this) == ConnectionResult.SUCCESS) {
        if (mGoogleApiClient == null) {
            Plus.PlusOptions plusOptions = new Plus.PlusOptions.Builder().addActivityTypes(
               "http://schemas.google.com/AddActivity", "http://schemas.google.com/ReviewActivity").build();
            mGoogleApiClient = new GoogleApiClient.Builder(this).addApi(Games.API).addScope(Games.SCOPE_GAMES)
               .addApi(Plus.API, plusOptions).addScope(Plus.SCOPE_PLUS_LOGIN)
               .addConnectionCallbacks(this).addOnConnectionFailedListener(this).build();
        }
        mGoogleApiClient.connect();
    } else {
        Toast.makeText(this, R.string.texteErreurGPlus, Toast.LENGTH_LONG).show();
    }
}

For Android 4 device, the onConnectionFailed callback is called with a message :

GoogleApiClient connection failed: ConnectionResult{statusCode=SIGN_IN_REQUIRED, resolution=PendingIntent{412f07c8: android.os.BinderProxy@413b0bd0}} :


@Override
public void onConnectionFailed(ConnectionResult result) {
    if (mResolvingConnectionFailure) {
        // Already resolving
        return;
    } else if (result.hasResolution()) {
        try {
            mResolvingConnectionFailure = true;
            result.startResolutionForResult(this, REQUEST_CODE_RESOLUTION);
        } catch (SendIntentException e) {
            // There was an error with the resolution intent. Try again.
            mGoogleApiClient.connect();
        }
    } else {
        // Show dialog using GooglePlayServicesUtil.getErrorDialog()
        showErrorDialog(result.getErrorCode());
        mResolvingConnectionFailure = true;
    }
}

This leads to activity onActivityResult :

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    switch (requestCode) {
        case REQUEST_CODE_RESOLUTION:
            mResolvingConnectionFailure = false;
            if (resultCode == RESULT_OK) {
                // Make sure the app is not already connected or attempting to connect
                if (!mGoogleApiClient.isConnecting() &&
                        !mGoogleApiClient.isConnected()) {
                    mGoogleApiClient.connect();
                }
            } else {
                mGoogleApiClient.connect();
            }
            break;

and an infinite loop because resultCode is not equal to RESULT_OK.

Here is the gradle file for Android Studio :

apply plugin: 'android'

android {
    compileSdkVersion 21
    buildToolsVersion '21.1.2'

    defaultConfig {
        applicationId "debut.blindtest"
        minSdkVersion 16
        targetSdkVersion 21
        compileOptions {
            sourceCompatibility JavaVersion.VERSION_1_7
            targetCompatibility JavaVersion.VERSION_1_7
        }
    }

buildTypes {
    release {
        minifyEnabled false
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
        }
    }
}

dependencies {
    compile project(':volley')
    compile 'com.android.support:appcompat-v7:21.0.2'
    compile 'com.google.android.gms:play-services-plus:6.5.+'
    compile 'com.google.android.gms:play-services-games:6.5.+'
    compile files('libs/deezer-sdk-0.10.16.jar')
}

The execution flow is :

  • main activity onCreate where GoogleApiClient connect is called
  • main activity onConnectionFailed called, result has resolution, so result.startResolutionForResult is called
  • main activity onActivityResult is called

The exception:

01-07 22:38:01.260    4894-4894/debut.blindtest I/TagApplicationBlindTest﹕ onActivityResult : REQUEST_CODE_RESOLUTION : resultCode : 0  
01-07 22:38:01.280    4935-4936/? D/dalvikvm﹕ GC_CONCURRENT freed 448K, 7% free 6800K/7303K, paused 24ms+3ms, total 55ms  
01-07 22:38:01.280    4935-4935/? D/dalvikvm﹕ WAIT_FOR_CONCURRENT_GC blocked 22ms  
01-07 22:38:01.280    4894-4894/debut.blindtest E/BaseGamesUtils﹕ No standard error dialog available. Making fallback dialog.  
01-07 22:38:01.380    4864-4864/? W/dalvikvm﹕ VFY: unable to find class referenced in signature (Landroid/app/SharedElementCallback;)  
01-07 22:38:01.380    4864-4864/? I/dalvikvm﹕ Could not find method android.app.Activity.setEnterSharedElementCallback, referenced from method android.support.v4.app.q.setEnterSharedElementCallback  
01-07 22:38:01.380    4864-4864/? W/dalvikvm﹕ VFY: unable to resolve virtual method 80: Landroid/app/Activity;.setEnterSharedElementCallback (Landroid/app/SharedElementCallback;)V  
01-07 22:38:01.380    4864-4864/? D/dalvikvm﹕ VFY: replacing opcode 0x6e at 0x000e  
01-07 22:38:01.380    4864-4864/? W/dalvikvm﹕ VFY: unable to find class referenced in signature (Landroid/app/SharedElementCallback;)  
01-07 22:38:01.380    4864-4864/? I/dalvikvm﹕ Could not find method android.app.Activity.setExitSharedElementCallback, referenced from method android.support.v4.app.q.setExitSharedElementCallback  
01-07 22:38:01.380    4864-4864/? W/dalvikvm﹕ VFY: unable to resolve virtual method 81: Landroid/app/Activity;.setExitSharedElementCallback (Landroid/app/SharedElementCallback;)V  
01-07 22:38:01.380    4864-4864/? D/dalvikvm﹕ VFY: replacing opcode 0x6e at 0x000e  
01-07 22:38:01.380    4864-4864/? I/dalvikvm﹕ Could not find method android.app.Activity.finishAfterTransition, referenced from method android.support.v4.app.q.supportFinishAfterTransition  
01-07 22:38:01.380    4864-4864/? W/dalvikvm﹕ VFY: unable to resolve virtual method 46: Landroid/app/Activity;.finishAfterTransition ()V  
01-07 22:38:01.380    4864-4864/? D/dalvikvm﹕ VFY: replacing opcode 0x6e at 0x0006  
01-07 22:38:01.380    4864-4864/? I/dalvikvm﹕ Could not find method android.app.Activity.postponeEnterTransition, referenced from method android.support.v4.app.q.supportPostponeEnterTransition  
01-07 22:38:01.380    4864-4864/? W/dalvikvm﹕ VFY: unable to resolve virtual method 77: Landroid/app/Activity;.postponeEnterTransition ()V  
01-07 22:38:01.380    4864-4864/? D/dalvikvm﹕ VFY: replacing opcode 0x6e at 0x0006  
01-07 22:38:01.380    4864-4864/? I/dalvikvm﹕ Could not find method android.app.Activity.startPostponedEnterTransition, referenced from method android.support.v4.app.q.supportStartPostponedEnterTransition  
01-07 22:38:01.380    4864-4864/? W/dalvikvm﹕ VFY: unable to resolve virtual method 89: Landroid/app/Activity;.startPostponedEnterTransition ()V  
01-07 22:38:01.380    4864-4864/? D/dalvikvm﹕ VFY: replacing opcode 0x6e at 0x0006  
01-07 22:38:01.410    4894-4898/debut.blindtest D/dalvikvm﹕ GC_CONCURRENT freed 325K, 6% free 7193K/7623K, paused 14ms+38ms, total 115ms  
01-07 22:38:01.410    4935-4936/? D/dalvikvm﹕ GC_CONCURRENT freed 460K, 8% free 6851K/7367K, paused 19ms+12ms, total 83ms  
01-07 22:38:01.410    4935-4935/? D/dalvikvm﹕ WAIT_FOR_CONCURRENT_GC blocked 41ms  
01-07 22:38:01.450    4864-4864/? E/dalvikvm﹕ Could not find class 'android.app.AppOpsManager', referenced from method com.google.android.gms.common.util.e.a  
01-07 22:38:01.450    4864-4864/? W/dalvikvm﹕ VFY: unable to resolve check-cast 35 (Landroid/app/AppOpsManager;) in Lcom/google/android/gms/common/util/e;  
01-07 22:38:01.450    4864-4864/? D/dalvikvm﹕ VFY: replacing opcode 0x1f at 0x0010  
01-07 22:38:01.460    4864-4864/? E/SignInActivity﹕ SignInActivity must be started with startActivityForResult  
01-07 22:38:01.530    4935-4936/? D/dalvikvm﹕ GC_CONCURRENT freed 457K, 7% free 6916K/7431K, paused 18ms+5ms, total 61ms  

Could you help me to discover what I should do to be compatible with Android 4 devices ?

Chad Bingham
  • 32,650
  • 19
  • 86
  • 115
bobygerm
  • 483
  • 10
  • 21

3 Answers3

1

By automatically connecting in onConnectionFailed(), you will continue to attempt to connect as many times as necessary until you get a valid connection, as you experience. This means that even if users did not want to sign in (say, they hit cancel on the sign in dialog), they would continually be prompted over and over again.

Instead, the Google+ Sign In guide, uses a mSignInClicked variable which helps determine if onConnectionFailed() should immediately reconnect (the ideal situation for an unconnected person is with onConnectionFailed() being called but you have yet to call startResolutionForResult() - just save the ConnectionResult until the user signs in).

If you'd like to maintain the initial auto sign in attempt, you could consider a approach used in the Google Play Games Services samples such as TrivialQuest where their onConnnectionFailed() method looks like:

public void onConnectionFailed(ConnectionResult connectionResult) {
  Log.d(TAG, "onConnectionFailed() called, result: " + connectionResult);

  if (mResolvingConnectionFailure) {
    Log.d(TAG, "onConnectionFailed() ignoring connection failure; already resolving.");
    return;
  }

  if (mSignInClicked || mAutoStartSignInFlow) {
    mAutoStartSignInFlow = false;
    mSignInClicked = false;
    mResolvingConnectionFailure = BaseGameUtils.resolveConnectionFailure(this, 
        mGoogleApiClient, connectionResult, RC_SIGN_IN, 
        getString(R.string.signin_other_error));
  }
  showSignInBar();
}

Where they make use of BaseGameUtils helper methods to make connecting to Google services much easier (note: nothing is specifically Game Services related in there - it works equally well with all GoogleApiClient connections).

ianhanniballake
  • 191,609
  • 30
  • 470
  • 443
  • 1
    Thank you for your quick and detailed answer. Unfortunately, after several tests, i still get the "SIGN_IN REQUIRED" error repeatedly. The resolution dialog is not interesting (unlnown error). This error is still occuring only on android 4 device ... – bobygerm Jan 06 '15 at 08:19
  • For most unknown errors, there is additional output in logcat – ianhanniballake Jan 06 '15 at 18:31
  • I have this : 01-06 23:13:15.390 26650-26650/debut.blindtest E/BaseGamesUtils﹕ No standard error dialog available. Making fallback dialog. 01-06 23:13:15.430 26332-26332/? E/SignInActivity﹕ SignInActivity must be started with startActivityForResult – bobygerm Jan 06 '15 at 22:15
  • Where is the 'SignInActivity must be started with startActivityForResult' message coming from? That seems like a pretty big issue. – ianhanniballake Jan 06 '15 at 22:23
  • I added the execution flow at the end of my question. It is coming from onActivityResult. – bobygerm Jan 07 '15 at 21:51
  • The 'SignInActivity must be started' error is an internal error that shouldn't ever occur if you are using `startResolutionForResult()`... My only thought is that it is something very device specific. I'd try uninstalling updates/updating Google Play Services (Google Settings, Menu, Help & Feedback, Menu, View in Google Play Store) and/or factory resetting. – ianhanniballake Jan 07 '15 at 23:05
  • Did anyone find a solution to this? – dazza5000 Apr 09 '16 at 01:27
  • I am also facing the same issue. Anyone with a solution ? – user1479802 Apr 25 '16 at 15:33
1

I removed the line "android:launchMode="singleInstance"" in my manifest file. After several build/run cycles it began to work. I just need to redesign my app to change my activities.

bobygerm
  • 483
  • 10
  • 21
0

make sure you have 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" />
Mansour Alnasser
  • 4,446
  • 5
  • 40
  • 51