FINAL EDIT
This was a bug. After filing the report it was addressed.
EDIT
I am trying to get user id in a webview of my facebook messenger bot. It works fine on mobile, yet fails on desktop (web). This should not be the case.
Messenger 2.1 release statement gives the following quote:
Desktop support for Extensions SDK: This new feature will extend functionality across mobile and web, creating a consistent experience across devices. Now, features like user ID and sharing that used to only be accessible on mobile will be available on desktop as well. This also provides developers with an easier way to test and debug when implementing webview and chat extensions.
There are two ways to get the user id with messenger extensions: getUserId() and getContext(). The docs state that getUserId() is not available on desktop, but make no mention of getContext().
Howevew, there is a bug report that states that getContext() call is not yet available on desktop.
The docs mention no other ways of getting user id. How is one supposed to do that?
As a kicker, if you read the original question, you will see that getContext() actually does work on desktop (web), but only if the webview is opened through a link sent directly by the bot.
ORIGINAL
I am working on a Facebook (messenger) bot using webview.
Now the most basic of all tasks is to get the userId.
This is where I hit a big problem. Having investigated it thoroughly, below I present cases and results.
case 1: my app sends me a generic template with a web_url button (that opens the webview) and a share button.
Everything works great. I get the user id.
case 2: I click share from the message in case 1, and share it with myself and my app.
from either message thread (I to myself, or the I to app) getContext() call return error 2018166 Permission not valid to call the SDK API. and askPermission() returns 2018154 Messenger Extensions unexpected error.
case 3: I click share from inside the webview using beginShareFlow() and share with myself and the bot.
same as case 2
case 4: here's the kicker.
activating the webview from case 2 or case 3 from Android, works and gives me the user id.
case 5: sharing to a friend who has interacted with the app before.
When that friend activates the webview, from desktop it fails, from android works.
case 6: sharing to a friend who has not interacted with the bot.
on desktop doesn't work (sharing by button or through beginShareFlow()), it works!
So, after writing all of this out, the pattern is:
on android, webview sharing works as expected: I can get the user id whether they have interacted with the bot befor or not.
on desktop, the only time the webview provides the user id, is when the message with the webview link was sent by the bot. Once it is shared by a user, the webview still opens, but does not provide context.
Just to clarify. I get the user id by using getContext, and not by getUserId which the docs specifically say doesn't work on desktop.
Is there anything I can do about this? I would like my bot's webviews to work both on desktop and mobile.
I can think of a workaround, but it's far from ideal
EDIT 2
As requested, the payload for sharing within webview is:
{
"attachment":{
"type":"template",
"payload":{
"template_type":"generic",
"elements": [{
"title":"Testing webview",
"default_action":{
"type":"web_url",
"webview_height_ratio": "full",
"messenger_extensions": true,
"url":"https://plenty.life/webview"
},
"buttons":[{
"type":"web_url",
"webview_height_ratio": "full",
"messenger_extensions": true,
"url":"https://plenty.life/webview",
"title":"Test"
}]
}]
}
}
}
Try this...
<script>
window.extAsyncInit = function() {
// the Messenger Extensions JS SDK is done loading
console.log("using getUserId in",window.name)
MessengerExtensions.getUserID(function success(uids) {
// User ID was successfully obtained.
var psid = uids.psid;
console.log(psid);
document.getElementById("userId").innerText="your User Id Is "+psid;
}, function error(err, errorMessage) {
// Error handling code
console.log("some Error",err,errorMessage)
});
MessengerExtensions.getContext('<appID>',
function success(result){
console.log("success",result)
},
function error(result){
console.log("error",result)
}
);
};
</script>
Related
I have implemented login using ChromeCustomTabsBrowser. After successful login, if app's Open Supported links setting is set to "Ask evety time" instead of "Open in this app", response is not getting back to the app and showing 404 screen as attached in screen.
Interesting - looks like you are using an https scheme for redirects and here is how we'd like the technology to work:
You are automatically deep linked back to your app when a login response is received over the https URL.
However, in practice I believe this is what happens:
Almost all mobile browsers try to run an internet hosted web page instead
A claimed https scheme solution is very hard to achieve and rarely used in practice today - more of an aspiration than a reality? But I believe it would need to work like this:
Capture the response on the internet web page which runs on your mobile device
Then deep link back to the app
A similar approach is used by a sample internet web page of mine - do a view source to see the logic
If it helps I have a demo Android sample that instead uses the more mainstream option of private URI schemes - though I may update it to claimed https schemes one of these days.
Code
Explanatory Articles
Even getting this form of Chrome Custom Tab based login working was a struggle, and my posts have some lessons learned that may be useful.
After open webpage in app browser where phone number is set I need get phone number in popup for call.
Any plugin for phonegap?
GL
Not sure what your question means, but as far as I understand you need to make a call to the number on button click. Try the following in your HTML file:
<a class="button" href="tel://123456">1234563</a>
If you are getting the number from controller, use:
<a class="button" href="tel://{{number}}">123456</a>
Today I came across a feature request that I had not done before – dialing a number from within an app. Some quick research shows that its possible using a specific URI scheme.
What are URI schemes? Honestly Wikipedia does a better job than I ever could in describing them but I think of them as something that allows a specific piece of functionality to happen over the internet, and thus they are usually referred to as protocols. You probably have already seen them – the most common ones are http: and https: (for web browsing), and ftp:, among others. Some are unique to an application and really don’t qualify as schemes and are definitely not a “protocol”, such as mailto: (to open up the mail client on a person’s computer), javascript: or about: – in fact, try typing about: in the address bar of your browser and hit “enter” on your keyboard, notice what happens…
In our case where we want to dial a number from within our app we need a way of telling the mobile phone that we want to make a call. There is a scheme for this purpose called tel:. A sample number using this scheme would look like this: “tel:+1-800-555-1234”. If you wanted a number to work around the world you would use an international number which includes the country code.
Implementing this is simple, we could do this within our mobile html5 app like so:
...
call this number
...
Ideally though we would delegate the event and fire a function to call our mythical phone number. To send the url (the “tel” url) to the browser we would write the following:
...
document.location.href = 'tel:+1-800-555-1234';
...
As of PhoneGap 3.6 all schemes are subject to whitelists. This means you have to add the tel scheme to a second whitelist that will allow your app to launch external applications. To do this you need to edit your config.XML to include the following (a mailto example is included):
Go here for more information: Cordova 3.6.0 Whitelist Guide.
Of interest to this topic is getting Android to treat phone numbers (as well as URLs and mailto schemes) as clickable links in text fields. I’ve not tested it but try adding the following to your config.xml.
Additional information on this can be found here: http://developer.android.com/reference/android/widget/TextView.html#attr_android:autoLink.
[EDIT: Note that what follows no longer applies but remains here for historical purposes.]
When we run the above code in Android 2.3.6 the phone dialer appears and does so with our number pre-populated ready to be dialed. Unfortunately on iOS 5 this doesn’t happen. A quick review of iOS documentation implies that it should work – so I suppose its just broken.
No need to panic, there is a PhoneGap plugin available which will take care of things. The plugin can be downloaded from here:
Click here to download the iOS Phone Dialer PhoneGap plugin
Its simple to install – just drag and drop the “m” and “h” files on to the classes folder of your xcode project. When you do this a dialog will appear with some options – be sure to click the radio button for copying “…files if needed..”.
Next, update the PhoneGap.plist file to reflect that you are adding a new plugin. The link for downloading the plugin explains the plist values as being “phonedialer > PhoneDialer”… but I think its easier to explain with an image:
The final step is to place the “PhoneDialer.js” javascript file somewhere within the root of your project and then to add it to your index.html file via a script tag.
Now that the Phone Dialer plugin is installed you’ll naturally want to know how to use it:
...
window.plugins.phoneDialer.dial('1-800-555-1234');
...
All in all pretty easy and straight forward, however now you have two methods of dialing a number within a single project. What you want is to use the tel: url scheme in Android and the Phone Dialer plugin in iOS.
Within Sencha Touch we have something called the Ext.is object whose attributes reflect everything that you could possibly want to know about the environment that your mobile app is living within.
For our purposes all we want to know is if we are in iOS or if we are in Android. These two lines provide us the answer:
...
Ext.is.Android // boolean, "true" for android, false otherwise
Ext.is.iOS // boolean, "true" for iOS, false otherwise
...
Thats all we need to impliment phone dialing across the two platforms within our mobile app. Lets build a function that makes use of one of the above (we don’t need both) and we should also give the user a choice in the matter, so the code below includes a message to the user to see if they really do want to suspend the app in favor of the device’s phone dialer:
...
function callSomeone(){
var msg = Ext.Msg.confirm('Please Confirm','Are you sure you want to make a phone call?',
function(r){
if (r == 'yes'){
if (Ext.is.Android){
document.location.href = 'tel:+1-800-555-1234';
} else { // we assume the device is running iOS
window.plugins.phoneDialer.dial('1-800-555-1234');
}
}
});
msg.doComponentLayout();
}
...
All done… I suppose the very last thing to do here is to provide a complete working Sencha Touch example, and some screen captures…
...
Ext.setup({
onReady: function(){
var rootPanel = new Ext.form.FormPanel({
fullscreen: true,
items: [
{
xtype:'button',
text:'Call 1-800-555-1234',
scope:this,
handler: callSomeone
}
],
dockedItems:[
{
xtype:'toolbar',
dock:'top',
title:'Phone Dialer Example'
}
]
}
);
function callSomeone(){
var msg = Ext.Msg.confirm('Please Confirm','Are you sure you want to make a phone call?',
function(r){
if (r == 'yes'){
if (Ext.is.Android){
document.location.href = 'tel:+1-800-555-1234';
} else { // we assume the device is running iOS
window.plugins.phoneDialer.dial('1-800-555-1234');
}
}
}
);
msg.doComponentLayout();
}
}
});
...
From http://rickluna.com/wp/2012/02/making-a-phone-call-from-within-phonegap-in-android-and-ios/
I am developing an application that requires to auto-fill logins in other installed apps and chrome. I am able to successfully auto-fill logins in other installed apps using AccessibilityService but could not get it working on Chrome browser. I am able to identify the username and password AccessibilityNodeInfo but I am not able to paste the content into it.
This is how I am trying, I am copying the content to be filled into Clipboard and then pasting the content into these username and password fields using AccessibilityNodeInfo.ACTION_PASTE. This technique works well for other installed apps but it fails to paste in Chrome. I am not able to find any relevant posts online except this one - link, but there is no clear solution in it. Also I am not able to find anything documented on developer site too. Should I be injecting javascript code to paste my content? If so can you please give me an example? I have done that using WebView previously but in this case I don't have reference to the view.
Any help on this will be greatly appreciated.
You can run javascript to accomplish this by executing something like the following:
document.getElementById("username").val = "username";
however I doubt if you can just run arbitary js in the chrome app as an outside app.
Well Google doesn't allow that
"You can't use an AccessibilityService to inject JavaScript"
"There are no plans to support javascript extensions or any other method of injecting javascript in Chrome or a WebView."
You can read more here...
You can use this method to accomplish the autofill:
private void setNodeText(AccessibilityNodeInfo node, String str) {
Bundle bundle = new Bundle();
bundle.putCharSequence(AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE, str);
node.performAction(AccessibilityNodeInfo.ACTION_SET_TEXT, bundle);
}
So I've created a simple WebView application that wraps an already existing mobile friendly site and displays it on the device. I've enabled javascript, supported screen orientation changes, etc...
I've run into an issue with the oAuth support though. Accessing the site from the chrome browser on the device, everything runs fine.
If I try to access the site from the app/WebView, it will push me over to the oAuth screen, let me input credentials and everything, but the moment it tries to push me back to the website and log me in, I get this:
Failed to recognize URL query:
https://exittix.com/frontend/login/redirect.html#access_token=******************************&expires_in=********&state=****client_id=******************network*****facebook*****display***popup****callback****_hellojs_agj27sx5****state****oauth_proxy***https***auth-server.herokuapp.com%2Fproxy***scope***basic_profile***email***basic***oauth***version***auth***https***facebook.com%2Foauth***
The * is used to protect data.
So, any ideas why oAuth isn't working inside a JS enabled webview but works fine in the mobile chrome browser for android?
Thanks in advance for your help!
EDIT:
Ok, so I've tracked the error I'm getting back to redirect.html.
This page calls some javascript. If the javascript fails to redirect, then it displays that error I have above instead.
The javascript being called to handle the oAuth is Andrew Dodson's hello.js script.
You can see it HERE.
I've concluded that the second half of the error's url is indeed the unhandled JSON.
Here's what the returned data looks like after I've decoded it from the URL encoded characters:
{"client_id":"************.apps.googleusercontent.com","network":"google","display":"popup","callback":"_hellojs_********","state":"","oauth_proxy":"https://auth-server.herokuapp.com/proxy","scope":["https://www.googleapis.com/auth/userinfo.profile","https://www.googleapis.com/auth/userinfo.email","basic"],"oauth":{"version":2,"auth":"https://accounts.google.com/o/oauth2/auth"}}&access_token=***.*.*****_*********************************************************&token_type=Bearer&expires_in=3600
Any ideas why this isn't getting handled properly in the WebView?
Not really sure how to correctly describe this so hopefully some of you know what I mean.
Our client is getting a mobile app for thier site, hopefully soon, and I have noticed on android devices and sure they probably exist on iphones too, a popup to inform you that said site has an app. I have seen it on forums that support tapatalk as well as the sammobile.com website. Its a small message and an "ok" and "cancel" button, ok takes you to the app in the market.
Googles only really helpful when you know or at least can correctly describe what you are looking for.
Does anyone know
A) Do iPhones also have this feature and
B) how would I go about triggering such a popup/notification?
Using some infor from a java push trigger as well as a few other Stacks I put this together.
if (/Android|iPhone|BlackBerry/i.test(navigator.userAgent)) {
var url = confirm("Would you like to download our mobile application?");
if (url === true) {
var url = window.location.href = 'http://www.google.com';
url.show();
}
}
Will test for the 3 devices mentioned, if so will create a confirmation box for which confirmation will direct the user to another url.