以下类无法实例化: – com.google.android.gms.plus.PlusOneButton

我正在按照这个教程https://developers.google.com/+/mobile/android/recommend在我的应用程序中集成+1button。

只要我把这个代码在XML中,我在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" /> 

我也尝试把xmlns:plus="http://schemas.android.com/apk/lib/com.google.android.gms.plus"放在父亲的RelativeLayout中,但同样的错误。

 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) 

帮帮我 !!

Solutions Collecting From Web of "以下类无法实例化: – com.google.android.gms.plus.PlusOneButton"

Android Studio解决scheme:

我刚刚得到一个简单的例子,从gplus-quickstart的代码开始,然后使用问题中链接的指南添加一个+1button。

build.gradle相关性:

 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> 

我将com.google.android.gms.plus.PlusOneButton添加到activity_main.xml的底部,该文件基于快速入门代码中的main_activity.xml :

 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,添加了+1button。

请注意,对于URL我使用了卡内基梅隆计算机科学学院的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(); } } } 

结果login后,点击+1button:

另外一个按钮结果

compile 'com.google.android.gms:play-services-plus:10.0.1'到您的应用的Gradle