├── .gitignore ├── FairyPlugin ├── .gitignore ├── agp2_3_3 │ ├── host.gradle │ ├── plugin.gradle │ └── public.xml ├── agp3_0_1 │ ├── host.gradle │ ├── plugin.gradle │ └── public.xml ├── agp3_2_1 │ ├── host.gradle │ └── plugin.gradle ├── agp3_3_1 │ ├── host.gradle │ └── plugin.gradle ├── agp3_3_2 │ ├── host.gradle │ └── plugin.gradle ├── agp3_4_0 │ ├── host.gradle │ └── plugin.gradle ├── agp3_4_1 │ ├── host.gradle │ └── plugin.gradle ├── agp3_4_2 │ ├── host.gradle │ └── plugin.gradle ├── agp3_5_0 │ ├── host.gradle │ └── plugin.gradle ├── agp3_5_3 │ ├── host.gradle │ └── plugin.gradle ├── agp4_1_3 │ ├── host.gradle │ └── plugin.gradle ├── agp4_2_1 │ ├── host.gradle │ └── plugin.gradle ├── agp7_0_3 │ ├── host.gradle │ └── plugin.gradle ├── agp7_1_3 │ ├── host.gradle │ └── plugin.gradle ├── agp7_2_0 │ ├── host.gradle │ └── plugin.gradle ├── agp7_4_2 │ ├── host.gradle │ └── plugin.gradle ├── build.gradle ├── host.gradle ├── jcenter.gradle ├── jitpack.yml ├── plugin.gradle ├── proguard-project.txt ├── proguard-rules.pro ├── project.properties └── src │ └── main │ ├── AndroidManifest.xml │ └── java │ └── com │ └── limpoxe │ └── fairy │ ├── content │ ├── LoadedPlugin.java │ ├── PluginActivityInfo.java │ ├── PluginDescriptor.java │ ├── PluginIntentFilter.java │ ├── PluginPatternMatcher.java │ ├── PluginProviderInfo.java │ └── PluginReceiverIntent.java │ ├── core │ ├── DemoApplication.java │ ├── FairyGlobal.java │ ├── HostClassLoader.java │ ├── PluginAppTrace.java │ ├── PluginBaseContextWrapper.java │ ├── PluginClassLoader.java │ ├── PluginContextTheme.java │ ├── PluginCreator.java │ ├── PluginFilter.java │ ├── PluginInjector.java │ ├── PluginInstrumentionWrapper.java │ ├── PluginIntentResolver.java │ ├── PluginLauncher.java │ ├── PluginLoader.java │ ├── PluginResourceWrapper.java │ ├── PluginThemeHelper.java │ ├── PluginViewCreator.java │ ├── RealHostClassLoader.java │ ├── RealPluginClassLoader.java │ ├── Runner.java │ ├── SyncRunnable.java │ ├── UncaugthExceptionWrapper.java │ ├── android │ │ ├── HackActivity.java │ │ ├── HackActivityManager.java │ │ ├── HackActivityManagerNative.java │ │ ├── HackActivityThread.java │ │ ├── HackActivityThreadProviderClientRecord.java │ │ ├── HackAndroidXLocalboarcastManager.java │ │ ├── HackAppBindData.java │ │ ├── HackApplication.java │ │ ├── HackApplicationPackageManager.java │ │ ├── HackAssetManager.java │ │ ├── HackComponentName.java │ │ ├── HackContentProvider.java │ │ ├── HackContentProviderClient.java │ │ ├── HackContentProviderHolder.java │ │ ├── HackContextImpl.java │ │ ├── HackContextThemeWrapper.java │ │ ├── HackContextWrapper.java │ │ ├── HackCreateServiceData.java │ │ ├── HackHandler.java │ │ ├── HackIContentProvider.java │ │ ├── HackInstrumentation.java │ │ ├── HackLayoutInflater.java │ │ ├── HackLoadedApk.java │ │ ├── HackNotificationManager.java │ │ ├── HackParceledListSlice.java │ │ ├── HackPendingIntent.java │ │ ├── HackReceiverData.java │ │ ├── HackRemoteViews.java │ │ ├── HackResources.java │ │ ├── HackService.java │ │ ├── HackServiceManager.java │ │ ├── HackSingleton.java │ │ ├── HackSupportV4LocalboarcastManager.java │ │ ├── HackToast.java │ │ ├── HackWebViewFactory.java │ │ └── HackWindow.java │ ├── annotation │ │ ├── AnnotationProcessor.java │ │ └── PluginContainer.java │ ├── bridge │ │ ├── PluginShadowProvider.java │ │ ├── PluginShadowProviderClient.java │ │ ├── PluginShadowService.java │ │ └── ProviderClientUnsafeProxy.java │ ├── compat │ │ ├── CompatForContentProvider.java │ │ ├── CompatForFragmentClassCache.java │ │ ├── CompatForSharedPreferencesImpl.java │ │ ├── CompatForSupportv7ViewInflater.java │ │ ├── CompatForSupportv7_23_2.java │ │ ├── CompatForWebViewFactoryApi21.java │ │ ├── EmptyHashMap.java │ │ └── EmptySimpleArrayMap.java │ ├── exception │ │ ├── PluginNotFoundError.java │ │ ├── PluginNotInitError.java │ │ └── PluginResInitError.java │ ├── loading │ │ └── WaitForLoadingPluginActivity.java │ ├── localservice │ │ └── LocalServiceManager.java │ ├── multidex │ │ └── PluginMultiDexHelper.java │ ├── proxy │ │ ├── MethodDelegate.java │ │ ├── MethodHandler.java │ │ ├── MethodProxy.java │ │ ├── ProxyUtil.java │ │ ├── WhiteList.java │ │ └── systemservice │ │ │ ├── AndroidAppIActivityManager.java │ │ │ ├── AndroidAppINotificationManager.java │ │ │ ├── AndroidAppIPackageManager.java │ │ │ ├── AndroidOsBinderProxyWrapper.java │ │ │ ├── AndroidOsIBinder.java │ │ │ ├── AndroidOsServiceManager.java │ │ │ ├── AndroidViewIWindowSession.java │ │ │ ├── AndroidViewWindowManager.java │ │ │ ├── AndroidWebkitWebViewFactoryProvider.java │ │ │ ├── AndroidWidgetToast.java │ │ │ └── SystemApiDelegate.java │ └── viewfactory │ │ ├── PluginFactoryCompat.java │ │ ├── PluginFactoryInterface.java │ │ ├── PluginViewFactory.java │ │ └── PluginViewInflater.java │ ├── manager │ ├── InstallResult.java │ ├── PluginActivityMonitor.java │ ├── PluginCallback.java │ ├── PluginCallbackImpl.java │ ├── PluginManager.java │ ├── PluginManagerHelper.java │ ├── PluginManagerProvider.java │ ├── PluginManagerProviderClient.java │ ├── PluginManagerService.java │ ├── PluginManifestParser.java │ ├── PluginStatusChangeListener.java │ └── mapping │ │ ├── PluginStubBinding.java │ │ ├── StubActivityExactMappingProcessor.java │ │ ├── StubActivityMappingProcessor.java │ │ ├── StubExact.java │ │ ├── StubMappingProcessor.java │ │ ├── StubReceiverMappingProcessor.java │ │ └── StubServiceMappingProcessor.java │ └── util │ ├── FakeUtil.java │ ├── FileUtil.java │ ├── FreeReflection.java │ ├── LogUtil.java │ ├── ManifestReader.java │ ├── PackageVerifyer.java │ ├── PendingIntentHelper.java │ ├── ProcessUtil.java │ ├── RefInvoker.java │ └── ResourceUtil.java ├── LICENSE.txt ├── README.md ├── Samples ├── PluginHelloWorld │ ├── .gitignore │ ├── README.md │ ├── build.gradle │ ├── jitpack.yml │ ├── proguard-rules.pro │ └── src │ │ └── main │ │ ├── AndroidManifest.xml │ │ ├── assets │ │ └── local_page_1.html │ │ ├── cpp │ │ ├── CMakeLists.txt │ │ └── hello-jni.cpp │ │ ├── java │ │ └── com │ │ │ └── example │ │ │ └── pluginhelloworld │ │ │ ├── HelloFileProvider.java │ │ │ ├── HelloJni.java │ │ │ ├── HellowWorldApplication.java │ │ │ ├── MainActivity.java │ │ │ ├── Stock.java │ │ │ ├── TransparentActivity.java │ │ │ └── WelcomeActivity.java │ │ └── res │ │ ├── layout │ │ ├── activity_main.xml │ │ ├── activity_transparent.xml │ │ └── activity_welcome.xml │ │ ├── menu │ │ └── menu_welcome.xml │ │ ├── mipmap-xhdpi │ │ └── custom_plugin_icon.png │ │ ├── values-w820dp │ │ └── dimens.xml │ │ ├── values │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── strings.xml │ │ └── styles.xml │ │ └── xml │ │ └── filepath.xml ├── PluginMain │ ├── .gitignore │ ├── build.gradle │ ├── jitpack.yml │ ├── limpoxe.keystore │ ├── proguard-project.txt │ ├── proguard-rules.pro │ ├── src │ │ └── main │ │ │ ├── AndroidManifest.xml │ │ │ ├── assets │ │ │ └── host_localweb_test.html │ │ │ ├── cpp │ │ │ ├── CMakeLists.txt │ │ │ ├── CxxTest.cpp │ │ │ ├── CxxTest2.cpp │ │ │ ├── id.c │ │ │ └── id.h │ │ │ ├── java │ │ │ └── com │ │ │ │ └── example │ │ │ │ └── pluginmain │ │ │ │ ├── CxxTest.java │ │ │ │ ├── Debug.java │ │ │ │ ├── DetailActivity.java │ │ │ │ ├── HostService.java │ │ │ │ ├── MainActivity.java │ │ │ │ ├── MainService.java │ │ │ │ ├── MessageEvent.kt │ │ │ │ ├── MyApplication.java │ │ │ │ ├── TestCaseListActivity.java │ │ │ │ ├── TestCoustProcessor.java │ │ │ │ ├── TestFragmentActivity.java │ │ │ │ ├── TestSkinActivity.java │ │ │ │ ├── TestTabActivity.java │ │ │ │ ├── TestViewActivity.java │ │ │ │ └── WebActivity.java │ │ │ ├── jniLibs │ │ │ ├── arm64-v8a │ │ │ │ └── libstub.so │ │ │ ├── armeabi-v7a │ │ │ │ └── libstub.so │ │ │ ├── x86 │ │ │ │ └── libstub.so │ │ │ └── x86_64 │ │ │ │ └── libstub.so │ │ │ └── res │ │ │ ├── anim │ │ │ ├── enter.xml │ │ │ ├── exit.xml │ │ │ ├── layout_fade_in.xml │ │ │ └── loading_fade_in.xml │ │ │ ├── drawable-v24 │ │ │ └── ic_launcher_foreground.xml │ │ │ ├── drawable │ │ │ └── ic_launcher_background.xml │ │ │ ├── layout │ │ │ ├── detail_activity.xml │ │ │ ├── fragment_activity.xml │ │ │ ├── list_item_plugin.xml │ │ │ ├── loading.xml │ │ │ ├── main_activity.xml │ │ │ ├── pop_test.xml │ │ │ ├── shin_activity.xml │ │ │ ├── tab_activity.xml │ │ │ ├── testcase_list_activity.xml │ │ │ ├── view_activity.xml │ │ │ └── web_activity.xml │ │ │ ├── mipmap-anydpi-v26 │ │ │ ├── ic_launcher.xml │ │ │ └── ic_launcher_round.xml │ │ │ ├── mipmap-xhdpi │ │ │ ├── cust_ic_launcher.png │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── values │ │ │ ├── dimens.xml │ │ │ ├── strings.xml │ │ │ └── styles.xml │ │ │ └── xml │ │ │ └── filepath.xml │ └── vcs.gradle ├── PluginShareLib │ ├── .gitignore │ ├── build.gradle │ ├── libs │ │ └── gson-2.2.4.jar │ ├── proguard-project.txt │ ├── proguard-rules.pro │ └── src │ │ └── main │ │ ├── AndroidManifest.xml │ │ ├── aidl │ │ └── com │ │ │ └── example │ │ │ └── pluginsharelib │ │ │ └── IHostAidlInterface.aidl │ │ ├── java │ │ └── com │ │ │ └── example │ │ │ ├── pluginsharelib │ │ │ ├── BaseActivity.java │ │ │ ├── RectImageView.java │ │ │ ├── ShareLayout.java │ │ │ ├── SharePOJO.java │ │ │ └── ShareService.java │ │ │ └── plugintest │ │ │ └── IMyAidlInterface.java │ │ └── res │ │ ├── anim │ │ ├── zoom_in.xml │ │ └── zoom_out.xml │ │ ├── drawable-xhdpi │ │ └── ic_launcher.png │ │ ├── layout │ │ ├── share_layout.xml │ │ └── share_main.xml │ │ └── values │ │ ├── attrs.xml │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── strings.xml │ │ └── styles.xml ├── PluginTesBase │ ├── .gitignore │ ├── build.gradle │ ├── proguard-rules.pro │ └── src │ │ └── main │ │ ├── AndroidManifest.xml │ │ └── java │ │ └── com │ │ └── example │ │ └── plugintestbase │ │ ├── ILoginService.java │ │ ├── LoginVO.java │ │ └── UserVO.java ├── PluginTest │ ├── .gitignore │ ├── build.gradle │ ├── jitpack.yml │ ├── proguard-project.txt │ ├── proguard-rules.pro │ └── src │ │ └── main │ │ ├── AndroidManifest.xml │ │ ├── assets │ │ ├── local_web_test.html │ │ └── test.json │ │ ├── cpp │ │ ├── CMakeLists.txt │ │ └── hello-jni.cpp │ │ ├── java │ │ └── com │ │ │ └── example │ │ │ └── plugintest │ │ │ ├── Log.java │ │ │ ├── PluginLoginService.java │ │ │ ├── PluginSharedService.java │ │ │ ├── PluginTestApplication.kt │ │ │ ├── activity │ │ │ ├── ButterKnifeCompat.java │ │ │ ├── CustomMappingActivity.java │ │ │ ├── DesignActivity.java │ │ │ ├── LauncherActivity.java │ │ │ ├── PluginForDialogActivity.java │ │ │ ├── PluginForOppoAndVivoActivity.java │ │ │ ├── PluginFragmentTestActivity.java │ │ │ ├── PluginNotInManifestActivity.java │ │ │ ├── PluginSingleTaskActivity.java │ │ │ ├── PluginTestActivity.java │ │ │ ├── PluginTestOpenPluginActivity.java │ │ │ ├── PluginTestTabActivity.java │ │ │ ├── PluginWebViewActivity.java │ │ │ └── TransparentActivity.java │ │ │ ├── fragment │ │ │ ├── PluginNormalFragment.java │ │ │ └── PluginSpecFragment.java │ │ │ ├── hellojni │ │ │ └── HelloJni.java │ │ │ ├── manymethods │ │ │ ├── a │ │ │ │ ├── a │ │ │ │ │ ├── A0.java │ │ │ │ │ ├── A1.java │ │ │ │ │ ├── A2.java │ │ │ │ │ ├── A3.java │ │ │ │ │ ├── A4.java │ │ │ │ │ ├── A5.java │ │ │ │ │ ├── A6.java │ │ │ │ │ ├── A7.java │ │ │ │ │ ├── A8.java │ │ │ │ │ └── A9.java │ │ │ │ ├── b │ │ │ │ │ ├── A0.java │ │ │ │ │ ├── A1.java │ │ │ │ │ ├── A2.java │ │ │ │ │ ├── A3.java │ │ │ │ │ ├── A4.java │ │ │ │ │ ├── A5.java │ │ │ │ │ ├── A6.java │ │ │ │ │ ├── A7.java │ │ │ │ │ ├── A8.java │ │ │ │ │ └── A9.java │ │ │ │ ├── c │ │ │ │ │ ├── A0.java │ │ │ │ │ ├── A1.java │ │ │ │ │ ├── A2.java │ │ │ │ │ ├── A3.java │ │ │ │ │ ├── A4.java │ │ │ │ │ ├── A5.java │ │ │ │ │ ├── A6.java │ │ │ │ │ ├── A7.java │ │ │ │ │ ├── A8.java │ │ │ │ │ └── A9.java │ │ │ │ ├── d │ │ │ │ │ ├── A0.java │ │ │ │ │ ├── A1.java │ │ │ │ │ ├── A2.java │ │ │ │ │ ├── A3.java │ │ │ │ │ ├── A4.java │ │ │ │ │ ├── A5.java │ │ │ │ │ ├── A6.java │ │ │ │ │ ├── A7.java │ │ │ │ │ ├── A8.java │ │ │ │ │ └── A9.java │ │ │ │ └── e │ │ │ │ │ ├── A0.java │ │ │ │ │ ├── A1.java │ │ │ │ │ ├── A2.java │ │ │ │ │ ├── A3.java │ │ │ │ │ ├── A4.java │ │ │ │ │ ├── A5.java │ │ │ │ │ ├── A6.java │ │ │ │ │ ├── A7.java │ │ │ │ │ ├── A8.java │ │ │ │ │ └── A9.java │ │ │ ├── b │ │ │ │ ├── a │ │ │ │ │ ├── A0.java │ │ │ │ │ ├── A1.java │ │ │ │ │ ├── A2.java │ │ │ │ │ ├── A3.java │ │ │ │ │ ├── A4.java │ │ │ │ │ ├── A5.java │ │ │ │ │ ├── A6.java │ │ │ │ │ ├── A7.java │ │ │ │ │ ├── A8.java │ │ │ │ │ └── A9.java │ │ │ │ ├── b │ │ │ │ │ ├── A0.java │ │ │ │ │ ├── A1.java │ │ │ │ │ ├── A2.java │ │ │ │ │ ├── A3.java │ │ │ │ │ ├── A4.java │ │ │ │ │ ├── A5.java │ │ │ │ │ ├── A6.java │ │ │ │ │ ├── A7.java │ │ │ │ │ ├── A8.java │ │ │ │ │ └── A9.java │ │ │ │ ├── c │ │ │ │ │ ├── A0.java │ │ │ │ │ ├── A1.java │ │ │ │ │ ├── A2.java │ │ │ │ │ ├── A3.java │ │ │ │ │ ├── A4.java │ │ │ │ │ ├── A5.java │ │ │ │ │ ├── A6.java │ │ │ │ │ ├── A7.java │ │ │ │ │ ├── A8.java │ │ │ │ │ └── A9.java │ │ │ │ ├── d │ │ │ │ │ ├── A0.java │ │ │ │ │ ├── A1.java │ │ │ │ │ ├── A2.java │ │ │ │ │ ├── A3.java │ │ │ │ │ ├── A4.java │ │ │ │ │ ├── A5.java │ │ │ │ │ ├── A6.java │ │ │ │ │ ├── A7.java │ │ │ │ │ ├── A8.java │ │ │ │ │ └── A9.java │ │ │ │ └── e │ │ │ │ │ ├── A0.java │ │ │ │ │ ├── A1.java │ │ │ │ │ ├── A2.java │ │ │ │ │ ├── A3.java │ │ │ │ │ ├── A4.java │ │ │ │ │ ├── A5.java │ │ │ │ │ ├── A6.java │ │ │ │ │ ├── A7.java │ │ │ │ │ ├── A8.java │ │ │ │ │ └── A9.java │ │ │ ├── c │ │ │ │ ├── a │ │ │ │ │ ├── A0.java │ │ │ │ │ ├── A1.java │ │ │ │ │ ├── A2.java │ │ │ │ │ ├── A3.java │ │ │ │ │ ├── A4.java │ │ │ │ │ ├── A5.java │ │ │ │ │ ├── A6.java │ │ │ │ │ ├── A7.java │ │ │ │ │ ├── A8.java │ │ │ │ │ └── A9.java │ │ │ │ ├── b │ │ │ │ │ ├── A0.java │ │ │ │ │ ├── A1.java │ │ │ │ │ ├── A2.java │ │ │ │ │ ├── A3.java │ │ │ │ │ ├── A4.java │ │ │ │ │ ├── A5.java │ │ │ │ │ ├── A6.java │ │ │ │ │ ├── A7.java │ │ │ │ │ ├── A8.java │ │ │ │ │ └── A9.java │ │ │ │ ├── c │ │ │ │ │ ├── A0.java │ │ │ │ │ ├── A1.java │ │ │ │ │ ├── A2.java │ │ │ │ │ ├── A3.java │ │ │ │ │ ├── A4.java │ │ │ │ │ ├── A5.java │ │ │ │ │ ├── A6.java │ │ │ │ │ ├── A7.java │ │ │ │ │ ├── A8.java │ │ │ │ │ └── A9.java │ │ │ │ ├── d │ │ │ │ │ ├── A0.java │ │ │ │ │ ├── A1.java │ │ │ │ │ ├── A2.java │ │ │ │ │ ├── A3.java │ │ │ │ │ ├── A4.java │ │ │ │ │ ├── A5.java │ │ │ │ │ ├── A6.java │ │ │ │ │ ├── A7.java │ │ │ │ │ ├── A8.java │ │ │ │ │ └── A9.java │ │ │ │ └── e │ │ │ │ │ ├── A0.java │ │ │ │ │ ├── A1.java │ │ │ │ │ ├── A2.java │ │ │ │ │ ├── A3.java │ │ │ │ │ ├── A4.java │ │ │ │ │ ├── A5.java │ │ │ │ │ ├── A6.java │ │ │ │ │ ├── A7.java │ │ │ │ │ ├── A8.java │ │ │ │ │ └── A9.java │ │ │ ├── d │ │ │ │ ├── a │ │ │ │ │ ├── A0.java │ │ │ │ │ ├── A1.java │ │ │ │ │ ├── A2.java │ │ │ │ │ ├── A3.java │ │ │ │ │ ├── A4.java │ │ │ │ │ ├── A5.java │ │ │ │ │ ├── A6.java │ │ │ │ │ ├── A7.java │ │ │ │ │ ├── A8.java │ │ │ │ │ └── A9.java │ │ │ │ ├── b │ │ │ │ │ ├── A0.java │ │ │ │ │ ├── A1.java │ │ │ │ │ ├── A2.java │ │ │ │ │ ├── A3.java │ │ │ │ │ ├── A4.java │ │ │ │ │ ├── A5.java │ │ │ │ │ ├── A6.java │ │ │ │ │ ├── A7.java │ │ │ │ │ ├── A8.java │ │ │ │ │ └── A9.java │ │ │ │ ├── c │ │ │ │ │ ├── A0.java │ │ │ │ │ ├── A1.java │ │ │ │ │ ├── A2.java │ │ │ │ │ ├── A3.java │ │ │ │ │ ├── A4.java │ │ │ │ │ ├── A5.java │ │ │ │ │ ├── A6.java │ │ │ │ │ ├── A7.java │ │ │ │ │ ├── A8.java │ │ │ │ │ └── A9.java │ │ │ │ ├── d │ │ │ │ │ ├── A0.java │ │ │ │ │ ├── A1.java │ │ │ │ │ ├── A2.java │ │ │ │ │ ├── A3.java │ │ │ │ │ ├── A4.java │ │ │ │ │ ├── A5.java │ │ │ │ │ ├── A6.java │ │ │ │ │ ├── A7.java │ │ │ │ │ ├── A8.java │ │ │ │ │ └── A9.java │ │ │ │ └── e │ │ │ │ │ ├── A0.java │ │ │ │ │ ├── A1.java │ │ │ │ │ ├── A2.java │ │ │ │ │ ├── A3.java │ │ │ │ │ ├── A4.java │ │ │ │ │ ├── A5.java │ │ │ │ │ ├── A6.java │ │ │ │ │ ├── A7.java │ │ │ │ │ ├── A8.java │ │ │ │ │ └── A9.java │ │ │ ├── e │ │ │ │ ├── a │ │ │ │ │ ├── A0.java │ │ │ │ │ ├── A1.java │ │ │ │ │ ├── A2.java │ │ │ │ │ ├── A3.java │ │ │ │ │ ├── A4.java │ │ │ │ │ ├── A5.java │ │ │ │ │ ├── A6.java │ │ │ │ │ ├── A7.java │ │ │ │ │ ├── A8.java │ │ │ │ │ └── A9.java │ │ │ │ ├── b │ │ │ │ │ ├── A0.java │ │ │ │ │ ├── A1.java │ │ │ │ │ ├── A2.java │ │ │ │ │ ├── A3.java │ │ │ │ │ ├── A4.java │ │ │ │ │ ├── A5.java │ │ │ │ │ ├── A6.java │ │ │ │ │ ├── A7.java │ │ │ │ │ ├── A8.java │ │ │ │ │ └── A9.java │ │ │ │ ├── c │ │ │ │ │ ├── A0.java │ │ │ │ │ ├── A1.java │ │ │ │ │ ├── A2.java │ │ │ │ │ ├── A3.java │ │ │ │ │ ├── A4.java │ │ │ │ │ ├── A5.java │ │ │ │ │ ├── A6.java │ │ │ │ │ ├── A7.java │ │ │ │ │ ├── A8.java │ │ │ │ │ └── A9.java │ │ │ │ ├── d │ │ │ │ │ ├── A0.java │ │ │ │ │ ├── A1.java │ │ │ │ │ ├── A2.java │ │ │ │ │ ├── A3.java │ │ │ │ │ ├── A4.java │ │ │ │ │ ├── A5.java │ │ │ │ │ ├── A6.java │ │ │ │ │ ├── A7.java │ │ │ │ │ ├── A8.java │ │ │ │ │ └── A9.java │ │ │ │ └── e │ │ │ │ │ ├── A0.java │ │ │ │ │ ├── A1.java │ │ │ │ │ ├── A2.java │ │ │ │ │ ├── A3.java │ │ │ │ │ ├── A4.java │ │ │ │ │ ├── A5.java │ │ │ │ │ ├── A6.java │ │ │ │ │ ├── A7.java │ │ │ │ │ ├── A8.java │ │ │ │ │ └── A9.java │ │ │ ├── f │ │ │ │ ├── a │ │ │ │ │ ├── A0.java │ │ │ │ │ ├── A1.java │ │ │ │ │ ├── A2.java │ │ │ │ │ ├── A3.java │ │ │ │ │ ├── A4.java │ │ │ │ │ ├── A5.java │ │ │ │ │ ├── A6.java │ │ │ │ │ ├── A7.java │ │ │ │ │ ├── A8.java │ │ │ │ │ └── A9.java │ │ │ │ ├── b │ │ │ │ │ ├── A0.java │ │ │ │ │ ├── A1.java │ │ │ │ │ ├── A2.java │ │ │ │ │ ├── A3.java │ │ │ │ │ ├── A4.java │ │ │ │ │ ├── A5.java │ │ │ │ │ ├── A6.java │ │ │ │ │ ├── A7.java │ │ │ │ │ ├── A8.java │ │ │ │ │ └── A9.java │ │ │ │ ├── c │ │ │ │ │ ├── A0.java │ │ │ │ │ ├── A1.java │ │ │ │ │ ├── A2.java │ │ │ │ │ ├── A3.java │ │ │ │ │ ├── A4.java │ │ │ │ │ ├── A5.java │ │ │ │ │ ├── A6.java │ │ │ │ │ ├── A7.java │ │ │ │ │ ├── A8.java │ │ │ │ │ └── A9.java │ │ │ │ ├── d │ │ │ │ │ ├── A0.java │ │ │ │ │ ├── A1.java │ │ │ │ │ ├── A2.java │ │ │ │ │ ├── A3.java │ │ │ │ │ ├── A4.java │ │ │ │ │ ├── A5.java │ │ │ │ │ ├── A6.java │ │ │ │ │ ├── A7.java │ │ │ │ │ ├── A8.java │ │ │ │ │ └── A9.java │ │ │ │ └── e │ │ │ │ │ ├── A0.java │ │ │ │ │ ├── A1.java │ │ │ │ │ ├── A2.java │ │ │ │ │ ├── A3.java │ │ │ │ │ ├── A4.java │ │ │ │ │ ├── A5.java │ │ │ │ │ ├── A6.java │ │ │ │ │ ├── A7.java │ │ │ │ │ ├── A8.java │ │ │ │ │ └── A9.java │ │ │ ├── g │ │ │ │ ├── a │ │ │ │ │ ├── A0.java │ │ │ │ │ ├── A1.java │ │ │ │ │ ├── A2.java │ │ │ │ │ ├── A3.java │ │ │ │ │ ├── A4.java │ │ │ │ │ ├── A5.java │ │ │ │ │ ├── A6.java │ │ │ │ │ ├── A7.java │ │ │ │ │ ├── A8.java │ │ │ │ │ └── A9.java │ │ │ │ ├── b │ │ │ │ │ ├── A0.java │ │ │ │ │ ├── A1.java │ │ │ │ │ ├── A2.java │ │ │ │ │ ├── A3.java │ │ │ │ │ ├── A4.java │ │ │ │ │ ├── A5.java │ │ │ │ │ ├── A6.java │ │ │ │ │ ├── A7.java │ │ │ │ │ ├── A8.java │ │ │ │ │ └── A9.java │ │ │ │ ├── c │ │ │ │ │ ├── A0.java │ │ │ │ │ ├── A1.java │ │ │ │ │ ├── A2.java │ │ │ │ │ ├── A3.java │ │ │ │ │ ├── A4.java │ │ │ │ │ ├── A5.java │ │ │ │ │ ├── A6.java │ │ │ │ │ ├── A7.java │ │ │ │ │ ├── A8.java │ │ │ │ │ └── A9.java │ │ │ │ ├── d │ │ │ │ │ ├── A0.java │ │ │ │ │ ├── A1.java │ │ │ │ │ ├── A2.java │ │ │ │ │ ├── A3.java │ │ │ │ │ ├── A4.java │ │ │ │ │ ├── A5.java │ │ │ │ │ ├── A6.java │ │ │ │ │ ├── A7.java │ │ │ │ │ ├── A8.java │ │ │ │ │ └── A9.java │ │ │ │ └── e │ │ │ │ │ ├── A0.java │ │ │ │ │ ├── A1.java │ │ │ │ │ ├── A2.java │ │ │ │ │ ├── A3.java │ │ │ │ │ ├── A4.java │ │ │ │ │ ├── A5.java │ │ │ │ │ ├── A6.java │ │ │ │ │ ├── A7.java │ │ │ │ │ ├── A8.java │ │ │ │ │ └── A9.java │ │ │ ├── h │ │ │ │ ├── a │ │ │ │ │ ├── A0.java │ │ │ │ │ ├── A1.java │ │ │ │ │ ├── A2.java │ │ │ │ │ ├── A3.java │ │ │ │ │ ├── A4.java │ │ │ │ │ ├── A5.java │ │ │ │ │ ├── A6.java │ │ │ │ │ ├── A7.java │ │ │ │ │ ├── A8.java │ │ │ │ │ └── A9.java │ │ │ │ ├── b │ │ │ │ │ ├── A0.java │ │ │ │ │ ├── A1.java │ │ │ │ │ ├── A2.java │ │ │ │ │ ├── A3.java │ │ │ │ │ ├── A4.java │ │ │ │ │ ├── A5.java │ │ │ │ │ ├── A6.java │ │ │ │ │ ├── A7.java │ │ │ │ │ ├── A8.java │ │ │ │ │ └── A9.java │ │ │ │ ├── c │ │ │ │ │ ├── A0.java │ │ │ │ │ ├── A1.java │ │ │ │ │ ├── A2.java │ │ │ │ │ ├── A3.java │ │ │ │ │ ├── A4.java │ │ │ │ │ ├── A5.java │ │ │ │ │ ├── A6.java │ │ │ │ │ ├── A7.java │ │ │ │ │ ├── A8.java │ │ │ │ │ └── A9.java │ │ │ │ ├── d │ │ │ │ │ ├── A0.java │ │ │ │ │ ├── A1.java │ │ │ │ │ ├── A2.java │ │ │ │ │ ├── A3.java │ │ │ │ │ ├── A4.java │ │ │ │ │ ├── A5.java │ │ │ │ │ ├── A6.java │ │ │ │ │ ├── A7.java │ │ │ │ │ ├── A8.java │ │ │ │ │ └── A9.java │ │ │ │ └── e │ │ │ │ │ ├── A0.java │ │ │ │ │ ├── A1.java │ │ │ │ │ ├── A2.java │ │ │ │ │ ├── A3.java │ │ │ │ │ ├── A4.java │ │ │ │ │ ├── A5.java │ │ │ │ │ ├── A6.java │ │ │ │ │ ├── A7.java │ │ │ │ │ ├── A8.java │ │ │ │ │ └── A9.java │ │ │ ├── i │ │ │ │ ├── a │ │ │ │ │ ├── A0.java │ │ │ │ │ ├── A1.java │ │ │ │ │ ├── A2.java │ │ │ │ │ ├── A3.java │ │ │ │ │ ├── A4.java │ │ │ │ │ ├── A5.java │ │ │ │ │ ├── A6.java │ │ │ │ │ ├── A7.java │ │ │ │ │ ├── A8.java │ │ │ │ │ └── A9.java │ │ │ │ ├── b │ │ │ │ │ ├── A0.java │ │ │ │ │ ├── A1.java │ │ │ │ │ ├── A2.java │ │ │ │ │ ├── A3.java │ │ │ │ │ ├── A4.java │ │ │ │ │ ├── A5.java │ │ │ │ │ ├── A6.java │ │ │ │ │ ├── A7.java │ │ │ │ │ ├── A8.java │ │ │ │ │ └── A9.java │ │ │ │ ├── c │ │ │ │ │ ├── A0.java │ │ │ │ │ ├── A1.java │ │ │ │ │ ├── A2.java │ │ │ │ │ ├── A3.java │ │ │ │ │ ├── A4.java │ │ │ │ │ ├── A5.java │ │ │ │ │ ├── A6.java │ │ │ │ │ ├── A7.java │ │ │ │ │ ├── A8.java │ │ │ │ │ └── A9.java │ │ │ │ ├── d │ │ │ │ │ ├── A0.java │ │ │ │ │ ├── A1.java │ │ │ │ │ ├── A2.java │ │ │ │ │ ├── A3.java │ │ │ │ │ ├── A4.java │ │ │ │ │ ├── A5.java │ │ │ │ │ ├── A6.java │ │ │ │ │ ├── A7.java │ │ │ │ │ ├── A8.java │ │ │ │ │ └── A9.java │ │ │ │ └── e │ │ │ │ │ ├── A0.java │ │ │ │ │ ├── A1.java │ │ │ │ │ ├── A2.java │ │ │ │ │ ├── A3.java │ │ │ │ │ ├── A4.java │ │ │ │ │ ├── A5.java │ │ │ │ │ ├── A6.java │ │ │ │ │ ├── A7.java │ │ │ │ │ ├── A8.java │ │ │ │ │ └── A9.java │ │ │ ├── j │ │ │ │ ├── a │ │ │ │ │ ├── A0.java │ │ │ │ │ ├── A1.java │ │ │ │ │ ├── A2.java │ │ │ │ │ ├── A3.java │ │ │ │ │ ├── A4.java │ │ │ │ │ ├── A5.java │ │ │ │ │ ├── A6.java │ │ │ │ │ ├── A7.java │ │ │ │ │ ├── A8.java │ │ │ │ │ └── A9.java │ │ │ │ ├── b │ │ │ │ │ ├── A0.java │ │ │ │ │ ├── A1.java │ │ │ │ │ ├── A2.java │ │ │ │ │ ├── A3.java │ │ │ │ │ ├── A4.java │ │ │ │ │ ├── A5.java │ │ │ │ │ ├── A6.java │ │ │ │ │ ├── A7.java │ │ │ │ │ ├── A8.java │ │ │ │ │ └── A9.java │ │ │ │ ├── c │ │ │ │ │ ├── A0.java │ │ │ │ │ ├── A1.java │ │ │ │ │ ├── A2.java │ │ │ │ │ ├── A3.java │ │ │ │ │ ├── A4.java │ │ │ │ │ ├── A5.java │ │ │ │ │ ├── A6.java │ │ │ │ │ ├── A7.java │ │ │ │ │ ├── A8.java │ │ │ │ │ └── A9.java │ │ │ │ ├── d │ │ │ │ │ ├── A0.java │ │ │ │ │ ├── A1.java │ │ │ │ │ ├── A2.java │ │ │ │ │ ├── A3.java │ │ │ │ │ ├── A4.java │ │ │ │ │ ├── A5.java │ │ │ │ │ ├── A6.java │ │ │ │ │ ├── A7.java │ │ │ │ │ ├── A8.java │ │ │ │ │ └── A9.java │ │ │ │ └── e │ │ │ │ │ ├── A0.java │ │ │ │ │ ├── A1.java │ │ │ │ │ ├── A2.java │ │ │ │ │ ├── A3.java │ │ │ │ │ ├── A4.java │ │ │ │ │ ├── A5.java │ │ │ │ │ ├── A6.java │ │ │ │ │ ├── A7.java │ │ │ │ │ ├── A8.java │ │ │ │ │ └── A9.java │ │ │ ├── k │ │ │ │ ├── a │ │ │ │ │ ├── A0.java │ │ │ │ │ ├── A1.java │ │ │ │ │ ├── A2.java │ │ │ │ │ ├── A3.java │ │ │ │ │ ├── A4.java │ │ │ │ │ ├── A5.java │ │ │ │ │ ├── A6.java │ │ │ │ │ ├── A7.java │ │ │ │ │ ├── A8.java │ │ │ │ │ └── A9.java │ │ │ │ ├── b │ │ │ │ │ ├── A0.java │ │ │ │ │ ├── A1.java │ │ │ │ │ ├── A2.java │ │ │ │ │ ├── A3.java │ │ │ │ │ ├── A4.java │ │ │ │ │ ├── A5.java │ │ │ │ │ ├── A6.java │ │ │ │ │ ├── A7.java │ │ │ │ │ ├── A8.java │ │ │ │ │ └── A9.java │ │ │ │ ├── c │ │ │ │ │ ├── A0.java │ │ │ │ │ ├── A1.java │ │ │ │ │ ├── A2.java │ │ │ │ │ ├── A3.java │ │ │ │ │ ├── A4.java │ │ │ │ │ ├── A5.java │ │ │ │ │ ├── A6.java │ │ │ │ │ ├── A7.java │ │ │ │ │ ├── A8.java │ │ │ │ │ └── A9.java │ │ │ │ ├── d │ │ │ │ │ ├── A0.java │ │ │ │ │ ├── A1.java │ │ │ │ │ ├── A2.java │ │ │ │ │ ├── A3.java │ │ │ │ │ ├── A4.java │ │ │ │ │ ├── A5.java │ │ │ │ │ ├── A6.java │ │ │ │ │ ├── A7.java │ │ │ │ │ ├── A8.java │ │ │ │ │ └── A9.java │ │ │ │ └── e │ │ │ │ │ ├── A0.java │ │ │ │ │ ├── A1.java │ │ │ │ │ ├── A2.java │ │ │ │ │ ├── A3.java │ │ │ │ │ ├── A4.java │ │ │ │ │ ├── A5.java │ │ │ │ │ ├── A6.java │ │ │ │ │ ├── A7.java │ │ │ │ │ ├── A8.java │ │ │ │ │ └── A9.java │ │ │ ├── l │ │ │ │ ├── a │ │ │ │ │ ├── A0.java │ │ │ │ │ ├── A1.java │ │ │ │ │ ├── A2.java │ │ │ │ │ ├── A3.java │ │ │ │ │ ├── A4.java │ │ │ │ │ ├── A5.java │ │ │ │ │ ├── A6.java │ │ │ │ │ ├── A7.java │ │ │ │ │ ├── A8.java │ │ │ │ │ └── A9.java │ │ │ │ ├── b │ │ │ │ │ ├── A0.java │ │ │ │ │ ├── A1.java │ │ │ │ │ ├── A2.java │ │ │ │ │ ├── A3.java │ │ │ │ │ ├── A4.java │ │ │ │ │ ├── A5.java │ │ │ │ │ ├── A6.java │ │ │ │ │ ├── A7.java │ │ │ │ │ ├── A8.java │ │ │ │ │ └── A9.java │ │ │ │ ├── c │ │ │ │ │ ├── A0.java │ │ │ │ │ ├── A1.java │ │ │ │ │ ├── A2.java │ │ │ │ │ ├── A3.java │ │ │ │ │ ├── A4.java │ │ │ │ │ ├── A5.java │ │ │ │ │ ├── A6.java │ │ │ │ │ ├── A7.java │ │ │ │ │ ├── A8.java │ │ │ │ │ └── A9.java │ │ │ │ ├── d │ │ │ │ │ ├── A0.java │ │ │ │ │ ├── A1.java │ │ │ │ │ ├── A2.java │ │ │ │ │ ├── A3.java │ │ │ │ │ ├── A4.java │ │ │ │ │ ├── A5.java │ │ │ │ │ ├── A6.java │ │ │ │ │ ├── A7.java │ │ │ │ │ ├── A8.java │ │ │ │ │ └── A9.java │ │ │ │ └── e │ │ │ │ │ ├── A0.java │ │ │ │ │ ├── A1.java │ │ │ │ │ ├── A2.java │ │ │ │ │ ├── A3.java │ │ │ │ │ ├── A4.java │ │ │ │ │ ├── A5.java │ │ │ │ │ ├── A6.java │ │ │ │ │ ├── A7.java │ │ │ │ │ ├── A8.java │ │ │ │ │ └── A9.java │ │ │ ├── m │ │ │ │ ├── a │ │ │ │ │ ├── A0.java │ │ │ │ │ ├── A1.java │ │ │ │ │ ├── A2.java │ │ │ │ │ ├── A3.java │ │ │ │ │ ├── A4.java │ │ │ │ │ ├── A5.java │ │ │ │ │ ├── A6.java │ │ │ │ │ ├── A7.java │ │ │ │ │ ├── A8.java │ │ │ │ │ └── A9.java │ │ │ │ ├── b │ │ │ │ │ ├── A0.java │ │ │ │ │ ├── A1.java │ │ │ │ │ ├── A2.java │ │ │ │ │ ├── A3.java │ │ │ │ │ ├── A4.java │ │ │ │ │ ├── A5.java │ │ │ │ │ ├── A6.java │ │ │ │ │ ├── A7.java │ │ │ │ │ ├── A8.java │ │ │ │ │ └── A9.java │ │ │ │ ├── c │ │ │ │ │ ├── A0.java │ │ │ │ │ ├── A1.java │ │ │ │ │ ├── A2.java │ │ │ │ │ ├── A3.java │ │ │ │ │ ├── A4.java │ │ │ │ │ ├── A5.java │ │ │ │ │ ├── A6.java │ │ │ │ │ ├── A7.java │ │ │ │ │ ├── A8.java │ │ │ │ │ └── A9.java │ │ │ │ ├── d │ │ │ │ │ ├── A0.java │ │ │ │ │ ├── A1.java │ │ │ │ │ ├── A2.java │ │ │ │ │ ├── A3.java │ │ │ │ │ ├── A4.java │ │ │ │ │ ├── A5.java │ │ │ │ │ ├── A6.java │ │ │ │ │ ├── A7.java │ │ │ │ │ ├── A8.java │ │ │ │ │ └── A9.java │ │ │ │ └── e │ │ │ │ │ ├── A0.java │ │ │ │ │ ├── A1.java │ │ │ │ │ ├── A2.java │ │ │ │ │ ├── A3.java │ │ │ │ │ ├── A4.java │ │ │ │ │ ├── A5.java │ │ │ │ │ ├── A6.java │ │ │ │ │ ├── A7.java │ │ │ │ │ ├── A8.java │ │ │ │ │ └── A9.java │ │ │ └── n │ │ │ │ ├── a │ │ │ │ ├── A0.java │ │ │ │ ├── A1.java │ │ │ │ ├── A2.java │ │ │ │ ├── A3.java │ │ │ │ ├── A4.java │ │ │ │ ├── A5.java │ │ │ │ ├── A6.java │ │ │ │ ├── A7.java │ │ │ │ ├── A8.java │ │ │ │ └── A9.java │ │ │ │ ├── b │ │ │ │ ├── A0.java │ │ │ │ ├── A1.java │ │ │ │ ├── A2.java │ │ │ │ ├── A3.java │ │ │ │ ├── A4.java │ │ │ │ ├── A5.java │ │ │ │ ├── A6.java │ │ │ │ ├── A7.java │ │ │ │ ├── A8.java │ │ │ │ └── A9.java │ │ │ │ ├── c │ │ │ │ ├── A0.java │ │ │ │ ├── A1.java │ │ │ │ ├── A2.java │ │ │ │ ├── A3.java │ │ │ │ ├── A4.java │ │ │ │ ├── A5.java │ │ │ │ ├── A6.java │ │ │ │ ├── A7.java │ │ │ │ ├── A8.java │ │ │ │ └── A9.java │ │ │ │ ├── d │ │ │ │ ├── A0.java │ │ │ │ ├── A1.java │ │ │ │ ├── A2.java │ │ │ │ ├── A3.java │ │ │ │ ├── A4.java │ │ │ │ ├── A5.java │ │ │ │ ├── A6.java │ │ │ │ ├── A7.java │ │ │ │ ├── A8.java │ │ │ │ └── A9.java │ │ │ │ └── e │ │ │ │ ├── A0.java │ │ │ │ ├── A1.java │ │ │ │ ├── A2.java │ │ │ │ ├── A3.java │ │ │ │ ├── A4.java │ │ │ │ ├── A5.java │ │ │ │ ├── A6.java │ │ │ │ ├── A7.java │ │ │ │ ├── A8.java │ │ │ │ └── A9.java │ │ │ ├── provider │ │ │ ├── PluginDbTables.java │ │ │ ├── PluginTestProvider.java │ │ │ └── TestFileProvider.java │ │ │ ├── receiver │ │ │ ├── BootCompletedReceiver.java │ │ │ ├── PluginTestReceiver.java │ │ │ └── PluginTestReceiver2.java │ │ │ ├── service │ │ │ ├── PluginTestService.java │ │ │ ├── PluginTestService2.java │ │ │ └── TestAccessibilitySerivce.java │ │ │ ├── view │ │ │ ├── PluginSurfceView.java │ │ │ ├── PluginTestCustomAttrView.java │ │ │ ├── PluginTestLayout.java │ │ │ └── PluginTestView.java │ │ │ └── vo │ │ │ ├── DataBindingTestVO.java │ │ │ └── ParamVO.java │ │ └── res │ │ ├── anim │ │ ├── enter1.xml │ │ └── exit1.xml │ │ ├── drawable-v24 │ │ └── ic_launcher_foreground.xml │ │ ├── drawable-xhdpi │ │ ├── btn_selector.xml │ │ ├── ic_dashboard.png │ │ ├── ic_discuss.png │ │ ├── ic_done.png │ │ ├── ic_event.png │ │ ├── ic_forum.png │ │ ├── ic_headset.png │ │ ├── ic_launcher.png │ │ ├── ic_menu.png │ │ ├── icon_launcher.png │ │ └── tablayout_bg.xml │ │ ├── drawable │ │ └── ic_launcher_background.xml │ │ ├── layout │ │ ├── activity_transparent.xml │ │ ├── design_activity.xml │ │ ├── include_list_view_pager.xml │ │ ├── nav_header.xml │ │ ├── plugin_cust_stub_activity.xml │ │ ├── plugin_launcher.xml │ │ ├── plugin_layout.xml │ │ ├── plugin_notification.xml │ │ ├── plugin_tab_activity.xml │ │ ├── plugin_test_view.xml │ │ └── plugin_webview.xml │ │ ├── menu │ │ ├── drawer_view.xml │ │ └── sample_actions.xml │ │ ├── mipmap-anydpi-v26 │ │ ├── ic_launcher.xml │ │ └── ic_launcher_round.xml │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── values │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── strings.xml │ │ └── styles.xml │ │ └── xml │ │ └── filepath.xml ├── PluginTest2 │ ├── .gitignore │ ├── build.gradle │ ├── proguard-rules.pro │ └── src │ │ └── main │ │ ├── AndroidManifest.xml │ │ ├── java │ │ ├── com │ │ │ └── mdroid │ │ │ │ └── repo │ │ │ │ └── depth_lib_android_ │ │ │ │ ├── BearSceneView.java │ │ │ │ ├── Foam.java │ │ │ │ ├── MenuAnimation.java │ │ │ │ ├── PlayGroundActivity.java │ │ │ │ ├── RenderableBear.java │ │ │ │ ├── RenderableThree.java │ │ │ │ ├── RootActivity.java │ │ │ │ ├── Smoke.java │ │ │ │ ├── TransitionHelper.java │ │ │ │ ├── Water.java │ │ │ │ ├── WaterFragment.java │ │ │ │ ├── WaterSceneView.java │ │ │ │ └── WindFragment.java │ │ └── no │ │ │ └── agens │ │ │ └── depth │ │ │ └── lib │ │ │ ├── CircularSplashView.java │ │ │ ├── ColorAnimator.java │ │ │ ├── CustomShadow.java │ │ │ ├── DepthLayout.java │ │ │ ├── DepthRendrer.java │ │ │ ├── MaterialMenuDrawable.java │ │ │ ├── MathHelper.java │ │ │ ├── RectEvaluator.java │ │ │ ├── RectFEvaluator.java │ │ │ ├── RippleHelper.java │ │ │ ├── headers │ │ │ ├── AuraDrawable.java │ │ │ ├── NoiseEffect.java │ │ │ ├── Particle.java │ │ │ ├── ParticleSystem.java │ │ │ ├── PathBitmapMesh.java │ │ │ └── Renderable.java │ │ │ └── tween │ │ │ ├── FrameRateCounter.java │ │ │ ├── ReboundObjectAnimator.java │ │ │ ├── TRectFEvaluator.java │ │ │ └── interpolators │ │ │ ├── BackIn.java │ │ │ ├── BackInOut.java │ │ │ ├── BackOut.java │ │ │ ├── CircIn.java │ │ │ ├── CircInOut.java │ │ │ ├── CircOut.java │ │ │ ├── ElasticIn.java │ │ │ ├── ElasticInOut.java │ │ │ ├── ElasticOut.java │ │ │ ├── ExpoIn.java │ │ │ ├── ExpoInOut.java │ │ │ ├── ExpoOut.java │ │ │ ├── QuadIn.java │ │ │ ├── QuadInOut.java │ │ │ ├── QuadOut.java │ │ │ ├── QuartIn.java │ │ │ ├── QuartInOut.java │ │ │ ├── QuartOut.java │ │ │ ├── QuintIn.java │ │ │ ├── QuintInOut.java │ │ │ ├── QuintOut.java │ │ │ ├── SineIn.java │ │ │ ├── SineInOut.java │ │ │ └── SineOut.java │ │ └── res │ │ ├── drawable-xxhdpi │ │ ├── actionbar_shadow.png │ │ ├── aura_gradient.png │ │ ├── aura_gradient_inner.png │ │ ├── bear_1.png │ │ ├── bear_2.png │ │ ├── bear_white.png │ │ ├── foam.png │ │ ├── grunge.png │ │ ├── ic_forward.png │ │ ├── ic_launcher.png │ │ ├── ic_menu.png │ │ ├── icon_launcher.png │ │ ├── noise.png │ │ ├── noise_scratch.png │ │ ├── smoke.png │ │ ├── splash1.png │ │ ├── splash2.png │ │ ├── splash3.png │ │ ├── splash4.png │ │ ├── stones.png │ │ ├── sun.png │ │ ├── sun_aura.png │ │ ├── tree.png │ │ ├── water.png │ │ ├── water_scene_background.9.png │ │ └── x_y.png │ │ ├── drawable │ │ ├── bear_bg_gradient.xml │ │ ├── circle.xml │ │ ├── menu_btn.xml │ │ ├── menu_btn2.xml │ │ ├── menu_btn3.xml │ │ ├── menu_btn4.xml │ │ ├── round_soft_shadow.png │ │ └── shadow.9.png │ │ ├── layout │ │ ├── activity_root.xml │ │ ├── fragment_playground.xml │ │ ├── fragment_water.xml │ │ ├── fragment_wind.xml │ │ └── menu_item.xml │ │ └── values │ │ ├── colors.xml │ │ ├── dept_view.xml │ │ ├── dimens.xml │ │ ├── strings.xml │ │ └── values.xml ├── README.md ├── admobdemo │ ├── .gitignore │ ├── build.gradle │ ├── proguard-rules.pro │ └── src │ │ └── main │ │ ├── AndroidManifest.xml │ │ ├── java │ │ └── cn │ │ │ └── ckh │ │ │ └── admob │ │ │ ├── GADManager.java │ │ │ └── MainActivity.java │ │ └── res │ │ ├── layout │ │ └── activity_main.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ └── values │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── styles.xml ├── baidumapsdk │ ├── .gitignore │ ├── build.gradle │ ├── libs │ │ └── BaiduLBS_Android.jar │ ├── proguard-rules.pro │ └── src │ │ └── main │ │ ├── AndroidManifest.xml │ │ ├── java │ │ └── com │ │ │ └── limpoxe │ │ │ └── baidumapsdk │ │ │ └── MainActivity.java │ │ ├── jniLibs │ │ └── armeabi-v7a │ │ │ ├── libBaiduMapSDK_base_v4_1_1.so │ │ │ ├── libBaiduMapSDK_cloud_v4_1_1.so │ │ │ ├── libBaiduMapSDK_map_v4_1_1.so │ │ │ ├── libBaiduMapSDK_radar_v4_1_1.so │ │ │ ├── libBaiduMapSDK_search_v4_1_1.so │ │ │ ├── libBaiduMapSDK_util_v4_1_1.so │ │ │ └── liblocSDK7.so │ │ └── res │ │ ├── drawable │ │ └── icon_launcher.png │ │ ├── layout │ │ └── activity_main.xml │ │ ├── mipmap-hdpi │ │ └── ic_launcher.png │ │ ├── mipmap-mdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxxhdpi │ │ └── ic_launcher.png │ │ ├── values-w820dp │ │ └── dimens.xml │ │ └── values │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── strings.xml │ │ └── styles.xml ├── plugintest3 │ ├── .gitignore │ ├── build.gradle │ ├── proguard-rules.pro │ └── src │ │ └── main │ │ ├── AndroidManifest.xml │ │ ├── java │ │ └── com │ │ │ └── limpoxe │ │ │ └── plugintest3 │ │ │ ├── Empty.java │ │ │ └── PluginTest3CustomAttrView.java │ │ └── res │ │ └── values │ │ ├── strings.xml │ │ └── style.xml └── wxsdklibrary │ ├── .gitignore │ ├── build.gradle │ ├── libs │ └── libammsdk.jar │ ├── proguard-rules.pro │ └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── example │ │ ├── pluginmain │ │ └── wxapi │ │ │ └── WXEntryActivity.java │ │ └── wxsdklibrary │ │ └── TestSendToWXActivity.java │ └── res │ ├── drawable │ └── icon_lanucher.png │ ├── layout │ └── send_activity.xml │ └── values │ └── strings.xml ├── build.gradle ├── build.sh ├── config.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── jitpack.yml └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/workspace.xml 5 | /.idea/libraries 6 | /.idea/misc.xml 7 | .DS_Store 8 | /build 9 | build 10 | .idea/ 11 | /captures 12 | .settings 13 | build-cache 14 | build-cache.lock 15 | /dump.txt 16 | dump.txt 17 | .cxx 18 | .externalNativeBuild 19 | -------------------------------------------------------------------------------- /FairyPlugin/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | local.properties 3 | /*.iml -------------------------------------------------------------------------------- /FairyPlugin/agp3_3_2/host.gradle: -------------------------------------------------------------------------------- 1 | apply from : "https://raw.githubusercontent.com/limpoxe/Android-Plugin-Framework/master/FairyPlugin/agp3_3_1/host.gradle" -------------------------------------------------------------------------------- /FairyPlugin/agp3_3_2/plugin.gradle: -------------------------------------------------------------------------------- 1 | apply from : "https://raw.githubusercontent.com/limpoxe/Android-Plugin-Framework/master/FairyPlugin/agp3_3_1/plugin.gradle" -------------------------------------------------------------------------------- /FairyPlugin/agp3_4_0/host.gradle: -------------------------------------------------------------------------------- 1 | apply from : "https://raw.githubusercontent.com/limpoxe/Android-Plugin-Framework/master/FairyPlugin/agp3_3_1/host.gradle" -------------------------------------------------------------------------------- /FairyPlugin/agp3_4_0/plugin.gradle: -------------------------------------------------------------------------------- 1 | apply from : "https://raw.githubusercontent.com/limpoxe/Android-Plugin-Framework/master/FairyPlugin/agp3_3_1/plugin.gradle" -------------------------------------------------------------------------------- /FairyPlugin/agp3_4_1/host.gradle: -------------------------------------------------------------------------------- 1 | apply from : "https://raw.githubusercontent.com/limpoxe/Android-Plugin-Framework/master/FairyPlugin/agp3_3_1/host.gradle" -------------------------------------------------------------------------------- /FairyPlugin/agp3_4_1/plugin.gradle: -------------------------------------------------------------------------------- 1 | apply from : "https://raw.githubusercontent.com/limpoxe/Android-Plugin-Framework/master/FairyPlugin/agp3_3_1/plugin.gradle" -------------------------------------------------------------------------------- /FairyPlugin/agp3_4_2/host.gradle: -------------------------------------------------------------------------------- 1 | apply from : "https://raw.githubusercontent.com/limpoxe/Android-Plugin-Framework/master/FairyPlugin/agp3_3_1/host.gradle" -------------------------------------------------------------------------------- /FairyPlugin/agp3_4_2/plugin.gradle: -------------------------------------------------------------------------------- 1 | apply from : "https://raw.githubusercontent.com/limpoxe/Android-Plugin-Framework/master/FairyPlugin/agp3_3_1/plugin.gradle" -------------------------------------------------------------------------------- /FairyPlugin/agp3_5_0/host.gradle: -------------------------------------------------------------------------------- 1 | apply from : "https://raw.githubusercontent.com/limpoxe/Android-Plugin-Framework/master/FairyPlugin/agp3_3_1/host.gradle" -------------------------------------------------------------------------------- /FairyPlugin/agp3_5_0/plugin.gradle: -------------------------------------------------------------------------------- 1 | apply from : "https://raw.githubusercontent.com/limpoxe/Android-Plugin-Framework/master/FairyPlugin/agp3_3_1/plugin.gradle" -------------------------------------------------------------------------------- /FairyPlugin/agp3_5_3/host.gradle: -------------------------------------------------------------------------------- 1 | apply from : "https://raw.githubusercontent.com/limpoxe/Android-Plugin-Framework/master/FairyPlugin/agp3_3_1/host.gradle" 2 | -------------------------------------------------------------------------------- /FairyPlugin/agp3_5_3/plugin.gradle: -------------------------------------------------------------------------------- 1 | apply from : "https://raw.githubusercontent.com/limpoxe/Android-Plugin-Framework/master/FairyPlugin/agp3_3_1/plugin.gradle" 2 | -------------------------------------------------------------------------------- /FairyPlugin/agp4_2_1/host.gradle: -------------------------------------------------------------------------------- 1 | apply from : "https://raw.githubusercontent.com/limpoxe/Android-Plugin-Framework/master/FairyPlugin/agp4_1_3/host.gradle" 2 | -------------------------------------------------------------------------------- /FairyPlugin/agp4_2_1/plugin.gradle: -------------------------------------------------------------------------------- 1 | apply from : "https://raw.githubusercontent.com/limpoxe/Android-Plugin-Framework/master/FairyPlugin/agp4_1_3/plugin.gradle" 2 | -------------------------------------------------------------------------------- /FairyPlugin/agp7_1_3/host.gradle: -------------------------------------------------------------------------------- 1 | apply from : "https://raw.githubusercontent.com/limpoxe/Android-Plugin-Framework/master/FairyPlugin/agp7_0_3/host.gradle" -------------------------------------------------------------------------------- /FairyPlugin/agp7_4_2/host.gradle: -------------------------------------------------------------------------------- 1 | apply from : "https://raw.githubusercontent.com/limpoxe/Android-Plugin-Framework/master/FairyPlugin/agp7_2_0/host.gradle" -------------------------------------------------------------------------------- /FairyPlugin/agp7_4_2/plugin.gradle: -------------------------------------------------------------------------------- 1 | apply from : "https://raw.githubusercontent.com/limpoxe/Android-Plugin-Framework/master/FairyPlugin/agp7_2_0/plugin.gradle" -------------------------------------------------------------------------------- /FairyPlugin/host.gradle: -------------------------------------------------------------------------------- 1 | apply from : "https://raw.githubusercontent.com/limpoxe/Android-Plugin-Framework/master/FairyPlugin/agp4_1_3/host.gradle" 2 | -------------------------------------------------------------------------------- /FairyPlugin/jitpack.yml: -------------------------------------------------------------------------------- 1 | before_install: 2 | - yes | sdkmanager "cmake;3.10.2.4988404" 3 | - sdk install java 11.0.10-open 4 | - sdk use java 11.0.10-open 5 | 6 | jdk: 7 | - openjdk11 -------------------------------------------------------------------------------- /FairyPlugin/plugin.gradle: -------------------------------------------------------------------------------- 1 | apply from : "https://raw.githubusercontent.com/limpoxe/Android-Plugin-Framework/master/FairyPlugin/agp4_1_3/plugin.gradle" 2 | -------------------------------------------------------------------------------- /FairyPlugin/proguard-project.txt: -------------------------------------------------------------------------------- 1 | # To enable ProGuard in your project, edit project.properties 2 | # to define the proguard.config property as described in that file. 3 | # 4 | # Add project specific ProGuard rules here. 5 | # By default, the flags in this file are appended to flags specified 6 | # in ${sdk.dir}/tools/proguard/proguard-android.txt 7 | # You can edit the include path and order by changing the ProGuard 8 | # include property in project.properties. 9 | # 10 | # For more details, see 11 | # http://developer.android.com/guide/developing/tools/proguard.html 12 | 13 | # Add any project specific keep options here: 14 | 15 | # If your project uses WebView with JS, uncomment the following 16 | # and specify the fully qualified class name to the JavaScript interface 17 | # class: 18 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 19 | # public *; 20 | #} 21 | -------------------------------------------------------------------------------- /FairyPlugin/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /Users/cailiming/Library/Android/sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | 19 | # 保护FairyPlugin不受混淆影响 Begin 20 | -keep public class * extends android.app.Instrumentation {public *;} 21 | -keep public class * extends android.content.ContextWrapper {public *;} 22 | -keep public class com.limpoxe.support.servicemanager.ServiceManager {public *;} 23 | # 保护FairyPlugin不受混淆影响 End -------------------------------------------------------------------------------- /FairyPlugin/project.properties: -------------------------------------------------------------------------------- 1 | project.name=Android-Plugin-Framework 2 | project.groupId=com.github.limpoxe 3 | project.artifactId=Android-Plugin-Framework 4 | project.packaging=aar 5 | project.siteUrl=https://github.com/limpoxe/Android-Plugin-Framework 6 | project.gitUrl=https://github.com/limpoxe/Android-Plugin-Framework.git 7 | 8 | #developer 9 | developer.id=limpoxe 10 | developer.name=limpoxe 11 | developer.email=fixerror@163.com 12 | 13 | #javadoc 14 | javadoc.name=Android-Plugin-Framework -------------------------------------------------------------------------------- /FairyPlugin/src/main/java/com/limpoxe/fairy/content/PluginReceiverIntent.java: -------------------------------------------------------------------------------- 1 | package com.limpoxe.fairy.content; 2 | 3 | import android.annotation.SuppressLint; 4 | import android.content.Intent; 5 | import android.os.Build; 6 | import android.os.Bundle; 7 | 8 | /** 9 | * Created by cailiming on 15/9/29. 10 | */ 11 | @SuppressLint("ParcelCreator") 12 | public class PluginReceiverIntent extends Intent { 13 | 14 | public PluginReceiverIntent(Intent o) { 15 | super(o); 16 | } 17 | 18 | @Override 19 | public void setExtrasClassLoader(ClassLoader loader) { 20 | if (Build.VERSION.SDK_INT > 11) { 21 | Bundle extra = getExtras(); 22 | if (extra != null) { 23 | loader = extra.getClassLoader(); 24 | } 25 | } 26 | super.setExtrasClassLoader(loader); 27 | } 28 | } -------------------------------------------------------------------------------- /FairyPlugin/src/main/java/com/limpoxe/fairy/core/DemoApplication.java: -------------------------------------------------------------------------------- 1 | package com.limpoxe.fairy.core; 2 | 3 | import android.app.Application; 4 | import android.content.Context; 5 | 6 | import com.limpoxe.fairy.util.ProcessUtil; 7 | 8 | public class DemoApplication extends Application { 9 | 10 | @Override 11 | protected void attachBaseContext(Context base) { 12 | super.attachBaseContext(base); 13 | 14 | //这个地方之所以这样写,是因为如果是插件进程,initloader必须在applicaiotn启动时执行 15 | //而如果是宿主进程,initloader可以在这里执行,也可以在需要时再在宿主的其他组件中执行, 16 | // 例如点击宿主的某个Activity中的button后再执行这个方法来启动插件框架。 17 | 18 | //总体原则有3点: 19 | //1、插件进程和宿主进程都必须有机会执行initloader 20 | //2、在插件进程和宿主进程的initloader方法都执行完毕之前,不可和插件交互 21 | //3、在插件进程和宿主进程的initlaoder方法都执行完毕之前启动的组件,即使在initloader都执行完毕之后,也不可和插件交互 22 | 23 | //如果initloader都在进程启动时就执行,自然很轻松满足上述条件。 24 | if (ProcessUtil.isPluginProcess(this)) { 25 | //插件进程,必须在这里执行initLoader 26 | PluginLoader.initLoader(this); 27 | } else { 28 | //宿主进程,可以在这里执行,也可以选择在宿主的其他地方在需要时再启动插件框架 29 | PluginLoader.initLoader(this); 30 | } 31 | } 32 | 33 | /** 34 | * 重写这个方法是为了支持Receiver,否则会出现ClassCast错误 35 | */ 36 | @Override 37 | public Context getBaseContext() { 38 | return PluginLoader.fixBaseContextForReceiver(super.getBaseContext()); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /FairyPlugin/src/main/java/com/limpoxe/fairy/core/HostClassLoader.java: -------------------------------------------------------------------------------- 1 | package com.limpoxe.fairy.core; 2 | 3 | import dalvik.system.PathClassLoader; 4 | 5 | /** 6 | * 为了支持Receiver和Service,增加此类。 7 | * 8 | * @author Administrator 9 | * 10 | */ 11 | public class HostClassLoader extends PathClassLoader { 12 | 13 | public HostClassLoader(String dexPath, ClassLoader parent) { 14 | super(dexPath, parent); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /FairyPlugin/src/main/java/com/limpoxe/fairy/core/PluginClassLoader.java: -------------------------------------------------------------------------------- 1 | package com.limpoxe.fairy.core; 2 | 3 | import com.limpoxe.fairy.util.LogUtil; 4 | import com.limpoxe.fairy.util.RefInvoker; 5 | 6 | import dalvik.system.PathClassLoader; 7 | 8 | /** 9 | * 插件间依赖以及so管理 10 | * 11 | * @author Administrator 12 | * 13 | */ 14 | public class PluginClassLoader extends PathClassLoader { 15 | 16 | public final String pluginPackageName; 17 | 18 | public PluginClassLoader(String pluginPackageName, String dexPath, ClassLoader parent) { 19 | super(dexPath, parent); 20 | this.pluginPackageName = pluginPackageName; 21 | } 22 | 23 | @Override 24 | public String findLibrary(String name) { 25 | String libPath = (String) RefInvoker.invokeMethod(getParent(), getParent().getClass(), "findLibrary", new Class[]{String.class}, new Object[]{name}); 26 | LogUtil.d("findLibrary", name, libPath); 27 | return libPath; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /FairyPlugin/src/main/java/com/limpoxe/fairy/core/PluginFilter.java: -------------------------------------------------------------------------------- 1 | package com.limpoxe.fairy.core; 2 | 3 | public class PluginFilter { 4 | 5 | public static boolean maybePlugin(String pluginId) { 6 | if (pluginId.startsWith("com.android.") 7 | || pluginId.startsWith("com.google.")) { 8 | return false; 9 | } 10 | return true; 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /FairyPlugin/src/main/java/com/limpoxe/fairy/core/Runner.java: -------------------------------------------------------------------------------- 1 | package com.limpoxe.fairy.core; 2 | 3 | public interface Runner { 4 | T run(); 5 | } 6 | -------------------------------------------------------------------------------- /FairyPlugin/src/main/java/com/limpoxe/fairy/core/android/HackActivityManager.java: -------------------------------------------------------------------------------- 1 | package com.limpoxe.fairy.core.android; 2 | 3 | import com.limpoxe.fairy.util.RefInvoker; 4 | 5 | /** 6 | * Created by cailiming on 17/5/18. 7 | */ 8 | 9 | public class HackActivityManager { 10 | 11 | private static final String ClassName = "android.app.ActivityManager"; 12 | 13 | private static final String Field_IActivityManagerSingleton = "IActivityManagerSingleton"; 14 | 15 | public static Object getIActivityManagerSingleton() { 16 | return RefInvoker.getField(null, ClassName, Field_IActivityManagerSingleton); 17 | } 18 | 19 | public static void setIActivityManagerSingleton(Object activityManagerSingleton) { 20 | RefInvoker.setField(null, ClassName, Field_IActivityManagerSingleton, activityManagerSingleton); 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /FairyPlugin/src/main/java/com/limpoxe/fairy/core/android/HackActivityManagerNative.java: -------------------------------------------------------------------------------- 1 | package com.limpoxe.fairy.core.android; 2 | 3 | import com.limpoxe.fairy.util.RefInvoker; 4 | 5 | /** 6 | * Created by cailiming on 16/10/30. 7 | */ 8 | 9 | public class HackActivityManagerNative { 10 | 11 | private static final String ClassName = "android.app.ActivityManagerNative"; 12 | 13 | private static final String Method_getDefault = "getDefault"; 14 | 15 | private static final String Field_gDefault = "gDefault"; 16 | 17 | public static Object getDefault() { 18 | return RefInvoker.invokeMethod(null, ClassName, Method_getDefault, (Class[])null, (Object[])null); 19 | } 20 | 21 | public static Object getGDefault() { 22 | return RefInvoker.getField(null, ClassName, Field_gDefault); 23 | } 24 | 25 | public static void setGDefault(Object gDefault) { 26 | RefInvoker.setField(null, ClassName, Field_gDefault, gDefault); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /FairyPlugin/src/main/java/com/limpoxe/fairy/core/android/HackActivityThreadProviderClientRecord.java: -------------------------------------------------------------------------------- 1 | package com.limpoxe.fairy.core.android; 2 | 3 | import android.content.ContentProvider; 4 | 5 | import com.limpoxe.fairy.util.LogUtil; 6 | import com.limpoxe.fairy.util.RefInvoker; 7 | 8 | public class HackActivityThreadProviderClientRecord { 9 | 10 | private static final String ClassName = "android.app.ActivityThread$ProviderClientRecord"; 11 | 12 | private static final String Field_mProvider = "mLocalProvider"; 13 | 14 | private Object instance; 15 | 16 | public HackActivityThreadProviderClientRecord(Object instance) { 17 | this.instance = instance; 18 | } 19 | 20 | public static Class clazz() { 21 | try { 22 | return RefInvoker.forName(ClassName); 23 | } catch (ClassNotFoundException e) { 24 | LogUtil.printException("HackActivityThreadProviderClientRecord.clazz", e); 25 | } 26 | return null; 27 | } 28 | 29 | public ContentProvider getProvider() { 30 | Object o = RefInvoker.getField(instance, ClassName, Field_mProvider); 31 | if (o instanceof ContentProvider) {//maybe ContentProviderProxy 32 | return (ContentProvider) o; 33 | } 34 | return null; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /FairyPlugin/src/main/java/com/limpoxe/fairy/core/android/HackAndroidXLocalboarcastManager.java: -------------------------------------------------------------------------------- 1 | package com.limpoxe.fairy.core.android; 2 | 3 | import android.content.BroadcastReceiver; 4 | 5 | import com.limpoxe.fairy.util.RefInvoker; 6 | 7 | import java.util.HashMap; 8 | 9 | /** 10 | * Created by cailiming on 19/11/3. 11 | */ 12 | 13 | public class HackAndroidXLocalboarcastManager { 14 | 15 | private static final String ClassName = "androidx.localbroadcastmanager.content.LocalBroadcastManager"; 16 | 17 | private static final String Field_mInstance = "mInstance"; 18 | private static final String Field_mReceivers = "mReceivers"; 19 | 20 | private static final String Method_unregisterReceiver = "unregisterReceiver"; 21 | 22 | private Object instance ; 23 | 24 | public HackAndroidXLocalboarcastManager(Object instance) { 25 | this.instance = instance; 26 | } 27 | 28 | public static Object getInstance() { 29 | return RefInvoker.getField(null, ClassName, Field_mInstance); 30 | } 31 | 32 | public HashMap getReceivers() { 33 | return (HashMap)RefInvoker.getField(instance, ClassName, Field_mReceivers); 34 | } 35 | 36 | public void unregisterReceiver(BroadcastReceiver item) { 37 | RefInvoker.invokeMethod(instance, ClassName, Method_unregisterReceiver, new Class[]{BroadcastReceiver.class}, new Object[]{item}); 38 | 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /FairyPlugin/src/main/java/com/limpoxe/fairy/core/android/HackAppBindData.java: -------------------------------------------------------------------------------- 1 | package com.limpoxe.fairy.core.android; 2 | 3 | import com.limpoxe.fairy.util.RefInvoker; 4 | 5 | /** 6 | * Created by cailiming on 16/10/30. 7 | */ 8 | 9 | public class HackAppBindData { 10 | private static final String ClassName = "android.app.ActivityThread$AppBindData"; 11 | 12 | private static final String Field_compatInfo = "compatInfo"; 13 | private static final String Field_info = "info"; 14 | 15 | private Object instance; 16 | 17 | public HackAppBindData(Object instance) { 18 | this.instance = instance; 19 | } 20 | 21 | public Object getInfo() { 22 | return RefInvoker.getField(instance, ClassName, Field_info); 23 | } 24 | 25 | public Object getCompatInfo() { 26 | return RefInvoker.getField(instance, ClassName, Field_compatInfo); 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /FairyPlugin/src/main/java/com/limpoxe/fairy/core/android/HackApplicationPackageManager.java: -------------------------------------------------------------------------------- 1 | package com.limpoxe.fairy.core.android; 2 | 3 | import com.limpoxe.fairy.util.RefInvoker; 4 | 5 | /** 6 | * Created by cailiming on 16/10/30. 7 | */ 8 | 9 | public class HackApplicationPackageManager { 10 | private static final String ClassName = "android.app.ApplicationPackageManager"; 11 | 12 | private static final String Field_mPM = "mPM"; 13 | 14 | private Object instance; 15 | 16 | public HackApplicationPackageManager(Object instance) { 17 | this.instance = instance; 18 | } 19 | 20 | public void setPM(Object pm) { 21 | RefInvoker.setField(instance, ClassName, Field_mPM, pm); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /FairyPlugin/src/main/java/com/limpoxe/fairy/core/android/HackComponentName.java: -------------------------------------------------------------------------------- 1 | package com.limpoxe.fairy.core.android; 2 | 3 | import android.content.ComponentName; 4 | 5 | import com.limpoxe.fairy.util.RefInvoker; 6 | 7 | /** 8 | * Created by cailiming on 16/10/30. 9 | */ 10 | 11 | public class HackComponentName extends HackContextThemeWrapper { 12 | private static final String ClassName = ComponentName.class.getName(); 13 | private static final String Field_mPackage = "mPackage"; 14 | private static final String Field_mClass = "mClass"; 15 | 16 | public HackComponentName(Object instance) { 17 | super(instance); 18 | } 19 | 20 | public final void setPackageName(String packageName) { 21 | RefInvoker.setField(instance, ClassName, Field_mPackage, packageName); 22 | } 23 | 24 | public final void setClassName(String className) { 25 | RefInvoker.setField(instance, ClassName, Field_mClass, className); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /FairyPlugin/src/main/java/com/limpoxe/fairy/core/android/HackContentProvider.java: -------------------------------------------------------------------------------- 1 | package com.limpoxe.fairy.core.android; 2 | 3 | import android.content.ContentProvider; 4 | 5 | import com.limpoxe.fairy.util.RefInvoker; 6 | 7 | public class HackContentProvider { 8 | 9 | private static final String Field_mAuthority = "mAuthority"; 10 | 11 | private Object instance; 12 | 13 | public HackContentProvider(ContentProvider instance) { 14 | this.instance = instance; 15 | } 16 | 17 | public String getAuthority() { 18 | return (String)RefInvoker.getField(instance, ContentProvider.class, Field_mAuthority); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /FairyPlugin/src/main/java/com/limpoxe/fairy/core/android/HackContentProviderClient.java: -------------------------------------------------------------------------------- 1 | package com.limpoxe.fairy.core.android; 2 | 3 | import com.limpoxe.fairy.util.RefInvoker; 4 | 5 | /** 6 | * Created by cailiming on 16/10/30. 7 | */ 8 | 9 | public class HackContentProviderClient { 10 | private static final String ClassName = "android.content.ContentProviderClient"; 11 | 12 | private static final String Field_mContentProvider = "mContentProvider"; 13 | 14 | private Object instance; 15 | 16 | public HackContentProviderClient(Object instance) { 17 | this.instance = instance; 18 | } 19 | 20 | public Object getContentProvider() { 21 | return RefInvoker.getField(instance, ClassName, Field_mContentProvider); 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /FairyPlugin/src/main/java/com/limpoxe/fairy/core/android/HackContentProviderHolder.java: -------------------------------------------------------------------------------- 1 | package com.limpoxe.fairy.core.android; 2 | 3 | import android.content.pm.ProviderInfo; 4 | import android.os.Build; 5 | 6 | import com.limpoxe.fairy.util.RefInvoker; 7 | 8 | /** 9 | * Created by cailiming on 2017/11/27. 10 | */ 11 | 12 | public class HackContentProviderHolder { 13 | private static final String ClassName = "android.app.IActivityManager$ContentProviderHolder"; 14 | private static final String ClassName8 = "android.app.ContentProviderHolder"; 15 | 16 | private static final String Field_mLocal = "mLocal"; 17 | 18 | private Object instance; 19 | 20 | public HackContentProviderHolder(Object instance) { 21 | this.instance = instance; 22 | } 23 | 24 | public static Object newInstance(ProviderInfo info) { 25 | if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.N_MR1) { 26 | return RefInvoker.newInstance(ClassName, new Class[]{ProviderInfo.class}, new Object[]{info}); 27 | } else { 28 | return RefInvoker.newInstance(ClassName8, new Class[]{ProviderInfo.class}, new Object[]{info}); 29 | } 30 | } 31 | 32 | public void setLocal(boolean local) { 33 | if (Build.VERSION.SDK_INT > Build.VERSION_CODES.N_MR1) { 34 | RefInvoker.setField(instance, ClassName8, Field_mLocal, local); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /FairyPlugin/src/main/java/com/limpoxe/fairy/core/android/HackContextThemeWrapper.java: -------------------------------------------------------------------------------- 1 | package com.limpoxe.fairy.core.android; 2 | 3 | import android.content.Context; 4 | import android.content.res.Resources; 5 | import android.os.Build; 6 | 7 | import com.limpoxe.fairy.util.RefInvoker; 8 | 9 | /** 10 | * Created by cailiming on 16/10/30. 11 | */ 12 | 13 | public class HackContextThemeWrapper extends HackContextWrapper { 14 | private static final String ClassName = "android.view.ContextThemeWrapper"; 15 | 16 | private static final String Field_mResources = "mResources"; 17 | private static final String Field_mTheme = "mTheme"; 18 | 19 | private static final String Method_attachBaseContext = "attachBaseContext"; 20 | 21 | public HackContextThemeWrapper(Object instance) { 22 | super(instance); 23 | } 24 | 25 | public final void attachBaseContext(Object paramValues) { 26 | RefInvoker.invokeMethod(instance, ClassName, Method_attachBaseContext, new Class[]{Context.class}, new Object[]{paramValues}); 27 | } 28 | 29 | public final void setResources(Resources resources) { 30 | if (Build.VERSION.SDK_INT > 16) { 31 | RefInvoker.setField(instance, ClassName, Field_mResources, resources); 32 | } 33 | } 34 | 35 | public final void setTheme(Resources.Theme theme) { 36 | RefInvoker.setField(instance, ClassName, Field_mTheme, theme); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /FairyPlugin/src/main/java/com/limpoxe/fairy/core/android/HackContextWrapper.java: -------------------------------------------------------------------------------- 1 | package com.limpoxe.fairy.core.android; 2 | 3 | import android.content.Context; 4 | 5 | import com.limpoxe.fairy.util.RefInvoker; 6 | 7 | /** 8 | * Created by cailiming on 16/10/30. 9 | */ 10 | 11 | public class HackContextWrapper { 12 | private static final String ClassName = "android.content.ContextWrapper"; 13 | 14 | private static final String Field_mBase = "mBase"; 15 | 16 | protected Object instance; 17 | 18 | public HackContextWrapper(Object instance) { 19 | this.instance = instance; 20 | } 21 | 22 | public final Context getBase() { 23 | return (Context)RefInvoker.getField(instance, ClassName, Field_mBase); 24 | } 25 | 26 | public final void setBase(Context context) { 27 | RefInvoker.setField(instance, ClassName, Field_mBase, context); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /FairyPlugin/src/main/java/com/limpoxe/fairy/core/android/HackCreateServiceData.java: -------------------------------------------------------------------------------- 1 | package com.limpoxe.fairy.core.android; 2 | 3 | import android.content.pm.ServiceInfo; 4 | 5 | import com.limpoxe.fairy.util.RefInvoker; 6 | 7 | /** 8 | * Created by cailiming on 16/10/30. 9 | */ 10 | 11 | public class HackCreateServiceData { 12 | private static final String ClassName = "android.app.ActivityThread$CreateServiceData"; 13 | 14 | private static final String Field_info = "info"; 15 | 16 | private Object instance; 17 | 18 | public HackCreateServiceData(Object instance) { 19 | this.instance = instance; 20 | } 21 | 22 | public ServiceInfo getInfo() { 23 | return (ServiceInfo)RefInvoker.getField(instance, ClassName, Field_info); 24 | } 25 | 26 | public void setInfo(ServiceInfo info) { 27 | RefInvoker.setField(instance, ClassName, Field_info, info); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /FairyPlugin/src/main/java/com/limpoxe/fairy/core/android/HackHandler.java: -------------------------------------------------------------------------------- 1 | package com.limpoxe.fairy.core.android; 2 | 3 | import android.os.Handler; 4 | 5 | import com.limpoxe.fairy.util.RefInvoker; 6 | 7 | /** 8 | * Created by cailiming on 16/10/30. 9 | */ 10 | 11 | public class HackHandler { 12 | private static final String ClassName = "android.os.Handler"; 13 | 14 | private static final String Field_mCallback = "mCallback"; 15 | private Object instance; 16 | 17 | public HackHandler(Object instance) { 18 | this.instance = instance; 19 | } 20 | 21 | public void setCallback(Handler.Callback callback) { 22 | RefInvoker.setField(instance, ClassName, Field_mCallback, callback); 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /FairyPlugin/src/main/java/com/limpoxe/fairy/core/android/HackIContentProvider.java: -------------------------------------------------------------------------------- 1 | package com.limpoxe.fairy.core.android; 2 | 3 | import android.os.Bundle; 4 | 5 | import com.limpoxe.fairy.util.RefInvoker; 6 | 7 | /** 8 | * Created by cailiming on 16/10/30. 9 | */ 10 | 11 | public class HackIContentProvider { 12 | private static final String ClassName = "android.content.IContentProvider"; 13 | 14 | private static final String Methdo_call = "call"; 15 | 16 | private Object instance; 17 | 18 | public HackIContentProvider(Object instance) { 19 | this.instance = instance; 20 | } 21 | 22 | public Object call(String method, String arg, Bundle extras) { 23 | return RefInvoker.invokeMethod(instance, ClassName, Methdo_call, 24 | new Class[]{String.class, String.class, Bundle.class}, 25 | new Object[]{method, arg, extras}); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /FairyPlugin/src/main/java/com/limpoxe/fairy/core/android/HackNotificationManager.java: -------------------------------------------------------------------------------- 1 | package com.limpoxe.fairy.core.android; 2 | 3 | import com.limpoxe.fairy.util.RefInvoker; 4 | 5 | /** 6 | * Created by cailiming on 16/10/30. 7 | */ 8 | 9 | public class HackNotificationManager { 10 | 11 | private static final String ClassName = "android.app.NotificationManager"; 12 | 13 | private static final String Method_getService = "getService"; 14 | 15 | private static final String Field_sService = "sService"; 16 | 17 | public static Object getService() { 18 | return RefInvoker.invokeMethod(null, ClassName, Method_getService, (Class[])null, (Object[])null); 19 | } 20 | 21 | public static void setService(Object serv) { 22 | RefInvoker.setField(null, ClassName, Field_sService, serv); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /FairyPlugin/src/main/java/com/limpoxe/fairy/core/android/HackParceledListSlice.java: -------------------------------------------------------------------------------- 1 | package com.limpoxe.fairy.core.android; 2 | 3 | import android.content.pm.ResolveInfo; 4 | import android.os.Build; 5 | 6 | import com.limpoxe.fairy.util.RefInvoker; 7 | 8 | import java.util.List; 9 | 10 | /** 11 | * Created by cailiming on 16/10/30. 12 | */ 13 | 14 | public class HackParceledListSlice { 15 | 16 | private static final String ClassName = "android.content.pm.ParceledListSlice"; 17 | 18 | private static final String Method_getList = "getList"; 19 | 20 | private Object instance; 21 | 22 | public HackParceledListSlice(Object instance) { 23 | this.instance = instance; 24 | } 25 | 26 | public Object getList() { 27 | return RefInvoker.invokeMethod(instance, ClassName, Method_getList, (Class[])null, (Object[])null); 28 | } 29 | 30 | public static Object newParecledListSlice(List itemList) { 31 | if (Build.VERSION.SDK_INT >= 21) { 32 | return RefInvoker.newInstance(ClassName, new Class[]{List.class}, new Object[]{itemList}); 33 | } else { 34 | return null; 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /FairyPlugin/src/main/java/com/limpoxe/fairy/core/android/HackPendingIntent.java: -------------------------------------------------------------------------------- 1 | package com.limpoxe.fairy.core.android; 2 | 3 | import android.content.Intent; 4 | 5 | import com.limpoxe.fairy.util.RefInvoker; 6 | 7 | /** 8 | * Created by cailiming on 16/10/30. 9 | */ 10 | 11 | public class HackPendingIntent { 12 | 13 | private static final String ClassName = "android.app.PendingIntent"; 14 | 15 | private static final String Method_getIntent = "getIntent"; 16 | 17 | private Object instance; 18 | 19 | public HackPendingIntent(Object instance) { 20 | this.instance = instance; 21 | } 22 | 23 | public Intent getIntent() { 24 | return (Intent)RefInvoker.invokeMethod(instance, ClassName, Method_getIntent, (Class[]) null, (Object[]) null); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /FairyPlugin/src/main/java/com/limpoxe/fairy/core/android/HackReceiverData.java: -------------------------------------------------------------------------------- 1 | package com.limpoxe.fairy.core.android; 2 | 3 | import android.content.Intent; 4 | import android.content.pm.ActivityInfo; 5 | 6 | import com.limpoxe.fairy.util.RefInvoker; 7 | 8 | /** 9 | * Created by cailiming on 16/10/30. 10 | */ 11 | 12 | public class HackReceiverData { 13 | private static final String ClassName = "android.app.ActivityThread$ReceiverData"; 14 | 15 | private static final String Field_intent = "intent"; 16 | private static final String Field_info = "info"; 17 | 18 | private Object instance; 19 | 20 | public HackReceiverData(Object instance) { 21 | this.instance = instance; 22 | } 23 | 24 | public Intent getIntent() { 25 | return (Intent)RefInvoker.getField(instance, ClassName, Field_intent); 26 | } 27 | 28 | public void setIntent(Intent intent) { 29 | RefInvoker.setField(instance, ClassName, Field_intent, intent); 30 | } 31 | 32 | public ActivityInfo getInfo() { 33 | return (ActivityInfo)RefInvoker.getField(instance, ClassName, Field_info); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /FairyPlugin/src/main/java/com/limpoxe/fairy/core/android/HackRemoteViews.java: -------------------------------------------------------------------------------- 1 | package com.limpoxe.fairy.core.android; 2 | 3 | import android.content.pm.ApplicationInfo; 4 | 5 | import com.limpoxe.fairy.util.RefInvoker; 6 | 7 | /** 8 | * Created by cailiming on 16/10/30. 9 | */ 10 | 11 | public class HackRemoteViews { 12 | private static final String ClassName = "android.widget.RemoteViews"; 13 | 14 | private static final String Field_mLayoutId = "mLayoutId"; 15 | private static final String Field_mApplication = "mApplication"; 16 | private static final String Field_mPackage = "mPackage"; 17 | 18 | private Object instance; 19 | 20 | public HackRemoteViews(Object instance) { 21 | this.instance = instance; 22 | } 23 | 24 | public Integer getLayoutId() { 25 | return (Integer)RefInvoker.getField(instance, ClassName, Field_mLayoutId); 26 | } 27 | 28 | public void setLayoutId(int layoutId) { 29 | RefInvoker.setField(instance, ClassName, Field_mLayoutId, new Integer(layoutId)); 30 | } 31 | 32 | public void setApplicationInfo(ApplicationInfo info) { 33 | RefInvoker.setField(instance, ClassName, Field_mApplication, info); 34 | } 35 | 36 | public void setPackage(String packageName) { 37 | RefInvoker.setField(instance, ClassName, Field_mPackage, packageName); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /FairyPlugin/src/main/java/com/limpoxe/fairy/core/android/HackResources.java: -------------------------------------------------------------------------------- 1 | package com.limpoxe.fairy.core.android; 2 | 3 | import com.limpoxe.fairy.util.RefInvoker; 4 | 5 | /** 6 | * Created by cailiming on 16/10/30. 7 | */ 8 | 9 | public class HackResources { 10 | private static final String ClassName = "android.content.res.Resources"; 11 | 12 | private static final String Method_selectDefaultTheme = "selectDefaultTheme"; 13 | 14 | public static Integer selectDefaultTheme(int mThemeResource, 15 | int targetSdkVersion) { 16 | return (Integer) RefInvoker.invokeMethod(null, ClassName, Method_selectDefaultTheme, new Class[]{ 17 | int.class, int.class}, new Object[]{mThemeResource, targetSdkVersion}); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /FairyPlugin/src/main/java/com/limpoxe/fairy/core/android/HackServiceManager.java: -------------------------------------------------------------------------------- 1 | package com.limpoxe.fairy.core.android; 2 | 3 | import android.os.IBinder; 4 | 5 | import com.limpoxe.fairy.util.RefInvoker; 6 | 7 | import java.util.Map; 8 | 9 | /** 10 | * Created by cailiming on 16/10/30. 11 | */ 12 | 13 | public class HackServiceManager { 14 | private static final String ClassName = "android.os.ServiceManager"; 15 | 16 | private static final String Field_sServiceManager = "sServiceManager"; 17 | private static final String Field_sCache = "sCache"; 18 | 19 | private static final String Method_getIServiceManager = "getIServiceManager"; 20 | private static final String Method_getService = "getService"; 21 | 22 | public static Object getIServiceManager() { 23 | return RefInvoker.invokeMethod(null, ClassName, Method_getIServiceManager, (Class[])null, (Object[])null); 24 | } 25 | 26 | public static void setServiceManager(Object serviceManager) { 27 | RefInvoker.setField(null, ClassName, Field_sServiceManager, serviceManager); 28 | } 29 | 30 | public static Map getCache() { 31 | return (Map)RefInvoker.getField(null, ClassName, Field_sCache); 32 | } 33 | 34 | public static IBinder getService(String name) { 35 | return (IBinder)RefInvoker.invokeMethod(null, ClassName, Method_getService, new Class[]{String.class}, new Object[]{name}); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /FairyPlugin/src/main/java/com/limpoxe/fairy/core/android/HackSingleton.java: -------------------------------------------------------------------------------- 1 | package com.limpoxe.fairy.core.android; 2 | 3 | import com.limpoxe.fairy.util.RefInvoker; 4 | 5 | /** 6 | * Created by cailiming on 16/10/30. 7 | */ 8 | 9 | public class HackSingleton { 10 | private static final String ClassName = "android.util.Singleton"; 11 | 12 | private static final String Field_mInstance = "mInstance"; 13 | 14 | private Object instance; 15 | 16 | public HackSingleton(Object instance) { 17 | this.instance = instance; 18 | } 19 | 20 | public void setInstance(Object object) { 21 | RefInvoker.setField(instance, ClassName, Field_mInstance, object); 22 | 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /FairyPlugin/src/main/java/com/limpoxe/fairy/core/android/HackToast.java: -------------------------------------------------------------------------------- 1 | package com.limpoxe.fairy.core.android; 2 | 3 | import com.limpoxe.fairy.util.RefInvoker; 4 | 5 | public class HackToast { 6 | 7 | private static final String ClassName = "android.widget.Toast"; 8 | 9 | private static final String Field_INotificationManager_sService = "sService"; 10 | 11 | private static final String Method_sService = "getService"; 12 | 13 | public static Object getService() { 14 | return RefInvoker.invokeMethod(null, ClassName, Method_sService, (Class[])null, (Object[])null); 15 | } 16 | 17 | public static void setService(Object inotificationManager) { 18 | RefInvoker.setField(null, ClassName, Field_INotificationManager_sService, inotificationManager); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /FairyPlugin/src/main/java/com/limpoxe/fairy/core/android/HackWebViewFactory.java: -------------------------------------------------------------------------------- 1 | package com.limpoxe.fairy.core.android; 2 | 3 | import android.content.pm.PackageInfo; 4 | 5 | import com.limpoxe.fairy.util.RefInvoker; 6 | 7 | /** 8 | * Created by cailiming on 16/10/30. 9 | */ 10 | 11 | public class HackWebViewFactory { 12 | 13 | private static final String ClassName = "android.webkit.WebViewFactory"; 14 | 15 | private static final String Field_sProviderInstance = "sProviderInstance"; 16 | 17 | private static final String Method_getProvider = "getProvider"; 18 | private static final String Method_getLoadedPackageInfo = "getLoadedPackageInfo"; 19 | 20 | public static Object getProvider() { 21 | return RefInvoker.invokeMethod(null, ClassName, Method_getProvider, (Class[]) null, (Object[]) null); 22 | } 23 | 24 | public static void setProviderInstance(Object provider) { 25 | RefInvoker.setField(null, ClassName, Field_sProviderInstance, provider); 26 | } 27 | 28 | public static PackageInfo getLoadedPackageInfo() { 29 | return (PackageInfo) RefInvoker.invokeMethod(null, ClassName, Method_getLoadedPackageInfo, (Class[]) null, (Object[]) null); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /FairyPlugin/src/main/java/com/limpoxe/fairy/core/android/HackWindow.java: -------------------------------------------------------------------------------- 1 | package com.limpoxe.fairy.core.android; 2 | 3 | import android.content.Context; 4 | import android.view.LayoutInflater; 5 | 6 | import com.limpoxe.fairy.util.RefInvoker; 7 | 8 | /** 9 | * Created by cailiming on 16/10/30. 10 | */ 11 | 12 | public class HackWindow { 13 | private static final String ClassName = "android.view.Window"; 14 | 15 | private static final String Field_mContext = "mContext"; 16 | private static final String Field_mWindowStyle = "mWindowStyle"; 17 | private static final String Field_mLayoutInflater = "mLayoutInflater"; 18 | 19 | private Object instance; 20 | 21 | public HackWindow(Object instance) { 22 | this.instance = instance; 23 | } 24 | 25 | public void setContext(Context context) { 26 | RefInvoker.setField(instance, ClassName, Field_mContext, context); 27 | } 28 | 29 | public void setWindowStyle(Object style) { 30 | RefInvoker.setField(instance, ClassName, Field_mWindowStyle, style); 31 | } 32 | 33 | public void setLayoutInflater(String className, LayoutInflater layoutInflater) { 34 | RefInvoker.setField(instance, className, Field_mLayoutInflater, layoutInflater); 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /FairyPlugin/src/main/java/com/limpoxe/fairy/core/annotation/AnnotationProcessor.java: -------------------------------------------------------------------------------- 1 | package com.limpoxe.fairy.core.annotation; 2 | 3 | public class AnnotationProcessor { 4 | 5 | public static PluginContainer getPluginContainer(Class clazz) { 6 | PluginContainer container = (PluginContainer)clazz.getAnnotation(PluginContainer.class); 7 | return container; 8 | } 9 | 10 | } 11 | -------------------------------------------------------------------------------- /FairyPlugin/src/main/java/com/limpoxe/fairy/core/annotation/PluginContainer.java: -------------------------------------------------------------------------------- 1 | package com.limpoxe.fairy.core.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Inherited; 5 | import java.lang.annotation.Retention; 6 | import java.lang.annotation.RetentionPolicy; 7 | import java.lang.annotation.Target; 8 | 9 | /** 10 | * 在activity中标记这个注解, 11 | * 用来通知插件框架,这个activity需要替换上下文,用来嵌入来自其他插件的组件 12 | * 例如这个宿主Activity需要内嵌插件Fragment/View时; 13 | * 同时配置了这个注解的Activity需要运行再插件进程中 14 | */ 15 | 16 | @Target(ElementType.TYPE) 17 | @Retention(RetentionPolicy.RUNTIME) 18 | @Inherited 19 | public @interface PluginContainer { 20 | public String pluginId() default ""; 21 | } 22 | -------------------------------------------------------------------------------- /FairyPlugin/src/main/java/com/limpoxe/fairy/core/compat/EmptyHashMap.java: -------------------------------------------------------------------------------- 1 | package com.limpoxe.fairy.core.compat; 2 | 3 | import java.util.HashMap; 4 | 5 | public class EmptyHashMap extends HashMap { 6 | 7 | @Override 8 | public V put(K key, V value) { 9 | //不缓存 10 | return super.put(key, null); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /FairyPlugin/src/main/java/com/limpoxe/fairy/core/compat/EmptySimpleArrayMap.java: -------------------------------------------------------------------------------- 1 | package com.limpoxe.fairy.core.compat; 2 | 3 | import androidx.annotation.NonNull; 4 | import androidx.annotation.Nullable; 5 | import androidx.collection.SimpleArrayMap; 6 | 7 | public class EmptySimpleArrayMap extends SimpleArrayMap { 8 | @Override 9 | public V put(K key, V value) { 10 | //put null 11 | return super.put(key, null); 12 | } 13 | 14 | @Nullable 15 | @Override 16 | public V putIfAbsent(K key, V value) { 17 | //put null 18 | return super.putIfAbsent(key, null); 19 | } 20 | 21 | @Override 22 | public void putAll(@NonNull SimpleArrayMap array) { 23 | //do nothing 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /FairyPlugin/src/main/java/com/limpoxe/fairy/core/exception/PluginNotFoundError.java: -------------------------------------------------------------------------------- 1 | package com.limpoxe.fairy.core.exception; 2 | 3 | /** 4 | * Created by cailiming on 16/11/18. 5 | */ 6 | 7 | public class PluginNotFoundError extends Error { 8 | 9 | public PluginNotFoundError(String detailMessage) { 10 | super(detailMessage); 11 | } 12 | 13 | public PluginNotFoundError(String detailMessage, Throwable throwable) { 14 | super(detailMessage, throwable); 15 | } 16 | 17 | public PluginNotFoundError(Throwable throwable) { 18 | super(throwable); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /FairyPlugin/src/main/java/com/limpoxe/fairy/core/exception/PluginNotInitError.java: -------------------------------------------------------------------------------- 1 | package com.limpoxe.fairy.core.exception; 2 | 3 | /** 4 | * Created by cailiming on 16/11/18. 5 | */ 6 | 7 | public class PluginNotInitError extends Error { 8 | 9 | public PluginNotInitError(String detailMessage) { 10 | super(detailMessage); 11 | } 12 | 13 | public PluginNotInitError(String detailMessage, Throwable throwable) { 14 | super(detailMessage, throwable); 15 | } 16 | 17 | public PluginNotInitError(Throwable throwable) { 18 | super(throwable); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /FairyPlugin/src/main/java/com/limpoxe/fairy/core/exception/PluginResInitError.java: -------------------------------------------------------------------------------- 1 | package com.limpoxe.fairy.core.exception; 2 | 3 | /** 4 | * Created by cailiming on 16/11/18. 5 | */ 6 | 7 | public class PluginResInitError extends Error { 8 | 9 | public PluginResInitError(String detailMessage) { 10 | super(detailMessage); 11 | } 12 | 13 | public PluginResInitError(String detailMessage, Throwable throwable) { 14 | super(detailMessage, throwable); 15 | } 16 | 17 | public PluginResInitError(Throwable throwable) { 18 | super(throwable); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /FairyPlugin/src/main/java/com/limpoxe/fairy/core/proxy/MethodDelegate.java: -------------------------------------------------------------------------------- 1 | package com.limpoxe.fairy.core.proxy; 2 | 3 | import java.lang.reflect.Method; 4 | 5 | /** 6 | * Created by cailiming on 16/1/15. 7 | */ 8 | public abstract class MethodDelegate { 9 | 10 | public Object beforeInvoke(Object target, Method method, Object[] args) { 11 | return null; 12 | } 13 | 14 | public Object afterInvoke(Object target, Method method, Object[] args, Object beforeInvoke, Object invokeResult) { 15 | if (beforeInvoke != null) { 16 | return beforeInvoke; 17 | } 18 | return invokeResult; 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /FairyPlugin/src/main/java/com/limpoxe/fairy/core/viewfactory/PluginFactoryInterface.java: -------------------------------------------------------------------------------- 1 | package com.limpoxe.fairy.core.viewfactory; 2 | 3 | import android.content.Context; 4 | import android.util.AttributeSet; 5 | import android.view.View; 6 | 7 | /** 8 | * Created by Administrator on 2015/12/13. 9 | * 10 | * Porting From SupportV7 11 | */ 12 | public interface PluginFactoryInterface { 13 | 14 | /** 15 | * Hook you can supply that is called when inflating from a LayoutInflater. 16 | * You can use this to customize the tag names available in your XML 17 | * layout files. 18 | * 19 | * @param parent The parent that the created view will be placed 20 | * in; note that this may be null. 21 | * @param name Tag name to be inflated. 22 | * @param context The context the view is being created in. 23 | * @param attrs Inflation attributes as specified in XML file. 24 | * 25 | * @return View Newly created view. Return null for the default 26 | * behavior. 27 | */ 28 | public View onCreateView(View parent, String name, Context context, AttributeSet attrs); 29 | 30 | } -------------------------------------------------------------------------------- /FairyPlugin/src/main/java/com/limpoxe/fairy/manager/InstallResult.java: -------------------------------------------------------------------------------- 1 | package com.limpoxe.fairy.manager; 2 | 3 | /** 4 | * Created by cailiming on 16/6/20. 5 | */ 6 | public class InstallResult { 7 | 8 | private int mResult; 9 | private String mPackageName; 10 | private String mVersion; 11 | 12 | public InstallResult(int result) { 13 | this.mResult = result; 14 | } 15 | 16 | public InstallResult(int result, String packageName, String version) { 17 | this.mResult = result; 18 | this.mPackageName = packageName; 19 | this.mVersion = version; 20 | } 21 | 22 | public int getResult() { 23 | return mResult; 24 | } 25 | 26 | public String getPackageName() { 27 | return mPackageName; 28 | } 29 | 30 | public String getVersion() { 31 | return mVersion; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /FairyPlugin/src/main/java/com/limpoxe/fairy/manager/PluginCallback.java: -------------------------------------------------------------------------------- 1 | package com.limpoxe.fairy.manager; 2 | 3 | /** 4 | *use PluginStatusChangeListener instead 5 | */ 6 | @Deprecated 7 | public interface PluginCallback { 8 | 9 | public static final String ACTION_PLUGIN_CHANGED = "com.limpoxe.fairy.action.PLUGIN_CHANGED"; 10 | 11 | public static final String EXTRA_TYPE = "type"; 12 | public static final String EXTRA_ID = "id"; 13 | public static final String EXTRA_VERSION = "version"; 14 | public static final String EXTRA_RESULT_CODE = "code"; 15 | public static final String EXTRA_SRC = "src"; 16 | 17 | public static final String TYPE_INSTALL = "install"; 18 | public static final String TYPE_REMOVE = "remove"; 19 | public static final String TYPE_START = "start"; 20 | public static final String TYPE_STOP = "stop"; 21 | 22 | void onInstall(int result, String packageName, String version, String src); 23 | void onRemove(String packageName, int code); 24 | 25 | void onStart(String packageName); 26 | void onStop(String packageName); 27 | } 28 | -------------------------------------------------------------------------------- /FairyPlugin/src/main/java/com/limpoxe/fairy/manager/PluginManager.java: -------------------------------------------------------------------------------- 1 | package com.limpoxe.fairy.manager; 2 | 3 | /** 4 | * Created by cailiming on 17/11/28. 5 | * 6 | */ 7 | public class PluginManager extends PluginManagerHelper { 8 | 9 | } 10 | -------------------------------------------------------------------------------- /FairyPlugin/src/main/java/com/limpoxe/fairy/manager/PluginStatusChangeListener.java: -------------------------------------------------------------------------------- 1 | package com.limpoxe.fairy.manager; 2 | 3 | /** 4 | * Created by cailiming on 17/11/28. 5 | */ 6 | public interface PluginStatusChangeListener extends PluginCallback { 7 | 8 | } 9 | -------------------------------------------------------------------------------- /FairyPlugin/src/main/java/com/limpoxe/fairy/manager/mapping/StubMappingProcessor.java: -------------------------------------------------------------------------------- 1 | package com.limpoxe.fairy.manager.mapping; 2 | 3 | import com.limpoxe.fairy.content.PluginDescriptor; 4 | 5 | /** 6 | * 插件组件动态绑定到宿主的虚拟stub组件的映射器 7 | * Manifest中节点下的各种组合比较多,而框架内置的stub有限,若有不同于框架内置的stub需要添加, 8 | * 则可以通过注册StubMappingProcessor来添加自定义的处理器 9 | */ 10 | public interface StubMappingProcessor { 11 | 12 | public static final int TYPE_ACTIVITY = 1; 13 | public static final int TYPE_RECEIVER = 2; 14 | public static final int TYPE_SERVICE = 3; 15 | 16 | /** 17 | * 组件类型,表面这个处理器可以处理哪些类型的组件的绑定工作 18 | * @return 19 | */ 20 | int getType(); 21 | 22 | /** 23 | * 24 | * @param pluginDescriptor 25 | * @param pluginComponentClassName 插件组件名 26 | * @return 返回插件组件绑定到的宿主stub组件名 27 | */ 28 | String bindStub(PluginDescriptor pluginDescriptor, String pluginComponentClassName); 29 | 30 | /** 31 | * 解除绑定,如果被绑定的StubClass不能同时被多个插件Class同时绑定, 32 | * 则需要实现此接口,用于解绑,回收StubClass否则可以忽略 33 | */ 34 | void unBindStub(String stubClassName, String pluginStubClass); 35 | 36 | /** 37 | * 判断这个组件是否是一个stub组件 38 | * @param stubClassName 39 | * @return 40 | */ 41 | boolean isStub(String stubClassName); 42 | 43 | /** 44 | * 反查这个stub和哪个插件组件绑定了 45 | * @param stubClassName 46 | * @return 插件组件名 47 | */ 48 | String getBindedPluginClassName(String stubClassName); 49 | 50 | } 51 | -------------------------------------------------------------------------------- /FairyPlugin/src/main/java/com/limpoxe/fairy/util/PendingIntentHelper.java: -------------------------------------------------------------------------------- 1 | package com.limpoxe.fairy.util; 2 | 3 | import android.content.Intent; 4 | 5 | import com.limpoxe.fairy.content.PluginDescriptor; 6 | import com.limpoxe.fairy.core.PluginIntentResolver; 7 | 8 | /** 9 | * Created by cailiming on 16/1/10. 10 | */ 11 | public class PendingIntentHelper { 12 | /** 13 | * used before send notification 14 | * @param intent 15 | * @return 16 | */ 17 | public static Intent resolvePendingIntent(Intent intent, int type) { 18 | 19 | if (type == PluginDescriptor.BROADCAST) { 20 | 21 | Intent newIntent = PluginIntentResolver.resolveReceiver(intent).get(0); 22 | return newIntent; 23 | 24 | } else if (type == PluginDescriptor.ACTIVITY) { 25 | 26 | PluginIntentResolver.resolveActivity(intent); 27 | return intent; 28 | 29 | } else if (type == PluginDescriptor.SERVICE) { 30 | 31 | PluginIntentResolver.resolveService(intent); 32 | return intent; 33 | 34 | } 35 | return intent; 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Cai Liming 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Samples/PluginHelloWorld/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /Samples/PluginHelloWorld/README.md: -------------------------------------------------------------------------------- 1 | 测试独立插件demo -------------------------------------------------------------------------------- /Samples/PluginHelloWorld/jitpack.yml: -------------------------------------------------------------------------------- 1 | before_install: 2 | - yes | sdkmanager "cmake;3.10.2.4988404" 3 | - sdk install java 11.0.10-open 4 | - sdk use java 11.0.10-open 5 | 6 | jdk: 7 | - openjdk11 -------------------------------------------------------------------------------- /Samples/PluginHelloWorld/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /Users/cailiming/Library/Android/sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /Samples/PluginHelloWorld/src/main/cpp/hello-jni.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | extern "C" JNIEXPORT jint JNICALL 6 | Java_com_example_pluginhelloworld_HelloJni_calculate( 7 | JNIEnv* env, 8 | jclass /* this */, 9 | jint x, 10 | jint y) { 11 | int ret = x + y; 12 | __android_log_print(ANDROID_LOG_INFO, "HelloJni", "pluginhelloworld %i + %i = %i", x, y, ret); 13 | return ret; 14 | } 15 | -------------------------------------------------------------------------------- /Samples/PluginHelloWorld/src/main/java/com/example/pluginhelloworld/HelloFileProvider.java: -------------------------------------------------------------------------------- 1 | package com.example.pluginhelloworld; 2 | 3 | import android.net.Uri; 4 | import android.os.ParcelFileDescriptor; 5 | 6 | import androidx.annotation.NonNull; 7 | import androidx.core.content.FileProvider; 8 | 9 | import java.io.FileNotFoundException; 10 | 11 | public class HelloFileProvider extends FileProvider { 12 | @Override 13 | public ParcelFileDescriptor openFile(@NonNull Uri uri, @NonNull String mode) 14 | throws FileNotFoundException { 15 | //插件中需要对外部app提供的intent,都需要通过宿主来桥接 16 | //本例中插件提供了一个contentprovider给外系统app:PackageInstaller调用。 17 | //所以插件中的这个contentprovider是被宿主桥接过来的 18 | //桥接时框架会给uri增加一个固定的前缀,这里需要将前缀移除掉,还原到原本期望的uri 19 | Uri realUri = Uri.parse(uri.toString().replace("unsafe.proxy.", "")); 20 | return super.openFile(realUri, mode); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Samples/PluginHelloWorld/src/main/java/com/example/pluginhelloworld/HelloJni.java: -------------------------------------------------------------------------------- 1 | package com.example.pluginhelloworld; 2 | 3 | public class HelloJni { 4 | 5 | public static native int calculate(int digit_1, int digit_2); 6 | 7 | static { 8 | System.loadLibrary("hello-jni"); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Samples/PluginHelloWorld/src/main/java/com/example/pluginhelloworld/HellowWorldApplication.java: -------------------------------------------------------------------------------- 1 | package com.example.pluginhelloworld; 2 | 3 | import android.app.Application; 4 | import android.util.Log; 5 | 6 | 7 | /** 8 | * 独立插件测试demo 9 | */ 10 | public class HellowWorldApplication extends Application { 11 | @Override 12 | public void onCreate() { 13 | super.onCreate(); 14 | Log.d("HelloWorld", "Application onCreate"); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Samples/PluginHelloWorld/src/main/java/com/example/pluginhelloworld/Stock.java: -------------------------------------------------------------------------------- 1 | package com.example.pluginhelloworld; 2 | 3 | import android.util.Log; 4 | 5 | public class Stock { 6 | 7 | public void testProxyMethod(String text) { 8 | Log.e("Stock", "testProxyMethod " + text); 9 | } 10 | 11 | } 12 | -------------------------------------------------------------------------------- /Samples/PluginHelloWorld/src/main/java/com/example/pluginhelloworld/TransparentActivity.java: -------------------------------------------------------------------------------- 1 | package com.example.pluginhelloworld; 2 | 3 | import android.app.Activity; 4 | import android.os.Bundle; 5 | 6 | /** 7 | * 独立插件测试demo 8 | */ 9 | public class TransparentActivity extends Activity { 10 | 11 | @Override 12 | protected void onCreate(Bundle savedInstanceState) { 13 | super.onCreate(savedInstanceState); 14 | setContentView(R.layout.activity_transparent); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Samples/PluginHelloWorld/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 7 | 8 |