好贷网好贷款

CSipSimple程序之拨打电话

发布时间:2016-12-4 22:19:30 编辑:www.fx114.net 分享查询网我要评论
本篇文章主要介绍了"CSipSimple程序之拨打电话",主要涉及到CSipSimple程序之拨打电话方面的内容,对于CSipSimple程序之拨打电话感兴趣的同学可以参考一下。

         与前面的短信发送一样,这里我们不再重复讲解ViewPage和Fragments以及进程间通信的内容,具体可参考前面的短信发送部分的内容。          在这一部分,主要说明程序是如何从上层到调用本地的JNI库,实现SIP打电话功能的。这里我们主要以用户输入被打用户的SPI URI,即如图点击右下角的txt按钮,然后输入被打用户的URI([email protected]),[email protected]所示: 图26 被打用户的SPI URI          接下来从点击键盘的“去往”按钮开始,分析程序是如何一步步调用底层JNI库的。首先如图27,有个键盘监听器,当键盘监听器监听到按下的action为EditorInfo.IME_ACTION_GO,即为去往按钮时,调用placeCall函数。 private OnEditorActionListener keyboardActionListener = new OnEditorActionListener() { @Override public boolean onEditorAction(TextView tv, int action, KeyEvent arg2) { if (action == EditorInfo.IME_ACTION_GO) { //IME_ACTION_GO即键盘上的Go按钮, System.out.println("IME_ACTION_GO"); placeCall(); return true; } return false; } }; 图27 键盘监听事件触发          进入placeCall函数之后,如判断为SIP用户,则进行SipService方法调用,否则直接进行基本用户拨打。如图28程序所示: private void placeCallWithOption(Bundle b) { if (service == null) { return; } String toCall = ""; Long accountToUse = SipProfile.INVALID_ID; // Find account to use SipProfile acc = accountChooserButton.getSelectedAccount(); if (acc != null) { accountToUse = acc.id; } // Find number to dial if(isDigit) { toCall = PhoneNumberUtils.stripSeparators(digits.getText().toString()); }else { toCall = digits.getText().toString(); } if (TextUtils.isEmpty(toCall)) { return; } // Well we have now the fields, clear theses fields digits.getText().clear(); // -- MAKE THE CALL --// if (accountToUse >= 0) { // It is a SIP account, try to call service for that System.out.println("to check that if it's a SIP account"); try { //用的是SIP用户,所以调用该函数 service.makeCallWithOptions(toCall, accountToUse.intValue(), b); } catch (RemoteException e) { Log.e(THIS_FILE, "Service can't be called to make the call"); } } else if (accountToUse != SipProfile.INVALID_ID) { // It's an external account, find correct external account //即用的是SIP电话还是基本电话 System.out.println("to check that if it's a external account"); CallHandlerPlugin ch = new CallHandlerPlugin(getActivity()); ch.loadFrom(accountToUse, toCall, new OnLoadListener() { @Override public void onLoad(CallHandlerPlugin ch) { placePluginCall(ch); } }); } } 图28 DialFragment程序          上面的语句是进入if语句还是else if与下图29的选择有关。当点击红色矩形的按钮之后会弹出蓝色矩形内的图标,选择第一个表示用SIP账号拨打电话,选择第二个则表示用基本电话拨打。 图29 选择SIP账号还是基本电话账号                   这里只说明使用SIP电话拨打情况。从图28可看出,程序调用了SipService的makeCallWithOptions方法。进而进入SipService的makeCallWithOptions方法。如图30所示: @Override public void makeCallWithOptions(final String callee, final int accountId, final Bundle options) throws RemoteException { SipService.this.enforceCallingOrSelfPermission(SipManager.PERMISSION_USE_SIP, null); //We have to ensure service is properly started and not just binded SipService.this.startService(new Intent(SipService.this, SipService.class)); if(pjService == null) { System.out.println("In makeCallWithOptions(),the PjSipService is not started"); Log.e(THIS_FILE, "Can't place call if service not started"); // TODO - we should return a failing status here return; } if(!supportMultipleCalls) { // Check if there is no ongoing calls if so drop this request by alerting user SipCallSession activeCall = pjService.getActiveCallInProgress(); if(activeCall != null) { if(!CustomDistribution.forceNoMultipleCalls()) { notifyUserOfMessage(R.string.not_configured_multiple_calls); } return; } } getExecutor().execute(new SipRunnable() { @Override protected void doRun() throws SameThreadException { //打电话 pjService.makeCall(callee, accountId, options); } }); } 图30 SipService的打电话方法          这样,最终调用PJsipService的makeCall。如图31,红色字体即为最终调用了底层的JNI库函数。 /** * Make a call * * @param callee remote contact ot call If not well formated we try to add * domain name of the default account */ public int makeCall(String callee, int accountId, Bundle b) throws SameThreadException { if (!created) { return -1; } //Transform a string callee into a valid sip uri in the context of an account final ToCall toCall = sanitizeSipUri(callee, accountId); if (toCall != null) { pj_str_t uri = pjsua.pj_str_copy(toCall.getCallee()); // Nothing to do with this values byte[] userData = new byte[1]; int[] callId = new int[1]; pjsua_call_setting cs = new pjsua_call_setting(); pjsua_msg_data msgData = new pjsua_msg_data(); int pjsuaAccId = toCall.getPjsipAccountId(); // Call settings to add video pjsua.call_setting_default(cs); cs.setAud_cnt(1); cs.setVid_cnt(0); if(b != null && b.getBoolean(SipCallSession.OPT_CALL_VIDEO, false)) { cs.setVid_cnt(1); } cs.setFlag(0); // Msg data to add headers pjsua.msg_data_init(msgData); pjsua.csipsimple_init_acc_msg_data(pjsuaAccId, msgData); //判断是否打通 int status = pjsua.call_make_call(pjsuaAccId, uri, cs, userData, msgData, callId); System.out.println("Get the call status -->" + status); if(status == pjsuaConstants.PJ_SUCCESS) { dtmfToAutoSend.put(callId[0], toCall.getDtmf()); Log.d(THIS_FILE, "DTMF - Store for " + callId[0] + " - "+toCall.getDtmf()); } return status; } else { System.out.println("to call is null"); service.notifyUserOfMessage(service.getString(R.string.invalid_sip_uri) + " : " + callee); } return -1; } 图31 PjSip的makeCall方法          若使用电话视频也一样,从图31可看出,不管是否开启电话视频,只要使用PjSua设置的相关参数就可以了。如上面的解释语句:call settings to add video。其下面的那些语句就是设置加入vedio的。

上一篇:深入理解Java内存模型(二)——重排序
下一篇:关系数据库的特点

相关文章

相关评论