I want to use Youtube API to get the subscription list of a user. It requires oauth.
I read that implementing google sign in will make it easier to access this API
I followed Google's documentation and now I got the signing in working
I have these files now.
My question:
1) Which sample do I need to use, IdTokenActivity.java or RestApiActivity.java
2) How can I use the sample code to access Youtube API? It doesn't say and the documentation is confusing
Which sample do I need to use, IdTokenActivity.java or RestApiActivity.java ?
IdTokenActivity.java aims at retrieving an id_token. The id_token is a JWT token designed to be sent to a backend to authenticate the user as a real (trusted) Google user. You can find more information about the flow for the backend here.
RestApiActivity.java is used to consume Google API which is what you are trying to do.
How can I use the sample code to access Youtube API?
Here are the steps :
Go to Google Signin setup for Android, download google-services.json and place it in your app folder
in google developer console enable Youtube Data API
add the following to app build.gradle :
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'
with apply plugin: 'com.google.gms.google-services' to the bottom of your file
update the following to your top level build.gradle :
dependencies {
classpath 'com.google.gms:google-services:3.0.0'
}
Include the RestApiActivity.java in your project and update the following :
// Scope for reading user's contacts
private static final String YOUTUBE_SCOPE = "https://www.googleapis.com/auth/youtube";
...
// 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();
and when the client is authenticated (in handleSignInResult) , request the subscription list as following :
/**
* 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
for (int i = 0; i < subscriptions.size(); i++) {
Log.v(TAG, "subscription : " + subscriptions.get(i).getId());
}
} else {
Log.d(TAG, "subscriptions: null");
mDetailTextView.setText("None");
}
}
}
which is launched in lieu of GetContacts with :
new GetSubscriptionTask().execute(mAccount);
You can find a complete example here
Related
I've been banging my head on my desk the past few days trying to figure out how to setup the sign-in for Google Play Games Services.
I am able to start an activity for an interactive signin, but the window just hangs and loads forever with no error:
Here is the code I have. It checks to see if the user has signed in before, if they have, it attempts to login silently. If not, it brings up interactive signin:
final GoogleSignInOptions signInOption =
new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_GAMES_SIGN_IN)
// Add the APPFOLDER scope for Snapshot support.
.requestScopes(Games.SCOPE_GAMES_SNAPSHOTS)
.requestIdToken(activity.getString(R.string.debug_client_id))
.requestEmail()
.build();
signInClient = GoogleSignIn.getClient(this, signInOption);
GoogleSignInAccount account = GoogleSignIn.getLastSignedInAccount(this);
if (account != null) {
// The user has signed in before
signInClient.silentSignIn().addOnCompleteListener(new OnCompleteListener < GoogleSignInAccount > () {
#Override
public void onComplete(#NonNull Task < GoogleSignInAccount > task) {
if (task.isSuccessful()) {
// Silent signin successful
onConnected(task.getResult());
} else {
// Player will need to sign-in explicitly using via UI
// Interactive sign-in
activity.startActivityForResult(signInClient.getSignInIntent(), AndroidLauncher.RC_SIGN_IN);
}
}
});
} else {
//The user has never signed in
// Interactive sign-in
this.activity.startActivityForResult(signInClient.getSignInIntent(), AndroidLauncher.RC_SIGN_IN);
}
I also have the onActivityResult() handler:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == RC_SIGN_IN) {
GoogleSignInResult result = Auth.GoogleSignInApi.getSignInResultFromIntent(data);
if (result.isSuccess()) {
signedIn = true;
// The signed in account is stored in the result.
GoogleSignInAccount signedInAccount = result.getSignInAccount();
} else {
signedIn = false;
String message = result.getStatus().getStatusMessage();
if (message == null || message.isEmpty()) {
message = "Sign in error!";
}
new AlertDialog.Builder(this).setMessage(message)
.setNeutralButton(android.R.string.ok, null).show();
}
}
}
What I've Tried/Done
I added the required metadata tags in the AndroidManifest.xml file (with correct values)
I've added the Google Play Games account as a tester on the Google Play Console for the app, for Google Play Services, and on the OAuth consent screen for the API on Google Cloud Platform.
I've checked that the SHA-1 hash of the signature on the app matches the SHA-1 hash of the OAuth credential in use on Google Play Games, and that the client ID is correct and is of the selected OAuth credential.
I have enabled all of the non-sensitive data scopes (which is all I need) on the Google Cloud Platform OAuth consent screen
More Info
If I try to call signInSilently(...) before the interactive signin, I get API exception code 4 (SIGN_IN_REQUIRED). When I execute the interactive signin, it just hangs like above. I actually am able to get the signin to work, but only if I use signin options like so:
final GoogleSignInOptions signInOption = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_GAMES_SIGN_IN).build();
(with no snapshots permissions and no passed client ID. But I need to be able to access snapshots)
The only possibly relevant exception I see in Logcat when running the interactive signin is:
E/ExecutionCriteria: Package unavailable for task: com.google.android.apps.tachyon/com.firebase.jobdispatcher.GooglePlayReceiver{u=0 tag="duo-analytics-summary-report" trigger=window{start=82080s,end=86401s,earliest=-97027894s,latest=-97023574s} requirements=[NET_ANY] attributes=[PERSISTED,RECURRING] scheduled=-97109975s last_run=N/A exec_window_multiplier=1.0000 jid=N/A status=PENDING retries=0 client_lib=FIREBASE_JOB_DISPATCHER-1} [CONTEXT service_id=218 ]
...but it seems like it might be a benign error.
I've been stuck on this for a while; any suggestions/help would be appreciated.
Im trying to do the email authentication of firebase.
I'm following the document and i get this error:
UNAUTHORIZED_DOMAIN:Domain not whitelisted by project
I saw this soultion:
Firebase Auth/unauthorized domain. Domain is not authorized
and it didn't work, so I went and tried to create a dynamic link because I saw here that I need to create dynamic link:
Firebase says "Domain not whitelisted" for a link that is whitelisted
and that also didn't work. i got when tried to create dynamic link:
An error occurred when creating a new Dynamic Link
so i went and tried this:
Firebase console create dynamic link error
and still the same problem
so now I don't know what else to do.
the code:
private void sendEmail(String email) {
Log.d(TAG, "sendEmail: here in sendEmail");
String url = "https://.........";
ActionCodeSettings actionCodeSettings = ActionCodeSettings.newBuilder().setUrl(url)
.setHandleCodeInApp(true)
.setAndroidPackageName("com.myapp_pack.my_app_name", true, "12").build();
auth.sendSignInLinkToEmail(email, actionCodeSettings).addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if (task.isSuccessful()) {
Log.d(TAG, "onComplete: email sent homie!");
} else{
Log.d(TAG, "onComplete: task failed " + task.getException().getMessage());
}
}
});
}
This was useful for me, using Firebase v.9 (current last version in January 2022)
Try not creating dynamic links but check if you are listing not just "localhost" (or where you would serve the project) but also the url you pass to the url property of the object you pass as the third parameter of "sendSignInLinkToEmail". Example:
const config = {
url: "https://example.com/",
*...other properties*
};
sendSignInLinkToEmail(auth, email, config).catch((error) => {
console.log(error);
});
In this case you would go to the firebase console and add in the whitelist "example.com".
Disclaimer: Checking this solved my problem as I was unintentionally only whitelisting the url where I was serving my project in dev mode.
In my android application, I'm integrating the Dialogflow V2 Agent. There's no specific SDK for Android yet. So I'm using the java client library from Dialogflow. followed the tutorial https://github.com/dialogflow/dialogflow-java-client-v2/issues/25.
I've added the dependencies(dialogflow & oauth2) and created a service account in the google-cloud console. Added the credential file into raw folder. followed the tutorial here https://github.com/dialogflow/dialogflow-java-client-v2/issues/25. Getting the error as
java.lang.NoSuchMethodError: No static method
decodeBase64(Ljava/lang/String;)[B in class
Lorg/apache/commons/codec/binary/Base64; or its super classes
(declaration of 'org.apache.commons.codec.binary.Base64' appears in
/system/framework/org.apache.http.legacy.boot.jar)
private void createDialogflow() {
try {
InputStream stream = getResources().openRawResource(R.raw.dialogflow_service_credentials);
GoogleCredentials credentials = GoogleCredentials.fromStream(stream);
String projectId = ((ServiceAccountCredentials) credentials).getProjectId();
SessionsSettings.Builder settingsBuilder = SessionsSettings.newBuilder();
SessionsSettings sessionsSettings = settingsBuilder.setCredentialsProvider(FixedCredentialsProvider.create(credentials)).build();
sessionsClient = SessionsClient.create(sessionsSettings);
String uuid = UUID.randomUUID().toString();
session = SessionName.of(projectId, uuid);
} catch (Exception e) {
e.printStackTrace();
}
}
private void sendMessage(String msg) {
// Java V2
setTypingMessage();
QueryInput queryInput = QueryInput.newBuilder().setText(TextInput.newBuilder().setText(msg).setLanguageCode("en-US")).build();
new RequestJavaV2Task(mContext, session, sessionsClient, queryInput).execute();
}
public void callbackV2(DetectIntentResponse response) {
removeTyingMessage();
if (response != null) {
// process aiResponse here
String botReply = response.getQueryResult().getFulfillmentText();
Log.d("botReply", "V2 Bot Reply: " + botReply);
setBotMessage(botReply);
} else {
Log.d("botReply", "Bot Reply: Null");
setBotMessage("There was some communication issue. Please Try again!");
}
}
Is there any clear documentations on how to integrate Dialogflow v2 into my android application.
The tutorial you were following was updated. In case anyone is facing this issue, according to the repo:
Save your CLIENT_ACCESS_TOKEN in gradle.properties
I have two app on Google Play. The old and new one. And I would like to use old auth token to the new app to be easier for users.
On the old app, the user has a popup to install the new app on Google Play.
I would like to pass the auth token in parameter to Google Play.
After new app has been installed, I would like to save the token in the new one app.
I tried to use Play Install Referrer Library but it didn't work.
The other way was to use SharedPreferences but MODE_WORLD_READABLE has been deprecated.
Old APP :
try {
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=com.<PACKAGENAME>&token=pokpok&refresh_token=lolol"));
startActivity(intent);
} catch (Exception e) {
e.printStackTrace();
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("https://play.google.com/store/apps/details?id=com.<PACKAGENAME>?token=pokpok&refresh_token=lolol")));
}
New APP code :
private fun shouldGetTokenFromOldApp() {
mReferrerClient = InstallReferrerClient.newBuilder(this).build()
mReferrerClient.startConnection(object : InstallReferrerStateListener {
override fun onInstallReferrerSetupFinished(responseCode: Int) {
when (responseCode) {
InstallReferrerClient.InstallReferrerResponse.OK -> {
// Connection established
val response: ReferrerDetails = mReferrerClient.installReferrer
val url = "https://play.google.com/store?${response.installReferrer}"
Log.d("APP", "Token old app 1 : $url")
val uri: Uri = Uri.parse(url)
val token = uri.getQueryParameter("token")
val refreshToken = uri.getQueryParameter("refresh_token")
Log.d("APP", "Token old app 2 : $token - $refreshToken")
mReferrerClient.endConnection()
}
InstallReferrerClient.InstallReferrerResponse.FEATURE_NOT_SUPPORTED -> {
// API not available on the current Play Store app
}
InstallReferrerClient.InstallReferrerResponse.SERVICE_UNAVAILABLE -> {
// Connection could not be established
}
}
}
override fun onInstallReferrerServiceDisconnected() {
// Try to restart the connection on the next request to
// Google Play by calling the startConnection() method.
}
})
}
This sounds like a nice thing to do for users, but seems very dangerous. You are sending an Auth token - something which if someone has it could allow them to login as that user anywhere off through untrusted systems like world readable files or referral parameters in URLs.
If you really need to do this, I'd suggest using some form of inter-app RPC (IPC) to communicate the token after the app is installed. One option would be a binder to a service that supplies the auth.
I wanted to try and keep my native android firebase development to minimum so as to when I'm ready to port to IOS/web I won't be doing a lot there.
Right now firebase's Javascript doesn't allow google login from Android, this can be taken care of from the plugin. But what I'm stuck on is how to initialize firebase based on the Java Android Google login.
So this is what I'm trying to achieve:
Cordova calls Java-Android-Native login into google ---> based on this, how would I initialize firebase?
This plugin can let me login into google natively: https://www.npmjs.com/package/cordova-plugin-googleplus
But I guess I need auth token? token ID?
firebase.auth().signInWithCredential(credential).catch(function(error) {
} else {
console.error(error);
}
});
Can this give me the above required toke? https://developers.google.com/identity/sign-in/android/sign-in
GoogleSignInResult result = Auth.GoogleSignInApi.getSignInResultFromIntent(data);
Update 1: Just want to share more information. When getting the user logged in through google on android I have the below object
GoogleSignInAccount
https://developers.google.com/android/reference/com/google/android/gms/auth/api/signin/GoogleSignInAccount
It has public String getIdToken () & public String getServerAuthCode () why can't these be used to authenticate firebase using JS?
Update 2: Answer provided by Faraz seems to be working. Here is reference for the function signInWithCredential https://firebase.google.com/docs/reference/js/firebase.auth.Auth#signInWithCredential
Thank you for your help.
Use auth.signInWithCredential with the GoogleAuthProvider credential.
Here is an example:
auth.signInWithCredential(firebase.auth.GoogleAuthProvider.credential(googleAccessToken)).then(function(user) {
// Google User is logged in
}).catch(function(error) {
// Error
});
Source for more infomation
You can read this GitHub example about Firebase usage.
And Here you can find -
mFirebaseRef.authWithOAuthToken("google", token, new AuthResultHandler("google"));
Which (if all is success) calls this
public void onAuthenticated(AuthData authData)
Where token is your getIdToken
I mean it is possble to login into Firebase using Google, Facebook,Twitter in all cases you have to send token you receive to Firebase server that checks your token whether you already logged in or not. You can setup your own server in the same way.
After google login you have to Use auth.signInWithCredential with the GoogleAuthProvider credential:
Here is an code:
private void firebaseAuthWithGoogle(GoogleSignInAccount account) {
Log.d(TAG, "firebaseAuthWithGoogle:" + account.getId());
final String name = account.getDisplayName();
final String email = account.getEmail();
AuthCredential credential = GoogleAuthProvider.getCredential(account.getIdToken(), null);
getAuth().signInWithCredential(credential)
.addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
Log.d(TAG, "onComplete: sign in with credentials " + task.isSuccessful());
if (task.ienter code heresSuccessful()) {
Log.e(TAG, "success: sign in with credentials ");
}
if (!task.isSuccessful()) {
Log.e(TAG, "onComplete: sign in with credentials " + task.getException());
}
}
});
}