mediaObject response in actions-on-google v2? - actions-on-google

mediaObject response is not working, without any error in logs
conv.ask(new MediaObject({
name: channel.name,
url: channel.stream_url,
description: `Regional`,
})
}));

By looking at the official document, it says
Your Action must include suggestion chips if the response is not a
final response.
This might be the case for you, try including suggestion chips also
conv.ask(new Suggestions(['Suggestion1', 'Suggestion2']));

Related

Flutter Firebase Authentication with Email Links not working

I'm following this guide, I'm having this code:
var acs = ActionCodeSettings(
url: 'https://example.com/auth/widget',
androidPackageName: 'com.example',
iOSBundleId: 'com.example',
handleCodeInApp: true,
androidInstallApp: true,
androidMinimumVersion: '12',
);
var emailAuth = 'john.doe#pm.me';
FirebaseAuth.instance
.sendSignInLinkToEmail(
email: emailAuth, actionCodeSettings: acs)
.catchError((onError, stackTrace) {})
.then((value) =>
print('Successfully sent email verification'));
Sending the email works, but when I click on the email, then…
in iOS it opens https://example.com/auth/widget - which is the fallback
in Android it shows a circular loader for about 1s and then it "falls down" and nothing happens
The incoming link handler
FirebaseDynamicLinks.instance.onLink.listen((dynamicLinkData) {
print('got dynamic link! $dynamicLinkData');
}).onError((error) {
print('error error!');
});
I configured dynamic links in Firebase to point to to.example.com. I also added a manual dynamic link to.example.com/test which opens my app (the got dynamic link! message shows up) - so all seems fine, the problem seems to lie in the link generation.
The link structure I get by email is:
https://to.example.com/?link=https://example-abcd.firebaseapp.com/__/auth/action?apiKey…%26continueUrl%3Dhttps://example.com/auth/widget%26lang%3Den&apn=com.example&amv=12&ibi=com.example&ifl=https://example-abcd.firebaseapp.com/__/auth/action?apiKey%3D…%26continueUrl%3Dhttps://example.com/auth/widget%26lang%3Den
After some more painful hours of debugging and reading documentation I finally found it out. Most of this is in the flutter documentation, but since the documentation has broken links and is a bit all over the place it was hard for me to catch it all!
Android
I needed to decrease the androidMinimumVersion from 12 to 1. Then my app opens and I can receive the dynamic link. No idea why. My android simulator is android version 13 but the app never opened.
Before decreasing the android version I also set the sha256 setting in firebase, using gradlew signingReport documented in this answer. Not sure though this was required.
iOS
I forgot to do all the steps documented in receiving links on iOS section, namely:
add the dynamic links domain into associated domains
add FirebaseDynamicLinksCustomDomains into Info.plist
Overall, I found that to get this feature working was really really hard for me as a Flutter beginner. But I guess a lot of the setup I can re-use as the dynamic links capability seems to be something which comes in handy in the future.

sign_in_with_apple: AuthorizationErrorCode.invalidResponse: No code query parameter set

I use the latest version of sign_in_with_apple using the following code to allow signing in with Apple to my Flutter app on Android.
final credential = await SignInWithApple.getAppleIDCredential(
scopes: [
AppleIDAuthorizationScopes.email,
AppleIDAuthorizationScopes.fullName,
],
webAuthenticationOptions: WebAuthenticationOptions(
clientId: '***Service Identifier***',
redirectUri:
// For web your redirect URI needs to be the host of the "current page",
// while for Android you will be using the API server that redirects back into your app via a deep link
kIsWeb ? Uri.parse('https://${window.location.host}/') : Uri.parse('https://***Backend***/callback'),
),
nonce: nonce,
);
I have taken the code for the backend from the package README.md:
apple_router.post("/callback", (request, response) => {
console.log(">>> Apple callback received <<<");
console.log("Body:");
console.log(request.body);
console.log("Query:");
console.log(request.query);
console.log("Params:");
console.log(request.params);
const redirect = `intent://callback?${new URLSearchParams(
request.body
).toString()}#Intent;package=${process.env.ANDROID_PACKAGE_IDENTIFIER
};scheme=signinwithapple;end`;
console.log(`Redirecting to ${redirect}`);
response.redirect(307, redirect);
});
I have also configured everything at Apple with the correct domains, but on my backend, when I log into the app, only an empty request arrives:
>>> Apple callback received <<<
Body:
{}
Query:
{}
Params:
{}
Redirecting to intent://callback?#Intent;package=***Android package ID***;scheme=signinwithapple;end
Which is why it doesn't work properly in the app either:
E/flutter (27962): [ERROR:flutter/lib/ui/ui_dart_state.cc(209)] Unhandled Exception: SignInWithAppleAuthorizationError(AuthorizationErrorCode.invalidResponse, parseAuthorizationCredentialAppleIDFromDeeplink: No `code` query parameter set))
I have checked everything several times and I no longer have any idea where this problem could come from. Does anyone have any ideas?
Using this sign_in_with_apple apple will provide you the email, fullName, etc. information only for the first authorizations.
So, you have to take few steps to apple authorization.
Flutter/client side code/mechanism
void loginSignUpWithApple() async {
SignInWithApple.getAppleIDCredential(
scopes: [
AppleIDAuthorizationScopes.email,
AppleIDAuthorizationScopes.fullName
],
).then((value) {
_socialLoginSignUp(value.authorizationCode, describeEnum(LoginMethod.APPLE));
}).catchError((e) {
showMessage("Something went wrong: $e", isError: true);
});
}
Backend side code/mechanism
Generate JWT using apple key id and private key
Get auth token from apple server by using generated jwt and clint sent authorizationCode then extract the IdToken from the auth token response
Decode the IdToken and get the IdTokenHeader
From the IdTokenHeader get the kId
Using the kId get the list of keys from apple server then extract the actual key
Using the actual key create apple key to public key
Using public key and IdToken get the claims then decode the claim to get the user email
After getting the user email you can store this email in your database or other place and you can trust this is mail as a valid apple mail.
You can see the backend implementation code which is we have implemented previously in java (spring boot).
Sample backend code for apple login (Try with VPN if link is not working)
I found the problem: if you are using express as your server, add
bodyParser.urlencoded({ extended: true })
as middleware for your callback handler and then request.body will not be empty.

Google Form Link Can't be accessed (/formResponse)

First of all, sorry asking this question cause it's not about current topic
It's just about google form link that my expectation is I could open url with /formResponse
(Website Behaviour)
Request: When I try enter the link https://docs.google.com/forms/d/1WyFssMa_l1e_es9zSMJsojnqTA2AahmpfWiWknXr_P8/formResponse
Response: it will redirected to https://docs.google.com/forms/d/1WyFssMa_l1e_es9zSMJsojnqTA2AahmpfWiWknXr_P8/viewform
(HTTP Post Behaviour)
Request: (POST to https://docs.google.com/forms/d/1WyFssMa_l1e_es9zSMJsojnqTA2AahmpfWiWknXr_P8/formResponse)
Response: get an error like this:
Sorry, the file you have requested does not exist.
Anyone can help how to solve this? I appreciate if you get me out of this issue
I solved it when I used fetch from JavaScript
const opts = {
method: "POST",
mode: "no-cors",
redirect: "follow",
referrer: "no-referrer",
body: formData
}
fetch(url, opts)
...

Playing MP3 with MediaResponse seems to be broken

Something seems to have broken when it comes to playing MP3 files and live streams using MediaResponse on Google Home.
Without releasing any new version or changing stream URLs, playback simply no longer work in our app (on a Google Home Mini - still works in Simulator though), and I notice the same problem in other similar apps. Playing radio from TuneIn still works.
Anyone else with this problem?
We had a similar issue with our Google Assistant application when providing a mp3 livestream using MediaResponse.
We previously ended the conversation like this
conv.close(new MediaObject({
name: "Name",
url: "https://url.to.livestream",
description: "Description",
image: new Image({
url: "https://url.to.image"
})
}));
What worked for us was to instead send the MediaObject using conv.ask()
conv.ask(new MediaObject({
...
}));
conv.ask(new Suggestions(["suggestion 1", "suggestion 2"]));
What is important here is to follow the MediaResponse with a Suggestions response since the app will fail otherwise.
"Your Action must include suggestion chips if the response is not a
final response." https://developers.google.com/actions/assistant/responses#media_responses
Maybe this will solve your issue as well?

Why doesn't the DeepLink helper launch my Android app?

My app is based on this code sample from Google: https://actions-on-google.github.io/actions-on-google-nodejs/classes/conversation_question.deeplink.html
Here is a snippet directly from my code:
app.intent('Default Welcome Intent', conv => {
conv.ask('Great! Looks like we can do that in the app.')
conv.ask(new DeepLink({
destination: 'MyBookApp',
url: 'https://www.mybooksite.com/read/123456789',
package: 'com.mybook.app.reader',
reason: 'handle this for you',
}))
})
// Create a Dialogflow intent with the `actions_intent_LINK` event
app.intent('Get Link Status', (conv, input, arg, status) => {
// possibly do something with status
conv.close('Okay maybe we can take care of that another time.')
})
When I run this app I see "Okay maybe we can take care of that another time." instead of my app being launched.
Is there code missing in my handler for the 'Get Link Status' intent? (I created the intent according to the comment above that line).
Am I passing the wrong params to the DeepLink object? I can't find docs for them anywhere.
Note: My app is definitely coded to handle http deep links including verification with Google Digital Asset Links and the deep link URL I'm testing with works perfectly from other apps.
Any suggestions or help is much appreciated!
Thanks in advance...
Your welcome intent handler is missing an additional call to conv.ask before the deep link call:
conv.ask('Great! Looks like we can do that in the app.')
All responses should have at least a simple response.