电脑知识|欧美黑人一区二区三区|软件|欧美黑人一级爽快片淫片高清|系统|欧美黑人狂野猛交老妇|数据库|服务器|编程开发|网络运营|知识问答|技术教程文章 - 好吧啦网

您的位置:首頁技術(shù)文章
文章詳情頁

Android 解決游戲發(fā)行切包資源索引沖突的問題

瀏覽:63日期:2022-09-20 15:49:08
背景

游戲發(fā)行切包過程中,經(jīng)常碰到渠道、研發(fā)、發(fā)行方,三方資源在合并過程中,資源ID沖突導(dǎo)致程序異常的問題,此類問題通過getIdentifier方式規(guī)避或者修改沖突資源ID的方式可以處理,但成本較高,本文旨在提出一種在切包過程中自動化處理資源沖突的解決方案

1、public.xml介紹1、public.xml這個文件是哪來的?

該文件是apktool在反編譯apk時,根據(jù)apk包中的resources.arsc文件生成。

沒看過resource.arsc? (自己拖個apk到IDE看吧)

2、public.xml有什么作用

publc.xml是aapt在打包資源時用來固定資源id的,如果資源在public.xml中有對應(yīng)的id了,那么打包資源時就用已經(jīng)有的id。

3、public.xml中的id的格式

共四個字節(jié)32位,第一個字節(jié)代表PackgeID,第二個字節(jié)代表TypeID,后兩個字節(jié)代表資源值

通常系統(tǒng)資源PackageID是01,而我們自己的資源PackageID是7f

TypeID,比如attr為01,string為02。但是并不固定,并不一定attr就是01。但是在public.xml中,同類型的該字節(jié)一定是一樣的,否則回編譯會失敗。

2、R類介紹

R類這里有個知識點,library模塊中生成的R類中的成員的值不是常量,不帶final。app模塊生成的R類的值是常量值。而常量值在java編譯時會被優(yōu)化,最終代碼中輸出的就是常量值,而不是R.id.xxx這樣。而library的因為是變量,不會被優(yōu)化,代碼中會保留R.id.xxx

R類和public.xml的關(guān)系

從本質(zhì)上講,其實并沒有啥關(guān)系。但是由于在代碼中我們會使用R.id去查找資源,這就關(guān)聯(lián)上了。如果都用getIdentifier的方式先獲取id,那把R類刪了也沒事。

public.xml打包后對應(yīng)的就是resources.arsc中的值,而資源值生成Java類,這個類就是R類。也就是說平時使用R類,就是用里面的索引值去到resources.arsc中找到對應(yīng)資源位置,再去加載。

3、切包融合過程中R類和public.xml的處理

切包過程中,R類屬于代碼,采用直接覆蓋的方式,但是由于我們生成的R類跟母包的R類其實值會是不同的。

下文中的cp指游戲研發(fā)方,即我們的SDK的接入方。

而public.xml是用的cp的,為什么用cp的?因為cp建立的是app工程,R類是常量值,如果我們把母包中public.xml中已有的值給改了,萬一母包中用了,那就gg了

由于R類在library中使用的時候是個變量,保留了R.id.xxx這種形式,解決方法就有了,糾正R類中的值跟public.xml對應(yīng),這樣就能繼續(xù)愉快的使用R.id.xxx了。

我們的切包過程有幾個步驟:

反編譯母包(指接入我們SDK的乙方)====》合并渠道資源====》合并入新sdk的資源(跳過研發(fā)更新我們的sdk的過程哈)

1、在反編譯母包的時候解析public.xml的值,存下來。

private void init() { List<Element> elements = mDocument.getRootElement().elements(); for (Element element : elements) { String type = element.attribute(TYPE).getStringValue(); String name = element.attribute(NAME).getStringValue(); String id = element.attribute(ID).getStringValue(); Map<String, String> typeMap = mTypeMap.get(type); if (typeMap == null) { typeMap = new HashMap<>(); typeMap.put(name, id); mTypeMap.put(type, typeMap); } else { typeMap.put(name, id); } }}2、合并渠道資源的時候,將渠道資源中的public.xml(以channelPublic代指)合并到母包的public.xml(以matrixPublic代指)中

合并策略:

a、channelPublic中有,而matrixPublic中沒有,增加到matrixPublic中

比如增加如下數(shù)據(jù)到matrixPublic中

<public type='attr' name='iconSrc' />

如果該type在matrixPublic中已經(jīng)存在:

首先要獲取到attr在matrixPublic中的PackageId+TypeId。在一個public.xml文件中,同類型比如attr對應(yīng)的PackageId+TypeId是不能變的,否則回編譯失敗。因此要添加數(shù)據(jù)時,數(shù)據(jù)的PackageId+TypeId需要糾正為matrixPublic的值。

其次資源值,不能和已有的資源值重復(fù),正常情況下public.xml中的值是aapt生成的有序的,這里可以掃描matrixPublic中attr類型值的最大值,然后加一作為新加的iconSrc的id值

如果該type在matrixPublic中不存在(假設(shè)母包中matrixPublic中不存在attr類型)

首先要獲取類型已經(jīng)被占用的有哪些,即獲取到matrixPublic中的TypeId,正常情況也是有序的,獲取出最大的TypeId,加一作為新Type的起始值。賦值給iconSrc的id值

b、channelPublic中有,而matrixPublic中也有的,不需要處理,保留matrixPublic中的值不變

3、合并入新sdk的資源,在覆蓋完R類,后開始糾正R類的值

掃描R類在PublicAndRHelper中

掃描覆蓋完R類的smali代碼中所有的R類,R$styleable類除外,因為styleable中保存的是一些數(shù)組的值,規(guī)則不同。

/** * 掃描代碼中的R類 * @return */ private void scannerRClass(String path) { File smaliFilePath = new File(path); for (File file : smaliFilePath.listFiles()) { if (file.isDirectory()) { scannerRClass(file.getAbsolutePath()); } else if(file.isFile()){ if (file.getName().equals('R.smali') || file.getName().startsWith('R$')) { //此處過濾掉styleable文件 if (!file.getName().endsWith('R$styleable.smali')) { mRClassFileList.add(file.getAbsolutePath()); } } } } }

針對每一個R類調(diào)用糾正R類中方法,糾正R類值在RValueHelper類中

策略:匹配出要糾正的行,獲取到type,name。在public.xml中找出對應(yīng)的值,糾正。

注意這里的糾正不要用replace(oldValue,newValue)這種方式,要用替換行的方式,因為存在新值在R類中也存在后,后續(xù)替換出問題。比如a替換成b,b替換成c的情況最終R類中的a和b都被替換成了c

其次是styleable的處理,當(dāng)掃描到的R是attr類型的時候,判斷是否有styleable類型的存在,如果存在,則緩存下來attr中所做的糾正,用于糾正styleable。

public static void handle(String RFilePath, PublicXmlBean publicXmlBean) { File RFile = new File(RFilePath); String RStyleFilePath = ''; Map<String, String> cacheMap = null; if (RFile.getName().endsWith('R$attr.smali')) { RStyleFilePath = RFilePath.replace('R$attr', 'R$styleable'); File RStyleAbleFile = new File(RStyleFilePath); //styleable存在,則把attr文件替換過的值緩存 if (RStyleAbleFile.exists()) { cacheMap = new HashMap<>(); } } String rFileContent = FileUtil.read(RFilePath); //找到RFile中是屬性的每一行 ArrayList<String> lines = FileUtil.readAllLines(RFilePath, '.field public static final'); String regex = '.field public static final (.*):(.*) = (.*)'; for (String line : lines) { Pattern pattern = Pattern.compile(regex); Matcher matcher = pattern.matcher(line); if (matcher.find()) { String type = RFile.getName().replace('R$', '').replace('.smali', ''); String name = matcher.group(1); String resetValue = publicXmlBean.getValue(type, name); if (StringUtils.isEmpty(resetValue)) { resetValue = publicXmlBean.addValue(type, matcher.group(1)); } //替換到文件內(nèi)容中 rFileContent = rFileContent.replace(line, '.field public static final ' + name + ':' + matcher.group(2) + ' = ' + resetValue); if (cacheMap != null) { //換過的值緩存起來 cacheMap.put(matcher.group(3), resetValue); } } } FileUtil.write(RFilePath, rFileContent); if (cacheMap != null) { //糾正R$styleable的值 List<String> styleAbleLines = FileUtil.readAllLines(RStyleFilePath); BufferedWriter bw = null; try { bw = new BufferedWriter(new FileWriter(RStyleFilePath)); for (String styleAbleLine : styleAbleLines) { for (String key : cacheMap.keySet()) { if (styleAbleLine.contains(key)) { styleAbleLine = styleAbleLine.replace(key, cacheMap.get(key)); } } bw.write(styleAbleLine); bw.newLine(); } } catch (IOException e) { e.printStackTrace(); } finally { if (bw != null) { try { bw.close(); } catch (IOException e) { bw = null; } } } } }

至此,糾正完了R類和public.xml的值

4、小結(jié)

游戲發(fā)行行業(yè)中,切包過程由于是多方代碼資源的一個合并過程,經(jīng)常出現(xiàn)資源沖突問題。本方案致力于優(yōu)化切包過程,自動化地解決資源沖突問題。本方案已申請專利,并在我們實際業(yè)務(wù)中使用并穩(wěn)定運行

以上就是Android 解決游戲發(fā)行切包資源索引沖突的問題的詳細(xì)內(nèi)容,更多關(guān)于Android 游戲發(fā)行切包資源索引沖突的資料請關(guān)注好吧啦網(wǎng)其它相關(guān)文章!

標(biāo)簽: Android
相關(guān)文章:
主站蜘蛛池模板: 水厂污泥地磅|污泥处理地磅厂家|地磅无人值守称重系统升级改造|地磅自动称重系统维修-河南成辉电子科技有限公司 | 沧州友城管业有限公司-内外涂塑钢管-大口径螺旋钢管-涂塑螺旋管-保温钢管生产厂家 | 权威废金属|废塑料|废纸|废铜|废钢价格|再生资源回收行情报价中心-中废网 | 欧美日韩国产一区二区三区不_久久久久国产精品无码不卡_亚洲欧洲美洲无码精品AV_精品一区美女视频_日韩黄色性爱一级视频_日本五十路人妻斩_国产99视频免费精品是看4_亚洲中文字幕无码一二三四区_国产小萍萍挤奶喷奶水_亚洲另类精品无码在线一区 | 恒温振荡混匀器-微孔板振荡器厂家-多管涡旋混匀器厂家-合肥艾本森(www.17world.net) | 99文库_实习生实用的范文资料文库站 | CTP磁天平|小电容测量仪|阴阳极极化_双液系沸点测定仪|dsj电渗实验装置-南京桑力电子设备厂 | 三价铬_环保铬_环保电镀_东莞共盈新材料贸易有限公司 | 京港视通报道-质量走进大江南北-京港视通传媒[北京]有限公司 | 蒸汽吸附分析仪-进口水分活度仪|康宝百科 | 不锈钢/气体/液体玻璃转子流量计(防腐,选型,规格)-常州天晟热工仪表有限公司【官网】 | 连续油炸机,全自动油炸机,花生米油炸机-烟台茂源食品机械制造有限公司 | 玻璃钢板-玻璃钢防腐瓦-玻璃钢材料-广东壹诺 | 陶瓷砂磨机,盘式砂磨机,棒销式砂磨机-无锡市少宏粉体科技有限公司 | CTP磁天平|小电容测量仪|阴阳极极化_双液系沸点测定仪|dsj电渗实验装置-南京桑力电子设备厂 | 北京康百特科技有限公司-分子蒸馏-短程分子蒸馏设备-实验室分子蒸馏设备 | 冲锋衣滑雪服厂家-冲锋衣定制工厂-滑雪服加工厂-广东睿牛户外(S-GERT) | elisa试剂盒-PCR试剂盒「上海谷研实业有限公司」 | 酒店厨房设计_中央厨房设计_北京商用厨房设计公司-奇能商厨 | 玻璃钢型材-玻璃钢风管-玻璃钢管道,生产厂家-[江苏欧升玻璃钢制造有限公司] | 学叉车培训|叉车证报名|叉车查询|叉车证怎么考-工程机械培训网 | 引领中高档酒店加盟_含舍·美素酒店品牌官网 | hc22_hc22价格_hc22哈氏合金—东锜特殊钢 | 金属雕花板_厂家直销_价格低-山东慧诚建筑材料有限公司 | 乐考网-银行从业_基金从业资格考试_初级/中级会计报名时间_中级经济师 | SMC-ASCO-CKD气缸-FESTO-MAC电磁阀-上海天筹自动化设备官网 | 噪声治理公司-噪音治理专业隔音降噪公司 | 优考试_免费在线考试系统_培训考试系统_题库系统_组卷答题系统_匡优考试 | SPC工作站-连杆综合检具-表盘气动量仪-内孔缺陷检测仪-杭州朗多检测仪器有限公司 | 山东齐鲁漆业有限公司【官网】-工业漆专业生产厂家 | elisa试剂盒价格-酶联免疫试剂盒-猪elisa试剂盒-上海恒远生物科技有限公司 | 馋嘴餐饮网_餐饮加盟店火爆好项目_餐饮连锁品牌加盟指南创业平台 | 环球电气之家-中国专业电气电子产品行业服务网站! | 转子泵_凸轮泵_凸轮转子泵厂家-青岛罗德通用机械设备有限公司 | 不锈钢闸阀_球阀_蝶阀_止回阀_调节阀_截止阀-可拉伐阀门(上海)有限公司 | 辐射仪|辐射检测仪|辐射巡测仪|个人剂量报警仪|表面污染检测仪|辐射报警仪|辐射防护网 | 全自动面膜机_面膜折叠机价格_面膜灌装机定制_高速折棉机厂家-深圳市益豪科技有限公司 | 土壤肥料养分速测仪_测土配方施肥仪_土壤养分检测仪-杭州鸣辉科技有限公司 | 上海物流公司,上海货运公司,上海物流专线-优骐物流公司 | 自动螺旋上料机厂家价格-斗式提升机定制-螺杆绞龙输送机-杰凯上料机 | 聚丙烯酰胺_厂家_价格-河南唐达净水材料有限公司 |