Replugin踩坑日记
Fragment坑
因为项目需要,开始接触插件化结构,最近RePlugin的信息比较火,社区比较活跃。查看了RePlugin的一些基本信息后,选择使用RePlugin作为插件化利器。
第一个需要的需求就是加载插件apk中的fragment在宿主中显示。在查看sample时,惊喜地发现其中就有相关的例子。由于RePlugin的Sample大而全,也不好直接下载运行,因此自己创建了对应的宿主,插件项目,对应的将Sample中的实例代码抽取出来并运行,是可以运行成功的。(此处比较高兴_)
但是…(转折来了o(╥﹏╥)o)
这里记录的坑是在实际操作过程中按顺序出现的(o( ̄︶ ̄)o)
Fragment加载
在使用RePlugin过程中,除了按照wiki中步骤接入宿主,插件外。就是开始在宿主中加载,调用插件内组件。目前需求的是在宿主中加载显示插件中的Fragment,因此下载到Sample来进行查看。其中的Fragment类DemoFragment,DemoCodeFragment两个类。
而创建自己的host,plugin工程后,首页需要解决的就是宿主,插件中共同的support包中的fragment。
按照官方wiki接入插件配置后,将fragment.jar也排除了。但是在运行时却还是会抛出异常ClassNotFoundException。
后来发现:
- fragment.jar版本不对,在自己创建的项目中是compileSdkVersion=28,targetSdkVersion=28.
- 在module下build.gradle中配置的排除support-v4的写法不准确。
修改:
- 将项目中已经依赖 appcompat-v7:版本号 中找到classes.jar包,将其拷贝出来后修改名为fragment.jar。
- 修改module下build.gradle中的configurations模块。
configurations {
if (rootProject.isPlugin) {
print '插件化,进行support-v4剔除工作'
all*.exclude group: 'com.android.support', module: 'support-fragment'
}
}
Sample中build.gradle在 module 的值是’support-v4’,在较新的版本中修改为 ‘support-fragment’。
这样在调用fragment的时候就你不会有问题了。
PS:相关的提示来自《插件 AppCompatActivity 与 v4.Fragment共存》
资源找不到(Resource$NotFoundException)
在使用appcompat-v7编译后,运行插件调用Activity时抛出异常,资源找不到。
4207 4207 D AndroidRuntime: Shutting down VM
09-25 15:36:32.680 4207 4207 W System.err: java.lang.RuntimeException: Unable to start activity ComponentInfo{com.xx.host/com.xx.host.loader.a.ActivityN1NRNTS5}: android.content.res.Resources$NotFoundException: Resource ID #0x7f08005a
09-25 15:36:32.680 4207 4207 W System.err: at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2681)
09-25 15:36:32.681 4207 4207 W System.err: at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2744)
09-25 15:36:32.681 4207 4207 W System.err: at android.app.ActivityThread.-wrap12(ActivityThread.java)
09-25 15:36:32.681 4207 4207 W System.err: at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1481)
09-25 15:36:32.681 4207 4207 W System.err: at android.os.Handler.dispatchMessage(Handler.java:102)
09-25 15:36:32.681 4207 4207 W System.err: at android.os.Looper.loop(Looper.java:154)
09-25 15:36:32.681 4207 4207 W System.err: at android.app.ActivityThread.main(ActivityThread.java:6144)
09-25 15:36:32.681 4207 4207 W System.err: at java.lang.reflect.Method.invoke(Native Method)
09-25 15:36:32.681 4207 4207 W System.err: at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:889)
09-25 15:36:32.681 4207 4207 W System.err: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:779)
09-25 15:36:32.681 4207 4207 W System.err: Caused by: android.content.res.Resources$NotFoundException: Resource ID #0x7f08005a
09-25 15:36:32.681 4207 4207 W System.err: at android.content.res.ResourcesImpl.getValue(ResourcesImpl.java:190)
09-25 15:36:32.681 4207 4207 W System.err: at android.content.res.Resources.getValue(Resources.java:1290)
09-25 15:36:32.681 4207 4207 W System.err: at android.support.v7.widget.AppCompatDrawableManager.createDrawableIfNeeded(AppCompatDrawableManager.java:235)
09-25 15:36:32.681 4207 4207 W System.err: at android.support.v7.widget.AppCompatDrawableManager.getDrawable(AppCompatDrawableManager.java:200)
09-25 15:36:32.682 4207 4207 W System.err: at android.support.v7.widget.AppCompatDrawableManager.getDrawable(AppCompatDrawableManager.java:191)
09-25 15:36:32.682 4207 4207 W System.err: at android.support.v7.widget.AppCompatDrawableManager.checkVectorDrawableSetup(AppCompatDrawableManager.java:753)
09-25 15:36:32.682 4207 4207 W System.err: at android.support.v7.widget.AppCompatDrawableManager.getDrawable(AppCompatDrawableManager.java:196)
09-25 15:36:32.682 4207 4207 W System.err: at android.support.v7.widget.TintTypedArray.getDrawableIfKnown(TintTypedArray.java:86)
09-25 15:36:32.682 4207 4207 W System.err: at android.support.v7.app.AppCompatDelegateImpl.<init>(AppCompatDelegateImpl.java:260)
09-25 15:36:32.682 4207 4207 W System.err: at android.support.v7.app.AppCompatDelegate.create(AppCompatDelegate.java:182)
09-25 15:36:32.682 4207 4207 W System.err: at android.support.v7.app.AppCompatActivity.getDelegate(AppCompatActivity.java:520)
09-25 15:36:32.682 4207 4207 W System.err: at android.support.v7.app.AppCompatActivity.onCreate(AppCompatActivity.java:71)
09-25 15:36:32.682 4207 4207 W System.err: at com.xx.androidteam.ui.activity.PluginTargetActivity.onCreate(PluginTargetActivity.kt:9)
09-25 15:36:32.682 4207 4207 W System.err: at android.app.Activity.performCreate(Activity.java:6727)
09-25 15:36:32.682 4207 4207 W System.err: at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1119)
09-25 15:36:32.682 4207 4207 W System.err: at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2634)
09-25 15:36:32.682 4207 4207 W System.err: ... 9 more
09-25 15:36:32.693 4207 4207 W System.err: java.io.IOException: Permission denied
09-25 15:36:32.693 4207 4207 W System.err: at java.io.UnixFileSystem.createFileExclusively0(Native Method)
09-25 15:36:32.693 4207 4207 W System.err: at java.io.UnixFileSystem.createFileExclusively(UnixFileSystem.java:280)
09-25 15:36:32.693 4207 4207 W System.err: at java.io.File.createNewFile(File.java:948)
09-25 15:36:32.693 4207 4207 W System.err: at com.xx.androidteam.ui.CrashHandler._dumpExceptionToSDCard(CrashHandler.java:149)
09-25 15:36:32.693 4207 4207 W System.err: at com.xx.androidteam.ui.CrashHandler._handleException(CrashHandler.java:117)
09-25 15:36:32.693 4207 4207 W System.err: at com.xx.androidteam.ui.CrashHandler.uncaughtException(CrashHandler.java:63)
09-25 15:36:32.693 4207 4207 W System.err: at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:1068)
09-25 15:36:32.693 4207 4207 W System.err: at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:1063)
09-25 15:36:33.145 2324 2407 D MEMGC : availMem = 1.21 GB, totalMem = 3.50 GB
09-25 15:36:33.146 2324 2407 D MEMGC : Service_0_updateWidget -- availMem = 1.21 GB, totalRam = 3.50 GB, ratioPercentFormat = 35%
09-25 15:36:34.378 2034 9922 D DeviceControlService: checkOp ------- op = UNLOCK, enabled = true
在AS中仔细查找开始没有找到如何找都无法找到,这里需要注意的是在AS有了git后,如果将build目录加入到了ignore中,在搜索时IDE不会搜索到隐藏目录中(AS 3.5)。因此直接搜索R.java文件也无果,徘徊很久不在IDE中搜索,直接在工程目录中利用其他工具进行搜索。找到了对应的R.java且找到了对应资源id(#0x7f08005a)对应的资源名。
public static final int abc_vector_test=0x7f08005a;
踩过此坑的也不在少数,这里有几种方式,参见
NotFoundException: File res/drawable/abc_vector_test.xml from drawable resourceID
矢量图相关
主要错误信息:
This app has been built with an incorrect configuration. Please configure your build for VectorDrawableCompat.
与适量图相关,查阅相关文章,appcompat-v7与矢量图不兼容。
解决:
由于我的项目中使用的矢量图较小,且APP运行设备差异性不会特别大差异,因此将原来的矢量图改为使用普通的png图。
PS: 错误信参考RePlugin issue #554
Theme.AppCompat主题问题
主要错误信息:
java.lang.IllegalStateException: You need to use a Theme.AppCompat theme (or descendant) with this activity.
显示Activity需要添加Theme.AppCompat主题。但在查看项目manifest中时,可以发现manifest文件内标签内已经添加了AppCompat主题,且为了验证问题,单独给目标Activity添加了单独的AppCompat主题。
但打包运行后依然抛出同样的错误。
java.lang.VerifyError
场景:
首页多个tab中,需要显示其中某个tab内容,其实现是Fragment内嵌套有ViewPager,FragmentPagerAdapter,Fragment显示多个可左右切换的页面。因此属于嵌套的Fragment使用。
在处理完上述的’support-fragment’包剔除工作后,在此处有遇到了类似的问题。
这里遇到的问题错误log如下:
10-09 11:12:11.128 14284 14284 E CrashHandler: java.lang.IllegalStateException: Fatal Exception thrown on Scheduler.Worker thread.
10-09 11:12:11.128 14284 14284 E CrashHandler: at rx.internal.schedulers.ScheduledAction.run(ScheduledAction.java:59)
10-09 11:12:11.128 14284 14284 E CrashHandler: at android.os.Handler.handleCallback(Handler.java:758)
10-09 11:12:11.128 14284 14284 E CrashHandler: at android.os.Handler.dispatchMessage(Handler.java:95)
10-09 11:12:11.128 14284 14284 E CrashHandler: at android.os.Looper.loop(Looper.java:154)
10-09 11:12:11.128 14284 14284 E CrashHandler: at android.app.ActivityThread.main(ActivityThread.java:6144)
10-09 11:12:11.128 14284 14284 E CrashHandler: at java.lang.reflect.Method.invoke(Native Method)
10-09 11:12:11.128 14284 14284 E CrashHandler: at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:889)
10-09 11:12:11.128 14284 14284 E CrashHandler: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:779)
10-09 11:12:11.128 14284 14284 E CrashHandler: Caused by: java.lang.VerifyError: Verifier rejected class com.androidteam.adapter.recycleradapter.MultiListNewAdapter: void com.androidteam.adapter.recycleradapter.MultiListNewAdapter._handleDailyComVPChart(com.androidteam.adapter.recyclerhelper.BaseViewHolder, java.util.ArrayList) failed to verify: void com.androidteam.adapter.recycleradapter.MultiListNewAdapter._handleDailyComVPChart(com.androidteam.adapter.recyclerhelper.BaseViewHolder, java.util.ArrayList): [0x1B2] register v10 has type Reference: com.androidteam.ui.Fragments.Chart.TabFragmentPagerAdapter but expected Reference: android.support.v4.view.PagerAdapter (declaration of 'com.androidteam.adapter.recycleradapter.MultiListNewAdapter' appears in /data/user/0/com.mobilepolice/app_p_a/-1607123362.jar)
10-09 11:12:11.128 14284 14284 E CrashHandler: at com.androidteam.ui.Activity.plugin.FrontPageActivity.loadData(FrontPageActivity.java:123)
10-09 11:12:11.128 14284 14284 E CrashHandler: at com.androidteam.ui.Fragments.Front.Personal.FrontPagePresent$14$1.onCompleted(FrontPagePresent.java:567)
10-09 11:12:11.128 14284 14284 E CrashHandler: at rx.observers.SafeSubscriber.onCompleted(SafeSubscriber.java:79)
10-09 11:12:11.128 14284 14284 E CrashHandler: at rx.internal.operators.OperatorMerge$MergeSubscriber.emitLoop(OperatorMerge.java:656)
10-09 11:12:11.128 14284 14284 E CrashHandler: at rx.internal.operators.OperatorMerge$MergeSubscriber.emit(OperatorMerge.java:568)
10-09 11:12:11.128 14284 14284 E CrashHandler: at rx.internal.operators.OperatorMerge$MergeSubscriber.onCompleted(OperatorMerge.java:281)
10-09 11:12:11.128 14284 14284 E CrashHandler: at rx.internal.operators.OnSubscribeMap$MapSubscriber.onCompleted(OnSubscribeMap.java:97)
10-09 11:12:11.128 14284 14284 E CrashHandler: at rx.observers.SerializedObserver.onCompleted(SerializedObserver.java:176)
10-09 11:12:11.128 14284 14284 E CrashHandler: at rx.observers.SerializedSubscriber.onCompleted(SerializedSubscriber.java:64)
10-09 11:12:11.128 14284 14284 E CrashHandler: at rx.internal.operators.OperatorTakeUntil$1.onCompleted(OperatorTakeUntil.java:58)
10-09 11:12:11.128 14284 14284 E CrashHandler: at rx.internal.operators.OperatorMerge$MergeSubscriber.emitLoop(OperatorMerge.java:656)
10-09 11:12:11.128 14284 14284 E CrashHandler: at rx.internal.operators.OperatorMerge$MergeSubscriber.emit(OperatorMerge.java:568)
10-09 11:12:11.128 14284 14284 E CrashHandler: at rx.internal.operators.OperatorMerge$MergeSubscriber.onCompleted(OperatorMerge.java:281)
10-09 11:12:11.128 14284 14284 E CrashHandler: at rx.internal.operators.OnSubscribeMap$MapSubscriber.onCompleted(OnSubscribeMap.java:97)
10-09 11:12:11.128 14284 14284 E CrashHandler: at rx.internal.operators.OperatorObserveOn$ObserveOnSubscriber.checkTerminated(OperatorObserveOn.java:281)
10-09 11:12:11.128 14284 14284 E CrashHandler: at rx.internal.operators.OperatorObserveOn$ObserveOnSubscriber.call(OperatorObserveOn.java:216)
10-09 11:12:11.128 14284 14284 E CrashHandler: at rx.internal.schedulers.ScheduledAction.run(ScheduledAction.java:55)
10-09 11:12:11.128 14284 14284 E CrashHandler: ... 7 more
10-09 11:12:11.467 1633 2289 E LocSvc_eng: E/Calling gnss_sv_status_cb
10-09 11:12:11.617 2034 9922 D DeviceControlService: checkOp ------- op = WIFI, enabled = true
其中主要因此加载后fragment异常退出的错误原因:
Caused by: java.lang.VerifyError: Verifier rejected class com.androidteam.adapter.recycleradapter.MultiListNewAdapter: void com.androidteam.adapter.recycleradapter.MultiListNewAdapter._handleDailyComVPChart(com.androidteam.adapter.recyclerhelper.BaseViewHolder, java.util.ArrayList) failed to verify: void com.androidteam.adapter.recycleradapter.MultiListNewAdapter._handleDailyComVPChart(com.androidteam.adapter.recyclerhelper.BaseViewHolder, java.util.ArrayList): [0x1B2] register v10 has type Reference: com.androidteam.ui.Fragments.Chart.TabFragmentPagerAdapter but expected Reference: android.support.v4.view.PagerAdapter (declaration of 'com.androidteam.adapter.recycleradapter.MultiListNewAdapter' appears in /data/user/0/com.mobilepolice/app_p_a/-1607123362.jar)
抛出java.lang.VerifyError。查阅了RePlugin官方wiki中,大多遇到的是LocalBroadcast的广播问题。而我在这里遇到的是Adapter的类型无法正确找到的错误提示。
可能出现VerifyError错误的原因,有兴趣的大家可以自己搜索。
我也搜索查看了许多其他遇到此类问题的解决方案,均无法满足或者根本不是同类问题。
最终尝试出解决方案的提示来自于VerifyError的继承关系。
注意其父类是
java.lang.LinkageError
是链接异常(字面含义),通过这个,想到了fragment最开始在插件及宿主均包含 support-fragemnt 包下,在加载Fragment显示时无法找到准确的Fragment类型来继承并实例化显示。
错误log中查看到的是PagerAdapter无法准确找到,因此查看查看源码ViewPager的setAdapter()参数继承关系,使用了FragmentPagerAdapter,其继承了PagerAdapter。
继承关系中两个类属于不同的包,查看后也可以知道两个类分别在不同的库中。FragmentPagerAdapter在 support-fragemnt 库内,而 PagerAdapter 类在 viewpager 库内。
而重点是在一开始使用的时候就剔除了 support-fragemnt ,仅在编译期参与编译而不参与打包。因此自然想到了将 viewpager 库也剔除。
在宿主工程中查看找到其classes.jar包拷贝出来,改名为 viewpager-v28.jar,拷贝到插件工程的 libs 目录下。类似剔除 fragment.jar 操作,在 build.gradle 文件的 dependencies 块中将其使用 compileOnly 进行编译期依赖。
build.gradle 修改
// 全局剔除viewpager
configurations {
if (rootProject.isPlugin) {
print '插件化,进行support-v4剔除工作'
all*.exclude group: 'com.android.support', module: 'support-fragment'
all*.exclude group: 'com.android.support', module: 'viewpager'
}
}
dependencies {
implementation files('libs/pinyin4j-2.5.0.jar')
implementation files('libs/policesdks_20170904.jar')
if (rootProject.isPlugin) {
compileOnly files('libs/fragment-v28.jar')
compileOnly files('libs/viewpager-v28.jar')
// ...
}
// ......
}
这样我解决了java.lang.VerifyError针对PagerAdapter的的检查检查异常。