phone

转载 2012年03月22日 00:27:23

1.1 要求能够向指定的号码发起呼叫;

1.2 能够监视呼入事件,并得到呼入的号码;

1.3 尝试对呼入事件进行处理(显示给用户或者直接拒绝);

1.4 通话记录的获取以及删除;

1.5 上述技术点都涉及到应用程序安全授权问题,研究Android在保证应用程序安全上采用的方法。

打电话流程

http://apps.hi.baidu.com/share/detail/30388064

1.1 1 OutgoingCallBroadcaster.java

点击拨号盘拨打按钮后,进入通话的Phone包。此时首先进入的函数OutgoingCallBroadcaster.java,该类是一个Activity

activity的生命周期可知,第一次进入时应调用onCreate()函数。(在该类中也只实现了这个函数。)解析一下这个函数:

1.1) 首先获取Intent对象,获取拨出的号码。

1.2) 接着判断号码是否为紧急号码,如果是紧急号码,将callNow变量赋值为true,启动InCallScreen,并发送广播。而在receiver里面判断callNowture就直接finish,而不再重复启动InCallScreen;如果不是紧急号码,将callNow变量赋值为false,发送广播Intent.ACTION_NEW_OUTGOING_CALL”。

1.2 2 OutgoingCallReceiver.java

广播发送后OutgoingCallReceiver将会收到该息。该类是一个内部类,在类OutgoingCallBroadcaster里面,作用是接收OutgoingCallBroadcaster发送的广播,判断是否已经启动InCallScreen。没有启动的话就进行一些初始化,如:对OTA进行初始化。接收到广播之后,从Intent里面取出电话号码及其URi。然后,设置IntentACTION_CALL,并带上号码和uri。启动InCallScreen。关闭该Activity

n OTA:Over-the-Air Technology空中下载技术,是通过移动通信(GSMCDMA)的空中接口对SIM卡数据及应用进行远程管理的技术。空中接口可以采用WAPGPRSCDMA1X及短消息技术。OTA技术的应用,使得移动通信不仅可以提供语音和数据服务,而且还能提供新业务下载。

n GSM:Global System for Mobile Communications,中文为全球移动通讯系统,俗称"全球通"

n CDMA:Code Division Multiple Access,又称码分多址,是在无线通讯上使用的技术,CDMA允许所有的使用者同时使用全部频带(1.2288Mhz),并且把其他使用者发出的讯号视为杂讯,完全不必考虑到讯号碰撞 (collision) 的问题。CDMA的优点包括:CDMA中所提供的语音编码技术,其通话品质比目前的GSM好,而且可以把用户对话时周围环境的噪音降低,使通话更为清晰。

1.3 3 InCallScreen.java——负责通话的那一个界面

该类extendsAcitivity,并且implementsOnClickListenerOnTouchListenerOnQueryCompleteListener。该类主要是负责通话的那一个界面,并且还负责菜单项各种按键事件和触摸时间的处理。同时本类还复写的finish()方法,所以一般不会被finish掉,调用这个方法时它又把自己放回栈中。InCallScreen可以接收这个Intent并启动。

1.3.1 3.1) onCreate(第一次)

3.1.1) callScreenOnCreate获得通话界面被创建的时间。

3.1.2) PhoneApp唤醒后台的服务程序。

3.1.3) 判断当前的通话状态(IDLE =没有通话行为,RINGING =正在通话或呼叫等待,OFFHOOK = The phone is off hook. At least one call exists that is dialing, active or holding and no calls are ringing or waiting.),如果正在通话,不会出现键盘锁。接着设置mPhone and mForegroundCall/mBackgroundCall/mRingingCall

3.1.4) getBluetoothHandsfree设置蓝牙耳机,如果存在蓝牙耳机,则安装该设备。

3.1.5) initInCallScreen加载各种view组建。

3.1.6) 对通话的各种状态进行广播。(registerForPreciseCallStateChangedregisterForDisconnectregisterForMmiInitiateregisterForMmiCompleteregisterForCallWaitingregisterForSuppServiceFailedregisterForCdmaOtaStatusChange)

3.1.7) internalResolveIntent判断是否使用了OTA技术,通过该判断设置通话界面的样式。

3.1.8) callScreenCreated记录通话界面创建完成后的时间

1.3.2 3.2) onNewIntent(非第一次)

我们重新启动一个Intent时调用该函数。由于我们围绕唯一的一个InCallScreen实例来完成通过的这个过程,那么除了第一次被创建的InCallScreen,只要有来电或者去电,该程序就会发生。如果InCallScreen已经在前台,该程序也会发生。

3.2.1) setIntent保存该Intent,以至于将来我们可以获得该intent

3.2.2) internalResolveIntent

1.3.3 3.3) onResume

进行一些初始化操作,

如:获取一个PhoneApp对象,解开Keyguard NotificationstatusBarDisable。还内置了一个Handler可以回调处理一些事件,比如:PHONE_STATE_CHANGEDPHONE_DISCONNECTEVENT_HEADSET_PLUG_STATE_CHANGED。同时有一个独立的BroadcastReceiver处理ACTION_HEADSET_PLUG,比如插入耳机等。

3.3.1) 首先对锁屏情况下的来电除了处理。

3.3.2) disableStatusBar当正在通话界面时,使得状态栏可用。

3.3.3) setIgnoreTouchUserActivity忽略通话过程中无意的触碰事件,使得这些无意的触碰不会阻止设备进入休眠。

3.3.4) registerReceiver监听广播

3.3.5) startDialerSession当在前台是,保持一个dialer session。首先判断时候需要播放本地铃声,如果需要,则判断双音多频是否可用,如果可用,则创建一个声音播放器。

3.3.6) isBluetoothAudioConnected做一个是否蓝牙连接的判断。

3.3.7) 如果是cdma通话,则初始化OTA状态,进而如果是采用了OTA,则设置InCallScreenModeOTA通话模型。

3.3.8) clearDisconnected在检查该通话状态之前,切断其他网络连接。

3.3.9) syncWithPhoneState同步通话界面与Phone的当前状态。如果没有同步成功,则dismissAllDialogs();结束当前的所以通话,endInCallScreenSession();关闭通话界面的显示。

3.3.10) updateWakeState设置基于当前Phone的唤醒状态和屏幕超时,以及通话界面的当前状态。

3.3.11) enableTouchLockonresume时“触摸锁“叠加是不可见的,尤其是这个检查可确保用户通话按MUNU来唤醒屏幕后将不会被锁。但如果拨号盘是打开的,而又需要通话计时,则造就了“触摸锁“覆盖。

1.4 4 Profiler.java——该类对通话各个时间点进行记录。

该类对通话各个时间点进行记录。

static long sTimeCallScreenRequested;//通话界面被请求的时间

static long sTimeCallScreenOnCreate;//通话界面被创建的时间

static long sTimeCallScreenCreated;//通话界面创建完成后的时间

static long sTimeIncomingCallPanelRequested;//正在通话时,通话界面被请求的时间

static long sTimeIncomingCallPanelOnCreate;//正在通话时,通话界面被创建的时间

static long sTimeIncomingCallPanelCreated;//正在通话时,通话界面创建完成后的时间

1.5 5 PhoneUtils.java——负责Phone对象的生成

负责Phone对象的生成,主要调用phone.getForegroundCall()phone.getBackgroundCall()phone.getRingingCall()phone.dial()

1.5.1 5.1) placeCall(Phone phone, String number, Uri contactRef)

拨打传入的电话号码,该函数被InCallScreen中的placeCall调用。

参数phone手机对象;参数number用户要拨打的号码;参数contactRef要么是“tel:”,要么是“content://contacts”,取决于通话初始化,该参数引发呼叫;返回CALL_STATUS_DIALEDCALL_STATUS_DIALED_MMI,或CALL_STATUS_FAILED

1.5.2 5.2) placeCallVia(Context context,Phone phone,String number,Uri contactRef,Uri gatewayUri)

使用第三方提供的网关拨打号码,该函数被InCallScreen中的placeCall调用。如果电话号码是紧急号码,GSM MMI码或者CDMA码则不能被呼叫。如果连接成立,这个方法发出一个同步调用阻止查询来电信息,使本地采用异步查询。

参数phone手机对象;参数context执行CallerInfo查询;参数number用户要拨打的号码,如果号码不能建立连接,则仅被用于建立电话卡,并更新通话记录;参数contactRef要么是“tel:”,要么是“content://contacts”,该参数引发呼叫;参数gatewayUri用于设置连接的地址;返回CALL_STATUS_DIALEDCALL_STATUS_FAILED

1.6 6 PhoneApp.java——负责Phone对象顶层应用的生成

该类是一个普通的java类,主要负责Phone对象顶层应用的生成。这是一个虚拟的Phone对象,它从framework层取得一个Phone对象。该类继承自Application,同时能常驻内存,他和PhoneUtils一起处理电话操作。在oncreate方法里面进行各种全局的初始化:获取Phone对象 NotificationMgr对象,PowerManager对象,SimCard对象等。同时内置的Handler可以回调处理各种事件,如:EVENT_SIM_ABSENTEVENT_SIM_NETWORK_LOCKEDEVENT_UPDATE_INCALL_NOTIFICATION等。

1.7 7 CallNotifier.java——监听Phone状态改变和telephony层事件,触发UI行为

监听Phone状态的改变和来自telephony层各种事件,并触发任何有关的UI行为(如开始的铃声和来电的用户界面,打在通话音,更新通知,写呼叫记录条目等)。

7.1) 在构造函数中,实现

mPhone.registerForNewRingingConnection(this, PHONE_NEW_RINGING_CONNECTION, null);/*当有新来电或等待连接时Notifies。收到的讯息是:Message.obj将是一个AsyncResultAsyncResult.userObj=objAsyncResult.result=a Connection。因为这个消息已经过时,所以通过检测Connection.isRinging()以确保连接有效。如果Connection.isRinging()true,那么Connection.getCall()==Phone.getRingingCall()*/

mPhone.registerForPreciseCallStateChanged(this, PHONE_STATE_CHANGED, null);/*为通话状态的改变注册notification。通过调用PreciseCallState以获取更准确的通话状态。*/

mPhone.registerForDisconnect(this, PHONE_DISCONNECT, null);/*当由于本地或远程电话挂断或者出现错误挂断通话时Notifies。收到的讯息是:Message.obj will be an AsyncResultAsyncResult.userObj = objAsyncResult.result = a Connection object that is no longer connected.*/

mPhone.registerForUnknownConnection(this, PHONE_UNKNOWN_CONNECTION_APPEARED, null);/*当以前未跟踪non-ringing/waiting连接时Notifies。这可能是由于一些其他实体(如SIM卡应用)发起呼叫。*/

mPhone.registerForIncomingRing(this, PHONE_INCOMING_RING, null);/*当有来电话响铃时Notifies。收到的讯息是:Message.obj will be an AsyncResultAsyncResult.userObj = objAsyncResult.result = a Connection.*/

另外如果是CDMA通讯类型,还执行:

mPhone.registerForCdmaOtaStatusChange(this, EVENT_OTA_PROVISION_CHANGE, null);/*CDMA OTA提供者位置改变时注册notification*/

mPhone.registerForCallWaiting(this, PHONE_CDMA_CALL_WAITING, null);/*CDMA呼叫等待时注册notification*/

mPhone.registerForDisplayInfo(this, PHONE_STATE_DISPLAYINFO, null);/*为来自网络显示信息通知注册。Message.obj将包含一个AsyncResultAsyncResult.result将是一个SuppServiceNotification实例。

*/

mPhone.registerForSignalInfo(this, PHONE_STATE_SIGNALINFO, null);/*为来自网络的信号信息通知注册。Message.obj将包含一个AsyncResultAsyncResult.result将是一个SuppServiceNotification实例。*/

mPhone.registerForInCallVoicePrivacyOn(this, PHONE_ENHANCED_VP_ON, null);/*sInCall VoicePrivacy可用时注册notification*/

mPhone.registerForInCallVoicePrivacyOff(this, PHONE_ENHANCED_VP_OFF, null);/*sInCall VoicePrivacy不可用时注册notification*/

mPhone.registerForCdmaFwdBurstDtmf(this, PHONE_CDMA_FWD_BURST_DTMF, null);/*为 CDMA Forward Burst DTMF的事件通知设置处理程序*/

mPhone.registerForCdmaFwdContDtmfStart(this, PHONE_CDMA_FWD_CONT_DTMF_START, null);/*为 CDMA Forward Burst DTMF启动的事件通知设置处理程序*/

mPhone.registerForCdmaFwdContDtmfStop(this, PHONE_CDMA_FWD_CONT_DTMF_STOP, null);/*为 CDMA Forward Burst DTMF停止的事件通知设置处理程序*/

如果是GSM类型,则执行:

mPhone.registerForRingbackTone(this, PHONE_RINGBACK_TONE, null);/*当带外回铃音(专业术语CRBTCOLOR RING BACK TONE,回铃音定义:当别人打电话给您时,()听到的声音叫做回铃音。回铃音是指拨打电话的呼叫方所听到的对方电话的声音,当拨通电话时听到通话音,通常是长音;而当对方占线时则听到忙音,声音短促,有时,忙音会变成人声语音提示。)时Notifies。收到的讯息是:Message.obj将是一个AsyncResultAsyncResult.userObj=objAsyncResult.result=true表示开始播放回铃音;=false表示停止。*/

mPhone.registerForResendIncallMute(this, PHONE_RESEND_MUTE, null);/*为复位上行静音状态成上行音频注册处理程序。*/

7.2) 整个类由函数handleMessage串起来。

电话部分

自动拨号,判断号码正确性与否,安全机制。

http://wenku.baidu.com/view/c63b69791711cc7931b71628.html

拨打电话过程:

一自动拨号是Intent.ACTION_CALL,另一种是Intent.ACTION_DIAl(只是到按键盘的界面,需要再手动拨打)

以下为CALL的代码

Xml代码  

1. AndroidManifest.xml  

2.   

3. <!-- 添加拨出电话的权限 -->   

4.         <uses-permission android:name="android.permission.CALL_PHONE">   

Java代码  

1. Intent intent=new Intent("android.intent.action.CALL",  

2.                            Uri.parse("tel:" + inputStr));  

3.                  startActivity(intent); 

1.1 判断电话接通状态

http://www.eoeandroid.com/thread-30383-1-1.html

1.2 删除通话记录

负责存放呼叫记录的内容提供者源码在 ContactsProvider 项目下:

源码路径:

       com\android\providers\contacts\CallLogProvider.java

使用到的数据库在:

       /data/data/com.android.providers.contacts/databases/contacts2.db

       表名:calls

      

 呼叫记录有三种类型:

       来电:CallLog.Calls.INCOMING_TYPE (常量值:1

       已拨:CallLog.Calls.OUTGOING_TYPE(常量值:2

       未接:CallLog.Calls.MISSED_TYPE(常量值:3

 查看源码中的声明:

              <provider android:name="CallLogProvider"

                   android:authorities="call_log"

                   android:syncable="false" android:multiprocess="false"

                   android:readPermission="android.permission.READ_CONTACTS"

                   android:writePermission="android.permission.WRITE_CONTACTS">

               </provider>

3.需要声明的权限

       <uses-permission android:name="android.permission.READ_CONTACTS" />

       <uses-permission android:name="android.permission.WRITE_CONTACTS" />

4. 系统的通话记录,是通过 ContentProvider 来对外共享的

5. Uri

       CallLog.Calls.CONTENT_URI : 等价于:Uri.parse("content://call_log/calls");

6. 查询出所有记录

       ContentResolver resolver = getContentResolver();

       resolver.query(CallLog.Calls.CONTENT_URI, null, null, new String[]{"15101689022"}, null);

7. 查询某一个联系人的所有记录(按电话号码)

       resolver.query(CallLog.Calls.CONTENT_URI, null, "number=?", new String[]{"15101689022"}, null);

8. 查询某一个联系人的所有未接电话记录(按电话号码)

       resolver.query(CallLog.Calls.CONTENT_URI, null, "number=? and type=3", new String[]{"15101689022"}, null);

8. 删除某联系人最近的一次来电

1. /* 本代码因为在 Activity 中,所以可以直接调用 getContentResolver()。这个方法实际上是 Context 中定义的。 */  

2. ContentResolver resolver = getContentResolver();  

3. /* 这里涉及到内容提供者的知识,其实这里是直接在操作 Android 的数据库,十分痛苦 */  

4. Cursor cursor = resolver.query(CallLog.Calls.CONTENT_URI, new String[]{"_id"}, "number=? and (type=1 or type=3)",  new String[]{"15101689022"},  "_id desc limit 1");  

5. if(cursor.moveToFirst()) {  

6.     int id = cursor.getInt(0);  

7.     resolver.delete(CallLog.Calls.CONTENT_URI, "_id=?"new String[] {id + ""});  

8. }  

 

U3D 调用打电话接口-phone call

  • 2017年10月31日 10:13
  • 96B
  • 下载

最简单的基于FFmpeg的移动端例子:Windows Phone HelloWorld

本文记录Windows Phone平台下基于FFmpeg的HelloWorld程序。该示例C语言的源代码来自于《最简单的基于FFMPEG的Helloworld程序》。相关的概念就不再重复记录了。 由于...

win8下不支持window phone SDK 的安装

Windows 8消费者预览版的发布让很多Windows Phone开发者尝试向Windows 8平台迁移,因此开发者对Windows 8支持一系列SDK工具的呼声也就日渐强烈,微软Windows 8...

BroadWorks SIP phone test plan

  • 2016年09月28日 10:29
  • 857KB
  • 下载

Windows phone开发初体验之(一)-基本概念的了解

(一)            Windows phone执行模型: 主旨:始终为最终用户提供快速响应的体验 特点:在任何给定时间内,Windows Phone 仅允许一个应用程序在前台运行。当应用...

Windows Phone 7 实战 (英文版)

  • 2016年09月13日 14:26
  • 16.84MB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:phone
举报原因:
原因补充:

(最多只允许输入30个字)