永发信息网

phonegap 什么插件能打电话

答案:1  悬赏:40  手机版
解决时间 2021-03-21 06:48
phonegap 什么插件能打电话
最佳答案
最近采用phonegap做一个APP,需要在应用内实现拨打电话,通话结束後能反馈通话相关状态,查看了一番phonegap官方文档,似乎没有跟电话相关的api,在互联网上也大概搜了一下,好像没找到相关的内容。其实html5是支持直接在网页上拨打电话的,只要加入如下html代码即可:
  [html] view plaincopy
  打电话移动客服
  发短信发短信

  但这中方式只能实现拨打电话和发送短信,不能反馈结果,比如我想在应用能实现拨打电话,通话结束後自动保存通话的电话号码、通话时间、时长等,默认的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
  

  在AndroidManifest.xml文件中增加权限
  [html] view plaincopy
  
  
  
  
我要举报
如以上问答信息为低俗、色情、不良、暴力、侵权、涉及违法等信息,可以点下面链接进行举报!
大家都在看
余额宝保障期限到期可以自动续保吗?
华美家园怎么去啊,有知道地址的么
有朋友知道弹性体TPE的密度是多少吗?
这条方程怎么解?
直接用英语怎么说
锐亿门业在哪里啊,我有事要去这个地方
手机的外置储存卡,为什么把东西放进去过一会
著名的伯纳乌体育场位于西班牙的哪座城市?
约束管理法学习后心得
剑灵武神塔10层怎么过 胡伟打法技巧
80 极刑绝之镰 属性这么叼,为什么没有人关注
摩托车驾驶证16岁可以考吗?
古风女生网游名字
中国移动(胜利营业厅)怎么去啊,有知道地址的
手机QQ群聊天怎么彻底删除聊天记录
推荐资讯
梦见自己能上天入海
令、氏字加部首有什么字?
燕山石化公司全称是什么?
滨州到苏州蠡,口家俱城多少公里?
云南省玉溪市元江县有哪些大件物品托运部
对联是我们中华民族独有的一种文学形式,请你
律师们赶紧帮忙看下
7厘米+9厘米=多少
春华我想知道这个在什么地方
为什么word打不开,而excel可以打开
我女儿今年三岁半,今晚,屁股里出来一条虫子
金苹果超市地址在什么地方,想过去办事
正方形一边上任一点到这个正方形两条对角线的
阴历怎么看 ?