EP9-給插件提供Serivce(二周目)

給插件提供Serivce(二周目)

昨天講到怎么模仿PluginActivity給插件提供一個(gè)PluginService,是一個(gè)大概思路臂容,今天寫的時(shí)候有些細(xì)節(jié)記錄在這里。

獲取Service的構(gòu)造器

首先张肾,要想獲得PluginService的構(gòu)造器管宵,就需要:

  1. 加載一個(gè)文件路徑+包名+PluginService的類文件(木偶Service)
  2. 要滿足1截珍,就要先把外部的dex/apk加載到指定的優(yōu)化路徑(optimizedDirectory)里面。

PluginActivity中具體是這樣操作的:

  1. new一個(gè)BaseDexClassLoader()箩朴,參數(shù)是:
super(apkPath, optimizedDirectory, libraryPath, parent);

這樣一來我們就有了一個(gè)指定了optimizedDirectory的classLoader。

  1. 用這個(gè)classLoader的loadClass(className)方法加載指定的類秋度。由于這個(gè)classLoader已經(jīng)綁定了optimizedDirectory炸庞,所以className是包名+類名就可以了。

  2. 用2中得到的serviceClass這個(gè)獲得構(gòu)造器荚斯。

Constructor<?> serviceConstructor = serviceClass
                    .getConstructor();

問題來了埠居,在PluginService需要這樣的步驟嗎查牌?

答案是我們需要獲得剛才new出來的那個(gè)classLoader,然后去直接用它去加載插件中繼承Serviceable的那個(gè)類滥壕。

怎么獲取剛才的classLoader呢纸颜?事實(shí)上,在剛才構(gòu)造classLoader的時(shí)候绎橘,PluginClassLoader用Map保存了classLoader的弱引用:

//PluginClassLoader.java
ClassLoader pluginLoader = new PluginClassLoader(apkPath,
            apkOutputDir, libPath, parent);
    if (pluginLoader != null) {
        loader = pluginLoader;
        pluginLoaders.put(apkPath, new WeakReference<ClassLoader>(
                loader));
    }

這樣的話目測(cè)就可以了胁孙,但總覺得還少點(diǎn)什么。

其他

另外称鳞,對(duì)于多Service的支持涮较,我們知道Activity是可以啟動(dòng)其他Activity的,也可以啟動(dòng)本身的Activity冈止,并且是standard啟動(dòng)模式狂票,可以覆蓋(有個(gè)疑問,目前插件中不是僅用到一個(gè)Activity實(shí)例嗎熙暴。闺属。);但是Service不能復(fù)用(為什么周霉?是不是因?yàn)樵俅蝞ew 同一個(gè)Service木偶的時(shí)候屋剑,ClassLoader發(fā)現(xiàn)parent已經(jīng)加載過這個(gè)類了,所以返回了同樣的實(shí)例诗眨?)唉匾。明天看看。

-DEC 1ST

Appendix:

現(xiàn)在的PluginService.java:

public class PluginService extends Service {
    /**
     * 插件文件路徑匠楚,文件路徑+包名+PluginService.java信息加起來才能構(gòu)造Plugin的Service實(shí)例
     */
    private String mPluginPath;
    /**
     * 插件包名
     */
    private String mPluginPackage;
    /**
     * 獲取PluginActivity初始化的classLoader
     */
    private ClassLoader mClassLoader;
    /**
     * Serviceable實(shí)例
     */
    protected Serviceable mPluginService;


    private void useClassLoaderToLoadService(String mPluginPath, String packageNameAndServicePath) {
        //mPluginPath是外部apk路徑巍膘,optimize之前的路徑;這里是用key取map中的值的操作
        mClassLoader = PluginClassLoader.getClassLoader(mPluginPath);
        try {
            Class<?> serviceClass;
//            if (CJConfig.DEF_STR.equals(mDexPath)) {
//                serviceClass = super.getClassLoader().loadClass(mClass);
//            } else {
//                serviceClass = this.getClassLoader().loadClass(mClass);
//            }
            //packageNameAndServicePath是包名+木偶類名芋簿,用來定位插件中的木偶位置
            serviceClass = mClassLoader.loadClass(packageNameAndServicePath);
            Constructor<?> serviceConstructor = serviceClass
                    .getConstructor();
            mPluginService = (Serviceable) serviceConstructor.newInstance();

        } catch (Exception e) {
        }
//        mPluginService.setProxy(this, mDexPath);
    }

    private void initPath() {
        //獲取插件路徑峡懈。mPluginPath這個(gè)路徑是要拿去loadPlugin的(構(gòu)造BaseDexClassLoader),所以与斤,mPluginPath是指下載的apk的路徑或是assets中內(nèi)置apk的路徑
        mPluginPath = PluginManager.getInstance().getPlugin();

        mPluginPackage = getPluginPackageName(mPluginPath);
    }

    private String getPluginPackageName(String pluginPath) {
        try {
            PackageInfo packageInfo = getPackageManager()
                    .getPackageArchiveInfo(pluginPath, 0);
            if (packageInfo == null) {
                return null;
            }
            return packageInfo.packageName;
        } catch (Exception e) {
            return null;
        }
    }

    @Override
    public void onCreate() {
        initPath();
        useClassLoaderToLoadService(mPluginPath, mPluginPackage + ".RemoteService");
        if (mPluginService != null) {
            mPluginService.onCreate();
        }
        super.onCreate();
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        if (mPluginService != null) {
            mPluginService.onConfigurationChanged(newConfig);
        }
        super.onConfigurationChanged(newConfig);
    }

    @Override
    public void onLowMemory() {
        if (mPluginService != null) {
            mPluginService.onLowMemory();
        }
        super.onLowMemory();
    }

    @Override
    @SuppressLint("NewApi")
    public void onTrimMemory(int level) {
        if (mPluginService != null) {
            mPluginService.onTrimMemory(level);
        }
        super.onTrimMemory(level);
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public boolean onUnbind(Intent intent) {
        if (mPluginService != null) {
            mPluginService.onUnbind(intent);
        }
        return super.onUnbind(intent);
    }

    @Override
    public void onRebind(Intent intent) {
        if (mPluginService != null) {
            mPluginService.onRebind(intent);
        }
        super.onRebind(intent);
    }

}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末肪康,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子撩穿,更是在濱河造成了極大的恐慌磷支,老刑警劉巖食寡,帶你破解...
    沈念sama閱讀 216,997評(píng)論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異善榛,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)移盆,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,603評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門咒循,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人昨凡,你說我怎么就攤上這事蚁署。” “怎么了光戈?”我有些...
    開封第一講書人閱讀 163,359評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵久妆,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我肋演,道長(zhǎng),這世上最難降的妖魔是什么爹殊? 我笑而不...
    開封第一講書人閱讀 58,309評(píng)論 1 292
  • 正文 為了忘掉前任奸绷,我火速辦了婚禮,結(jié)果婚禮上反症,老公的妹妹穿的比我還像新娘畔派。我一直安慰自己,他們只是感情好父虑,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,346評(píng)論 6 390
  • 文/花漫 我一把揭開白布士嚎。 她就那樣靜靜地躺著,像睡著了一般莱衩。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上睹晒,一...
    開封第一講書人閱讀 51,258評(píng)論 1 300
  • 那天括细,我揣著相機(jī)與錄音,去河邊找鬼锉试。 笑死览濒,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的应又。 我是一名探鬼主播乏苦,決...
    沈念sama閱讀 40,122評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼洞就!你這毒婦竟也來了拢驾?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,970評(píng)論 0 275
  • 序言:老撾萬榮一對(duì)情侶失蹤咖为,失蹤者是張志新(化名)和其女友劉穎稠腊,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體架忌,經(jīng)...
    沈念sama閱讀 45,403評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,596評(píng)論 3 334
  • 正文 我和宋清朗相戀三年挠羔,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了埋嵌。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,769評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡范舀,死狀恐怖了罪,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情辅辩,我是刑警寧澤吱七,帶...
    沈念sama閱讀 35,464評(píng)論 5 344
  • 正文 年R本政府宣布,位于F島的核電站景醇,受9級(jí)特大地震影響吝岭,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜窜管,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,075評(píng)論 3 327
  • 文/蒙蒙 一幕帆、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧失乾,春花似錦、人聲如沸裸卫。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,705評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽聋袋。三九已至,卻和暖如春缰泡,著一層夾襖步出監(jiān)牢的瞬間代嗤,已是汗流浹背缠借。 一陣腳步聲響...
    開封第一講書人閱讀 32,848評(píng)論 1 269
  • 我被黑心中介騙來泰國打工泼返, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人绅喉。 一個(gè)月前我還...
    沈念sama閱讀 47,831評(píng)論 2 370
  • 正文 我出身青樓柴罐,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國和親革屠。 傳聞我的和親對(duì)象是個(gè)殘疾皇子似芝,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,678評(píng)論 2 354

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

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,095評(píng)論 25 707
  • 是時(shí)候來一波Android插件化了 是時(shí)候來一波Android插件化了前言Android開發(fā)演進(jìn)模塊化介紹插件化介...
    流水不腐小夏閱讀 4,790評(píng)論 3 51
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理详炬,服務(wù)發(fā)現(xiàn)寞奸,斷路器,智...
    卡卡羅2017閱讀 134,654評(píng)論 18 139
  • 8月2日呻率,55.1kg
    shirleyZhou雪閱讀 120評(píng)論 0 0
  • 上星期和朋友圈里的一個(gè)老板娘約定了互相督促跑步礼仗。我就正式開始跑步的計(jì)劃了。跑的第一天很興奮的發(fā)了朋友圈韭脊。想說单旁。看象浑。...
    何仙姑的胭脂水粉閱讀 119評(píng)論 1 0