廣播接收者
- BroadcastReceiver
- 接收系統(tǒng)發(fā)出的廣播
- 現(xiàn)實(shí)中的廣播:電臺(tái)為了傳達(dá)一些消息礼旅,而發(fā)送的廣播鸳玩,通過廣播攜帶要傳遞的消息赊抖,群眾只要買了收音機(jī),就可以收到廣播了
- Android中的廣播:系統(tǒng)在運(yùn)行過程中肤晓,會(huì)發(fā)生很多事件,系統(tǒng)為了讓其他應(yīng)用知道系統(tǒng)發(fā)生了這個(gè)事件,會(huì)發(fā)送一個(gè)對應(yīng)事件的廣播补憾,比如:電量改變漫萄,收到短信,撥打電話盈匾,屏幕解鎖腾务,系統(tǒng)開機(jī),只有注冊一個(gè)廣播接收者削饵,就可以接收到系統(tǒng)發(fā)送的廣播岩瘦。
IP撥號器
系統(tǒng)撥打號碼時(shí),會(huì)發(fā)出一個(gè)廣播窿撬,廣播中會(huì)攜帶撥打的號碼启昧,注冊廣播接收者接收這個(gè)廣播,取出這個(gè)號碼劈伴,修改號碼密末,然后把修改的號碼重新放入廣播。
-
原理
定義方式
- 定義一個(gè)類繼承BroadCastReceiver
-
在清單文件中配置該類,并指定接收的廣播種類必須配置intent-filter跛璧。
需要加入權(quán)限:
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"/>
- 廣播是通過Intent發(fā)送的严里,Intent中會(huì)攜帶一個(gè)action,系統(tǒng)會(huì)在所有的清單文件中尋找追城,看哪個(gè)一個(gè)廣播接收器的intent-filter 和廣播中的intent是匹配的田炭,那么這個(gè)廣播接收器就會(huì)收到這條廣播。
- 廣播運(yùn)行在哪個(gè)進(jìn)程里面就看她運(yùn)行在哪個(gè)項(xiàng)目里面。
如果關(guān)掉應(yīng)用進(jìn)程之后,廣播接收者還是會(huì)接收粘捎,即便沒有啟動(dòng)應(yīng)用進(jìn)程,廣播發(fā)出來時(shí)瞬矩,系統(tǒng)也會(huì)啟動(dòng)這個(gè)進(jìn)程,然后把廣播交給廣播接受者锋玲。
廣播接受者所在進(jìn)程是不怕被殺掉的景用。
短信防火墻原理
需要的權(quán)限:
<uses-permission android:name="android.permission.RECEIVE_SMS"/>
可以取大于1000的數(shù),取整數(shù)的最大值
- 一條短信是由很多 條短信拼接起來的惭蹂,所以是數(shù)組形式
-
短信攔截必須在有短信時(shí)就攔截就必須優(yōu)先級要高伞插,系統(tǒng)短信優(yōu)先級不高于1000,先一步收到短信廣播盾碗,然后攔截廣播媚污,短信應(yīng)用就收不到短信的。
- 4.0之后廷雅,用戶手動(dòng)開啟進(jìn)程耗美,那么廣播接收者才能生效
- 4.0之后京髓,用戶手動(dòng)停止進(jìn)程,那么廣播接受者再也不會(huì)啟動(dòng)了商架,直到用戶下一次手動(dòng)啟動(dòng)進(jìn)程堰怨。
監(jiān)聽SD卡狀態(tài)
監(jiān)聽SD卡不需要權(quán)限
開機(jī)勒索軟件
-
在廣播接收器中啟動(dòng)Activity 出現(xiàn)錯(cuò)誤
- 啟動(dòng)一個(gè)新的任務(wù)棧來保存Activity,之前我們啟動(dòng)Activity是直接點(diǎn)擊圖標(biāo)啟動(dòng)的蛇摸,啟動(dòng)Activity本身是有任務(wù)棧的备图,我們現(xiàn)在在一個(gè)Activity任務(wù)棧之外啟動(dòng)Activity就會(huì)出現(xiàn)問題。因?yàn)楫?dāng)前沒有任務(wù)棧赶袄。需要直接創(chuàng)建一個(gè)任務(wù)棧揽涮。
應(yīng)用的安裝卸載和更新
-
注冊廣播
-
廣播接收處理
發(fā)送自定義廣播
-
發(fā)送廣播
*接收廣播
有序和無序廣播
無序廣播
所有與廣播中的Intent匹配的廣播接收者,都可以收到這條廣播弃鸦,并且不分先后順序绞吁,視為同時(shí)收到幢痘。有序廣播
所有與廣播中的intent匹配的廣播接收者唬格,都可以收到這條廣播,但是分先后順序颜说,優(yōu)先級高的先收到购岗,優(yōu)先級低的后收到。
服務(wù)
Service
四大組件之一
運(yùn)行于后臺(tái)门粪,沒有前臺(tái)界面喊积,用于運(yùn)行需要在后臺(tái)運(yùn)行的代碼
如:下載任務(wù),音樂播放玄妈。
如果下載線程放在Activity中時(shí)乾吻,
按home和返回鍵 銷毀Activity之后 下載還可以運(yùn)行,這是因?yàn)榫€程還在進(jìn)程運(yùn)行拟蜻,但是進(jìn)程被殺掉之后绎签,線程就會(huì)被銷毀。當(dāng)內(nèi)存不足時(shí)就會(huì)殺掉進(jìn)程酝锅,因此不要把下載放在Activity中诡必。Empty 進(jìn)程(沒有任何活動(dòng)的應(yīng)用組件(Activity和Service))
一個(gè)進(jìn)程不包含任何活躍的應(yīng)用組件(指的是服務(wù)和Activity),保持該類型進(jìn)程活躍的原因只是是緩存搔扁,提高下次組件在該進(jìn)程中的開啟速度爸舒。
該進(jìn)程很容易被殺掉后臺(tái)進(jìn)程(如按home鍵)
如果一個(gè)進(jìn)程持有一個(gè)對用戶不可見的Activity時(shí)(該activity的onStop()方法已經(jīng)被調(diào)用),這些進(jìn)程對用戶的體驗(yàn)沒有直接的影響稿蹲。
很容易被殺死服務(wù)進(jìn)程(相比bindService而言扭勉,這個(gè)才是真正用來下載,不到萬不得已不會(huì)被殺死)
擁有一個(gè)服務(wù)的進(jìn)程苛聘。
該進(jìn)程中正在運(yùn)行的是以startService()方法開啟的服務(wù)剖效。可見進(jìn)程
擁有一個(gè)不在前臺(tái)但對用戶依然可見的Activity(onPause()方法被調(diào)用)的進(jìn)程
擁有一個(gè)與可見Activity(onPause()方法被調(diào)用)綁定的服務(wù)(特指遠(yuǎn)程服務(wù))
-
前臺(tái)進(jìn)程
- 擁有一個(gè)正在與用戶交互的Activity(onResume()方法調(diào)用)
- 擁有一個(gè)與正在與用戶交互的Activity綁定的服務(wù)(特指遠(yuǎn)程服務(wù))
- 擁有一個(gè)運(yùn)行在前臺(tái)的服務(wù)(服務(wù)調(diào)用了startForeground())
- 擁有一個(gè)正在執(zhí)行其中一個(gè)生命周期方法( onCreate(),onStartCommand(),or onDestory())的服務(wù)嫉入。
保證生命周期執(zhí)行完畢,短暫提高優(yōu)先級璧尸,保證代碼執(zhí)行完畢咒林,完成后就自動(dòng)降為服務(wù)進(jìn)程。在內(nèi)存不足不被殺掉爷光。 - 擁有一個(gè)正在執(zhí)行onReceive的方法的廣播接受者垫竞。執(zhí)行完畢該殺就被殺。
服務(wù)的啟動(dòng)和停止
-
定義方式:創(chuàng)建java類再繼承Service類蛀序,清單文件做配置欢瞪。
可以理解為:沒有界面的Activity。
- 服務(wù)單位生命周期
startService的生命周期:
onStartCommand:可以多次被調(diào)用
onCreate:只會(huì)被調(diào)用一次
onDestory:值會(huì)被調(diào)用 - onCreate->onStartCommand->onDestory
重復(fù)的startService不會(huì)調(diào)用onCreate只會(huì)重復(fù)調(diào)用onStartCommand
通話錄音機(jī)
- 空閑
- 響鈴
- 摘機(jī)
先監(jiān)聽電話狀態(tài)
MediaRecorder使用方法
服務(wù)的兩種啟動(dòng)方式及生命周期
startService
- 通過startService啟動(dòng)的服務(wù)徐裸,該服務(wù)所在的進(jìn)程會(huì)變成服務(wù)進(jìn)程遣鼓。
- Service 與啟動(dòng)它的Activity沒有關(guān)系。
bindService
- 通過bindService啟動(dòng)的服務(wù)重贺,進(jìn)程優(yōu)先級不變骑祟。
- 綁定出來的Service不是服務(wù)進(jìn)程,它的優(yōu)先級跟他本身綁定的Activit有關(guān)气笙,Activity 是后臺(tái)的次企,那就是后臺(tái)進(jìn)程,Activity沒有了潜圃,那就是空進(jìn)程缸棵。
綁定出來的Service是不能作為后臺(tái)操作的。很容易死掉進(jìn)程谭期。
不能再次解綁的堵第,重復(fù)解綁會(huì)報(bào)錯(cuò)。
綁定服務(wù)后隧出,直接按返回鍵會(huì)報(bào)錯(cuò)踏志。說明綁定服務(wù)不能作為后臺(tái)操作
- 綁定的服務(wù)于啟動(dòng)它的Activity是同生共死的,Activity銷毀了鸳劳,服務(wù)也要銷毀狰贯。服務(wù)銷毀了,activity不銷毀赏廓。
調(diào)用服務(wù)中的方法
回調(diào)類ServiceConnection
把中間人的方法抽取到接口中
為什么要這么做,不私有化方法呢涵紊?
模擬音樂播放器
混合啟動(dòng)Service(startService和bindService)
start->bind->unbind->stop
因?yàn)橐WC音樂播放器退出后音樂還在播放,就必須啟動(dòng)服務(wù)進(jìn)程
- 一定要先啟動(dòng)后綁定
先啟動(dòng)startService
onCreate->onStartCommand
再綁定
->onBind
再解綁 服務(wù)還在
->onUnbind ( 不會(huì)被摧毀)
再摧毀
->onDetory - 如果先bindService(邏輯會(huì)出問題)
onCreate->onbind
再startService
->onStartCommand
再stopService
->服務(wù)什么也不干
最后解綁
->onUnbind(會(huì)銷毀)
使用代碼注冊和反注冊廣播接受者
清單文件注冊
- 廣播接收者永遠(yuǎn)生效幔摸,除非卸載應(yīng)用摸柄,或者手動(dòng)停止進(jìn)程(如防火墻)
代碼注冊
通常和service聯(lián)系在一起,一般啟動(dòng)服務(wù)來注冊。
需要廣播接收者生效時(shí)既忆,注冊它驱负,不需要時(shí)嗦玖,反注冊它,反注冊之后跃脊,廣播接收者就失效了宇挫。(只在需要時(shí)注冊)
-
特殊廣播接收者,必須代碼注冊酪术。
這種需求沒有必要一直生效器瘪。因?yàn)檫@些廣播變化得很快,次數(shù)很頻繁绘雁。
(清單文件注冊了而沒有代碼注冊也接收不到)- 屏幕開關(guān)
- 電量改變
第一步定義服務(wù)并在清單文件中注冊服務(wù)
- 第二步定義廣播接收器
啟動(dòng)和綁定遠(yuǎn)程服務(wù)
服務(wù)的分類
都是在手機(jī)上與web不一樣
本地服務(wù)
- 與啟動(dòng)者都在同一應(yīng)用的服務(wù)
遠(yuǎn)程服務(wù)
- 與啟動(dòng)者不在同一應(yīng)用的服務(wù)
本地服務(wù)使用顯示啟動(dòng)
遠(yuǎn)程服務(wù)使用隱式啟動(dòng)
注意:
Android 5.0 之后 Service必須顯示啟動(dòng)橡疼,不然會(huì)報(bào)錯(cuò)
解決方案:
遠(yuǎn)程服務(wù)中使用aidl
進(jìn)程間通信
- AIDL
android interface definition language
在Android中進(jìn)行進(jìn)程間通訊
步驟:
遠(yuǎn)程Service
1.把接口文件的后后綴名.aidl;(在gen中自動(dòng)生成.java文件)
2.aidl文件中的所有東西都是public ,不需要訪問修飾符庐舟;
3.中間人對象繼承Stub欣除,這個(gè)抽象類Stub已經(jīng)繼承了Binder并實(shí)現(xiàn)了aidl里面的方法。
訪問遠(yuǎn)程服務(wù)
1.把上述的aidl文件復(fù)制到訪問遠(yuǎn)程服務(wù)的工程中挪略,然后aidl所在的包名必須和遠(yuǎn)程Service中的aidl一致历帚。
2.把獲取的中間人對象使用Stub.asInterface強(qiáng)轉(zhuǎn)。
支付寶遠(yuǎn)程服務(wù)
進(jìn)程優(yōu)先級的補(bǔ)充
確定取消對話框
單選對話框
setMessage 是絕對不能設(shè)置的瘟檩,會(huì)將單選內(nèi)容蓋掉抹缕。
設(shè)置多選對話框
設(shè)置進(jìn)度條對話框
樣式和主題
- 樣式和主題定義的方式是一模一樣的
- 布局文件中使用樣式
-
清單文件中使用主題
國際化
圖片也能國際化: