最近采用phonegap做一个APP,需要在应用内实现拨打电话,通话结束后能反馈通话相关状态,查看了一番phonegap官方文档,似乎没有跟电话相关的api,在互联网上也大概搜了一下,好像没找到相关的内容。其实html5是支持直接在网页上拨打电话的,只要加入如下html代码即可:
- 打电话<a href="tel:10086" >移动客服</a>
- 发短信<a href="sms:10086" >发短信</a>
但这中方式只能实现拨打电话和发送短信,不能反馈结果,比如我想在应用能实现拨打电话,通话结束后自动保存通话的电话号码、通话时间、时长等,默认的html功能就不能满足了。
phonegap官方不提供的功能,我们只有自己通过开发插件了实现了,phonegap官网上有一个phonegap插件开发指导http://docs.phonegap.com/en/2.5.0/guide_plugin-development_index.md.html#Plugin%20Development%20Guide,
下面我们通过代码来简单介绍下phonegap插件开发步骤:
一、定义JS插件API
- var Phone = function() {
- };
- Phone.prototype.call = function (successCallback, failureCallback,number) {
- cordova.exec(successCallback, failureCallback, "Phone", "call", [number]);
- };
- window.Phone = new Phone();
上面的代码我们定义了一个Phone插件,插件有一个call API,我们传入
- successCallback
- failureCallback
分别做为电话拨打成功和失败的回调函数
传入
- number
做为电话号码
在方法里边调用
phonegap的cordova.exec()
- cordova.exec(successCallback, failureCallback, "Phone", "call", [number]);
就是在这个方法里将执行到native端的功能调用
最后我们new一个Phone对象,把他附件到window对象上,方便以后调用。
这样,插件的JS代码完成。
二、native端代码(以android平台为例)
先直接上代码
- 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
如果电话号码合法则弹出呼叫界面,如下代码
- 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方法,我们将在此方法内实现通话状态信息的反馈。主要看一下这段代码
- 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
- 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端的代码完成。
三、客户端调用
- window.Phone.call(function (obj) { alert(JSON.stringify(obj));
- }, function (err) { alert(err); }, "13401100000");
四、配置插件
在config.xml文件中注册插件
- <plugin name="Phone" value="com.juhuibao.PhoneGapPlugin.Phone"/>
在AndroidManifest.xml文件中增加权限
- <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"/>
《完》
相关推荐
phonegap开发插件包,各个平台的都有,像什么短信收发插件,蓝牙控制插件等等,具体的看文件包吧
PhoneGap常用插件 里面包括ios android等等 基本需要的插件都有 如拨打电话 上传图像等
最新phonegap插件集合 包括安卓 ios等平台
PhoneGap iOS 自定义插件
Phonegap在安卓平台上的插件开发 一个前台html传string到native端经过md5处理后返回结果到前台html的例子
phonegap2.9.0插件
自己写的一个PhoneGap Camera插件调用 Demo,实现拍照/图库获取图片功能,编译通过~~~具体实现我博客里面有
phonegap 打开文档插件 <script type="text/javascript" charset="utf-8" src="fileopener.js"></script>
phonegap android在线更新插件,兼容android7.0下载后安装闪退的问题;详细使用见README.md文件。
支付宝快捷支付phonegap插件demo,项目使用phonegap又用到了支付宝,自测通过。
phonegap插件包Android版本 此代码是完全依赖PhoneGap的项目 此文件夹是为Android特定的插件。
它使开发者能够利用iPhone,Android,Palm,Symbian,WP7,Bada和Blackberry智能手机的核心功能——包括地理定位,加速器,联系人,声音和振动等,此外PhoneGap拥有丰富的插件,可以以此扩展无限的功能。
使用phonegap框架开发android应用程序,免不了需要涉及js与java原生代码的交互,自定义phonegap插件可以满足这个需求。 在本教程中,介绍了怎么使用phonegap插件跳转到另一个Android Activity
百度移动广告联盟phonegap/cordova插件,百度ssp广告phonegap插件,支持cordova和phonegap打包的ios和android应用,简单好用,只需要几行js就能在phonegap和cordova应用里面接入百度广告
phonegap实现摇一摇拨打电话功能,摇一摇功能使用phonegap的加速计,拨打电话功能用使用了自定义的插件,phonegap版本是3.0的版本
phonegap 微信共享插件
在phonegap 2.2中配置好插件,该插件能打开一个新的Activity。仅供学习,为配置phonegap2.2插件环境头痛的同志贡献了
cordova.js 是phonegap开发必备插件JS包 cordova.js 是phonegap开发必备插件JS包
二维玛扫描phonegap插件,包括java代码,js代码,html代码
phonegap扫描二位码插件,顺便给大家推荐phonegap扫描二维码的教程http://blog.csdn.net/u014646984/article/details/25655725,这篇博客写得比较详细,按照步骤可以搭建出扫描二维码的android程序