AppWidget綁定失敗問題分析

一迈着、問題場景


最近在做Launcher,想要實(shí)現(xiàn)一個(gè)效果就是孕蝉,根據(jù)默認(rèn)配置文件把設(shè)定好的Widget在一開始就綁定到桌面上呐馆,但發(fā)現(xiàn)網(wǎng)上大多數(shù)的教程都是讓人通過Intent去調(diào)用系統(tǒng)的對(duì)話框风科,然后選擇widget添加斯议,這并不是我想要的效果产捞。

二、問題分析


Launcher3中的關(guān)鍵代碼:

void?addAppWidgetFromDrop(PendingAddWidgetInfo info,longcontainer,longscreenId,

int[]?cell,int[]?span,int[]?loc)?{

if(LauncherLog.DEBUG)?{

LauncherLog.d(TAG,"addAppWidgetFromDrop:?info?=?"+?info?+",?container?=?"+ container?+",?screenId?=?"

+?screenId);

}

resetAddInfo();

mPendingAddInfo.container?=?info.container?=?container;

mPendingAddInfo.screenId?=?info.screenId?=?screenId;

mPendingAddInfo.dropPos?=?loc;

mPendingAddInfo.minSpanX?=?info.minSpanX;

mPendingAddInfo.minSpanY?=?info.minSpanY;

if(cell?!=null)?{

mPendingAddInfo.cellX?=?cell[0];

mPendingAddInfo.cellY?=?cell[1];

}

if(span?!=null)?{

mPendingAddInfo.spanX?=?span[0];

mPendingAddInfo.spanY?=?span[1];

}

AppWidgetHostView?hostView?=?info.boundWidget;

intappWidgetId;

if(hostView?!=null)?{

appWidgetId?=?hostView.getAppWidgetId();

addAppWidgetImpl(appWidgetId,?info,?hostView,?info.info);

}else{

//?In?this?case,?we?either?need?to?start?an?activity?to?get?permission?to?bind

//?the?widget,?or?we?need?to?start?an?activity?to?configure?the?widget,?or?both.

appWidgetId?=?getAppWidgetHost().allocateAppWidgetId();

Bundle?options?=?info.bindOptions;

booleansuccess?=false;

mAppWidgetManager.setBindAppWidgetPermission(this.getPackageName(),true);//txk?add

if(options?!=null)?{

success?=?mAppWidgetManager.bindAppWidgetIdIfAllowed(appWidgetId,

info.componentName,?options);

}else{

success?=?mAppWidgetManager.bindAppWidgetIdIfAllowed(appWidgetId,

info.componentName);

}

if(success)?{

addAppWidgetImpl(appWidgetId,?info,null,?info.info);

}else{

mPendingAddWidgetInfo?=?info.info;

Intent?intent?=newIntent(AppWidgetManager.ACTION_APPWIDGET_BIND);

intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,?appWidgetId);

intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_PROVIDER,?info.componentName);

//?TODO:?we?need?to?make?sure?that?this?accounts?for?the?options?bundle.

//?intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_OPTIONS,?options);

startActivityForResult(intent,?REQUEST_BIND_APPWIDGET);

}

}

}

上面的關(guān)鍵代碼:

int?newWidgetId?=?mAppWidgetHost.allocateAppWidgetId();

boolean?bindResult?=?mAppWidgetManager.bindAppWidgetIdIfAllowed(newWidgetId,?info.provider);

上面的bindAppWidgetIdIfAllowed正常一開始都會(huì)返回false哼御,原因是沒有進(jìn)行綁定的權(quán)限坯临。所以就算將該AppWidget添加到桌面上,也將是失活的恋昼,沒辦法接受到應(yīng)用的通知看靠。那有什么辦法解決呢?

三液肌、解決方案


其實(shí)當(dāng)?shù)谝淮翁砑觲idget的時(shí)候都會(huì)走到這里挟炬,檢查該Launcher應(yīng)用是否在系統(tǒng)白名單中,如果是的嗦哆,則直接bind成功谤祖,否則彈出一個(gè)提示框讓用戶授權(quán),否則直接返回false老速。

但現(xiàn)在我們想要讓代碼不走到這里粥喜,就得在mAppWidgetManager.bindAppWidgetIdIfAllowed(……)之前提前授權(quán)就好了¢偃可以添加一行授權(quán)代碼mAppWidgetManager.setBindAppWidgetPermission(this.getPackageName(),?true);

但因?yàn)閟etBindAppWidgetPermission是系統(tǒng)隱藏的额湘,所以必須要進(jìn)行反射調(diào)用才行但是需要在Launcher3的AndroidManifest.xml里添加相應(yīng)權(quán)限


而這個(gè)權(quán)限是系統(tǒng)級(jí)權(quán)限秕铛,所以還需要把Launcher3改為系統(tǒng)級(jí)應(yīng)用。

四缩挑、如何把應(yīng)用變成系統(tǒng)應(yīng)用


第一個(gè)方法簡單點(diǎn),不過需要在Android系統(tǒng)源碼的環(huán)境下用make來編譯:

1鬓梅、在應(yīng)用程序的AndroidManifest.xml中的manifest節(jié)點(diǎn)中加入android:sharedUserId="android.uid.system"這個(gè)屬性供置。

2、修改Android.mk文件绽快,加入LOCAL_CERTIFICATE?:=?platform這一行

3芥丧、使用mm命令來編譯,生成的apk就有修改系統(tǒng)時(shí)間的權(quán)限了坊罢。

第二個(gè)方法麻煩點(diǎn)续担,不過不用開虛擬機(jī)跑到源碼環(huán)境下用make來編譯:

1、同上活孩,加入android:sharedUserId="android.uid.system"這個(gè)屬性物遇。

2、使用eclipse編譯出apk文件憾儒,但是這個(gè)apk文件是不能用的询兴。

3、用壓縮軟件打開apk文件起趾,刪掉META-INF目錄下的CERT.SF和CERT.RSA兩個(gè)文件诗舰。

4、使用目標(biāo)系統(tǒng)的platform密鑰來重新給apk文件簽名训裆。這步比較麻煩眶根,首先找到密鑰文件,在我的Android源碼目錄中的位置是"build\target\product\security"边琉,下面的platform.pk8和platform.x509.pem兩個(gè)文件属百。然后用Android提供的Signapk工具來簽名,signapk的源代碼是在"build\tools\signapk"下艺骂,用法為"signapk?platform.x509.pem?platform.pk8?input.apk?output.apk"诸老,文件名最好使用絕對(duì)路徑防止找不到,也可以修改源代碼直接使用钳恕。

這兩個(gè)方法得到的apk是一樣的别伏。

五忧额、原理分析


首先加入android:sharedUserId="android.uid.system"這個(gè)屬性厘肮。通過Shared User id,擁有同一個(gè)User id的多個(gè)APK可以配置成運(yùn)行在同一個(gè)進(jìn)程中。那么把程序的UID配成android.uid.system睦番,也就是要讓程序運(yùn)行在系統(tǒng)進(jìn)程中类茂,這樣就有權(quán)限來修改系統(tǒng)時(shí)間了耍属。

只是加入U(xiǎn)ID還不夠,如果這時(shí)候安裝APK的話發(fā)現(xiàn)無法安裝巩检,提示簽名不符厚骗,原因是程序想要運(yùn)行在系統(tǒng)進(jìn)程中還要有目標(biāo)系統(tǒng)的platform.?key,就是上面第二個(gè)方法提到的platform.pk8和platform.x509.pem兩個(gè)文件兢哭。用這兩個(gè)key簽名后apk才真正可以放入系統(tǒng)進(jìn)程中领舰。第一個(gè)方法中加入LOCAL_CERTIFICATE?:=?platform其實(shí)就是用這兩個(gè)key來簽名。

這也有一個(gè)問題迟螺,就是這樣生成的程序只有在原始的Android系統(tǒng)或者是自己編譯的系統(tǒng)中才可以用冲秽,因?yàn)檫@樣的系統(tǒng)才可以拿到platform.pk8和platform.x509.pem兩個(gè)文件。要是別家公司做的Android上連安裝都安裝不了矩父。試試原始的Android中的key來簽名锉桑,程序在模擬器上運(yùn)行OK,不過放到G3上安裝直接提示"Package?...?has?no?signatures?that?match?those?in?shared?user?android.uid.system"窍株,這樣也是保護(hù)了系統(tǒng)的安全民轴。

最后還說下,這個(gè)android:sharedUserId屬性不只可以把a(bǔ)pk放到系統(tǒng)進(jìn)程中球订,也可以配置多個(gè)APK運(yùn)行在一個(gè)進(jìn)程中杉武,這樣可以共享數(shù)據(jù),應(yīng)該會(huì)很有用的辙售。

六轻抱、提示


文件位置:可以在platform/build/target/product/security/中找到platform.pk8 platform.x509.pem等簽名文件,對(duì)應(yīng)不同的權(quán)限旦部。

signapk.jar:由/platform/build/tools/signapk/編譯產(chǎn)出,可以在/out/host/linux-x86/framework/中找到祈搜。

簽名:

java?-jar?signapk.jar?platform.x509.pem?platform.pk8?MyDemo.apk?MyDemo_signed.apk?得到具有對(duì)應(yīng)權(quán)限的APK

優(yōu)化APK:

zipalign?-v?4?MyDemo_signed.apk?MyDemo_new.apk

查循APK是否優(yōu)化過:

zipalign?-c?-v?4?MyDemo.apk

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市士八,隨后出現(xiàn)的幾起案子容燕,更是在濱河造成了極大的恐慌,老刑警劉巖婚度,帶你破解...
    沈念sama閱讀 211,265評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蘸秘,死亡現(xiàn)場離奇詭異,居然都是意外死亡蝗茁,警方通過查閱死者的電腦和手機(jī)醋虏,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,078評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來哮翘,“玉大人颈嚼,你說我怎么就攤上這事》顾拢” “怎么了阻课?”我有些...
    開封第一講書人閱讀 156,852評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵叫挟,是天一觀的道長。 經(jīng)常有香客問我限煞,道長抹恳,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,408評(píng)論 1 283
  • 正文 為了忘掉前任署驻,我火速辦了婚禮适秩,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘硕舆。我一直安慰自己,他們只是感情好骤公,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,445評(píng)論 5 384
  • 文/花漫 我一把揭開白布抚官。 她就那樣靜靜地躺著,像睡著了一般阶捆。 火紅的嫁衣襯著肌膚如雪凌节。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,772評(píng)論 1 290
  • 那天洒试,我揣著相機(jī)與錄音倍奢,去河邊找鬼。 笑死垒棋,一個(gè)胖子當(dāng)著我的面吹牛卒煞,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播叼架,決...
    沈念sama閱讀 38,921評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼畔裕,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼!你這毒婦竟也來了乖订?” 一聲冷哼從身側(cè)響起扮饶,我...
    開封第一講書人閱讀 37,688評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎乍构,沒想到半個(gè)月后甜无,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,130評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡哥遮,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,467評(píng)論 2 325
  • 正文 我和宋清朗相戀三年岂丘,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片眠饮。...
    茶點(diǎn)故事閱讀 38,617評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡元潘,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出君仆,到底是詐尸還是另有隱情翩概,我是刑警寧澤牲距,帶...
    沈念sama閱讀 34,276評(píng)論 4 329
  • 正文 年R本政府宣布,位于F島的核電站钥庇,受9級(jí)特大地震影響牍鞠,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜评姨,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,882評(píng)論 3 312
  • 文/蒙蒙 一难述、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧吐句,春花似錦胁后、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,740評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至文虏,卻和暖如春侣诺,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背氧秘。 一陣腳步聲響...
    開封第一講書人閱讀 31,967評(píng)論 1 265
  • 我被黑心中介騙來泰國打工年鸳, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人丸相。 一個(gè)月前我還...
    沈念sama閱讀 46,315評(píng)論 2 360
  • 正文 我出身青樓搔确,卻偏偏與公主長得像,于是被迫代替她去往敵國和親灭忠。 傳聞我的和親對(duì)象是個(gè)殘疾皇子妥箕,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,486評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,749評(píng)論 25 707
  • 總結(jié)整理了一下android權(quán)限相關(guān)的知識(shí),由于篇幅過長更舞,分為兩篇博客來寫畦幢,上篇博客主要是詳解權(quán)限和安全,下篇主要...
    Shawn_Dut閱讀 3,775評(píng)論 2 10
  • 對(duì)于安卓系統(tǒng)來說缆蝉,模擬用戶操作是一件很危險(xiǎn)的事情宇葱,因此到目前我所使用過的系統(tǒng)(Android 7以下)均沒有開放模...
    呼兒海雅閱讀 6,123評(píng)論 0 2
  • #29天寫作魔鬼訓(xùn)練營# #第十節(jié)課作業(yè) # #29天寫作魔鬼訓(xùn)練營#20170827 當(dāng)你注視時(shí) 當(dāng)你注視一朵花...
    美若照輝閱讀 498評(píng)論 1 2
  • 一天,呆頭來到一家店刊头,呆頭看見海報(bào)上有裝滿一大碗炒飯 呆頭就問:“能裝滿這么一大碗嗎黍瞧? 廚師...
    那一片云閱讀 240評(píng)論 0 1