2-4 通话+信息功能技术_第1页
2-4 通话+信息功能技术_第2页
2-4 通话+信息功能技术_第3页
2-4 通话+信息功能技术_第4页
2-4 通话+信息功能技术_第5页
已阅读5页,还剩13页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

/目录1 根本要求 12 打电话流程 12.1 1OutgoingCallBroadcaster.java 22.2 2OutgoingCallReceiver.java 22.3 3InCallScreen.java——负责通话的那一个界面 22.3.1 3.1)onCreate(第一次) 22.3.2 3.2)onNewIntent(非第一次)。 32.3.3 3.3)onResume 32.4 4Profiler.java——该类对通话各个时间点进行记录。 32.5 5PhoneUtils.java——负责Phone对象的生成 32.5.1 5.1)placeCall(Phonephone,Stringnumber,UricontactRef) 42.5.2 5.2)placeCallVia(Contextcontext,Phonephone,Stringnumber,UricontactRef,UrigatewayUri) 42.6 6PhoneApp.java——负责Phone对象顶层应用的生成 42.7 7CallNotifier.java——监听Phone状态改变和telephony层事件,触发UI行为 43 电话局部 53.1 判断电话接通状态 63.2 删除通话记录 64 短信局部 84.1 发送短信 84.2 发送彩信 84.3 删除短信 84.4 监听短信收发 104.4.1 利用播送 104.4.2 利用数据库 114.5 收到短信不顶栏通知 124.6 获取短信内容 12根本要求要求能够向指定的号码发起呼叫;能够监视呼入事件,并得到呼入的号码;尝试对呼入事件进行处理(显示给用户或者直接拒绝);通话记录的获取以及删除;上述技术点都涉及到应用程序平安授权问题,研究Android在保证应用程序平安上采用的方法。打电话流程1OutgoingCallBroadcaster.java点击拨号盘拨打按钮后,进入通话的Phone包。此时首先进入的函数OutgoingCallBroadcaster.java,该类是一个Activity。由activity的生命周期可知,第一次进入时应调用onCreate()函数。(在该类中也只实现了这个函数。)解析一下这个函数:1.1)首先获取Intent对象,获取拨出的号码。1.2)接着判断号码是否为紧急号码,如果是紧急号码,将callNow变量赋值为true,启动InCallScreen,并发送播送。而在receiver里面判断callNow为ture就直接finish,而不再重复启动InCallScreen;如果不是紧急号码,将callNow变量赋值为false,发送播送“Intent.ACTION_NEW_OUTGOING_CALL〞。2OutgoingCallReceiver.java播送发送后OutgoingCallReceiver将会收到该息。该类是一个内部类,在类OutgoingCallBroadcaster里面,作用是接收OutgoingCallBroadcaster发送的播送,判断是否已经启动InCallScreen。没有启动的话就进行一些初始化,如:对OTA进行初始化。接收到播送之后,从Intent里面取出电话号码及其URi。然后,设置Intent为ACTION_CALL,并带上号码和uri。启动InCallScreen。关闭该Activity。OTA:Over-the-AirTechnology空中下载技术,是通过移动通信(GSM或CDMA)的空中接口对SIM卡数据及应用进行远程管理的技术。空中接口可以采用、CDMA1X及短消息技术。OTA技术的应用,使得移动通信不仅可以提供语音和数据效劳,而且还能提供新业务下载。GSM:GlobalSystemforMobileCommunications,中文为全球移动通讯系统,俗称"全球通"。CDMA:CodeDivisionMultipleAccess,又称码分多址,是在无线通讯上使用的技术,CDMA允许所有的使用者同时使用全部频带(1.2288Mhz),并且把其他使用者发出的讯号视为杂讯,完全不必考虑到讯号碰撞(collision)的问题。CDMA的优点包括:CDMA中所提供的语音编码技术,其通话品质比目前的GSM好,而且可以把用户对话时周围环境的噪音降低,使通话更为清晰。3InCallScreen.java——负责通话的那一个界面该类extends了Acitivity,并且implements了OnClickListener,OnTouchListener和OnQueryCompleteListener。该类主要是负责通话的那一个界面,并且还负责菜单项各种按键事件和触摸时间的处理。同时本类还复写的finish()方法,所以一般不会被finish掉,调用这个方法时它又把自己放回栈中。InCallScreen可以接收这个Intent并启动。3.1)onCreate(第一次)3.1.1)callScreenOnCreate获得通话界面被创立的时间。3.1.2)PhoneApp唤醒后台的效劳程序。3.1.3)判断当前的通话状态(IDLE=没有通话行为,RINGING=正在通话或呼叫等待,OFFHOOK=Thephoneisoffhook.Atleastonecallexiststhatisdialing,activeorholdingandnocallsareringingorwaiting.),如果正在通话,不会出现键盘锁。接着设置mPhoneandmForegroundCall/mBackgroundCall/mRingingCall。3.1.4)getBluetoothHandsfree设置蓝牙耳机,如果存在蓝牙耳机,则安装该设备。3.1.5)initInCallScreen加载各种view组建。3.1.6)对通话的各种状态进行播送。(registerForPreciseCallStateChanged,registerForDisconnect,registerForMmiInitiateregisterForMmiComplete,registerForCallWaiting,registerForSuppServiceFailed,registerForCdmaOtaStatusChange)3.1.7)internalResolveIntent判断是否使用了OTA技术,通过该判断设置通话界面的样式。3.1.8)callScreenCreated记录通话界面创立完成后的时间3.2)onNewIntent(非第一次)。我们重新启动一个Intent时调用该函数。由于我们围绕唯一的一个InCallScreen实例来完成通过的这个过程,那么除了第一次被创立的InCallScreen,只要有来电或者去电,该程序就会发生。如果InCallScreen已经在前台,该程序也会发生。3.2.1)setIntent保存该Intent,以至于将来我们可以获得该intent。3.2.2)internalResolveIntent3.3)onResume进行一些初始化操作,如:获取一个PhoneApp对象,解开KeyguardNotification的statusBar给Disable。还内置了一个Handler可以回调处理一些事件,比方:PHONE_STATE_CHANGED,PHONE_DISCONNECT,EVENT_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当在前台是,保持一个dialersession。首先判断时候需要播放本地铃声,如果需要,则判断双音多频是否可用,如果可用,则创立一个声音播放器。3.3.6)isBluetoothAudioConnected做一个是否蓝牙连接的判断。3.3.7)如果是cdma通话,则初始化OTA状态,进而如果是采用了OTA,则设置InCallScreenMode为OTA通话模型。3.3.8)clearDisconnected在检查该通话状态之前,切断其他网络连接。3.3.9)syncWithPhoneState同步通话界面与Phone的当前状态。如果没有同步成功,则dismissAllDialogs();结束当前的所以通话,endInCallScreenSession();关闭通话界面的显示。3.3.10)updateWakeState设置基于当前Phone的唤醒状态和屏幕超时,以及通话界面的当前状态。3.3.11)enableTouchLock当onresume时“触摸锁“叠加是不可见的,尤其是这个检查可确保用户通话按MUNU来唤醒屏幕后将不会被锁。但如果拨号盘是翻开的,而又需要通话计时,则造就了“触摸锁“覆盖。4Pro——该类对通话各个时间点进行记录。该类对通话各个时间点进行记录。staticlongsTimeCallScreenRequested;//通话界面被请求的时间staticlongsTimeCallScreenOnCreate;//通话界面被创立的时间staticlongsTimeCallScreenCreated;//通话界面创立完成后的时间staticlongsTimeIncomingCallPanelRequested;//正在通话时,通话界面被请求的时间staticlongsTimeIncomingCallPanelOnCreate;//正在通话时,通话界面被创立的时间staticlongsTimeIncomingCallPanelCreated;//正在通话时,通话界面创立完成后的时间5PhoneUtils.java——负责Phone对象的生成负责Phone对象的生成,主要调用phone.getForegroundCall(),phone.getBackgroundCall(),phone.getRingingCall(),phone.dial()。5.1)placeCall(Phonephone,Stringnumber,UricontactRef)拨打传入的电话号码,该函数被InCallScreen中的placeCall调用。参数phone手机对象;参数number用户要拨打的号码;参数contactRef要么是“tel:〞,要么是“content://contacts〞,取决于通话初始化,该参数引发呼叫;返回CALL_STATUS_DIALED,CALL_STATUS_DIALED_MMI,或CALL_STATUS_FAILED。5.2)placeCallVia(Contextcontext,Phonephone,Stringnumber,UricontactRef,UrigatewayUri)使用第三方提供的网关拨打号码,该函数被InCallScreen中的placeCall调用。如果电话号码是紧急号码,GSMMMI码或者CDMA码则不能被呼叫。如果连接成立,这个方法发出一个同步调用阻止查询来电信息,使本地采用异步查询。参数phone手机对象;参数context执行CallerInfo查询;参数number用户要拨打的号码,如果号码不能建立连接,则仅被用于建立电话卡,并更新通话记录;参数contactRef要么是“tel:〞,要么是“content://contacts〞,该参数引发呼叫;参数gatewayUri用于设置连接的地址;返回CALL_STATUS_DIALED或CALL_STATUS_FAILED。6PhoneApp.java——负责Phone对象顶层应用的生成该类是一个普通的java类,主要负责Phone对象顶层应用的生成。这是一个虚拟的Phone对象,它从framework层取得一个Phone对象。该类继承自Application,同时能常驻内存,他和PhoneUtils一起处理电话操作。在oncreate方法里面进行各种全局的初始化:获取Phone对象NotificationMgr对象,PowerManager对象,SimCard对象等。同时内置的Handler可以回调处理各种事件,如:EVENT_SIM_ABSENT,EVENT_SIM_NETWORK_LOCKED,EVENT_UPDATE_INCALL_NOTIFICATION等。7CallNotifier.java——监听Phone状态改变和telephony层事件,触发UI行为监听Phone状态的改变和来自telephony层各种事件,并触发任何有关的UI行为(如开始的铃声和来电的用户界面,打在通话音,更新通知,写呼叫记录条目等)。7.1)在构造函数中,实现mPhone.registerForNewRingingConnection(this,PHONE_NEW_RINGING_CONNECTION,null);/*当有新来电或等待连接时Notifies。收到的讯息是:Message.obj将是一个AsyncResult,AsyncResult.userObj=obj,AsyncResult.result=aConnection。因为这个消息已经过时,所以通过检测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.objwillbeanAsyncResult,AsyncResult.userObj=obj,AsyncResult.result=aConnectionobjectthatisnolongerconnected.*/mPhone.registerForUnknownConnection(this,PHONE_UNKNOWN_CONNECTION_APPEARED,null);/*当以前未跟踪non-ringing/waiting连接时Notifies。这可能是由于一些其他实体(如SIM卡应用)发起呼叫。*/mPhone.registerForIncomingRing(this,PHONE_INCOMING_RING,null);/*当有来电话响铃时Notifies。收到的讯息是:Message.objwillbeanAsyncResult,AsyncResult.userObj=obj,AsyncResult.result=aConnection.*/另外如果是CDMA通讯类型,还执行:mPhone.registerForCdmaOtaStatusChange(this,EVENT_OTA_PROVISION_CHANGE,null);/*当CDMAOTA提供者位置改变时注册notification*/mPhone.registerForCallWaiting(this,PHONE_CDMA_CALL_WAITING,null);/*当CDMA呼叫等待时注册notification*/mPhone.registerForDisplayInfo(this,PHONE_STATE_DISPLAYINFO,null);/*为来自网络显示信息通知注册。Message.obj将包含一个AsyncResult。AsyncResult.result将是一个SuppServiceNotification实例。*/mPhone.registerForSignalInfo(this,PHONE_STATE_SIGNALINFO,null);/*为来自网络的信号信息通知注册。Message.obj将包含一个AsyncResult。AsyncResult.result将是一个SuppServiceNotification实例。*/mPhone.registerForInCallVoicePrivacyOn(this,PHONE_ENHANCED_VP_ON,null);/*当sInCallVoicePrivacy可用时注册notification*/mPhone.registerForInCallVoicePrivacyOff(this,PHONE_ENHANCED_VP_OFF,null);/*当sInCallVoicePrivacy不可用时注册notification*/mPhone.registerForCdmaFwdBurstDtmf(this,PHONE_CDMA_FWD_BURST_DTMF,null);/*为CDMAForwardBurstDTMF的事件通知设置处理程序*/mPhone.registerForCdmaFwdContDtmfStart(this,PHONE_CDMA_FWD_CONT_DTMF_START,null);/*为CDMAForwardBurstDTMF启动的事件通知设置处理程序*/mPhone.registerForCdmaFwdContDtmfStop(this,PHONE_CDMA_FWD_CONT_DTMF_STOP,null);/*为CDMAForwardBurstDTMF停止的事件通知设置处理程序*/如果是GSM类型,则执行:mPhone.registerForRingbackTone(this,PHONE_RINGBACK_TONE,null);/*当带外回铃音(专业术语CRBT:COLORRINGBACKTONE,回铃音定义:当别人打电话给您时,他(她)听到的声音叫做回铃音。回铃音是指拨打电话的呼叫方所听到的对方电话的声音,当拨通电话时听到通话音,通常是长音;而当对方占线时则听到忙音,声音短促,有时,忙音会变成人声语音提示。)时Notifies。收到的讯息是:Message.obj将是一个AsyncResult,AsyncResult.userObj=obj,AsyncResult.result=true表示开始播放回铃音;=false表示停止。*/mPhone.registerForResendIncallMute(this,PHONE_RESEND_MUTE,null);/*为复位上行静音状态成上行音频注册处理程序。*/7.2)整个类由函数handleMessage串起来。电话局部自动拨号,判断号码正确性与否,平安机制。拨打电话过程:一自动拨号是Intent.ACTION_CALL,另一种是Intent.ACTION_DIAl(只是到按键盘的界面,需要再手动拨打)以下为CALL的代码Xml代码

AndroidManifest.xml

<!--

添加拨出电话的权限

-->

<uses-permission

android:name="android.permission.CALL_PHONE">

Java代码

Intent

intent=new

Intent("ent.action.CALL",

Uri.parse("tel:"

+

inputStr));

startActivity(intent);

判断电话接通状态删除通话记录负责存放呼叫记录的内容提供者源码在

ContactsProvider

工程下:源码路径:

com\android\providers\contacts\CallLogProvider.java使用到的数据库在:

/data/data/viders.contacts/databases/contacts2.db

表名:calls

呼叫记录有三种类型:

来电:CallLog.Calls.INCOMING_TYPE

(常量值:1)

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

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

查看源码中的声明:

<providerandroid: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-permissionandroid:name="android.permission.READ_CONTACTS"/>

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

系统的通话记录,是通过

ContentProvider

来对外共享的5.Uri

CallLog.Calls.CONTENT_URI:

等价于:Uri.parse("content://call_log/calls");6.

查询出所有记录

ContentResolverresolver=getContentResolver();

resolver.query(CallLog.Calls.CONTENT_URI,null,null,newString[]{""},null);7.

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

resolver.query(CallLog.Calls.CONTENT_URI,null,"number=?",newString[]{""},null);8.

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

resolver.query(CallLog.Calls.CONTENT_URI,null,"number=?andtype=3",newString[]{""},null);8.

删除某联系人最近的一次来电/*

本代码因为在

Activity

中,所以可以直接调用

getContentResolver()。这个方法实际上是

Context

中定义的。

*/

ContentResolver

resolver

=

getContentResolver();

/*

这里涉及到内容提供者的知识,其实这里是直接在操作

Android

的数据库,十分痛苦

*/

Cursor

cursor

=

resolver.query(CallLog.Calls.CONTENT_URI,

new

String[]{"_id"},

"number=?

and

(type=1

or

type=3)",

new

String[]{""},

"_id

desc

limit

1");

if(cursor.moveToFirst())

{

int

id

=

cursor.getInt(0);

resolver.delete(CallLog.Calls.CONTENT_URI,

"_id=?",

new

String[]

{id

+

""});

}

短信局部Android设备接收到的SMS是以pdu形式的(protocoldescriptionunit)(计算机网络的概念)(APDUisa"protocoldiscriptionunit",whichistheindustryformatforanSMSmessage.becauseSMSMessagereads/writesthemyoushouldn'tneedtodisectthem.Alargemessagemightbebrokenintomany,whichiswhyitisanarrayofobjects.)android.telephony.gsm.SmsMessage这个类可以储存SMS的相关信息,我们也可以从接收到的pdu中创立新的SmsMessage实例SmsMessage的使用比较特殊,并不直接实例化,而是利用静态方法getDefault()获得smsmanager对象发送短信用户权限设置<uses-permissionandroid:name="android.permission.SEND_SMS"></uses-permission>发送局部 PendingIntentpi=PendingIntent.getActivity(this,0,newIntent(this,MainActivity.class),0); SmsManagersms=(SmsManager.getDefault()); sms.sendTextMessage(phoneno,null,context,pi,null);publicvoidsendTextMessage(StringdestinationAddress,StringscAddress,Stringtext,PendingIntentsentIntent,PendingIntentdeliveryIntent)destinationAddress:

收件人地址scAddress:

短信中心号码,空为默认中心号码sentIntent:当消息发出时,成功或者失败的信息报告通过PendingIntent来播送。如果该参数为空,则发信程序会被所有位置程序检查一遍,这样会导致发送时间延长。deliveryIntent:当消息发送到收件人时,该PendingIntent会被播送。pdu数据在状态报告的extendeddata(“pdu〞)中。抛出IllegalArgumentException

如果收件人或者信息为空。出错时考虑是不是text长度太长的问题!!吃过两次亏了。。。==发送彩信删除短信未尝试packagepega.android.socket2;importandroid.database.Cursor;import.Uri;importandroid.util.Log;publicclassDeleteMessage{privatePegaSocket2deleteMessage;privateintidelete;privateCursoreventCursor,remindersCursor;privateint[]column=newint[1];privateString[]threadid=newString[1];privateCursorquerymessage;DeleteMessage(PegaSocket2deleteMessage,intid){this.deleteMessage=deleteMessage;idelete=id;StringuriInbox="content://sms";String[]projection=newString[]{"thread_id"};UriuriSms=Uri.parse(uriInbox);Stringwhere="_id="+Integer.toString(idelete);querymessage=deleteMessage.getContentResolver().query(uriSms,projection,where,null,null);}privatevoidMoveToFirst(){querymessage.moveToFirst();}publicintDeleteShortMessage(){if(querymessage.getCount()!=0){MoveToFirst();threadid[0]="thread_id";column[0]=querymessage.getColumnIndex("thread_id");threadid[0]=querymessage.getString(column[0]);//deletemessageintnumber=deleteMessage.getContentResolver().delete(Uri.parse("content://sms/conversations/"+threadid[0]),"_id="+idelete,null);Log.e("delete_number",Integer.toString(number));if(number!=0)return1;elsereturn0;}else{Log.e("number","cann'tfinethemessage!");return0;}}}通过主键id来找到他对应的thread_id。然后进行删除就可以了2:监听短信收发两种方式利用播送缺点:查看BroadReceiversdkreference,可以了解到所有的BroadReceiver对短信的接收是无顺序的状态,即使是使用了Orderedbroadcasts对于同等优先级别的BroadReceiver,也会产生无顺序的行为。流程理解:用bundle从intent.getExtras中得到,再用object[]从bundle.get("pdus")得到,此时为pdu形式,接着用SmsMessage.createFromPdu((byte[])pdusObj[i])一位位的读到SmsMessage[]msg中(每个i表示的是一条短信,此时为smsmessage格式),接着再对每个msg[i].getMessageBody()得到短信的内容stringpublicclassreceiveextendsBroadcastReceiver{StringreceiveMsg="";publicvoidonReceive(Contextcontext,Intentintent){SmsMessage[]msg=null;if(intent.getAction().equals("vider.Telephony.SMS_RECEIVED")){Bundlebundle=intent.getExtras();if(bundle!=null){Object[]pdusObj=(Object[])bundle.get("pdus");//bundle中存储了信息,有传递的作用,既然有get..,前面一定有存入以这个字符串一个键值对的形式储存了values!把pdus理解为一种标识符!msg=newSmsMessage[pdusObj.length];for(inti=0;i<pdusObj.length;i++)msg[i]=SmsMessage.createFromPdu((byte[])pdusObj[i]);}for(inti=0;i<msg.length;i++){StringmsgTxt=msg[i].getMessageBody();

if(msgTxt.equals("Testing!")){Toast.makeText(context,"success!",Toast.LENGTH_LONG).show();return;}else{Toast.makeText(context,msgTxt,Toast.LENGTH_LONG).show();return;}}return;}}利用数据库//如下主要用于内部数据库改变,向外面的界面(Activity)做反应classSMSHandlerextendsHandler{

publicvoidhandleMessage(Messagemsg)

{

//Handlemessage

}}//对收到短消息后,做出的处理,这里直接删除,并没有反应到界面,所以上面的handleMessage是空的。classSMSObserverextendsContentObserver{

privateHandlem_handle=null;

publicSMSObserver(Handlehandle)

{

super(handle);

m_handle=handle;

}

publicvoidonChange(booleanbSelfChange)

{

super.onChange(bSelfChange);

//SendmessagetoActivity

Messagemsg=newMessage();

msg.obj="xxxxxxxxxx";

m_handle.sendMessage(msg);StringstrUriInbox="content://sms/inbox";UriuriSms=Uri.parse(strUriInbox);

//IfyouwanttoaccessallSMS,justreplacetheuristringto"content://sms/"Cursorc=mContext.getContentResolver().query(uriSms,null,null,null,null);//deleteallsmsherewheneverynewsmsoccures.while(c.moveToNext()){

//ReadthecontentsoftheSMS;

for(inti;i<c.getColumnCount();i++)

{

StringstrColumnName=c.getColumnName(i);

StringstrColumnValue=c.getString(i);

}

//DeletetheSMS

Stringpid=c.getString(1);

//Getthreadid;

Stringuri="content://sms/conversations/"+pid;

mContext.getContentResolver().delete(Uri.parse(uri),null,null);

}

}}//把根本类功能性地应用起来ContentResolvercontentResolver=getContentResolver();//Context环境下getContentResolver()Handlerhandler=newSMSHandler();ContentObserverm_SMSObserver=newSMSObserver(handler);contentResolver.registerContentObserver(Uri.parse("content://sms/inbox"),true,m_SMSObserver);//RegistertoobserveSMSinoutbox,wecanobserveSMSinotherlocationbychangingUristring,suchasinbox,sent,draft,outbox,etc.)//someAvailableUristring

forsms.REMEBER:mustrequestfollowingpermission1)ReadSMS

<uses-permssionandroid:name="android.permission.READ_SMS"/>2)Delete/Modify/SendSMS

<uses-permssionandroid:name="android.permission.WRITE_SMS"/>inAndroidManifest.xml

1.publicclassScreenTestextendsActivity{

2.

3.

classSmsContentextendsContentObserver{

4.

privateCursorcursor=null;

5.

publicSmsContent(Handlerhandler){

6.

super(handler);

7.

}

8.

9.

/**

10.

*@Description当短信表发送改变时,调用该方法

11.

*

需要两种权限

12.

*

android.permission.READ_SMS读取短信

13.

*

android.permission.WRITE_SMS写短信

14.

*@AuthorSnake

15.

*@Date2010-1-12

16.

*/

17.

@Override

18.

publicvoidonChange(booleanselfChange){

19.

//TODOAuto-generatedmethodstub

20.

super.onChange(selfChange);

21.

//读取收件箱中指定号码的短信

22.

cursor=managedQuery(Uri.parse("content://sms/inbox"),newString[]{"_id","address","read"},"address=?andread=?",newString[]{"12345678901","0"},"datedesc");

23.

24.

if(cursor!=null){

25.

ContentValuesvalues=newContentValues();

26.

values.put("read","1");

//修改短信为已读模式

27.

cursor.moveToFirst();

28.

while(cursor.isLast()){

29.

//更新当前未读短信状态为已读

30.

getContentResolver().update(Uri.parse("content://sms/inbox"),values,"_id=?",newString[]{""+cursor.getInt(0)});

31.

cursor.moveToNext();

32.

}

33.

}

34.

}

35.

}

36.

37.

/**Calledwhentheactivityisfirstcreated.*/

38.

@Override

39.

publicvoidonCreate(BundlesavedInstanceState){

40.

super.onCreate(savedInstanceState);

41.

setContentView(R.layout.main);

42.

SmsContentcontent=newSmsContent(newHandler());

43.

//注册短信变化监听

44.

this.getContentResolver().registerContentObserver(Uri.parse("content://sms/"),true,content);

}

}

收到短信不顶栏通知获取短信内容android的短信都保存在数据库中,通过操作数据库即可获得短信的信息用android数据库编程吗,直接调用provider很方便的。短信的是content://sms/彩信是content://mms/,收件箱是content://sms/inbox已发送是content://sms/sent发件箱是content://sms/outbox草稿箱是content://sms/draft短信——结构+数据库相关相关的协议

content://sms/inbox

收件箱content://sms/sent

已发送(大多数在这里)content://sms/draft

草稿content://sms/outbox

发件箱(是要发的)content://sms/failed

发送失败content://sms/queued

待发送列表在模拟器上Outbox没有查询到数据,在模拟器上找了老半天也没找到发件箱,很郁闷。

数据库中sms相关的字段如下:

_id

一个自增字段,从1开始thread_id

序号,同一发信人的id相同address

发件人手机号码person

联系人列表里的序号,陌生人为null

date

发件日期protocol

协议,分为:

0

SMS_RPOTO,

1

MMS_PROTO

read

是否阅读

0未读,

1已读

status

状态

-1接收,0

complete,

64

pending,

128

failed

type

ALL

=0;

INBOX

=1;

SENT

=2;

DRAFT

=3;

OUTBOX=4;

FAILED=5;

QUEUED=6;

body

短信内容service_center

短信效劳中心号码编号subject

短信的主题reply_path_present

TP-Reply-Pathlocked

_id=490thread_id=31address=1234567892person=null3date=004protocol=05read=06status=-17type=18reply_path_present=09subject=null10body=ertyyhrtsh11service_center=null12locked=013error_code=014seen=015检索数据方法

Uriuri=Uri.parse("content://sms/inbox");

Cursorcur=this.managedQuery(uri,null,null,null,null);

if(cur.moveToFirst()){

do{

for(intj=0;j<cur.getColumnCount();j++){

info="name:"+cur.getColumnName(j)+"="+cur.getString(j);

Log.i("====>",info);

}

}while(cur.moveToNext());

}managedQuery最终也要将参数转换为SQL语句向SQLite发送消息,因此参数跟SQL语句很类似,所以可以在查询字段中参加SQL函数,比方newString[]projection=newString[]{"count(*)ascount"}等等。

managedQuery中的参数依次为uri,

查询字段

查询字段数组,也可以将所有需要查询的字段放入一个字符内

比方newprojection[]{"_id","thread_id"}和newprojection[]{"_id,thread_id"}是一致的跟SQL一样,字段名不区分大小写

条件

不带Where的SQL条件字符,如果有参数则用?替代,比方"_id=?Andthread_id=?Ortype='1'"

条件中的参数

参数字符数组,跟上述的条件一一对应

排序

不带Orderby排序字符串,比方_iddesc,type

如果参数为null,SQL中查询字段为“*〞,相关的条件为空白getContentResolver()还可以用getContentResolver()获得一个ContentResolver,

getContentResolver().query()同样返回一个Cursor对象,参数跟managedQuery一致。

不过用ContentResolver对象去更新、删除和插入一条数据时报SecurityException。看来没有权限,在Manifest.xml中参加权限:<uses-permissionandroid:name="android.permission.WRITE_SMS"></uses-permission>

然后删除短信:this.getContentResolver().delete(Uri.parse("content://sms"),"_id=?",newString[]{"3"});

删除成功。Url中content://sms

替换成content://sms/

也成功,但是其它url时程序报错,比方content://sms/inboxsms支持的协议sURLMatcher.addURI("sms",null,SMS_ALL);sURLMatcher.addURI("sms","#",SMS_ALL_ID);sURLMatcher.addURI("sms","inbox",SMS_INBOX);sURLMatcher.addURI("sms","inbox/#",SMS_INBOX_ID);sURLMatcher.addURI("sms","sent",SMS_SENT);sURLMatcher.addURI("sms","sent/#",SMS_SENT_ID);sURLMatcher.addURI("sms","draft",SMS_DRAFT);sURLMatcher.addURI("sms","draft/#",SMS_DRAFT_ID);sURLMatcher.addURI("sms","outbox",SMS_OUTBOX);sURLMatcher.addURI("sms","outbox/#",SMS_OUTBOX_ID);sURLMatcher.addURI("sms","undelivered",SMS_UNDELIVERED);sURLMatcher.addURI("sms","failed",SMS_FAILED);sURLMatcher.addURI("sms","failed/#",SMS_FAILED_ID);sURLMatcher.addURI("sms","queued",SMS_QUEUED);sURLMatcher.addURI("sms","conversations",SMS_CONVERSATIONS);sURLMatcher.addURI("sms","conversations/*",SMS_CONVERSATIONS_ID);sURLMatcher.addURI("sms","raw",SMS_RAW_MESSAGE);sURLMatcher.addURI("sms","attachments",SMS_ATTACHMENT);sURLMatcher.addURI("sms","attachments/#",SMS_ATTACHMENT_ID);sURLMatcher.addURI("sms","threadID",SMS_NEW_THREAD_ID);sURLMatcher.addURI("sms","threadID/*",SMS_QUERY_THREAD_ID);sURLMatcher.addURI("sms","status/#",SMS_STATUS_ID);sURLMatcher.addURI("sms","sr_pending",SMS_STATUS_PENDING);sURLMatcher.addURI("sms","sim",SMS_ALL_SIM);sURLMatcher.addURI("sms","sim/#",SMS_SIM);其中,delete方法中支持的协议为:SMS_ALL

根据参数中的条件删除sms表数据SMS_ALL_ID

根据_id删除sms表数据SMS_CONVERSATIONS_ID

根据thread_id删除sms表数据,可以带其它条件SMS_RAW_MESSAGE

根据参数中的条件删除raw表SMS_STATUS_PENDING

根据参数中的条件删除sr_pending表SMS_SIM

从Sim卡上删除数据试一下SMS_CONVERSATIONS_ID:"content://sms/conversations/3

",删除thread_id="3",_id="5"的数据

在eclipse中的EmulatorControl中,以13800给模拟器发送三条数据,然后以13900发送一条

this.getContentResolver().delete(Uri.parse("content://sms/conversations/3"),"_id=?",newString[]{"5"});

成功删除一条数据。

在数据库中每个发送者的thread_id虽然一样,但不是固定的,如果把一个发送者的全部数据删除掉,

然后换一个新号码发送短信时,thread_id是以数据库中最大的id+1赋值的。

update支持的协议有很多:SMS_RAW_MESSAGE

SMS_ST

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论