當前位置:名人名言大全網 - 短信平臺 - phonegap 什麽插件能打電話

phonegap 什麽插件能打電話

最近采用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"/>