所謂sandbox App是指那些為了發(fā)布到App Store的,受到權(quán)限控制的App。一般Sandbox App擁有如下權(quán)限
一波三折 之一
項(xiàng)目需要我們在符合Sandbox權(quán)限約束下的App中使用第三方的一個(gè)開源項(xiàng)目的Binary攒磨。并在之中調(diào)用這個(gè)Binary以進(jìn)行一些功能上的實(shí)現(xiàn)。
于是屹堰,我興高采烈地直接拿到了local build版本的這個(gè)Binary沿腰,以下簡稱N文件。我通過包一個(gè)帶UI的Sandbox App的方式事哭,通過NSTask調(diào)用了這個(gè)Binary漫雷,一切功能運(yùn)行正常。
于是乎直接申請對應(yīng)App ID,上傳之鳍咱,準(zhǔn)備發(fā)布降盹。
然而,正以為一切都盡在掌控之際谤辜,陡生變故蓄坏。在使用Xcode上傳時(shí),連第一步的Validate都未通過丑念。并且錯(cuò)誤顯示我的這個(gè)N文件無Sandbox權(quán)限涡戳。
經(jīng)過研究,原來脯倚,在Sandbox下的可獨(dú)立執(zhí)行的文件都必須符合Sandbox權(quán)限管控渔彰。可是挠将,這是一個(gè)Command Line Tool的項(xiàng)目啊胳岂,這個(gè)如何加入Sandbox權(quán)限呢?
一波三折 之二
經(jīng)過研究舔稀,發(fā)現(xiàn)可以通過
codesign --entitlements ./entitlements.plist -s "copy & paste your certificate from keychain" ./commandlinetool
來將我們手動(dòng)創(chuàng)建的entitlements文件(記錄了app的sandbox權(quán)限信息)sign進(jìn)對應(yīng)的commondlinetool
請參考Stackoverflow原貼
以為一切就如此順利的搞定了乳丰。剛準(zhǔn)備為自己的運(yùn)氣而慶幸,直接運(yùn)行内贮,出現(xiàn)
Illegal instruction: 4
這是因?yàn)槲覀優(yōu)橐粋€(gè)原本不受權(quán)限控制的可執(zhí)行文件強(qiáng)行添加權(quán)限之后無法執(zhí)行产园。
再次研究汞斧,從Apple官方文檔中找到
Add the following arguments to your linker flags:
-sectcreate __TEXT __info_plist Info.plist_path
Info.plist 是記錄一個(gè)SandboxApp 相關(guān)Bundle信息的文件,我一拍腦袋什燕。我只顧為一個(gè)Binary進(jìn)行權(quán)限分配粘勒,而沒有為這個(gè)Binary包相關(guān)的Bundle信息,那么這個(gè)程序在運(yùn)行時(shí)由于缺少Bundle信息屎即,在Sandbox 化時(shí)系統(tǒng)無法為其生成相關(guān)的Container庙睡。根據(jù)文檔,我修改了Makefile技俐,添加了Linkflag
一波三折 之三
折騰了一天乘陪,終于可以下班了吧。在Terminal中完美運(yùn)行了這個(gè)Sandbox化的N文件之后雕擂,我把它重新包進(jìn)了之前帶UI的Sandbox App啡邑。然而,運(yùn)行后程序毫無反饋井赌。調(diào)試后發(fā)現(xiàn)谤逼,既無報(bào)錯(cuò)也無Console。因?yàn)檎H绻腥魏萎惓6紩?huì)有Console報(bào)錯(cuò)仇穗,如果能夠運(yùn)行流部,Console中會(huì)有運(yùn)行中的Log信息。
欲哭無淚纹坐,毫無頭緒贵涵。
經(jīng)過多方求助終于在Apple的一個(gè)developer forum回帖中發(fā)現(xiàn)了一個(gè)相關(guān)回答
其中,有價(jià)值的兩點(diǎn)
1.Sandbox inheritance (com.apple.security.inherit)
2.converting your tool to some sort of script (a shell script, Python, whatever).
先嘗試了包一個(gè)shell恰画,發(fā)現(xiàn)在Sandbox的app中調(diào)用bash去run 自己寫的shell,再通過這個(gè)shell去run我們的binary是不可行的瓷马,報(bào)錯(cuò):operation not permitted
再看第二點(diǎn)拴还,查Apple 文檔和具體的這個(gè)com.apple.security.inherit權(quán)限文檔
深入研究后發(fā)現(xiàn),
To enable sandbox inheritance, a child must use exactly two App Sandbox entitlement keys: com.apple.security.app-sandbox and com.apple.security.inherit. If you specify any other App Sandbox entitlement, the system aborts the child process. You can, however, confer other capabilities to a child process by way of iCloud and notification entitlements.
也就是說欧聘,我們的N文件現(xiàn)在是作為我們包的UI App的子項(xiàng)片林,于是我們需要讓這個(gè)N文件繼承UI App的Sandbox權(quán)限,而不是把它自己作為一個(gè)獨(dú)立的Sandbox App怀骤。
于是费封,
- 去掉Makefile中之前添加的linkflag
- 將entitlement文件改為
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.inherit</key>
<true/>
</dict>
</plist>
重新make,然后codesign蒋伦,并把新N文件包進(jìn)去
黎明
終于弓摘,這個(gè)程序正常了,并且N文件和外包的UI App公用同樣的Bundle信息痕届,同一個(gè)Container韧献,使用同樣的Sandbox權(quán)限末患。
總結(jié)
整個(gè)過程一波三折,每當(dāng)有進(jìn)展之后以為圓滿解決了又來了更大的問題锤窑。同時(shí)璧针,相關(guān)資料非常少,我全程查英文第一手資料渊啰,但是無奈Apple文檔目錄太深探橱,Google也幫不了我。好在各種機(jī)緣和強(qiáng)大的同事绘证,我們一步一步的猜想隧膏,實(shí)驗(yàn),破解了謎團(tuán)迈窟。
App已經(jīng)提交了私植,也許Apple不允許這樣的通過N文件的方式進(jìn)行包裝,不過在這個(gè)過程中對Sandbox權(quán)限和項(xiàng)目構(gòu)建有了更深的理解车酣。
相關(guān)的中文資料基本沒有曲稼,希望能夠給同樣在坑中的人們帶來一些參考。