android - Google登录+ Youtube数据Api问题

标签 android api youtube google-signin oauth2

以下代码演示了一种情况,用户可以使用google帐户登录,该授权代码被检索并用于使用oAuth2同时查询youtube数据api以获得一些数据。这是使用tokenResponses和GoogleCredential完成的,如下面的代码所示。通过异步任务“ALLYOUTUBE”处理。

当我使用一个帐户登录->(imageview更改为youtube个人资料图片)->然后注销,使用第二个帐户登录->(imageview更改为youtube个人资料pic)->然后注销时,就会出现问题。 现在出现问题,我再次使用第一个帐户登录,状态textview更改为代表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>

最佳答案

因此,经过大量的研究和调试,将其范围缩小到代码中最无辜的参与者 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),问题的根源(与代码有关!)总会出现在您最不希望发生问题的地方

关于android - Google登录+ Youtube数据Api问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41443438/

相关文章:

android - 我的 webview 视频不断加载,如何播放?

android - 在运行时请求权限,Android M+

android - 与工具栏、多屏布局等相关

javascript - 检测在 Android Stock 浏览器上作为主屏幕应用程序运行的 Web 应用程序

javascript - 如何发送带有 header 参数的 HTTP 请求?

web-services - REST API 的目录结构

api - 如何通过 API 调用将 kibana(ELK 堆栈)中的数据导出为 CSV?

javascript - 如果播放是由postMessage触发的,则不会触发Youtube的onStateChange

android - 使用GSON反序列化嵌套数组

javascript - Youtube api 未知部分统计