How to implement this example :
let device = this.googleAction().getRequest().getDevice();
console.log(device);
this.tell('Thanks for your precise location');
https://raw.githubusercontent.com/jovotech/jovo-framework-nodejs/master/examples/google_action_specific/appAskForPermission.js
Did you ask for 'precise location' first as shown in the example you linked?
this.googleAction().askForPreciseLocation('Precise Location pre text');
If a user gives you the permission, it then jumps into the 'ON_PERMISSION' handler, where you can access the information as explained:
if (requestUser.permissions.indexOf('DEVICE_PRECISE_LOCATION') > -1) {
let device = this.googleAction().getRequest().getDevice();
console.log(device);
this.tell('Thanks for your precise location');
}
You can find more information in the Jovo Docs: Google Assistant > Data > ON_PERMISSION.
Related
Recently I publish my mobile application but there is a unique problem. In some devices people download application in google play and easily use the application. But some devices has need to clear all application data from settings then open again because if they don't do this they can't see onboarding screen and also can't fetch data from internet. In flutter I basically use Hive local storage at main dart to route after installation
//Here if onBoard box is true user will see welcomescreen
if (Hive.box('settings').get('onBoard') == true) {
screen = const WelcomeScreen();
}
//Here if user already registered but click sign out button isRegistered box will be false and user
//will go LoginPage again
else if(Hive.box('settings').get('isRegistered') == false){
screen = const LoginPageDesign();
}
//! If on boarding not true (false or null) user will route OnBoarding page
else {
screen = const OnBoarding();
}
The problem is some android devices backsup local storage data to the cloud. You can go through this article from android: https://developer.android.com/guide/topics/data/autobackup.html
So, to overcome this issue, just navigate to your AndroidManifest and do the following just under application tag:
<application
...
android:allowBackup="false"
android:fullBackupContent="false"
tools:replace="android:allowBackup"
...
</application>
switch(Hive.box('settings').get('isRegistered')){
case null:
screen = const OnBoarding();
break;
case false:
screen = const LoginPageDesign();
break;
case true:
screen = const WelcomeScreen();
break;
}
Interestingly once I tested with internal test,
Android 13 real devices has no problem it goes first onBoaring but with Android 10 it goes directly WelcomeScreen I don't understand how it is possible to take true for this situation should always null at fresh start.
EDIT : Problem is interestingly fixed once add another Hive.box for registeration ...
I am currently learning how to ask the user for an AppStore rating in the app. I have read through numerous documentations and reports from Apple and other bloggers, but I still have questions:
I thought that I want to display my request after the user has completed a sequence of actions 3 times. But if the user doesn't want to rate my app right now, can I ask him to rate my app again later? I also read that Apple controls when and how often the review request is displayed (up to 3x / year)
My app has different functions. Therefore it is not guaranteed that the user accesses exactly this function, where I want to show the rating view. Is it therefore possible to call up the rating request at different points in the app and simply leave it up to Apple whether the rating request is also displayed?
Best regards
Edit for #K bakalov :
enum AppReviewRequest {
#AppStorage("runCountSinceLastRequest") static var runCountSinceLastRequest = 0
#AppStorage("lastVersion") static var lastVersion = ""
static let threshold = 4
static let currentVersion = Bundle.main.object(forInfoDictionaryKey: "CFBundleVersion") as! String
static func countUpRequestReview() {
if currentVersion != lastVersion {
if runCountSinceLastRequest < threshold - 1 {
runCountSinceLastRequest += 1
print(runCountSinceLastRequest)
}
}
}
static func requestReviewIfNeeded() {
if currentVersion != lastVersion {
if runCountSinceLastRequest == threshold {
if let scene = UIApplication.shared.connectedScenes.first(where: { $0.activationState == .foregroundActive }) as? UIWindowScene {
SKStoreReviewController.requestReview(in: scene)
lastVersion = currentVersion
runCountSinceLastRequest = 0
}
}
}
}
}
I assume you already read that but if you haven't I am leaving a link for you to check it out: https://developer.apple.com/documentation/storekit/requesting_app_store_reviews
It contains helpful information and guides when and how to prompt the user to leave a review.
Back to your questions.
Yes, you can ask again for review but there is no guarantee that the Review pop-up (alert) will be presented again. It is usually delayed in time and sometimes requires a new update of the app to trigger a new review prompt; That is correct, Apple has control over it but I don't know if its limited to only 3 times a year.
Yes, you can call it as many times as you want and wherever you find it suitable. Although, I highly encourage you to read (if still haven't) the link above. You need to think of a non-intrusive way to ask for review, otherwise you risk the user to dismiss the prompt, even if they like the app.
Just an advice, many apps use an approach with a custom popup "Do you like the app? Yes/No", if "Yes" then request a review using requestReview() call. And/or as mentioned in the article above, you can always use a manual review by redirecting to the AppStore, if you need it as a result of a CTA (tap on a button for example).
Is there a way to push a link for more information to the users device if they asked a question to your Action through a voice only google home device?
You seem to be looking for multi-surface conversations, where the Action can transfer seamlessly from a Google Home to a phone.
Then you create a New Surface intent and you'll get a notification on your phone to show the content.
if (conv.screen) {
conv.ask(`You're already on a screen device.`);
conv.ask('What else would you like to try?');
} else if (screenAvailable) {
const context =
`Let's move you to a screen device for cards and other visual responses`;
const notification = 'Try your Action here!';
const capabilities = ['actions.capability.SCREEN_OUTPUT'];
conv.ask(new NewSurface({context, notification, capabilities}));
} else {
conv.ask('It looks like there is no screen device ' +
'associated with this user.');
conv.ask('What else would you like to try?');
};
I'm trying to get user location inside a Facebook Messenger Chat-Extension.
I open the webview and ask as usual :
var options = {
enableHighAccuracy: true,
timeout: 5000,
maximumAge: 0
};
function success(pos) {
var crd = pos.coords;
console.log('Your current position is:');
console.log(`Latitude : ${crd.latitude}`);
console.log(`Longitude: ${crd.longitude}`);
console.log(`More or less ${crd.accuracy} meters.`);
};
function error(err) {
console.warn(`ERROR(${err.code}): ${err.message}`);
};
navigator.geolocation.getCurrentPosition(success, error, options);
I'm getting this issue : ERROR(1): User denied Geolocation.Is there a way to get user location through Chat Extension Webview ? Thank you
geolocation should work fine on most iOS devices, but will fail on most (if not all) Android devices. That said there is no cross-platform solution for retrieving a user's geo location properly within a webview or Chat extension.
I'm using .net ui automation framework to capture user clicks of links when they are viewing a message in an outlook application.
The problem is that, I'm not able to get the link as an AutomationElement(as I can in a web page in IE window). I can only get the document pane as a whole.
Is there any way to do it?
Well, I got it myself.
Though I'm not able to get the link directly, I can locate the link and get it from the TextPattern of the document element.
Suppose element is the document element that directly gets the focus or clicked:
if (element.Current.LocalizedControlType == "document")
{
var point = new System.Windows.Point(Cursor.Position.X, Cursor.Position.Y);
object textPattern;
if (element.TryGetCurrentPattern(TextPattern.Pattern, out textPattern))
{
var range = ((TextPattern)textPattern).RangeFromPoint(point); //it's an empty range
var e = range.GetEnclosingElement(); //get the enclosing AutomationElement
if (e.Current.LocalizedControlType == "link" || e.Current.LocalizedControlType == "hyperlink")
{
//use e
}
}
}