Last active
September 4, 2022 18:37
-
-
Save bertrandmartel/7d323b09af889f5c03b862612c796046 to your computer and use it in GitHub Desktop.
Example of using Google Signin to access Youtube subscription API
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" encoding="utf-8"?> | |
<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:orientation="vertical" | |
android:weightSum="4" | |
tools:context=".SignInActivity"> | |
<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="48dp" | |
android:layout_height="48dp" | |
android:layout_marginBottom="10dp"/> | |
<TextView | |
android:id="@+id/title_text" | |
android:layout_width="wrap_content" | |
android:layout_height="wrap_content" | |
android:layout_marginBottom="10dp" | |
android:text="title" | |
android:gravity="center" | |
android:textColor="@android:color/white" | |
android:textSize="36sp" /> | |
<TextView | |
android:id="@+id/status" | |
android:layout_width="wrap_content" | |
android:layout_height="wrap_content" | |
android:text="signout" | |
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: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="gone" | |
tools:text="Optional Action" | |
tools:visibility="visible" /> | |
</LinearLayout> | |
<RelativeLayout | |
android:layout_width="fill_parent" | |
android:layout_height="0dp" | |
android:layout_weight="1"> | |
<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="signout"/> | |
<Button | |
android:id="@+id/disconnect_button" | |
android:layout_width="0dp" | |
android:layout_height="wrap_content" | |
android:layout_weight="1" | |
android:text="disconnect" /> | |
</LinearLayout> | |
</RelativeLayout> | |
</LinearLayout> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
apply plugin: 'com.android.application' | |
android { | |
compileSdkVersion 24 | |
buildToolsVersion "23.0.3" | |
defaultConfig { | |
applicationId "com.example.test" | |
minSdkVersion 19 | |
targetSdkVersion 24 | |
versionCode 12 | |
versionName "1.83" | |
} | |
buildTypes { | |
release { | |
minifyEnabled true | |
zipAlignEnabled true | |
signingConfig signingConfigs.playStore | |
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' | |
} | |
} | |
lintOptions { | |
abortOnError false | |
} | |
} | |
dependencies { | |
compile fileTree(dir: 'libs', include: ['*.jar']) | |
compile "com.android.support:appcompat-v7:24.2.0" | |
compile 'com.android.support:design:24.2.0' | |
compile 'com.android.support:recyclerview-v7:24.2.0' | |
compile 'com.google.android.gms:play-services-auth:10.0.1' | |
compile 'com.google.api-client:google-api-client-android:1.22.0' exclude module: 'httpclient' | |
compile 'com.google.apis:google-api-services-youtube:v3-rev182-1.22.0' | |
} | |
apply plugin: 'com.google.gms.google-services' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.github.akinaru.hcidebugger.activity; | |
import android.accounts.Account; | |
import android.app.ProgressDialog; | |
import android.content.Intent; | |
import android.os.AsyncTask; | |
import android.os.Bundle; | |
import android.support.annotation.NonNull; | |
import android.support.v7.app.AppCompatActivity; | |
import android.util.Log; | |
import android.view.View; | |
import android.widget.TextView; | |
import android.widget.Toast; | |
import com.github.akinaru.hcidebugger.R; | |
import com.google.android.gms.auth.api.Auth; | |
import com.google.android.gms.auth.api.signin.GoogleSignInAccount; | |
import com.google.android.gms.auth.api.signin.GoogleSignInOptions; | |
import com.google.android.gms.auth.api.signin.GoogleSignInResult; | |
import com.google.android.gms.common.ConnectionResult; | |
import com.google.android.gms.common.SignInButton; | |
import com.google.android.gms.common.api.GoogleApiClient; | |
import com.google.android.gms.common.api.OptionalPendingResult; | |
import com.google.android.gms.common.api.ResultCallback; | |
import com.google.android.gms.common.api.Scope; | |
import com.google.android.gms.common.api.Status; | |
import com.google.api.client.extensions.android.http.AndroidHttp; | |
import com.google.api.client.googleapis.extensions.android.gms.auth.GoogleAccountCredential; | |
import com.google.api.client.googleapis.extensions.android.gms.auth.UserRecoverableAuthIOException; | |
import com.google.api.client.http.HttpTransport; | |
import com.google.api.client.json.JsonFactory; | |
import com.google.api.client.json.jackson2.JacksonFactory; | |
import com.google.api.services.youtube.YouTube; | |
import com.google.api.services.youtube.model.Subscription; | |
import com.google.api.services.youtube.model.SubscriptionListResponse; | |
import java.io.IOException; | |
import java.util.Collections; | |
import java.util.List; | |
/** | |
* Activity to demonstrate using the Google Sign In API with a Google API that uses the Google | |
* Java Client Library rather than a Google Play services API. See {@link GetContactsTask} | |
* for how to access the People API using this method. | |
* <p> | |
* In order to use this Activity you must enable the People API on your project. Visit the following | |
* link and replace 'YOUR_PROJECT_ID' to enable the API: | |
* https://console.developers.google.com/apis/api/people.googleapis.com/overview?project=YOUR_PROJECT_ID | |
*/ | |
public class RestApiActivity extends AppCompatActivity implements | |
GoogleApiClient.OnConnectionFailedListener, | |
View.OnClickListener { | |
private static final String TAG = "RestApiActivity"; | |
// Scope for reading user's contacts | |
private static final String YOUTUBE_SCOPE = "https://www.googleapis.com/auth/youtube"; | |
// Bundle key for account object | |
private static final String KEY_ACCOUNT = "key_account"; | |
// Request codes | |
private static final int RC_SIGN_IN = 9001; | |
private static final int RC_RECOVERABLE = 9002; | |
// Global instance of the HTTP transport | |
private static final HttpTransport HTTP_TRANSPORT = AndroidHttp.newCompatibleTransport(); | |
// Global instance of the JSON factory | |
private static final JsonFactory JSON_FACTORY = JacksonFactory.getDefaultInstance(); | |
private GoogleApiClient mGoogleApiClient; | |
private Account mAccount; | |
private TextView mStatusTextView; | |
private TextView mDetailTextView; | |
private ProgressDialog mProgressDialog; | |
@Override | |
protected void onCreate(Bundle savedInstanceState) { | |
super.onCreate(savedInstanceState); | |
setContentView(R.layout.activity_main); | |
// Views | |
mStatusTextView = (TextView) findViewById(R.id.status); | |
mDetailTextView = (TextView) findViewById(R.id.detail); | |
// Button listeners | |
findViewById(R.id.sign_in_button).setOnClickListener(this); | |
findViewById(R.id.sign_out_button).setOnClickListener(this); | |
// For this example we don't need the disconnect button | |
findViewById(R.id.disconnect_button).setVisibility(View.GONE); | |
// Restore instance state | |
if (savedInstanceState != null) { | |
mAccount = savedInstanceState.getParcelable(KEY_ACCOUNT); | |
} | |
// Configure sign-in to request the user's ID, email address, basic profile, | |
// and readonly access to contacts. | |
GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN) | |
.requestScopes(new Scope(YOUTUBE_SCOPE)) | |
.requestEmail() | |
.build(); | |
// 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(); | |
// Show a standard Google Sign In button. If your application does not rely on Google Sign | |
// In for authentication you could replace this with a "Get Google Contacts" button | |
// or similar. | |
SignInButton signInButton = (SignInButton) findViewById(R.id.sign_in_button); | |
signInButton.setSize(SignInButton.SIZE_STANDARD); | |
} | |
@Override | |
public void onStart() { | |
super.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. | |
showProgressDialog(); | |
opr.setResultCallback(new ResultCallback<GoogleSignInResult>() { | |
@Override | |
public void onResult(GoogleSignInResult googleSignInResult) { | |
hideProgressDialog(); | |
handleSignInResult(googleSignInResult); | |
} | |
}); | |
} | |
} | |
@Override | |
protected void onSaveInstanceState(Bundle outState) { | |
super.onSaveInstanceState(outState); | |
outState.putParcelable(KEY_ACCOUNT, mAccount); | |
} | |
@Override | |
public void onActivityResult(int requestCode, int resultCode, Intent data) { | |
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); | |
} | |
// Handling a user-recoverable auth exception | |
if (requestCode == RC_RECOVERABLE) { | |
if (resultCode == RESULT_OK) { | |
getSubscriptions(); | |
} else { | |
Toast.makeText(this, "failed", Toast.LENGTH_SHORT).show(); | |
} | |
} | |
} | |
private void signIn() { | |
Intent signInIntent = Auth.GoogleSignInApi.getSignInIntent(mGoogleApiClient); | |
startActivityForResult(signInIntent, RC_SIGN_IN); | |
} | |
private void signOut() { | |
// Signing out clears the current authentication state and resets the default user, | |
// this should be used to "switch users" without fully un-linking the user's google | |
// account from your application. | |
Auth.GoogleSignInApi.signOut(mGoogleApiClient).setResultCallback( | |
new ResultCallback<Status>() { | |
@Override | |
public void onResult(@NonNull Status status) { | |
updateUI(false); | |
} | |
}); | |
} | |
private void handleSignInResult(GoogleSignInResult result) { | |
Log.d(TAG, "handleSignInResult:" + result.isSuccess()); | |
if (result.isSuccess()) { | |
// Get the account from the sign in result | |
GoogleSignInAccount account = result.getSignInAccount(); | |
// Signed in successfully, show authenticated UI. | |
mStatusTextView.setText(account.getDisplayName()); | |
updateUI(true); | |
// Store the account from the result | |
mAccount = account.getAccount(); | |
// Asynchronously access the People API for the account | |
getSubscriptions(); | |
} else { | |
Log.v(TAG, "fail : " + result.getStatus()); | |
// Clear the local account | |
mAccount = null; | |
// Signed out, show unauthenticated UI. | |
updateUI(false); | |
} | |
} | |
private void getSubscriptions() { | |
if (mAccount == null) { | |
Log.w(TAG, "getContacts: null account"); | |
return; | |
} | |
new GetSubscriptionTask().execute(mAccount); | |
} | |
@Override | |
public void onConnectionFailed(@NonNull ConnectionResult connectionResult) { | |
Log.w(TAG, "onConnectionFailed:" + connectionResult); | |
} | |
@Override | |
public void onClick(View view) { | |
switch (view.getId()) { | |
case R.id.sign_in_button: | |
signIn(); | |
break; | |
case R.id.sign_out_button: | |
signOut(); | |
break; | |
} | |
} | |
private void showProgressDialog() { | |
if (mProgressDialog == null) { | |
mProgressDialog = new ProgressDialog(this); | |
mProgressDialog.setMessage("loading"); | |
mProgressDialog.setIndeterminate(true); | |
} | |
mProgressDialog.show(); | |
} | |
private void hideProgressDialog() { | |
if (mProgressDialog != null && mProgressDialog.isShowing()) { | |
mProgressDialog.hide(); | |
} | |
} | |
private void updateUI(boolean signedIn) { | |
if (signedIn) { | |
findViewById(R.id.sign_in_button).setVisibility(View.GONE); | |
findViewById(R.id.sign_out_and_disconnect).setVisibility(View.VISIBLE); | |
} else { | |
mStatusTextView.setText("signout"); | |
mDetailTextView.setText(null); | |
findViewById(R.id.sign_in_button).setVisibility(View.VISIBLE); | |
findViewById(R.id.sign_out_and_disconnect).setVisibility(View.GONE); | |
} | |
} | |
/** | |
* AsyncTask that uses the credentials from Google Sign In to access Youtube subscription API. | |
*/ | |
private class GetSubscriptionTask extends AsyncTask<Account, Void, List<Subscription>> { | |
@Override | |
protected void onPreExecute() { | |
showProgressDialog(); | |
} | |
@Override | |
protected List<Subscription> doInBackground(Account... params) { | |
try { | |
GoogleAccountCredential credential = GoogleAccountCredential.usingOAuth2( | |
RestApiActivity.this, | |
Collections.singleton(YOUTUBE_SCOPE)); | |
credential.setSelectedAccount(params[0]); | |
YouTube youtube = new YouTube.Builder(HTTP_TRANSPORT, JSON_FACTORY, credential) | |
.setApplicationName("Google Sign In Quickstart") | |
.build(); | |
SubscriptionListResponse connectionsResponse = youtube | |
.subscriptions() | |
.list("snippet") | |
.setChannelId("UCfyuWgCPu5WneQwuLBWd7Pg") | |
.execute(); | |
return connectionsResponse.getItems(); | |
} catch (UserRecoverableAuthIOException userRecoverableException) { | |
Log.w(TAG, "getSubscription:recoverable exception", userRecoverableException); | |
startActivityForResult(userRecoverableException.getIntent(), RC_RECOVERABLE); | |
} catch (IOException e) { | |
Log.w(TAG, "getSubscription:exception", e); | |
} | |
return null; | |
} | |
@Override | |
protected void onPostExecute(List<Subscription> subscriptions) { | |
hideProgressDialog(); | |
if (subscriptions != null) { | |
Log.d(TAG, "subscriptions : size=" + subscriptions.size()); | |
// Get names of all connections | |
StringBuilder msg = new StringBuilder(); | |
for (int i = 0; i < subscriptions.size(); i++) { | |
Log.v(TAG, "subscription : " + subscriptions.get(i).getId()); | |
} | |
// Display names | |
mDetailTextView.setText(msg.toString()); | |
} else { | |
Log.d(TAG, "subscriptions: null"); | |
mDetailTextView.setText("None"); | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hi,
GoogleAccountCredential.usingOAuth2
this method used to log in right, why are you using this method to get subscriptionSubscriptionListResponse
. It looks like another time login.