短信技術(shù):
短信數(shù)據(jù)庫(kù)存在于/data/data/com.android.providers.telephoney目錄下樊卓;
相關(guān)的表:
sms:_id(信息id) thread_id(會(huì)話(huà)id) address(地址) body(內(nèi)容) date(日期) type(1為收件箱信息,2為發(fā)件箱信息奈应,3為草稿箱)
★常用相關(guān)的uri(沒(méi)有API捏肢,須手動(dòng)輸入以下uri)
content://sms
content://sms/inbox 用于插入
content://sms/sent 用于發(fā)送信息表
content://sms/draft 用于草稿表
content://sms/conversations 用于會(huì)話(huà)表
★相關(guān)的使用權(quán)限:
android.permission.READ_SMS
android.permission.WRITE_SMS
★使用content://sms/conversations 查詢(xún)會(huì)話(huà)時(shí)使用的列名(google官方使用):
groups.group_thread_id 該會(huì)話(huà)Id
groups.group_date 該會(huì)話(huà)最后一條信息時(shí)間
groups.msg_count 該會(huì)話(huà)信息總數(shù)
sms.address 該會(huì)話(huà)發(fā)送的地址
sms.body 該會(huì)話(huà)最后一條信息的內(nèi)容
▲發(fā)送短信:
SmsManager manager = SmsManager.getDefault();//獲取短信管理器實(shí)例伤疙;
manager.sendTextMessage(destinationAddress, scAddress, text,
sentIntent, deliveryIntent); //參數(shù)別為要發(fā)送的號(hào)碼唬渗;中心號(hào)碼钞螟,手機(jī)設(shè)置好了可置為null,
//text為要發(fā)送的文本;sentIntent為發(fā)送后要做的處理绸狐;deliveryIntent為送達(dá)后要做的處理卤恳。
▲其他方法:
ArrayList<String> parts = manager.divideMessage(content);
//若短信過(guò)長(zhǎng)累盗,自動(dòng)拆分成幾部分寒矿;拆分后可直接發(fā)送:
manager.sendMultipartTextMessage(number, null, parts, null, null);
但當(dāng)發(fā)送完成后需要手動(dòng)將發(fā)送的信息寫(xiě)入到數(shù)據(jù)庫(kù):故用遍歷逐條發(fā)送,成功發(fā)送后再發(fā)送一條廣播若债,在接收到廣播后插入到數(shù)據(jù)庫(kù)符相;
PendingIntent sentIntent = PendingIntent.getBroadcast(this, code,intent,
PendingIntent.FLAG_UPDATE_CURRENT);
★§注意://PendingInent的對(duì)象是在內(nèi)存中的對(duì)象池中獲取的蠢琳,第二個(gè)參數(shù)code即為每個(gè)對(duì)象的code標(biāo)記啊终;若設(shè)為不同,則可每次都從對(duì)象池中獲取一個(gè)新的實(shí)例傲须,但效率不高。一般設(shè)置最后一個(gè)參數(shù)falg泰讽,有四種不同的值例衍,一般采用PendingIntent.FLAG_UPDATE_CURRENT昔期,意思為每次從對(duì)象池中取出一個(gè)對(duì)象,但將對(duì)象的數(shù)據(jù)做更新佛玄。這種方法效率較高硼一,其他三種參數(shù)效率較低,適作他用梦抢。
○加載發(fā)送完成后的意圖:manager.sendTextMessage(number, null, text, sentIntent, null);
○在廣播接收器的onRecive(..)方法中:對(duì)短信是否成功發(fā)送作判斷般贼,可直接判斷結(jié)果碼:
if (RESULT_OK == code) {//將號(hào)碼和信息內(nèi)容、當(dāng)前時(shí)間寫(xiě)入到數(shù)據(jù)庫(kù)中奥吩,并清空輸入框}
★№[發(fā)送信息需要權(quán)限; android:name="android.permission.SEND_SMS”]
▲接收短信:
當(dāng)系統(tǒng)收到短信時(shí)會(huì)發(fā)送一個(gè)廣播:
android.provider.Telephony.SMS_RECEIVED;這是一個(gè)有序廣播哼蛆,可進(jìn)行攔截。
●PDU(協(xié)議數(shù)據(jù)單元)
☆[pdu:是指對(duì)等層次之間傳遞的數(shù)據(jù)單位圈驼;在分層網(wǎng)絡(luò)結(jié)構(gòu)中人芽,在傳輸系統(tǒng)的每一層都將建立協(xié)議數(shù)據(jù)單元]
在系統(tǒng)接收到信息時(shí),以pdu的協(xié)議保存信息數(shù)據(jù)绩脆;若收到廣播是接收信息的廣播萤厅,就取出該數(shù)據(jù),再生成短信即可靴迫;
▲創(chuàng)建一個(gè)接收器惕味,在onReceive(..)方法中判斷:
if ("android.provider.Telephony.SMS_RECEIVED".equals(intent.getaction())) {
Object[] pdus = (Object[]) intent.getExtras().get("pdus");//取出pdus數(shù)據(jù)字節(jié)數(shù)組
for (Object pdu : pdus) { //遍歷
SmsMessage sms=SmsMessage.createFromPdu((byte[]) pdu);//將字節(jié)數(shù)組生成為短信;
}
...
☆可用到的內(nèi)容:
sms.getOriginatingAddress(): 發(fā)送人的號(hào)碼
sms.getDisplayMessageBody(): 短信內(nèi)容文本
sms.getServiceCenterAddress(): 中心號(hào)碼
sms.getTimestampMillis(): 接收信息時(shí)的時(shí)間玉锌;
№★ 如果攔截到短信后名挥,不讓系統(tǒng)再收到此短信,就須注銷(xiāo)該廣播主守,并在注冊(cè)該廣播接收器時(shí)設(shè)置最高優(yōu)先級(jí)才可進(jìn)行攔截禀倔。
if (isOrderedBroadcast()) {
abortBroadcast();
}}
☆№[短信攔截可用于手機(jī)防盜,吸費(fèi)軟件]
◆Android間的進(jìn)程間通信,采用了Binder架構(gòu)参淫,
▲B(niǎo)inder架構(gòu)本身就是一個(gè)C/S架構(gòu)
→1救湖、在服務(wù)端創(chuàng)建Binder對(duì)象
→2、在客戶(hù)端獲取Binder的代理對(duì)象
→3涎才、然后就可以在客戶(hù)端通過(guò)BinderProxy對(duì)象像調(diào)用本地方法一樣去調(diào)用服務(wù)端的代碼鞋既。
★№[在onServiceConnected(..)方法中IBinder的對(duì)象若是在同一進(jìn)程中則是一個(gè)服務(wù)器Binder對(duì)象,若是不同的進(jìn)程則是在服務(wù)器的Binder代理]
★Service三種啟動(dòng)模式:
●Service的啟動(dòng)模式:startService(intent);
●Service的綁定模式
§1耍铜、創(chuàng)建Service的子類(lèi)MyService邑闺,在其onBind方法中返回一個(gè)binder對(duì)象;
△創(chuàng)建Binder對(duì)象:在MyService下創(chuàng)建一個(gè)內(nèi)部類(lèi)MyBinder extends Binder棕兼;則MyBinder即是一個(gè)Binder又可訪(fǎng)問(wèn)MyService下的方法陡舅;
☆№有兩種共享方法的方案:
◇a.在MyBinder創(chuàng)建與MyService中對(duì)應(yīng)的方法,并調(diào)用MyService中的方法,如:MyService.this.play();在客戶(hù)端通過(guò)獲取的binder調(diào)用這些方法來(lái)實(shí)現(xiàn)MyService中對(duì)應(yīng)的方法伴挚。
◇b.在MyBinder中提供一個(gè)方法直接返回MyService對(duì)象的引用靶衍,如:
public MyService getService() {
return MyService.this;
}
在客戶(hù)端就可直接獲取到該MyService的引用臂寝,可直接調(diào)用MyServie下所有方法。
★[但此方案僅適用于同一個(gè)進(jìn)程內(nèi)摊灭,因?yàn)樵诹硗庖粋€(gè)進(jìn)程中可能沒(méi)有MyService,就不能獲取到MyService的引用]
§2咆贬、在客戶(hù)端(Activity)中綁定到該Service,并獲取Binder帚呼;
№a掏缎、創(chuàng)建一個(gè)ServiceConnection;
private ServiceConnection conn = new ServiceConnection() {
public void onServiceDisconnected(ComponentName name) { // 該方法為與Service連接失敗時(shí)的方法 }
public void onServiceConnected(ComponentName name, IBinder binder) {
// 該方法為與Service連接成功時(shí)的方法
MainActivity.this.binder = (MyBinder) binder; //構(gòu)建該binder
service = MainActivity.this.binder.getService();
}
};
№b、與Service進(jìn)行綁定:
Intent intent = new Intent(this, MyService.class);
bindService(intent, conn, BIND_AUTO_CREATE);
№c煤杀、Service的銷(xiāo)毀條件:
started為false且clientCount為0眷蜈;故當(dāng)一個(gè)客戶(hù)端(Activity)銷(xiāo)毀時(shí)應(yīng)當(dāng)解除綁定,否則會(huì)造成內(nèi)存泄露沈自;即在onDetroy(..)方法中執(zhí)行:unbindService(conn);
started為false且clientCount為0酌儒;故當(dāng)一個(gè)客戶(hù)端(Activity)銷(xiāo)毀時(shí)應(yīng)當(dāng)解除綁定,否則會(huì)造成內(nèi)存泄露枯途;即在onDetroy(..)方法中執(zhí)行:unbindService(conn);
★ Service綁定模式下的生命周期方法:
onCreate
onBind :Service實(shí)例第一次被綁定時(shí)執(zhí)行(只執(zhí)行一次)
onUnbind :Service實(shí)例的最后一個(gè)客戶(hù)端被解綁時(shí)執(zhí)行
onDestroy :在service銷(xiāo)毀時(shí)執(zhí)行onUnbind方法忌怎。
★№ [一般使用啟動(dòng)+綁定模式構(gòu)成的混合模式。很少單獨(dú)使用綁定模式酪夷,無(wú)法銷(xiāo)毀Service]