exported
在Activity中該屬性用來標(biāo)示讽坏,當(dāng)前Activity是否可以被另一個(gè)Application的組件啟動(dòng)胚委。如果被設(shè)置為了false渐苏,那么這個(gè)Activity將只會(huì)被當(dāng)前Application或者擁有同樣uid的Application的組件調(diào)用凑术。
exported 的默認(rèn)值
exported 的默認(rèn)值根據(jù)Activity中是否有intent filter 來定。
沒有任何的filter意味著這個(gè)Activity只有在詳細(xì)的描述了他的class name后才能被喚醒币喧。這意味著這個(gè)Activity只能在應(yīng)用內(nèi)部使用,因?yàn)槠渌黙pplication并不知道這個(gè)class的存在袱耽。所以在這種情況下杀餐,它的默認(rèn)值是false。
如果Activity里面至少有一個(gè)filter的話朱巨,意味著這個(gè)Activity可以被其它應(yīng)用從外部喚起史翘,這個(gè)時(shí)候它的默認(rèn)值是true。
其實(shí),不只有這個(gè)屬性可以指定Activity是否暴露給其它應(yīng)用琼讽,也可以使用permission來限制外部實(shí)體喚醒當(dāng)前Activity(詳情見permission屬性)
uid機(jī)制
我們?cè)谕粋€(gè)application內(nèi)部必峰,可以隨意的startActivity from Activity A to Activity B,而官方的文檔中說startActivity可能會(huì)報(bào)NotFoundException钻蹬,表示被start的Activity不存在吼蚁。因此,我們很容易忽略另一個(gè)可能的Exception脉让,Permission Denial桂敛。
當(dāng)我們?cè)诓煌腶pplication中,如application A中的Activity去start一個(gè)application B中的Activity溅潜,也許你什么Exception都不會(huì)得到术唬,也可能會(huì)直接Force Close掉。因?yàn)樵赟tart Activity時(shí)滚澜,代碼是有去檢驗(yàn)permission的粗仓。 如下情況,可以成功startActivity而不會(huì)得到permission denial设捐。
1)同一個(gè)application下
2)Uid相同
3)permission匹配
4)目標(biāo)Activity的屬性Android:exported=true
5)目標(biāo)Activity具有相應(yīng)的IntentFilter借浊,存在Action動(dòng)作或其他過濾器并且沒有設(shè)置exported=false
6)啟動(dòng)者的Pid是一個(gè)System Server的Pid
7)啟動(dòng)者的Uid是一個(gè)System Uid(Android規(guī)定android.system.uid=1000,具有該Uid的application萝招,我們稱之為獲得Root權(quán)限)
如果上述調(diào)節(jié)蚂斤,滿足一條,一般即可(與其他幾條不發(fā)生強(qiáng)制設(shè)置沖突)槐沼,否則曙蒸,將會(huì)得到Permission Denial的Exception而導(dǎo)致Force Close。
眾所周知岗钩,Pid是進(jìn)程ID纽窟,Uid是用戶ID,只是Android和計(jì)算機(jī)不一樣兼吓,計(jì)算機(jī)每個(gè)用戶都具有一個(gè)Uid臂港,哪個(gè)用戶start的程序,這個(gè)程序的Uid就是那個(gè)用戶视搏,而Android中每個(gè)程序都有一個(gè)Uid审孽,默認(rèn)情況下,Android會(huì)給每個(gè)程序分配一個(gè)普通級(jí)別互不相同的Uid凶朗,如果用戶互相調(diào)用瓷胧,只能是Uid相同才行,這就使得共享數(shù)據(jù)具有了一定安全性棚愤,每個(gè)軟件之間是不能隨意獲得數(shù)據(jù)的(當(dāng)然這也就表明了一個(gè)問題搓萧,android只能是單用戶系統(tǒng)杂数,在設(shè)計(jì)之初就被他們的工程師給閹割了多用戶)。而同一個(gè)application只有一個(gè)Uid瘸洛,所以application下的Activity之間不存在訪問權(quán)限的問題揍移。
如果你需要做一個(gè)application,將某些服務(wù)service反肋,provider或者activity等的數(shù)據(jù)那伐,共享出來怎么辦,三個(gè)辦法石蔗。
1)完全暴露罕邀,這就是android:exported=true的作用,而一旦設(shè)置了intentFilter之后养距,exported就默認(rèn)被設(shè)置為true了诉探,除非再?gòu)?qiáng)制設(shè)為false。當(dāng)然棍厌,對(duì)那些沒有intentFilter的程序體肾胯,它的exported屬性默認(rèn)仍然是false,也就不能共享出去耘纱。
2)權(quán)限提示暴露敬肚,這就是為什么經(jīng)常要設(shè)置usePermission的原因,如果人家設(shè)置了android:permission=“xxx.xxx.xx”那么束析,你就必須在你的application的Mani fest中usepermission xxx.xxx.xx才能訪問人家的東西艳馒。
3)私有暴露,假如說一個(gè)公司做了兩個(gè)產(chǎn)品员寇,只想這兩個(gè)產(chǎn)品之間可互相調(diào)用鹰溜,那么這個(gè)時(shí)候就必須使用shareUserID將兩個(gè)軟件的Uid強(qiáng)制設(shè)置為一樣的。這種情況下必須使用具有該公司簽名的簽名文檔才能丁恭,如果使用一個(gè)系統(tǒng)自帶軟件的ShareUID,例如Contact斋日,那么無(wú)須第三方簽名牲览。 這種方式保護(hù)了第三方軟件公司的利益于數(shù)據(jù)安全。
當(dāng)然如果一個(gè)activity是從system process跑出來的恶守,那么它就可以橫行霸道第献,任意權(quán)限,只是你無(wú)法開發(fā)一個(gè)第三方application具有系統(tǒng)的Pid(系統(tǒng)Pid不固定)兔港,但是你完全可以開發(fā)一個(gè)具有系統(tǒng)Uid的程序庸毫,對(duì)系統(tǒng)中的所有程序任意訪問,只需在Manufest中聲明shareUserId為android.system.uid即可衫樊,生成的文件也必須經(jīng)過高權(quán)限簽名才行飒赃,一般不具備這種審核條件的application利花,google不會(huì)提供給你這樣的簽名文件。當(dāng)然你是在編譯自己的系統(tǒng)的話载佳,想把它作成系統(tǒng)軟件程序炒事,只需在Android.mk中聲明Certificate:platform則可以了,既采用系統(tǒng)簽名蔫慧。這個(gè)系統(tǒng)Uid的獲得過程挠乳,我們把它叫做獲得Root權(quán)限的過程。所以很多第三方系統(tǒng)管理軟件就是有Root權(quán)限的軟件姑躲,因?yàn)樗枰獙?duì)系統(tǒng)有任意訪問的權(quán)限睡扬。那么它的Root簽名則需要和編譯的系統(tǒng)一致,例如官方的系統(tǒng)得用官方的簽名文件黍析,CM的系統(tǒng)就得用CM的簽名文件卖怜。
在android中PID,和UID都是用來識(shí)別應(yīng)用程序的身份的橄仍,但UID是為了不同的程序來使用共享的數(shù)據(jù)韧涨。通過配置android:sharedUserId="com.share(保持一致)",就可以在A程序中通過跳轉(zhuǎn)activity的形式訪問B中的數(shù)據(jù)侮繁。這樣的話你也許會(huì)有疑問虑粥,如果讓其他的開發(fā)這知道了我們的shareUserId知道了我們的ID,那我們的數(shù)據(jù)不是暴露了宪哩,放心吧google不會(huì)犯這樣的低級(jí)錯(cuò)誤的娩贷,我們要使不同的程序能夠相互訪問,還需要擁有相同的簽名锁孟,每個(gè)公司或者開發(fā)者的簽名是唯一的彬祖,這樣我們就不用擔(dān)心了,另外兩者能夠訪問品抽,別忘了權(quán)限储笑。
參考文獻(xiàn):
http://blog.csdn.net/watermusicyes/article/details/46460347
http://yelinsen.iteye.com/blog/977683
https://www.cnblogs.com/perseus/articles/2354173.html