Android Sipdroid 语音通话项目简单使用
2016-08-04 20:53
344 查看
Sipdroid 项目类、结构的介绍可以参考下面博客:
http://blog.csdn.net/harvey2008/article/details/8484970
具体的文档介绍百度百科有,可以查阅,这里不贴链接了。
使用:
sipdroid 账号设置,开启注册
在onCreate 中进行初始化
最后在onDestory 注销注册
一般到这里就可以使用sipdroid自带的功能,当然,需要将sipdroid包中的配置文件相对路径全部替换为绝对路径
如:
应改为
库自带的通话界面相对简陋(call_card.xml 通话界面显示,incall.xml )
修改直接进入 InCallScreen 中onCreate 设置布局,部分组件在CallCard使用,故CallCard.calss 也需要修改,主要是界面数据更新。
最直接的一行代码是mCallCard.mElapsedTime = mElapsedTime; 更新通话的时间。
InCallScreen 和 CallCard 交互主要在 mCallCard.displayMainCallStatus(ccPhone, Receiver.ccCall); 这行代码
换句话说,如果要更换通话界面显示,可以直接在InCallScreen 里进行修改,删除initInCallScreen( ) 中的界面,替换为自己的界面,CallCard 里保留具体功能,将 ui 界面通话时间(mElapsedTime )和通话状态(upperTitle)和CallCard 关联进行数据更新,其他ui 控件可以和CallCard 分离,具体实现如挂断电话、静音、外放、录音等功能在InCallScreen中实现,而CallCard 保留通话状态更新。
CallCard
通话状态更新实现:
public void displayMainCallStatus(Phone phone, Call call)
InCallScreen 具体功能
录音功能:
sipdroid 没有提供通话中语音录音功能,也许你想使用自带的麦克风收音,很遗憾,即使成功,也只有自己的声音,而对方的语音是不能被录到,而且麦克风是不能启动成功,为什么?因为通话中,麦克风已经被Sipdroid 占用,你是不能拿到控制权,所以,只能通过修改Sipdroid 中的语音数据传输代码来实现我们的目的。
事实上,Sipdroid有录音功能,但是必须在通话前确定是否录音,因此查看 org.sipdroid.media 包中可以找到我们想要的。
先判断录音有没有被勾选,有就new CallRecorder通话记录,没有的话,call_recorder 就是 null
那么,在数据发送器和数据接收器中必定有判断 CallRecorder 是否为空,不为空的时候再进行数据的保存,
org.sipdroid.media.RtpStreamReceiver 中:
run 方法里面有:
org.sipdroid.media.RtpStreamSender 中
run 方法中有:
所以在JAudioLauncher提供一个方法获取JAudioLauncher单例,再拿到RtpStreamReceiver和RtpStreamSender实例,在RtpStreamReceiver和RtpStreamSender类中增加方法能够对 call_recorder 进行赋值,就可以取得录音文件。
JAudioLauncher 中增加,如果处于非通话状态或者通话结束,发送器和接收器有可能为空,需在外面增加为空判断
在 RtpStreamReceiver 和 RtpStreamSender 中增加:
这样可以通过下面调用实现录音:
取消录音:
录音文件默认存放在:/sdcard/Sipdroid_Recordings/
你也可以在 CallRecorder 中实现自己的路径存放
语音界面修改到这里也就结束了,其他再说吧。
http://blog.csdn.net/harvey2008/article/details/8484970
具体的文档介绍百度百科有,可以查阅,这里不贴链接了。
使用:
sipdroid 账号设置,开启注册
在onCreate 中进行初始化
Receiver.mContext = this; Sipdroid.on(this, true); //账号信息设置,具体的账号信息自己修改 PreferenceManager.getDefaultSharedPreferences(Receiver.mContext).edit(). putString(Settings.PREF_USERNAME, "用户名") .putString(Settings.PREF_PASSWORD, "密码") .putString(Settings.PREF_SERVER, "服务器地址") .putString(Settings.PREF_DOMAIN, "") .putString(Settings.PREF_PORT, "服务器端口") .putString(Settings.PREF_PROTOCOL, "UDP") .putBoolean(Settings.PREF_CALLBACK, true) .putString(Settings.PREF_POSURL, "") .putBoolean(Settings.PREF_ON,true) .putBoolean(Settings.PREF_3G, true) .putBoolean(Settings.PREF_WLAN,true) .putBoolean(Settings.PREF_EDGE,true) .putString(Settings.PREF_FROMUSER, "") .commit(); //注册账号 Receiver.engine(this).register(); Receiver.engine(this).halt(); Receiver.engine(this).StartEngine();
最后在onDestory 注销注册
Editor edit = PreferenceManager.getDefaultSharedPreferences(this).edit().putBoolean(Settings.PREF_ON, false); edit.commit(); Sipdroid.on(MainView.this, false); Receiver.pos(true); eceiver.engine(MainView.this).halt(); Receiver.mSipdroidEngine = null; Receiver.reRegister(0); stopService(new Intent(MainView.this,RegisterService.class));
一般到这里就可以使用sipdroid自带的功能,当然,需要将sipdroid包中的配置文件相对路径全部替换为绝对路径
如:
<activity android:name=".ui.Sipdroid" />
应改为
<activity android:name="org.sipdroid.sipua.ui.Sipdroid" />
库自带的通话界面相对简陋(call_card.xml 通话界面显示,incall.xml )
修改直接进入 InCallScreen 中onCreate 设置布局,部分组件在CallCard使用,故CallCard.calss 也需要修改,主要是界面数据更新。
最直接的一行代码是mCallCard.mElapsedTime = mElapsedTime; 更新通话的时间。
//初始化通话界面显示 public void initInCallScreen() { //拨号盘 mInCallPanel =(ViewGroup)findViewById(R.id.inCallPanel); //通话界面Layout mMainFrame = (ViewGroup)findViewById(R.id.mainFrame); //通话界面 CallCard View callCardLayout = getLayoutInflater().inflate( R.layout.call_card_popup,mInCallPanel); mCallCard = (CallCard)callCardLayout.findViewById(R.id.callCard); mCallCard.reset(); //通话布局中的滑动控制 mSlidingCardManager = new SlidingCardManager(); mSlidingCardManager.init(ccPhone, this, mMainFrame); SlidingCardManager.WindowAttachNotifierView wanv =new SlidingCardManager.WindowAttachNotifierView(this); wanv.setSlidingCardManager(mSlidingCardManager); wanv.setVisibility(View.GONE); RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(0, 0); mMainFrame.addView(wanv, lp); mStats = (TextView) findViewById(R.id.stats); mCodec = (TextView) findViewById(R.id.codec); mDialerDrawer = (SlidingDrawer)findViewById(R.id.dialer_container); mCallCard.displayOnHoldCallStatus(ccPhone,null); mCallCard.displayOngoingCallStatus(ccPhone,null); if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE){ mCallCard.updateForLandscapeMode(); } // Have the WindowManager filter out touch events that are "too fat". getWindow().addFlags(WindowManager.LayoutParams.FLAG_IGNORE_CHEEK_PRESSES); //拨号盘按键、声音 mDigits = (EditText) findViewById(R.id.digits); mDisplayMap.put(R.id.one, '1'); mDisplayMap.put(R.id.two, '2'); mDisplayMap.put(R.id.three, '3'); mDisplayMap.put(R.id.four, '4'); mDisplayMap.put(R.id.five, '5'); mDisplayMap.put(R.id.six, '6'); mDisplayMap.put(R.id.seven, '7'); mDisplayMap.put(R.id.eight, '8'); mDisplayMap.put(R.id.nine, '9'); mDisplayMap.put(R.id.zero, '0'); mDisplayMap.put(R.id.pound, '#'); mDisplayMap.put(R.id.star, '*'); mToneMap.put('1', ToneGenerator.TONE_DTMF_1); mToneMap.put('2', ToneGenerator.TONE_DTMF_2); mToneMap.put('3', ToneGenerator.TONE_DTMF_3); mToneMap.put('4', ToneGenerator.TONE_DTMF_4); mToneMap.put('5', ToneGenerator.TONE_DTMF_5); mToneMap.put('6', ToneGenerator.TONE_DTMF_6); mToneMap.put('7', ToneGenerator.TONE_DTMF_7); mToneMap.put('8', ToneGenerator.TONE_DTMF_8); mToneMap.put('9', ToneGenerator.TONE_DTMF_9); mToneMap.put('0', ToneGenerator.TONE_DTMF_0); mToneMap.put('#', ToneGenerator.TONE_DTMF_P); mToneMap.put('*', ToneGenerator.TONE_DTMF_S); View button; for (int viewId : mDisplayMap.keySet()) { button = findViewById(viewId); button.setOnClickListener(this); } }
InCallScreen 和 CallCard 交互主要在 mCallCard.displayMainCallStatus(ccPhone, Receiver.ccCall); 这行代码
换句话说,如果要更换通话界面显示,可以直接在InCallScreen 里进行修改,删除initInCallScreen( ) 中的界面,替换为自己的界面,CallCard 里保留具体功能,将 ui 界面通话时间(mElapsedTime )和通话状态(upperTitle)和CallCard 关联进行数据更新,其他ui 控件可以和CallCard 分离,具体实现如挂断电话、静音、外放、录音等功能在InCallScreen中实现,而CallCard 保留通话状态更新。
CallCard
通话状态更新实现:
public void displayMainCallStatus(Phone phone, Call call)
InCallScreen 具体功能
主动结束通话: public void reject() { if (Receiver.ccCall != null) { Receiver.stopRingtone(); Receiver.ccCall.setState(Call.State.DISCONNECTED); mCallCard.displayMainCallStatus(ccPhone, Receiver.ccCall); } (new Thread() { public void run() { Receiver.engine(mContext).rejectcall(); } }).start(); } 开启外放: Receiver.engine(InCallScreen.this).speaker(RtpStreamReceiver.speakermode == AudioManager.MODE_NORMAL ? AudioManager.MODE_IN_CALL : AudioManager.MODE_NORMAL); 静音: 获取音频管理器,设置麦克风静音 audioManager.setMicrophoneMute(true);
录音功能:
sipdroid 没有提供通话中语音录音功能,也许你想使用自带的麦克风收音,很遗憾,即使成功,也只有自己的声音,而对方的语音是不能被录到,而且麦克风是不能启动成功,为什么?因为通话中,麦克风已经被Sipdroid 占用,你是不能拿到控制权,所以,只能通过修改Sipdroid 中的语音数据传输代码来实现我们的目的。
事实上,Sipdroid有录音功能,但是必须在通话前确定是否录音,因此查看 org.sipdroid.media 包中可以找到我们想要的。
org.sipdroid.media.JAudioLauncher 实现多媒体数据的控制器,其中有这么一段构造代码
/** Costructs the audio launcher */ public JAudioLauncher(int local_port, String remote_addr, int remote_port, int direction, String audiofile_in,String audiofile_out, int sample_rate, int sample_size, int frame_size, Log logger,Codecs.Map payload_type, int dtmf_pt){ jLauncher = this; log=logger; frame_rate=sample_rate/frame_size; useDTMF = (dtmf_pt != 0); try { CallRecorder call_recorder = null; **if (PreferenceManager.getDefaultSharedPreferences(Receiver.mContext).getBoolean(org.sipdroid.sipua.ui.Settings.PREF_CALLRECORD, org.sipdroid.sipua.ui.Settings.DEFAULT_CALLRECORD))** **call_recorder** = new CallRecorder(null,payload_type.codec.samp_rate()); // Autogenerate filename from date. socket=new SipdroidSocket(local_port); dir=direction; // sender if (dir>=0) { printLog("new audio sender to "+remote_addr+":"+remote_port,LogLevel.MEDIUM); //audio_input=new AudioInput(); sender=new RtpStreamSender(true,payload_type,frame_rate,frame_size,socket,remote_addr,remote_port,call_recorder); sender.setSyncAdj(2); sender.setDTMFpayloadType(dtmf_pt); } // receiver if (dir<=0) { printLog("new audio receiver on "+local_port,LogLevel.MEDIUM); receiver=new RtpStreamReceiver(socket,payload_type,call_recorder); } } catch (Exception e) { printException(e,LogLevel.HIGH); } }
先判断录音有没有被勾选,有就new CallRecorder通话记录,没有的话,call_recorder 就是 null
那么,在数据发送器和数据接收器中必定有判断 CallRecorder 是否为空,不为空的时候再进行数据的保存,
org.sipdroid.media.RtpStreamReceiver 中:
run 方法里面有:
// Call recording: Save incoming. // Data is in buffer lin, from 0 to len. if (call_recorder != null) call_recorder.writeIncoming(lin, 0, len);
org.sipdroid.media.RtpStreamSender 中
run 方法中有:
// Call recording: Save the frame to the CallRecorder. if (call_recorder != null) call_recorder.writeOutgoing(lin, pos, num);
所以在JAudioLauncher提供一个方法获取JAudioLauncher单例,再拿到RtpStreamReceiver和RtpStreamSender实例,在RtpStreamReceiver和RtpStreamSender类中增加方法能够对 call_recorder 进行赋值,就可以取得录音文件。
JAudioLauncher 中增加,如果处于非通话状态或者通话结束,发送器和接收器有可能为空,需在外面增加为空判断
/** retrun JAudioLauncher if exit or null*/ private static JAudioLauncher jLauncher = null; public static JAudioLauncher getInstance(){ return jLauncher; } /** return RtpStreamReceiver instance or null*/ public RtpStreamReceiver getRtpStreamReceiver(){ return receiver; } /** return RtpStreamSender instance or null*/ public RtpStreamSender getRtpStreamSender(){ return sender; }
在 RtpStreamReceiver 和 RtpStreamSender 中增加:
/** dynamic change CallRecorder */ public void setCallRecorder(CallRecorder rec){ this.call_recorder = rec; }
这样可以通过下面调用实现录音:
callRecorder = new CallRecorder(System.currentTimeMillis() + "", 8000);// sample_rate JAudioLauncher jal = JAudioLauncher.getInstance(); if (jal != null) { jal.getRtpStreamReceiver().setCallRecorder(callRecorder); jal.getRtpStreamSender().setCallRecorder(callRecorder); }
取消录音:
if (callRecorder != null) { callRecorder.stopIncoming(); callRecorder.stopOutgoing(); callRecorder=null; } JAudioLauncher jal = JAudioLauncher.getInstance(); if (jal != null) { jal.getRtpStreamReceiver().setCallRecorder(null); jal.getRtpStreamSender().setCallRecorder(null); }
录音文件默认存放在:/sdcard/Sipdroid_Recordings/
你也可以在 CallRecorder 中实现自己的路径存放
String path = "";//your file path public CallRecorder(String filename,int sample_rate) { if (filename == null) { Time t = new Time(); t.setToNow(); filename = t.format2445(); // Create filename from current date. } // Make sure directory exists. File dir = new File(path);//"/sdcard/Sipdroid_Recordings/"); dir.mkdirs(); // If this fails, all of the other calls just silently return immediately. callWav = new WavWriter( //"/sdcard/Sipdroid_Recordings/" path+ filename + ".wav",sample_rate); }
语音界面修改到这里也就结束了,其他再说吧。
相关文章推荐
- Android开源项目pulltorefresh分析与简单使用
- Google Zxing开源项目的Android集成与简单使用
- Android中的TextToSpeech 将文本转换成语音的简单使用。
- Android项目之WebView的简单使用(本文来自http://blog.csdn.net/qq_29269233)
- Android项目使用 protobuf和grpc简单例子
- Android开源项目pulltorefresh分析与简单使用
- android滑动删除的一个开源项目SwipeDelMenuLayout的简单使用
- Android使用OpenCV和FFMpeg的简单方法-开源项目javacv的使用
- SVG-Android开源库——项目简单接入与使用
- Android 科大讯飞语音交互API简单使用
- Android手机间语音通话使用webrtc消除回音
- Android 小项目之--使用【AudioManager】类控制音量
- [使用心得]maven2之m2eclipse使用手册之六使用Maven2插件创建一个简单的SSH2项目之jetty篇(二)
- 地图入门(一):Android上使用Google Maps加标注的最最简单的例子
- [使用心得]maven2之m2eclipse使用手册之六使用Maven2插件创建一个简单的SSH2项目之tomcat篇
- Android 小项目之--使用【AudioManager】类控制音量 推荐
- [使用心得]maven2之m2eclipse使用手册之六使用Maven2插件创建一个简单的SSH2项目之jetty篇(三)
- Quartz 最简单使用,没有用到配置文件,不适用于项目
- Android中LocationManager的简单使用,获取当前位置
- Android中LocationManager的简单使用,获取当前位置[转