HTML5 a标签电话功能无法使用是什么原因?

html-css033

HTML5 a标签电话功能无法使用是什么原因?,第1张

因为老的浏览器能够识别doctype,但是并不意味它可以处理HTML5标签和功能。

HTML5 a标签电话功能:

1、<a href="tel:4008001234" class="call"></a>。

2、亲测是可以的,注意tel:的和html中的meta写法为 <meta name="format-detection" content="telephone=yes">。

3、target是打开链接时用什么目标打开,是在新窗口中打开就用target=_blank,在父窗口中打开就用target=_parent,在当前窗口中打开就用target=_self,

target=_top表示在顶层窗口中打开

最近采用phonegap做一个APP,需要在应用内实现拨打电话,通话结束後能反馈通话相关状态,查看了一番phonegap官方文档,似乎没有跟电话相关的api,在互联网上也大概搜了一下,好像没找到相关的内容。其实html5是支持直接在网页上拨打电话的,只要加入如下html代码即可:

[html] view plaincopy

打电话<a href="tel:10086" >移动客服</a>

发短信<a href="sms:10086" >发短信</a>

但这中方式只能实现拨打电话和发送短信,不能反馈结果,比如我想在应用能实现拨打电话,通话结束後自动保存通话的电话号码、通话时间、时长等,默认的html功能就不能满足了。

phonegap官方不提供的功能,我们只有自己通过开发插件了实现了

下面我们通过代码来简单介绍下phonegap插件开发步骤:

一、定义JS插件API

[javascript] view plaincopy

var Phone = function() {

}

Phone.prototype.call = function (successCallback, failureCallback,number) {

cordova.exec(successCallback, failureCallback, "Phone", "call", [number])

}

window.Phone = new Phone()

上面的代码我们定义了一个Phone插件,插件有一个call API,我们传入

[javascript] view plaincopy

successCallback

failureCallback

分别做为电话拨打成功和失败的回调函数

传入

[javascript] view plaincopy

number

做为电话号码

在方法裏边调用

phonegap的cordova.exec()

[javascript] view plaincopy

cordova.exec(successCallback, failureCallback, "Phone", "call", [number])

就是在这个方法裏将执行到native端的功能调用

最後我们new一个Phone对象,把他附件到window对象上,方便以後调用。

这样,插件的JS代码完成。

二、native端代码(以android平台为例)

先直接上代码

[java] view plaincopy

package com.juhuibao.PhoneGapPlugin

import java.util.Date

import org.apache.cordova.api.CallbackContext

import org.apache.cordova.api.CordovaPlugin

import org.apache.cordova.api.PluginResult

import org.json.JSONArray

import org.json.JSONException

import android.app.Activity

import android.content.Intent

import android.database.Cursor

import android.net.Uri

import android.provider.CallLog.Calls

import android.telephony.PhoneNumberUtils

public class Phone extends CordovaPlugin {

private static final int PHONE_CALL = 0// 拨打电话

private static final int PHONE_ABORT = 1// 挂断电话

private Date start_time

private CallbackContext callbackContext

private String phonenumber

@Override

public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {

try{

this.callbackContext = callbackContext

if ("call".equals(action)) {

this.phonenumber=args.getString(0)

this.call(args.getString(0),callbackContext)

return true

}

if ("abort".equals(action)) {

this.abort(callbackContext)

return true

}

return false

}

catch(Exception e){

callbackContext.error(e.getMessage())

}

return false

}

//拨打电话

private void call(String phonenumber, CallbackContext callbackContext) {

if (phonenumber != null &&phonenumber.length() >0) {

if(PhoneNumberUtils.isGlobalPhoneNumber(phonenumber)){

Intent i = new Intent()

i.setAction(Intent.ACTION_CALL)

i.setData(Uri.parse("tel:"+phonenumber))

start_time=new Date()

this.cordova.startActivityForResult(this, i,PHONE_CALL)

}

else{

callbackContext.error(phonenumber+"不是有效的电话号码。")

}

} else {

callbackContext.error("电话号码不能为空.")

}

}

//中断电话

private void abort(CallbackContext callbackContext) {

}

public void onActivityResult(int requestCode, int resultCode, Intent intent) {

Date end_time=new Date()

if (resultCode == Activity.RESULT_OK) {

if (requestCode == PHONE_CALL) {

this.callbackContext.error("未知状态")

}

}

else if (resultCode == Activity.RESULT_CANCELED) {

try{

if (requestCode == PHONE_CALL) {

long duration=GetLastCallDuration()

PhoneResult result=new PhoneResult()

result.setNumber(Phone.this.phonenumber)

result.setStartTime(Phone.this.start_time)

result.setEndTime(end_time)

result.setDuration(duration)

this.callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, result.toJSONObject()))

}

}

catch(Exception e){

this.callbackContext.error(e.getMessage())

}

}

else {

this.callbackContext.error("其他错误!")

}

}

long delayTime=0

long timeOut=2000

long GetLastCallDuration() throws InterruptedException{

Activity activity = this.cordova.getActivity()

Cursor cursor = activity.getContentResolver().query(Calls.CONTENT_URI,

new String[] {Calls.NUMBER,Calls.DATE, Calls.DURATION, Calls.TYPE, Calls.DATE },

"number=?and type=?",

new String[]{this.phonenumber,"2"},

Calls.DEFAULT_SORT_ORDER)

activity.startManagingCursor(cursor)

boolean hasRecord = cursor.moveToFirst()

if (hasRecord) {

long endTime=cursor.getLong(cursor.getColumnIndex(Calls.DATE))

Date date = new Date(endTime)

long duration = cursor.getLong(cursor.getColumnIndex(Calls.DURATION))

long dif=this.start_time.getTime()-date.getTime()

long second=dif/1000

if(second<2&&second>-2){

return duration

}else{

if(delayTime>=timeOut){

return 0

}

Thread.sleep(200)

delayTime+=200

return GetLastCallDuration()

}

}else{

if(delayTime>=timeOut){

return 0

}

Thread.sleep(200)

delayTime+=200

return GetLastCallDuration()

}

}

}

然後调用具体实现拨打电话功能的方法call方法,在call方法内我们首先判断电话号码合法性,不合法直接调用callbackContext.error("不是有效的电话号码。"),这个方法将触发JS端的error回调函数执行,并传入一个字符串参数,比如以上的failureCallback

如果电话号码合法则弹出呼叫界面,如下代码

[java] view plaincopy

if(PhoneNumberUtils.isGlobalPhoneNumber(phonenumber)){

Intent i = new Intent()

i.setAction(Intent.ACTION_CALL)

i.setData(Uri.parse("tel:"+phonenumber))

start_time=new Date()

this.cordova.startActivityForResult(this, i,PHONE_CALL)

}

else{

callbackContext.error(phonenumber+"不是有效的电话号码。")

}

在代码中我们通过变量start_time记录开始时间,然後使用this.cordova.startActivityForResult(this, i,PHONE_CALL)启动Activity。

在终止拨号或挂断电话时将执行onActivityResult方法,我们将在此方法内实现通话状态信息的反馈。主要看一下这段代码

[java] view plaincopy

else if (resultCode == Activity.RESULT_CANCELED) {

try{

if (requestCode == PHONE_CALL) {

long duration=GetLastCallDuration()

PhoneResult result=new PhoneResult()

result.setNumber(Phone.this.phonenumber)

result.setStartTime(Phone.this.start_time)

result.setEndTime(end_time)

result.setDuration(duration)

this.callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, result.toJSONObject()))

}

}

catch(Exception e){

this.callbackContext.error(e.getMessage())

}

}

不管电话有没有接通,resultCode总是等於Activity.RESULT_CANCELED。

我们通过GetLastCallDuration()方法获得通话时长,原理就是读取通话记录裏边的duration字段,由於通话刚结束时通话记录可能还没出现记录,所以我们要反复调用该方法,直到有记录或到超时时间为止。

取得了时长我们通过this.callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, result.toJSONObject()))把结果反馈给JS端。

附 PhoneResult.java

[java] view plaincopy

package com.juhuibao.PhoneGapPlugin

import java.text.SimpleDateFormat

import java.util.Date

import org.json.JSONException

import org.json.JSONObject

public class PhoneResult {

private String number = ""

private Date startTime

private Date endTime

private long duration = 0

public JSONObject toJSONObject() throws JSONException {

SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss:S")

return new JSONObject(

"{number:" + JSONObject.quote(number) +

",startTime:" + JSONObject.quote(sdf.format(startTime)) +

",endTime:" + JSONObject.quote(sdf.format(endTime)) +

",duration:" + duration + "}")

}

public String getNumber() {

return number

}

public void setNumber(String number) {

this.number = number

}

public Date getStartTime() {

return startTime

}

public void setStartTime(Date startTime) {

this.startTime = startTime

}

public Date getEndTime() {

return endTime

}

public void setEndTime(Date endTime) {

this.endTime = endTime

}

public long getDuration() {

return duration

}

public void setDuration(long duration) {

this.duration = duration

}

}

这样native端的代码完成。

三、客户端调用

[javascript] view plaincopy

window.Phone.call(function (obj) { alert(JSON.stringify(obj))

}, function (err) { alert(err)}, "13401100000")

四、配置插件

在config.xml文件中注册插件

[html] view plaincopy

<plugin name="Phone" value="com.juhuibao.PhoneGapPlugin.Phone"/>

在AndroidManifest.xml文件中增加权限

[html] view plaincopy

<uses-permission android:name="android.permission.CALL_PHONE" />

<uses-permission android:name="android.permission.READ_CALL_LOG" />

<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />

<uses-permission android:name="android.permission.READ_PHONE_STATE"/>

下面列举HTML5适合移动应用开发的几大特性:

1.离线缓存为HTML5开发移动应用提供了基础

HTML5 Web Storage API可以看做是加强版的cookie,不受数据大小限制,有更好的弹性以及架构,可以将数据写入到本机的ROM中,还可以在关闭浏览器后再次打开时恢复数据,以减少网络流量。

同时,这个功能算得上是另一个方向的后台“操作记录”,而不占用任何后台资源,减轻设备硬件压力,增加运行流畅性。

在线app支持边使用边下载离线缓存,或者不下载离线缓存;而离线app必须是下载完离线缓存才能使用。

形象点说,cookie就是存了电话和菜单,想吃什么要叫外卖,等多长时间才能吃到就得看交通情况了;离线缓存就是直接在冰箱里存了食物,想吃就能马上吃到(当然,想吃最新的食物同样可以打电话预定)。

设计师要知道,什么时候让用户下载离线缓存(注意在线和离线app的区别)。

2.音频视频自由嵌入,多媒体形式更为灵活

原生开发方式对于文字和音视频混排的多媒体内容处理相对麻烦,需要拆分开文字、图片、音频、视频,解析对应的URL并分别用不同的方式处理。

HTML5在这个方面完全不受限制,可以完全放在一起进行处理。

设计师要知道,如果新闻类、微博类、社交类应用的信息呈现中实现文字与多媒体混排,而不用专门嵌入webview,将是一件多美好的事情,至少现在原生方式实现起来还有困难。

3.地理定位,随时随地分享位置

充分发挥移动设备对定位上的优势,推动LBS应用发展。

可以综合使用GPS、wifi、手机等方式让定位更为精准、灵活。

地理位置定位,让定位和导航不再专属导航软件,地图也不用下载非常大的地图包,可以通过缓存来解决,到哪儿下哪儿,更灵活。

设计师要知道,现在嵌入LBS功能的应用越来越多,这也是移动设备与台式PC相比最大的优势之一,HTML5能把这个优势再度扩大化,好好想想怎么在你设计的应用里用上吧!

4.Canvas绘图,提升移动平台的绘图能力

使用Canvas API可以简单绘制热点图收集用户体验资料

支持图片的移动、旋转、缩放等常规编辑

Canvas – 2D的绘图功能支持

Canvas 3D – 3D的绘图功能支持

SVG – 向量图支援

设计师要知道,图片的移动、旋转、缩放?那都太基础了,自己画都是小case,至于怎么用,好好想想吧!

5.专为移动平台定制的表单元素

浏览器中出现的html5表单元素与对应的键盘:

类型用途键盘

Text正常输入内容标准键盘

Tel电话号码数字键盘

Email电子邮件地址文本框带有@和.的键盘

url网页的URL带有.com和.的键盘

Search用于搜索引擎,比如在站点顶部显示的搜索框标准键盘

range特定值范围内的数值选择器,典型的显示方式是滑动条滑动条或转盘

只需要简单的声明 <input type=”email”>即可完成对不同样式键盘的调用,简捷方便。

设计师要知道,用的时候记得告诉研发同事一声!