8

Postępuję zgodnie z tym samouczkiem https://developers.google.com/+/mobile/android/recommend, aby zintegrować przycisk +1 w mojej aplikacji.Nie można utworzyć instancji następujących klas: - com.google.android.gms.plus.PlusOneButton

Jak tylko umieścić ten kod w XML pojawiają się błędy w GraphicalLayout

<com.google.android.gms.plus.PlusOneButton 
xmlns:plus="http://schemas.android.com/apk/lib/com.google.android.gms.plus" 
android:id="@+id/plus_one_button" 
android:layout_width="wrap_content" 
android:layout_height="wrap_content" 
plus:size="standard" 
plus:annotation="inline" /> 

Próbowałem też wprowadzenie xmlns:plus="http://schemas.android.com/apk/lib/com.google.android.gms.plus" w macierzystej RelativeLayout, ale ten sam błąd.

The following classes could not be instantiated: 
- com.google.android.gms.plus.PlusOneButton (Open Class, Show Error Log) 
See the Error Log (Window > Show View) for more details. 


java.lang.NullPointerException 
at com.google.android.gms.plus.PlusOneDummyView$zzb.isValid( at com.google.android.gms.plus.PlusOneDummyView.zzrJ( at com.google.android.gms.plus.PlusOneDummyView.<init>( at com.google.android.gms.plus.internal.zzg.zza( at com.google.android.gms.plus.PlusOneButton.zzN( at com.google.android.gms.plus.PlusOneButton.<init>( at sun.reflect.NativeConstructorAccessorImpl.newInstance0( at sun.reflect.NativeConstructorAccessorImpl.newInstance( at sun.reflect.DelegatingConstructorAccessorImpl.newInstance( at java.lang.reflect.Constructor.newInstance( at com.android.ide.eclipse.adt.internal.editors.layout.ProjectCallback.instantiateClass(ProjectCallback.java:438) 
at com.android.ide.eclipse.adt.internal.editors.layout.ProjectCallback.loadView(ProjectCallback.java:190) 
at android.view.BridgeInflater.loadCustomView(BridgeInflater.java:207) 
at android.view.BridgeInflater.createViewFromTag(BridgeInflater.java:132) 
at android.view.LayoutInflater.rInflate_Original(LayoutInflater.java:806) 
at android.view.LayoutInflater_Delegate.rInflate(LayoutInflater_Delegate.java:64) 
at android.view.LayoutInflater.rInflate(LayoutInflater.java:782) 
at android.view.LayoutInflater.inflate(LayoutInflater.java:504) 
at android.view.LayoutInflater.inflate(LayoutInflater.java:385) 

Pomoc !!

+0

Używasz Android Studio? Opublikuj swój plik build.gradle. –

+0

Przykro mi, używając Eclipse do tego –

+0

Ahh! Ok. Czy zaimportowałeś projekt biblioteki Google Play Services? –

Odpowiedz

2

Android Studio rozwiązanie:

Właśnie prosty przykład działa poprzez uruchomienie z kodem z gplus-quickstart, a następnie dodanie przycisku +1 przy pomocy przewodnika umieszczonego w pytaniu.

build.gradle zależności:

dependencies { 
    compile fileTree(dir: 'libs', include: ['*.jar']) 
    compile 'com.android.support:appcompat-v7:22.1.1' 
    compile 'com.google.android.gms:play-services:7.0.0' 
} 

AndroidManifest.xml:

<?xml version="1.0" encoding="utf-8"?> 
<manifest xmlns:android="http://schemas.android.com/apk/res/android" 
    package="com.plustest.daniel.googleplusone" > 

    <application 
     android:allowBackup="true" 
     android:icon="@drawable/ic_launcher" 
     android:label="@string/app_name" 
     android:theme="@style/AppTheme" > 
     <activity 
      android:name=".MainActivity" 
      android:label="@string/app_name" > 
      <intent-filter> 
       <action android:name="android.intent.action.MAIN" /> 

       <category android:name="android.intent.category.LAUNCHER" /> 
      </intent-filter> 
     </activity> 
    </application> 

    <meta-data 
     android:name="com.google.android.gms.version" 
     android:value="@integer/google_play_services_version" /> 

</manifest> 

dodałem com.google.android.gms.plus.PlusOneButton do dołu activity_main.xml, która jest oparta na main_activity.xml z szybkiego kodu startowego:

xmlns:plus="http://schemas.android.com/apk/lib/com.google.android.gms.plus" 
      android:id="@+id/plus_one_button" 
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content" 
      plus:size="standard" 
      plus:annotation="inline" /> 

MainActivity.java, z dodanym przyciskiem +1 .

Zauważyłem, że dla URL użyłem strony Carnegie Mellon School of Computer Science w Google+.

public class MainActivity extends FragmentActivity implements 
     ConnectionCallbacks, OnConnectionFailedListener, 
     ResultCallback<LoadPeopleResult>, View.OnClickListener, 
     CheckBox.OnCheckedChangeListener, GoogleApiClient.ServerAuthCodeCallbacks { 

    private static final String TAG = "android-plus-quickstart"; 

    private static final int STATE_DEFAULT = 0; 
    private static final int STATE_SIGN_IN = 1; 
    private static final int STATE_IN_PROGRESS = 2; 

    private static final int RC_SIGN_IN = 0; 

    private static final String SAVED_PROGRESS = "sign_in_progress"; 

    // Client ID for a web server that will receive the auth code and exchange it for a 
    // refresh token if offline access is requested. 
    private static final String WEB_CLIENT_ID = "WEB_CLIENT_ID"; 

    // Base URL for your token exchange server, no trailing slash. 
    private static final String SERVER_BASE_URL = "SERVER_BASE_URL"; 

    // URL where the client should GET the scopes that the server would like granted 
    // before asking for a serverAuthCode 
    private static final String EXCHANGE_TOKEN_URL = SERVER_BASE_URL + "/exchangetoken"; 

    // URL where the client should POST the serverAuthCode so that the server can exchange 
    // it for a refresh token, 
    private static final String SELECT_SCOPES_URL = SERVER_BASE_URL + "/selectscopes"; 


    private int mSignInProgress; 

    // Used to store the PendingIntent most recently returned by Google Play 
    // services until the user clicks 'sign in'. 
    private PendingIntent mSignInIntent; 

    // Used to store the error code most recently returned by Google Play services 
    // until the user clicks 'sign in'. 
    private int mSignInError; 

    // Used to determine if we should ask for a server auth code when connecting the 
    // GoogleApiClient. False by default so that this sample can be used without configuring 
    // a WEB_CLIENT_ID and SERVER_BASE_URL. 
    private boolean mRequestServerAuthCode = false; 

    // Used to mock the state of a server that would receive an auth code to exchange 
    // for a refresh token, If true, the client will assume that the server has the 
    // permissions it wants and will not send an auth code on sign in. If false, 
    // the client will request offline access on sign in and send and new auth code 
    // to the server. True by default because this sample does not implement a server 
    // so there would be nowhere to send the code. 
    private boolean mServerHasToken = true; 

    private SignInButton mSignInButton; 
    private Button mSignOutButton; 
    private Button mRevokeButton; 
    private TextView mStatus; 
    private ListView mCirclesListView; 
    private ArrayAdapter<String> mCirclesAdapter; 
    private ArrayList<String> mCirclesList; 

    //added: 
    private PlusOneButton mPlusOneButton; 
    private String URL = "https://plus.google.com/101009371381835899795/posts"; 

    private static final int PLUS_ONE_REQUEST_CODE = 0; 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 

     mSignInButton = (SignInButton) findViewById(R.id.sign_in_button); 
     mSignOutButton = (Button) findViewById(R.id.sign_out_button); 
     mRevokeButton = (Button) findViewById(R.id.revoke_access_button); 
     mStatus = (TextView) findViewById(R.id.sign_in_status); 
     mCirclesListView = (ListView) findViewById(R.id.circles_list); 

     //added: 
     mPlusOneButton = (PlusOneButton) findViewById(R.id.plus_one_button); 

     // Button listeners 
     mSignInButton.setOnClickListener(this); 
     mSignOutButton.setOnClickListener(this); 
     mRevokeButton.setOnClickListener(this); 

     // CheckBox listeners 
     ((CheckBox) findViewById(R.id.request_auth_code_checkbox)).setOnCheckedChangeListener(this); 
     ((CheckBox) findViewById(R.id.has_token_checkbox)).setOnCheckedChangeListener(this); 

     mCirclesList = new ArrayList<String>(); 
     mCirclesAdapter = new ArrayAdapter<String>(
       this, R.layout.circle_member, mCirclesList); 
     mCirclesListView.setAdapter(mCirclesAdapter); 

     if (savedInstanceState != null) { 
      mSignInProgress = savedInstanceState 
        .getInt(SAVED_PROGRESS, STATE_DEFAULT); 
     } 

     mGoogleApiClient = buildGoogleApiClient(); 
    } 

    private GoogleApiClient buildGoogleApiClient() { 
     // When we build the GoogleApiClient we specify where connected and 
     // connection failed callbacks should be returned, which Google APIs our 
     // app uses and which OAuth 2.0 scopes our app requests. 
     GoogleApiClient.Builder builder = new GoogleApiClient.Builder(this) 
       .addConnectionCallbacks(this) 
       .addOnConnectionFailedListener(this) 
       .addApi(Plus.API, Plus.PlusOptions.builder().build()) 
       .addScope(Plus.SCOPE_PLUS_LOGIN); 

     if (mRequestServerAuthCode) { 
      checkServerAuthConfiguration(); 
      builder = builder.requestServerAuthCode(WEB_CLIENT_ID, this); 
     } 

     return builder.build(); 
    } 

    //added: 
    @Override 
    protected void onResume() { 
     super.onResume(); 
     // Refresh the state of the +1 button each time the activity receives focus. 
     mPlusOneButton.initialize(URL, PLUS_ONE_REQUEST_CODE); 
    } 

    @Override 
    protected void onStart() { 
     super.onStart(); 
     mGoogleApiClient.connect(); 
    } 

    @Override 
    protected void onStop() { 
     super.onStop(); 

     if (mGoogleApiClient.isConnected()) { 
      mGoogleApiClient.disconnect(); 
     } 
    } 

    @Override 
    protected void onSaveInstanceState(Bundle outState) { 
     super.onSaveInstanceState(outState); 
     outState.putInt(SAVED_PROGRESS, mSignInProgress); 
    } 

    @Override 
    public void onClick(View v) { 
     if (!mGoogleApiClient.isConnecting()) { 
      // We only process button clicks when GoogleApiClient is not transitioning 
      // between connected and not connected. 
      switch (v.getId()) { 
       case R.id.sign_in_button: 
        mStatus.setText(R.string.status_signing_in); 
        mSignInProgress = STATE_SIGN_IN; 
        mGoogleApiClient.connect(); 
        break; 
       case R.id.sign_out_button: 
        // We clear the default account on sign out so that Google Play 
        // services will not return an onConnected callback without user 
        // interaction. 
        if (mGoogleApiClient.isConnected()) { 
         Plus.AccountApi.clearDefaultAccount(mGoogleApiClient); 
         mGoogleApiClient.disconnect(); 
        } 
        onSignedOut(); 
        break; 
       case R.id.revoke_access_button: 
        // After we revoke permissions for the user with a GoogleApiClient 
        // instance, we must discard it and create a new one. 
        Plus.AccountApi.clearDefaultAccount(mGoogleApiClient); 
        // Our sample has caches no user data from Google+, however we 
        // would normally register a callback on revokeAccessAndDisconnect 
        // to delete user data so that we comply with Google developer 
        // policies. 
        Plus.AccountApi.revokeAccessAndDisconnect(mGoogleApiClient); 
        mGoogleApiClient = buildGoogleApiClient(); 
        mGoogleApiClient.connect(); 
        break; 
      } 
     } 
    } 

    @Override 
    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 
     switch (buttonView.getId()) { 
      case R.id.request_auth_code_checkbox: 
       mRequestServerAuthCode = isChecked; 
       buildGoogleApiClient(); 
       if (isChecked) { 
        findViewById(R.id.layout_has_token).setVisibility(View.VISIBLE); 
       } else { 
        findViewById(R.id.layout_has_token).setVisibility(View.INVISIBLE); 
       } 
       break; 
      case R.id.has_token_checkbox: 
       mServerHasToken = isChecked; 
       break; 
     } 
    } 

    /* onConnected is called when our Activity successfully connects to Google 
    * Play services. onConnected indicates that an account was selected on the 
    * device, that the selected account has granted any requested permissions to 
    * our app and that we were able to establish a service connection to Google 
    * Play services. 
    */ 
    @Override 
    public void onConnected(Bundle connectionHint) { 
     // Reaching onConnected means we consider the user signed in. 
     Log.i(TAG, "onConnected"); 

     // Update the user interface to reflect that the user is signed in. 
     mSignInButton.setEnabled(false); 
     mSignOutButton.setEnabled(true); 
     mRevokeButton.setEnabled(true); 

     // Hide the sign-in options, they no longer apply 
     findViewById(R.id.layout_server_auth).setVisibility(View.GONE); 

     // Retrieve some profile information to personalize our app for the user. 
     Person currentUser = Plus.PeopleApi.getCurrentPerson(mGoogleApiClient); 

     mStatus.setText(String.format(
       getResources().getString(R.string.signed_in_as), 
       currentUser.getDisplayName())); 

     Plus.PeopleApi.loadVisible(mGoogleApiClient, null) 
       .setResultCallback(this); 

     // Indicate that the sign in process is complete. 
     mSignInProgress = STATE_DEFAULT; 
    } 

    /* onConnectionFailed is called when our Activity could not connect to Google 
    * Play services. onConnectionFailed indicates that the user needs to select 
    * an account, grant permissions or resolve an error in order to sign in. 
    */ 
    @Override 
    public void onConnectionFailed(ConnectionResult result) { 
     // Refer to the javadoc for ConnectionResult to see what error codes might 
     // be returned in onConnectionFailed. 
     Log.i(TAG, "onConnectionFailed: ConnectionResult.getErrorCode() = " 
       + result.getErrorCode()); 

     if (result.getErrorCode() == ConnectionResult.API_UNAVAILABLE) { 
      // An API requested for GoogleApiClient is not available. The device's current 
      // configuration might not be supported with the requested API or a required component 
      // may not be installed, such as the Android Wear application. You may need to use a 
      // second GoogleApiClient to manage the application's optional APIs. 
      Log.w(TAG, "API Unavailable."); 
     } else if (mSignInProgress != STATE_IN_PROGRESS) { 
      // We do not have an intent in progress so we should store the latest 
      // error resolution intent for use when the sign in button is clicked. 
      mSignInIntent = result.getResolution(); 
      mSignInError = result.getErrorCode(); 

      if (mSignInProgress == STATE_SIGN_IN) { 
       // STATE_SIGN_IN indicates the user already clicked the sign in button 
       // so we should continue processing errors until the user is signed in 
       // or they click cancel. 
       resolveSignInError(); 
      } 
     } 

     // In this sample we consider the user signed out whenever they do not have 
     // a connection to Google Play services. 
     onSignedOut(); 
    } 


    private void resolveSignInError() { 
     if (mSignInIntent != null) { 
      // We have an intent which will allow our user to sign in or 
      // resolve an error. For example if the user needs to 
      // select an account to sign in with, or if they need to consent 
      // to the permissions your app is requesting. 

      try { 
       // Send the pending intent that we stored on the most recent 
       // OnConnectionFailed callback. This will allow the user to 
       // resolve the error currently preventing our connection to 
       // Google Play services. 
       mSignInProgress = STATE_IN_PROGRESS; 
       startIntentSenderForResult(mSignInIntent.getIntentSender(), 
         RC_SIGN_IN, null, 0, 0, 0); 
      } catch (SendIntentException e) { 
       Log.i(TAG, "Sign in intent could not be sent: " 
         + e.getLocalizedMessage()); 
       // The intent was canceled before it was sent. Attempt to connect to 
       // get an updated ConnectionResult. 
       mSignInProgress = STATE_SIGN_IN; 
       mGoogleApiClient.connect(); 
      } 
     } else { 
      // Google Play services wasn't able to provide an intent for some 
      // error types, so we show the default Google Play services error 
      // dialog which may still start an intent on our behalf if the 
      // user can resolve the issue. 
      createErrorDialog().show(); 
     } 
    } 

    @Override 
    protected void onActivityResult(int requestCode, int resultCode, 
            Intent data) { 
     switch (requestCode) { 
      case RC_SIGN_IN: 
       if (resultCode == RESULT_OK) { 
        // If the error resolution was successful we should continue 
        // processing errors. 
        mSignInProgress = STATE_SIGN_IN; 
       } else { 
        // If the error resolution was not successful or the user canceled, 
        // we should stop processing errors. 
        mSignInProgress = STATE_DEFAULT; 
       } 

       if (!mGoogleApiClient.isConnecting()) { 
        // If Google Play services resolved the issue with a dialog then 
        // onStart is not called so we need to re-attempt connection here. 
        mGoogleApiClient.connect(); 
       } 
       break; 
     } 
    } 

    @Override 
    public void onResult(LoadPeopleResult peopleData) { 
     if (peopleData.getStatus().getStatusCode() == CommonStatusCodes.SUCCESS) { 
      mCirclesList.clear(); 
      PersonBuffer personBuffer = peopleData.getPersonBuffer(); 
      try { 
       int count = personBuffer.getCount(); 
       for (int i = 0; i < count; i++) { 
        mCirclesList.add(personBuffer.get(i).getDisplayName()); 
       } 
      } finally { 
       personBuffer.close(); 
      } 

      mCirclesAdapter.notifyDataSetChanged(); 
     } else { 
      Log.e(TAG, "Error requesting visible circles: " + peopleData.getStatus()); 
     } 
    } 

    private void onSignedOut() { 
     // Update the UI to reflect that the user is signed out. 
     mSignInButton.setEnabled(true); 
     mSignOutButton.setEnabled(false); 
     mRevokeButton.setEnabled(false); 

     // Show the sign-in options 
     findViewById(R.id.layout_server_auth).setVisibility(View.VISIBLE); 

     mStatus.setText(R.string.status_signed_out); 

     mCirclesList.clear(); 
     mCirclesAdapter.notifyDataSetChanged(); 
    } 

    @Override 
    public void onConnectionSuspended(int cause) { 
     // The connection to Google Play services was lost for some reason. 
     // We call connect() to attempt to re-establish the connection or get a 
     // ConnectionResult that we can attempt to resolve. 
     mGoogleApiClient.connect(); 
    } 

    private Dialog createErrorDialog() { 
     if (GooglePlayServicesUtil.isUserRecoverableError(mSignInError)) { 
      return GooglePlayServicesUtil.getErrorDialog(
        mSignInError, 
        this, 
        RC_SIGN_IN, 
        new DialogInterface.OnCancelListener() { 
         @Override 
         public void onCancel(DialogInterface dialog) { 
          Log.e(TAG, "Google Play services resolution cancelled"); 
          mSignInProgress = STATE_DEFAULT; 
          mStatus.setText(R.string.status_signed_out); 
         } 
        }); 
     } else { 
      return new AlertDialog.Builder(this) 
        .setMessage(R.string.play_services_error) 
        .setPositiveButton(R.string.close, 
          new DialogInterface.OnClickListener() { 
           @Override 
           public void onClick(DialogInterface dialog, int which) { 
            Log.e(TAG, "Google Play services error could not be " 
              + "resolved: " + mSignInError); 
            mSignInProgress = STATE_DEFAULT; 
            mStatus.setText(R.string.status_signed_out); 
           } 
          }).create(); 
     } 
    } 

    @Override 
    public CheckResult onCheckServerAuthorization(String idToken, Set<Scope> scopeSet) { 
     Log.i(TAG, "Checking if server is authorized."); 
     Log.i(TAG, "Mocking server has refresh token: " + String.valueOf(mServerHasToken)); 

     if (!mServerHasToken) { 
      // Server does not have a valid refresh token, so request a new 
      // auth code which can be exchanged for one. This will cause the user to see the 
      // consent dialog and be prompted to grant offline access. This callback occurs on a 
      // background thread so it is OK to do synchronous network access. 

      // Ask the server which scopes it would like to have for offline access. This 
      // can be distinct from the scopes granted to the client. By getting these values 
      // from the server, you can change your server's permissions without needing to 
      // recompile the client application. 
      HttpClient httpClient = new DefaultHttpClient(); 
      HttpGet httpGet = new HttpGet(SELECT_SCOPES_URL); 
      HashSet<Scope> serverScopeSet = new HashSet<Scope>(); 

      try { 
       HttpResponse httpResponse = httpClient.execute(httpGet); 
       int responseCode = httpResponse.getStatusLine().getStatusCode(); 
       String responseBody = EntityUtils.toString(httpResponse.getEntity()); 

       if (responseCode == 200) { 
        String[] scopeStrings = responseBody.split(" "); 
        for (String scope : scopeStrings) { 
         Log.i(TAG, "Server Scope: " + scope); 
         serverScopeSet.add(new Scope(scope)); 
        } 
       } else { 
        Log.e(TAG, "Error in getting server scopes: " + responseCode); 
       } 

      } catch (ClientProtocolException e) { 
       Log.e(TAG, "Error in getting server scopes.", e); 
      } catch (IOException e) { 
       Log.e(TAG, "Error in getting server scopes.", e); 
      } 

      // This tells GoogleApiClient that the server needs a new serverAuthCode with 
      // access to the scopes in serverScopeSet. Note that we are not asking the server 
      // if it already has such a token because this is a sample application. In reality, 
      // you should only do this on the first user sign-in or if the server loses or deletes 
      // the refresh token. 
      return CheckResult.newAuthRequiredResult(serverScopeSet); 
     } else { 
      // Server already has a valid refresh token with the correct scopes, no need to 
      // ask the user for offline access again. 
      return CheckResult.newAuthNotRequiredResult(); 
     } 
    } 

    @Override 
    public boolean onUploadServerAuthCode(String idToken, String serverAuthCode) { 
     // Upload the serverAuthCode to the server, which will attempt to exchange it for 
     // a refresh token. This callback occurs on a background thread, so it is OK 
     // to perform synchronous network access. Returning 'false' will fail the 
     // GoogleApiClient.connect() call so if you would like the client to ignore 
     // server failures, always return true. 
     HttpClient httpClient = new DefaultHttpClient(); 
     HttpPost httpPost = new HttpPost(EXCHANGE_TOKEN_URL); 

     try { 
      List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(1); 
      nameValuePairs.add(new BasicNameValuePair("serverAuthCode", serverAuthCode)); 
      httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs)); 

      HttpResponse response = httpClient.execute(httpPost); 
      int statusCode = response.getStatusLine().getStatusCode(); 
      final String responseBody = EntityUtils.toString(response.getEntity()); 
      Log.i(TAG, "Code: " + statusCode); 
      Log.i(TAG, "Resp: " + responseBody); 

      // Show Toast on UI Thread 
      runOnUiThread(new Runnable() { 
       @Override 
       public void run() { 
        Toast.makeText(MainActivity.this, responseBody, Toast.LENGTH_LONG).show(); 
       } 
      }); 
      return (statusCode == 200); 
     } catch (ClientProtocolException e) { 
      Log.e(TAG, "Error in auth code exchange.", e); 
      return false; 
     } catch (IOException e) { 
      Log.e(TAG, "Error in auth code exchange.", e); 
      return false; 
     } 
    } 

    private void checkServerAuthConfiguration() { 
     // Check that the server URL is configured before allowing this box to 
     // be unchecked 
     if ("WEB_CLIENT_ID".equals(WEB_CLIENT_ID) || 
       "SERVER_BASE_URL".equals(SERVER_BASE_URL)) { 
      Log.w(TAG, "WEB_CLIENT_ID or SERVER_BASE_URL configured incorrectly."); 
      Dialog dialog = new AlertDialog.Builder(this) 
        .setMessage(getString(R.string.configuration_error)) 
        .setNeutralButton(android.R.string.ok, new DialogInterface.OnClickListener() { 
         @Override 
         public void onClick(DialogInterface dialog, int which) { 
          dialog.dismiss(); 
         } 
        }) 
        .create(); 

      dialog.show(); 
     } 
    } 
} 

Wynik po zalogowaniu i kliknięciu przycisku +1:

Plus One Button Result

+0

Twój kod zwraca wartość onConnectionFailed z errorCode 17. Czy znasz bezpośrednią przyczynę tego? Być może brakuje mi pozwolenia. – portfoliobuilder

+1

@portfoliobuilder Trudno powiedzieć, nie widząc kodu i konfiguracji projektu. Zwróć uwagę, że jest to głównie kod szybkiego uruchamiania od Google. Właśnie wprowadziłem niewielką modyfikację, aby dodać przycisk +1. Jeśli jeszcze tego nie zrobiłeś, wykonaj wstępne instrukcje tutaj: https://developers.google.com/+/mobile/android/getting-started –

+0

Hej, Daniel, zaimportowałem kod szybkiego uruchamiania i właśnie uruchomiłem projekt. Ilekroć klikam przycisk logowania otrzymuję kod błędu 17. Zauważyłem, że to, co wysłałeś, było bezpośrednio z tego demo, o czym wspomniałeś. Miałem nadzieję, że coś wiesz. – portfoliobuilder

1

Dodaj compile 'com.google.android.gms:play-services-plus:10.0.1' do swojej aplikacji Gradle