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: andhttps: (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 asmailto: (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:
- ...
- <a href="tel:+1-800-555-1234">call this numbera>
- ...
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):
origin="tel:*" launch-external="yes" /> origin="mailto:*" launch-external="yes" />
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.
android:autoLink="phone" />
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();
- }
- }
- });
- ...
The final product on a Samsung Galaxy S2: