IMS SIP Android 软终端——电话答录机功能 实现纪要
实现电话答录机功能,主要想到了两个办法:
@Override public void startRingTone() { if(mRingtonePlayer == null){ try{ mRingtonePlayer = RingtoneManager.getRingtone(NgnApplication.getContext(), android.provider.Settings.System.DEFAULT_RINGTONE_URI); }catch(Exception e){ e.printStackTrace(); return; } } if(mRingtonePlayer != null){ synchronized(mRingtonePlayer){ mRingtonePlayer.play(); //Added by wangy 20140702 for AnswerPhone features: Thread timer_ansPhone_answer=new Thread(){ @Override public void run(){ try { Thread.sleep(1000*10); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } if(mRingtonePlayer.isPlaying()){//true if no one answer the phone, then start the answer phone. //Message to be sent to the handler,which handles the no_answer_event Message msg_no_answer_send=new Message(); msg_no_answer_send.what=0;//"Ready to send!" String msg_obj_reply=null;//Record Answer Phone Video File to be Transferred. msg_no_answer_send.obj=(Object)msg_obj_reply; //Handler which handles the no_answer_event Looper.prepare(); Handler ansPhone_handler_play_record=new Handler() { public void handleMessage(Message msg) {//send record file switch (msg.what) {//根据收到的消息的what类型处理 case 0: NgnSipService m_send_active_answer_phone_msg=new NgnSipService(); m_send_active_answer_phone_msg.send_active_answer_phone_msg(); Log.v("handler", "Handler===="+msg.arg2);//打印收到的消息 break; default: //super.handleMessage(msg);//这里最好对不需要或者不关心的消息抛给父类,避免丢失消息 break; } } }; ansPhone_handler_play_record.sendMessage(msg_no_answer_send); stopRingTone(); } } }; timer_ansPhone_answer.start(); } } }
这是主叫端和被叫端对铃声触发的处理。@Override public void startRingBackTone() { if (mRingbackPlayer == null) { try { mRingbackPlayer = new ToneGenerator(AudioManager.STREAM_VOICE_CALL, TONE_RELATIVE_VOLUME); } catch (RuntimeException e) { Log.w(TAG, "Exception caught while creating local tone generator: " + e); mRingbackPlayer = null; } } if(mRingbackPlayer != null){ synchronized(mRingbackPlayer){ mRingbackPlayer.startTone(ToneGenerator.TONE_SUP_RINGTONE); } } Thread timer_ansPhone_call=new Thread(){ @Override public void run(){ try { Thread.sleep(1000*10); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } if(mRingtonePlayer.isPlaying()){//true if no one answer the phone, then start the answer phone. //Message to be sent to the handler,which handles the no_answer_event Message msg_no_answer_rec=new Message(); msg_no_answer_rec.what=1;//"Ready to receive!" String msg_obj_rec=null; msg_no_answer_rec.obj=(Object)msg_obj_rec; //Handler which handles the no_answer_event Looper.prepare(); Handler ansPhone_handler=new Handler() { public void handleMessage(Message msg) {//receive remote party's record file,and play it. switch (msg.what) {//根据收到的消息的what类型处理 case 1: NgnSipService m_send_active_answer_phone_msg=new NgnSipService(); m_send_active_answer_phone_msg.rec_active_answer_phone_msg(); Log.v("handler", "Handler===="+msg.arg2);//打印收到的消息 break; default: //super.handleMessage(msg);//这里最好对不需要或者不关心的消息抛给父类,避免丢失消息 break; } } }; Looper.loop(); ansPhone_handler.sendMessage(msg_no_answer_rec); stopRingBackTone(); } } }; timer_ansPhone_call.start(); }
发送文件之后,由MRSP Session的callback进行处理,广播接收到文件的事件Event,通过Broadcast Receiver接收该广播并处理(即播放出来)。public void send_active_answer_phone_msg(){ String file_path=Recorder.getFilePath();//path of the record file. if(file_path==null) System.out.println("file not found!"); //final String textToSend = "***|||***"; final String remotePartyUri =NgnSipSession.getRemotePartyUri(); // remote party uri final NgnMsrpSession imSession = NgnMsrpSession.createOutgoingSession(this.getSipStack(), NgnMediaType.FileTransfer, remotePartyUri); if(!imSession.sendFile(file_path)){ Log.e(TAG,"Failed to send"); } else{ Log.d(TAG,"Message sent"); } // release session NgnMsrpSession.releaseSession(imSession); } public void rec_active_answer_phone_msg(){ //retrieve msrp session from broadcast receiver Answer_phone, and get the received file name&&path to play it. BroadcastReceiver ans_phone=new Answer_Phone(); //this.registerReceiver(ans_phone,new IntentFilter(NgnMsrpEventArgs.ACTION_MSRP_EVENT)); } }
大功告成。目前问题是,文件传输不成功,底部协议栈仍需处理。public class Answer_Phone extends BroadcastReceiver{ final String LOG_TAG = "AudioRecordTest"; @Override public void onReceive(Context context, Intent intent) { // TODO Auto-generated method stub String a=intent.getStringExtra("eargs"); Log.d(a,"eargs"); //how to retrieve session remains to be done.may be the args things. Bundle bundle=intent.getExtras(); Set<String> keys=bundle.keySet(); for(String key:keys){ Log.d("key",key); } Object[] objArray=(Object[])bundle.get("eargs");// key "eargs" contains 'session Id'and 'type' ,see NgnMsrpSession-->broadcastEvent line718 String [] sessionId_rec=new String [objArray.length];// to retrieve the segment(mainly sessionID, so that we can get transferred filename) in eargs, see NgnMsrpEventArgs, line43 long [] sessionId=new long [objArray.length]; for(int i=0;i<objArray.length;i++){ sessionId_rec[i]=(String)objArray[i]; sessionId[i]=NgnStringUtils.parseLong(sessionId_rec[i],0); NgnMsrpSession mSession=NgnMsrpSession.getSession(sessionId[i]); String mFileName=mSession.getFileName(); //to play the retrieved file MediaPlayer mPlayer = null; mPlayer = new MediaPlayer(); try { //设置要播放的文件 mPlayer.setDataSource(mFileName); mPlayer.prepare(); //播放之 mPlayer.start(); } catch (IOException e) { Log.e(LOG_TAG, "prepare() failed"); } } } }