以下代码演示了用户可以使用Google帐户登录的情况,检索授权代码并使用oAuth2同时查询youtube数据api以获取某些数据。这是使用tokenResponses和GoogleCredential完成的,如下面的代码所示。处理asynctask" ALLYOUTUBE"
当我使用一个帐户登录时出现问题 - > (imageview更改为youtube个人资料图片) - >然后退出,使用第二个帐户登录 - > (imageview更改为youtube个人资料图片) - >然后退出。 现在问题发生我再次使用第一个帐户登录,状态文本视图更改为代表Google登录帐户名称,而通过Youtube API 提取的个人资料图片保持与之前相同帐户无论什么,由于某种原因,youtube API仍然认为我已经使用第二个帐户登录。
为了测试以下内容,我建议使用此GITHUB项目https://github.com/googlesamples/google-services/tree/master/android/signin
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;
private Button button;
private Boolean signedIn = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.v(TAG , "CREATED");
// Views
mStatusTextView = (TextView) findViewById(R.id.status);
button = (Button) findViewById(R.id.button_optional_action);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (signedIn && youTube != null) {
Toast.makeText(v.getContext(), "OK", Toast.LENGTH_SHORT).show();
} else {
if(!signedIn)
Toast.makeText(v.getContext(), "Please sign in" , Toast.LENGTH_SHORT).show();
else
Toast.makeText(v.getContext(), "Request failed" , Toast.LENGTH_SHORT).show();
}
}
});
// 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)
.requestServerAuthCode(getString(R.string.server_client_id))
.requestScopes(new Scope(YouTubeScopes.YOUTUBE))
.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();
Log.v(TAG , "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.
Log.d(TAG , "No sign in cached");
showProgressDialog(null);
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.v(TAG , "Activity result");
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.getStatus());
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);
signedIn = true;
String x = String.format("handleSignInResult: auth code %s and display name %s " , acct.getServerAuthCode() , acct.getDisplayName());
Log.d(TAG, x);
new AllYoutube(this, acct.getServerAuthCode()).execute();
} else {
// Signed out, show unauthenticated UI.
updateUI(false);
signedIn = false;
}
}
// [END handleSignInResult]
// [START signIn]
private void signIn() {
Log.v(TAG , "Sign in");
Intent signInIntent = Auth.GoogleSignInApi.getSignInIntent(mGoogleApiClient);
startActivityForResult(signInIntent, RC_SIGN_IN);
}
// [END signIn]
// [START signOut]
private void signOut() {
Log.v(TAG , "SignOut");
Auth.GoogleSignInApi.signOut(mGoogleApiClient).setResultCallback(
new ResultCallback<Status>() {
@Override
public void onResult(Status status) {
// [START_EXCLUDE]
Log.v(TAG , "SUCCESS-SIGN-OUT");
mGoogleApiClient.clearDefaultAccountAndReconnect();
updateUI(false);
signedIn = false;
// [END_EXCLUDE]
}
});
}
// [END signOut]
// [START revokeAccess]
private void revokeAccess() {
Log.v(TAG , "Revoke");
Auth.GoogleSignInApi.revokeAccess(mGoogleApiClient).setResultCallback(
new ResultCallback<Status>() {
@Override
public void onResult(Status status) {
// [START_EXCLUDE]
Log.v(TAG , "SUCCESS-REVOKE");
mGoogleApiClient.clearDefaultAccountAndReconnect();
signedIn = false;
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(String text) {
Log.v(TAG , "progressdialog-showing");
if (mProgressDialog == null) {
mProgressDialog = new ProgressDialog(this);
if(text == null)
mProgressDialog.setMessage(getString(R.string.loading));
else
mProgressDialog.setMessage(text);
mProgressDialog.setIndeterminate(true);
}
mProgressDialog.show();
}
private void hideProgressDialog() {
Log.v(TAG , "progressdialog-hidden");
if (mProgressDialog != null && mProgressDialog.isShowing()) {
mProgressDialog.hide();
}
}
private void updateUI(boolean signedIn) {
Log.v(TAG , "Updating UI.. to " + signedIn);
if (signedIn) {
findViewById(R.id.sign_in_button).setVisibility(View.GONE);
findViewById(R.id.sign_out_and_disconnect).setVisibility(View.VISIBLE);
findViewById(R.id.button_optional_action).setClickable(true);
Button b = (Button) findViewById(R.id.button_optional_action);
b.setTextColor(fetchAccentColor());
} 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);
findViewById(R.id.button_optional_action).setClickable(false);
Button b = (Button) findViewById(R.id.button_optional_action);
b.setTextColor(Color.parseColor("#607d8b"));
}
}
private int fetchAccentColor() {
Log.v(TAG , "fetching accent color");
TypedValue typedValue = new TypedValue();
TypedArray a = this.obtainStyledAttributes(typedValue.data, new int[] { R.attr.colorAccent });
int color = a.getColor(0, 0);
a.recycle();
return color;
}
@Override
public void onClick(View v) {
Log.v(TAG , "OnClick-Event-Registered");
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;
}
}
private GoogleCredential credential;
private class AllYoutube extends AsyncTask<Void,Void,Void>{
String code ;
Context context;
ChannelListResponse listResponse = null;
YouTube.Builder builder;
YouTube yaoutube;
public AllYoutube(Context context , String code) {
this.context = context;
this.code = code;
}
@Override
protected void onPreExecute() {
Log.v(TAG , "ALLYOUTUEB-PRE");
super.onPreExecute();
showProgressDialog("Setting up");
}
@Override
protected Void doInBackground(Void... params) {
Log.v(TAG , "ALLYOUTU-BG");
credential = null;
HttpTransport httpTransport = new NetHttpTransport();
JacksonFactory jsonFactory = JacksonFactory.getDefaultInstance();
// Redirect URL for web based applications.
// Can be empty too.
String redirectUrl = "urn:ietf:wg:oauth:2.0:oob";
// STEP 1
GoogleTokenResponse tokenResponse = null;
try {
tokenResponse = new GoogleAuthorizationCodeTokenRequest(
httpTransport,
jsonFactory,
context.getString(R.string.server_client_id),
context.getString(R.string.server_client_secret),
code,
redirectUrl).execute();
} catch (IOException e) {
e.printStackTrace();
}
// STEP 2
credential = new GoogleCredential.Builder()
.setClientSecrets(context.getString(R.string.server_client_id), context.getString(R.string.server_client_secret))
.setTransport(httpTransport)
.setJsonFactory(jsonFactory)
.build();
if(tokenResponse == null) Log.v(TAG , "tokenResponse null");
credential.setFromTokenResponse(tokenResponse);
builder = new YouTube.Builder(httpTransport , jsonFactory,credential)
.setApplicationName("TubeManager");
this.yaoutube = builder.build();
YouTube.Channels.List query;
try {
query = this.yaoutube.channels().list("snippet").setMine(true);
listResponse = query.execute();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
@Override
protected void onPostExecute(Void aVoid) {
Log.v(TAG , "ALL-POST");
hideProgressDialog();
try {
List<Channel> list = listResponse.getItems();
Toast.makeText(MainActivity.this, list.get(0).getSnippet().getTitle() + "", Toast.LENGTH_LONG).show();
Picasso.with(MainActivity.this).load(list.get(0).getSnippet().getThumbnails().getHigh().getUrl()).placeholder(R.drawable.googleg_color).into((ImageView) findViewById(R.id.google_icon));
try {
Log.d("YOUTUBE#CHANNEL", " " + list.get(0).getSnippet().toPrettyString());
} catch (IOException e) {
e.printStackTrace();
}
}catch (NullPointerException f){
f.printStackTrace();
Toast.makeText(MainActivity.this , "Invalid response" , Toast.LENGTH_SHORT).show();
}
}
}
}
布局: - activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#3e2723"
android:orientation="vertical"
android:weightSum="4">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="3"
android:gravity="center_horizontal"
android:orientation="vertical">
<ImageView
android:id="@+id/google_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:layout_marginTop="100dp"
android:contentDescription="@string/desc_google_icon"
android:src="@drawable/googleg_color" />
<TextView
android:id="@+id/title_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:text="TubeManager"
android:gravity="center"
android:textColor="@android:color/white"
android:textSize="36sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:text="Powered By YouTube"
android:gravity="center"
android:textColor="@android:color/white"
android:textSize="16sp" />
<TextView
android:id="@+id/status"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Signed out"
android:textColor="@android:color/white"
android:textSize="14sp" />
<TextView
android:id="@+id/detail"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fadeScrollbars="true"
android:gravity="center"
android:maxLines="5"
android:padding="10dp"
android:scrollbars="vertical"
android:textColor="@android:color/white"
android:textSize="14sp" />
<Button
android:background="#ffffff"
android:text="OPTIONAL"
android:id="@+id/button_optional_action"
style="@style/Base.Widget.AppCompat.Button.Borderless.Colored"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="visible"
tools:text="Optional Action"
tools:visibility="visible" />
</LinearLayout>
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="#263238">
<com.google.android.gms.common.SignInButton
android:id="@+id/sign_in_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:visibility="visible"
tools:visibility="gone" />
<LinearLayout
android:id="@+id/sign_out_and_disconnect"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:orientation="horizontal"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:visibility="gone"
tools:visibility="visible">
<Button
android:id="@+id/sign_out_button"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Sign out"
android:theme="@style/ThemeOverlay.MyDarkButton" />
<Button
android:id="@+id/disconnect_button"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Revoke"
android:theme="@style/ThemeOverlay.MyDarkButton" />
</LinearLayout>
</RelativeLayout>
答案 0 :(得分:0)
所以经过大量的研究和调试后,将其缩小到代码中最无辜的玩家 Youtube Request Builder ,这显然会导致整个凭据管理问题,为了避免这种情况,我只需切换该 以下代码
builder = new YouTube.Builder(httpTransport , jsonFactory,credential)
.setApplicationName("TubeManager");
this.yaoutube = builder.build();
YouTube.Channels.List query;
try {
query = this.yaoutube.channels().list("snippet").setMine(true);
listResponse = query.execute();
} catch (IOException e) {
e.printStackTrace();
}
带
OkHttpClient client = new OkHttpClient();
try {
Request request = new Request.Builder()
.url("https://www.googleapis.com/youtube/v3/channels?part=snippet&mine=true&maxResults=10")
.addHeader("Authorization", String.format("Bearer %s", credential.getAccessToken()))
.build();
Response response = client.newCall(request).execute();
String jsonBody = response.body().string();
// jsonBody is the Required json response , parse this and use
} catch (IOException e) {
e.printStackTrace();
} catch (GoogleAuthException e) {
e.printStackTrace();
}
GOOGLE请修复你的YouTube修补程序,我的时间耗尽了这个。
作为一个聪明人曾经说过(我自己:3),问题的根源(代码相关的!)总会在你最不希望发生问题的地方找到