├── .gitignore ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── ic_launcher-playstore.png │ ├── java │ └── com │ │ └── common │ │ └── sample │ │ ├── app │ │ ├── ActivityLifecycleCallbacksImpl.kt │ │ ├── AppConfiguration.kt │ │ └── AppLifecyclesImpl.kt │ │ └── ui │ │ └── activity │ │ └── SplashActivity.kt │ └── res │ ├── drawable │ └── layer_splash_launch.xml │ ├── layout │ └── activity_splash.xml │ ├── mipmap-anydpi-v26 │ ├── ic_launcher.xml │ └── ic_launcher_round.xml │ ├── mipmap-hdpi │ ├── ic_launcher.png │ ├── ic_launcher_foreground.png │ └── ic_launcher_round.png │ ├── mipmap-mdpi │ ├── ic_launcher.png │ ├── ic_launcher_foreground.png │ └── ic_launcher_round.png │ ├── mipmap-xhdpi │ ├── ic_launcher.png │ ├── ic_launcher_foreground.png │ └── ic_launcher_round.png │ ├── mipmap-xxhdpi │ ├── ic_launcher.png │ ├── ic_launcher_foreground.png │ └── ic_launcher_round.png │ ├── mipmap-xxxhdpi │ ├── ic_launcher.png │ ├── ic_launcher_foreground.png │ └── ic_launcher_round.png │ └── values │ ├── colors.xml │ ├── ic_launcher_background.xml │ ├── strings.xml │ └── styles.xml ├── build.gradle ├── buildSrc ├── .gitignore ├── build.gradle.kts ├── build_version.gradle └── src │ └── main │ ├── java │ ├── Dependencies.kt │ └── com │ │ └── common │ │ └── plugin │ │ ├── CommonAndroid.kt │ │ ├── CommonDependencies.kt │ │ ├── CommonPlugins.kt │ │ ├── PluginApp.kt │ │ └── PluginLib.kt │ └── resources │ └── META-INF │ └── gradle-plugins │ ├── com.common.plugin.app.properties │ └── com.common.plugin.lib.properties ├── build_app.gradle ├── common-core ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── common │ │ └── arms │ │ ├── base │ │ ├── App.java │ │ ├── BaseActivity.kt │ │ ├── BaseApplication.java │ │ ├── BaseFragment.kt │ │ ├── BaseService.java │ │ ├── delegate │ │ │ ├── ActivityDelegate.java │ │ │ ├── ActivityDelegateImpl.java │ │ │ ├── AppDelegate.java │ │ │ ├── AppLifecycles.java │ │ │ ├── FragmentDelegate.java │ │ │ ├── FragmentDelegateImpl.java │ │ │ ├── IActivity.java │ │ │ └── IFragment.java │ │ ├── mvvm │ │ │ ├── BaseRepository.kt │ │ │ ├── BaseVMActivity.kt │ │ │ ├── BaseVMFragment.kt │ │ │ ├── BaseVMLazyLoadFragment.kt │ │ │ └── BaseViewModel.kt │ │ ├── net │ │ │ └── NetRequestExt.kt │ │ └── state │ │ │ ├── State.kt │ │ │ └── StateType.kt │ │ ├── callback │ │ ├── EmptyCallBack.kt │ │ ├── ErrorCallBack.kt │ │ └── LoadingCallBack.kt │ │ ├── di │ │ ├── component │ │ │ └── AppComponent.java │ │ └── module │ │ │ ├── AppModule.java │ │ │ ├── ClientModule.java │ │ │ └── GlobalConfigModule.java │ │ ├── glide │ │ ├── BlurTransformation.java │ │ ├── CacheStrategy.java │ │ ├── GlideImageLoaderStrategy.java │ │ └── ImageConfigImpl.java │ │ ├── http │ │ ├── BaseUrl.java │ │ ├── GlobalHttpHandler.java │ │ ├── OkHttpStreamFetcher.java │ │ ├── OkHttpUrlLoader.java │ │ ├── imageloader │ │ │ ├── BaseImageLoaderStrategy.java │ │ │ ├── ImageConfig.java │ │ │ ├── ImageLoader.java │ │ │ └── glide │ │ │ │ ├── GlideAppliesOptions.java │ │ │ │ └── GlideConfiguration.java │ │ └── log │ │ │ ├── DefaultFormatPrinter.java │ │ │ ├── FormatPrinter.java │ │ │ └── RequestInterceptor.java │ │ ├── integration │ │ ├── ActivityLifecycle.java │ │ ├── AppManager.java │ │ ├── ConfigModule.java │ │ ├── FragmentLifecycle.java │ │ ├── IRepositoryManager.java │ │ ├── ManifestParser.java │ │ ├── RepositoryManager.java │ │ ├── RetrofitServiceProxyHandler.java │ │ ├── cache │ │ │ ├── Cache.java │ │ │ ├── CacheType.java │ │ │ ├── IntelligentCache.java │ │ │ └── LruCache.java │ │ └── lifecycle │ │ │ ├── ActivityLifecycleForRxLifecycle.java │ │ │ ├── ActivityLifecycleable.java │ │ │ ├── FragmentLifecycleForRxLifecycle.java │ │ │ ├── FragmentLifecycleable.java │ │ │ └── Lifecycleable.java │ │ ├── utils │ │ ├── ArmsUtil.java │ │ ├── CharacterHandler.java │ │ ├── ClassUtil.kt │ │ ├── DataHelper.java │ │ ├── DeviceUtil.java │ │ ├── DialogUtil.kt │ │ ├── DrawableProvider.java │ │ ├── FastBlur.java │ │ ├── LogUtil.java │ │ ├── PermissionUtil.java │ │ ├── Preconditions.java │ │ ├── UrlEncoderUtil.java │ │ └── ZipHelper.java │ │ └── widget │ │ └── CustomPopupWindow.java │ └── res │ ├── drawable-xhdpi │ ├── base_ic_load_empty.xml │ └── base_ic_load_error.xml │ ├── layout │ ├── base_layout_empty.xml │ ├── base_layout_error.xml │ └── base_layout_loading.xml │ ├── values │ ├── colors.xml │ └── strings.xml │ └── xml │ └── network_security_config.xml ├── common-res ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── assets │ ├── CallBackLoading.json │ └── CommonLoading.json │ ├── java │ └── com │ │ └── common │ │ └── res │ │ ├── adapter │ │ └── BaseBindingQuickAdapter.kt │ │ ├── api │ │ └── Api.kt │ │ ├── app │ │ ├── ActivityLifecycleCallbacksImpl.kt │ │ ├── FragmentLifecycleCallbacksImpl.kt │ │ ├── GlobalConfiguration.kt │ │ ├── GlobalHttpHandlerImpl.kt │ │ ├── GlobalLifecyclesImpl.kt │ │ └── SSLSocketClient.java │ │ ├── config │ │ └── AppConfig.kt │ │ ├── entity │ │ ├── ListEntity.kt │ │ ├── SendEventEntity.kt │ │ └── UpdateResultEntity.kt │ │ ├── event │ │ └── EventKeys.kt │ │ ├── ext │ │ ├── Boolean+Extension.kt │ │ ├── Bundle+Extension.kt │ │ ├── Context+Extension.kt │ │ ├── Exception+Extension.kt │ │ ├── IO+Extension.kt │ │ ├── ImageView+Extension.kt │ │ ├── Number+Extension.kt │ │ ├── Object+Extension.kt │ │ ├── SystemService+Extension.kt │ │ └── View+Extension.kt │ │ ├── immersionbar │ │ ├── BindFullScreen.kt │ │ └── BindImmersionBar.kt │ │ ├── page │ │ └── PageDataHelper.kt │ │ ├── qrcode │ │ └── QrCodeActivity.kt │ │ ├── router │ │ ├── RouterHub.kt │ │ ├── RouterUtil.kt │ │ └── service │ │ │ └── IWebFrameService.kt │ │ ├── smartkey │ │ └── MmkvSettingsImpl.kt │ │ ├── update │ │ ├── CustomUpdateChecker.kt │ │ ├── CustomUpdateParser.kt │ │ ├── OKHttpUpdateHttpService.kt │ │ └── UpdateUtil.kt │ │ ├── utils │ │ ├── AndroidBug5497Workaround.kt │ │ ├── AppUtil.kt │ │ ├── CProgressDialogUtil.kt │ │ ├── EventBusUtil.kt │ │ ├── FastClickUtil.kt │ │ ├── FileUtil.kt │ │ ├── GlideCacheUtil.kt │ │ ├── GsonUtil.kt │ │ ├── HttpPartUtil.kt │ │ ├── LocationUtil.kt │ │ ├── NotificationUtil.kt │ │ ├── OnClickUtil.kt │ │ ├── PlatformUtil.kt │ │ ├── RxJavaUtil.kt │ │ ├── SAFUtil.kt │ │ ├── SDCardUtil.kt │ │ ├── ShellUtil.kt │ │ ├── ToastUtil.kt │ │ └── UriUtil.kt │ │ └── view │ │ ├── IOSScrollView.java │ │ ├── NiceImageView.java │ │ ├── NoSlideViewPager.java │ │ └── RefreshLottieHeader.java │ └── res │ ├── drawable-xhdpi │ ├── res_ic_image_default.9.png │ └── res_ic_toolbar_back.png │ ├── layout │ ├── res_activity_qrcode.xml │ ├── res_layout_refresh_header.xml │ └── res_layout_top_common.xml │ └── values │ ├── attrs.xml │ ├── colors.xml │ ├── dimens.xml │ ├── ids.xml │ ├── strings.xml │ └── styles.xml ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── module-login ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── common │ │ └── login │ │ ├── api │ │ └── LoginService.kt │ │ ├── app │ │ ├── LoginConfiguration.kt │ │ └── LoginLifecyclesImpl.kt │ │ ├── entity │ │ └── LoginEntity.kt │ │ ├── repository │ │ └── LoginRepository.kt │ │ ├── ui │ │ └── activity │ │ │ └── LoginActivity.kt │ │ └── vm │ │ └── LoginViewModel.kt │ └── res │ ├── drawable-xhdpi │ ├── ic_password.webp │ └── ic_username.webp │ ├── drawable │ └── selector_btn_bg_login.xml │ ├── layout │ └── activity_login.xml │ └── values │ ├── colors.xml │ ├── strings.xml │ └── styles.xml ├── module-main ├── .gitignore ├── build.gradle └── src │ └── main │ ├── AndroidManifest.xml │ ├── debug │ └── AndroidManifest.xml │ ├── java │ └── com │ │ └── common │ │ └── main │ │ ├── api │ │ └── MainService.kt │ │ ├── app │ │ ├── MainConfiguration.kt │ │ └── MainLifecyclesImpl.kt │ │ ├── entity │ │ └── ArticleEntity.kt │ │ ├── repository │ │ └── MainRepository.kt │ │ ├── ui │ │ ├── activity │ │ │ └── MainActivity.kt │ │ └── adapter │ │ │ └── ArticleAdapter.kt │ │ └── vm │ │ └── MainViewModel.kt │ └── res │ ├── drawable │ ├── ic_avatar.webp │ ├── ic_black_right_24.xml │ ├── ic_black_settings_24.xml │ └── ic_white_settings_24.xml │ ├── layout │ ├── activity_main.xml │ └── item_article_list_layout.xml │ └── values │ ├── colors.xml │ ├── strings.xml │ └── styles.xml ├── module-web ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── assets │ ├── dsbridge.js │ └── jsbridge.html │ ├── java │ └── com │ │ └── common │ │ └── webframe │ │ ├── app │ │ ├── WebConfiguration.kt │ │ └── WebLifecyclesImpl.kt │ │ ├── entity │ │ ├── BrowserEntity.kt │ │ ├── CloseNumPageEntity.kt │ │ ├── DialogEntity.kt │ │ ├── NewPageEntity.kt │ │ ├── OpenAudioEntity.kt │ │ ├── OpenVideoEntity.kt │ │ ├── PicturePreviewEntity.kt │ │ ├── RefreshTabRightBtnEntity.kt │ │ ├── SetDataEntity.kt │ │ ├── ShowToastEntity.kt │ │ ├── TabPageEntity.kt │ │ ├── ToolBarEntity.kt │ │ └── WebPageEntity.kt │ │ ├── jsapi │ │ └── JsApi.kt │ │ ├── service │ │ ├── PreLoadX5Service.kt │ │ └── WebFrameServiceImpl.kt │ │ ├── ui │ │ ├── activity │ │ │ ├── TabPageActivity.kt │ │ │ └── WebPageActivity.kt │ │ ├── adapter │ │ │ ├── H5UrlAdapter.kt │ │ │ └── TabPagerAdapter.kt │ │ └── fragment │ │ │ └── WebPageFrgment.kt │ │ ├── utils │ │ ├── CookieUtil.kt │ │ ├── H5UrlCacheUtils.java │ │ └── JsApiHelper.kt │ │ └── view │ │ ├── BaseDWebView.java │ │ ├── CommonIndicator.java │ │ ├── CompletionHandler.java │ │ ├── DWebView.java │ │ ├── DX5WebView.java │ │ ├── LoadingView.java │ │ ├── OnReturnValue.java │ │ ├── ProgressDWebView.java │ │ ├── ProgressDX5WebView.java │ │ └── agentweb │ │ ├── AbsAgentWebSettings.java │ │ ├── AbsAgentWebUIController.java │ │ ├── Action.java │ │ ├── ActionActivity.java │ │ ├── AgentWeb.java │ │ ├── AgentWebConfig.java │ │ ├── AgentWebFileProvider.java │ │ ├── AgentWebJsInterfaceCompat.java │ │ ├── AgentWebPermissions.java │ │ ├── AgentWebSettingsImpl.java │ │ ├── AgentWebUIControllerImplBase.java │ │ ├── AgentWebUtils.java │ │ ├── AgentWebView.java │ │ ├── BaseIndicatorSpec.java │ │ ├── BaseIndicatorView.java │ │ ├── BaseJsAccessEntrace.java │ │ ├── DefaultChromeClient.java │ │ ├── DefaultDesignUIController.java │ │ ├── DefaultUIController.java │ │ ├── DefaultWebClient.java │ │ ├── DefaultWebCreator.java │ │ ├── DefaultWebLifeCycleImpl.java │ │ ├── EventHandlerImpl.java │ │ ├── EventInterceptor.java │ │ ├── HookManager.java │ │ ├── HttpHeaders.java │ │ ├── IAgentWebSettings.java │ │ ├── IEventHandler.java │ │ ├── IUrlLoader.java │ │ ├── IVideo.java │ │ ├── IWebIndicator.java │ │ ├── IWebLayout.java │ │ ├── IndicatorController.java │ │ ├── IndicatorHandler.java │ │ ├── JsAccessEntrace.java │ │ ├── JsAccessEntraceImpl.java │ │ ├── JsBaseInterfaceHolder.java │ │ ├── JsCallJava.java │ │ ├── JsCallback.java │ │ ├── JsInterfaceHolder.java │ │ ├── JsInterfaceHolderImpl.java │ │ ├── JsInterfaceObjectException.java │ │ ├── LayoutParamsOffer.java │ │ ├── LogUtils.java │ │ ├── MiddlewareWebChromeBase.java │ │ ├── MiddlewareWebClientBase.java │ │ ├── NestedScrollAgentWebView.java │ │ ├── PermissionInterceptor.java │ │ ├── Provider.java │ │ ├── QuickCallJs.java │ │ ├── UrlCommonException.java │ │ ├── UrlLoaderImpl.java │ │ ├── VideoImpl.java │ │ ├── WebChromeClient.java │ │ ├── WebChromeClientDelegate.java │ │ ├── WebCreator.java │ │ ├── WebIndicator.java │ │ ├── WebLifeCycle.java │ │ ├── WebListenerManager.java │ │ ├── WebParentLayout.java │ │ ├── WebSecurityCheckLogic.java │ │ ├── WebSecurityController.java │ │ ├── WebSecurityControllerImpl.java │ │ ├── WebSecurityLogicImpl.java │ │ ├── WebViewClient.java │ │ └── WebViewClientDelegate.java │ └── res │ ├── drawable-xhdpi │ ├── download.png │ ├── ic_load.png │ ├── ic_load_fail.png │ ├── ic_load_success.png │ ├── ic_webframe_back_black.png │ └── ic_webframe_back_white.png │ ├── drawable │ ├── anim_progress.xml │ ├── ic_add_black_24dp.xml │ ├── ic_add_white_24dp.xml │ ├── layer_progress_bar_states.xml │ ├── selector_radio_bg.xml │ ├── selector_tab_text.xml │ ├── shape_checked.xml │ ├── shape_share_class_bg.xml │ ├── shape_unchecked.xml │ └── shape_webframe_dialog_bg.xml │ ├── layout │ ├── activity_config.xml │ ├── activity_tabpage.xml │ ├── activity_webpage.xml │ ├── fragment_webpage.xml │ ├── layout_agentweb_error_page.xml │ ├── layout_error_page.xml │ ├── layout_item_h5_url.xml │ ├── layout_loading_view.xml │ ├── layout_radiobutton.xml │ └── layout_toolbar.xml │ ├── values │ ├── colors.xml │ ├── dimens.xml │ ├── ids.xml │ ├── strings.xml │ └── styles.xml │ └── xml │ └── web_files_public.xml └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | # Built application files 2 | *.apk 3 | *.ap_ 4 | 5 | # Files for the ART/Dalvik VM 6 | *.dex 7 | 8 | # Java class files 9 | *.class 10 | 11 | # Generated files 12 | bin/ 13 | gen/ 14 | out/ 15 | 16 | # Gradle files 17 | .gradle/ 18 | build/ 19 | 20 | # Local configuration file (sdk path, etc) 21 | local.properties 22 | 23 | # Proguard folder generated by Eclipse 24 | proguard/ 25 | 26 | # Log Files 27 | *.log 28 | 29 | # Android Studio Navigation editor temp files 30 | .navigation/ 31 | 32 | # Android Studio captures folder 33 | captures/ 34 | 35 | # Intellij 36 | *.iml 37 | .idea 38 | 39 | # Keystore files 40 | *.jks 41 | 42 | # MacOS 43 | .DS_Store 44 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ### 相关内容 2 | * 组件化、支持模块单独运行 3 | * androidx 4 | * mvvm 5 | * kotlin 6 | * koin 7 | * jetpack(livedata、viewmodel、lifecycle、viewbinding、...) 8 | * buildsrc 9 | * coroutines 10 | * liveeventbus 11 | * ... 12 | 13 | [项目用到的依赖库](https://github.com/panyy/mvvm-jetpack-sample/blob/master/buildSrc/src/main/java/Dependencies.kt) 14 | 15 | ### APK下载体验 16 | [https://www.pgyer.com/Ispr](https://www.pgyer.com/Ispr) 17 | 18 | ### 如何检查依赖库的版本更新 19 | 在项目的根目录下执行以下命令。 20 | ``` 21 | ./gradlew dependencyUpdates 22 | ``` 23 | 会在当前目录下生成 build/dependencyUpdates/report.txt 文件,内容如下所示: 24 | ``` 25 | The following dependencies have later release versions: 26 | - androidx.swiperefreshlayout:swiperefreshlayout [1.0.0 -> 1.1.0] 27 | https://developer.android.com/jetpack/androidx 28 | - com.squareup.okhttp3:logging-interceptor [3.9.0 -> 4.7.2] 29 | https://square.github.io/okhttp/ 30 | - junit:junit [4.12 -> 4.13] 31 | http://junit.org 32 | - org.koin:koin-android [2.1.5 -> 2.1.6] 33 | - org.koin:koin-androidx-viewmodel [2.1.5 -> 2.1.6] 34 | - org.koin:koin-core [2.1.5 -> 2.1.6] 35 | Gradle release-candidate updates: 36 | - Gradle: [6.1.1 -> 6.5.1] 37 | ``` 38 | 会列出所有需要更新的依赖库的最新版本,并且 Gradle Versions Plugin 比 AndroidStudio 所支持的更加全面: 39 | * 支持手动方式管理依赖库最新版本检查 40 | * 支持 ext 的方式管理依赖库最新版本检查 41 | * 支持 buildSrc 方式管理依赖库最新版本检查 42 | * 支持 gradle-wrapper 最新版本检查 43 | * 支持多模块的依赖库最新版本检查 44 | * 支持多项目的依赖库最新版本检查 45 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id "com.common.plugin.app" 3 | } 4 | dependencies { 5 | implementation project(':common-res') 6 | implementation project(':module-login') 7 | implementation project(':module-main') 8 | implementation project(':module-web') 9 | } 10 | -------------------------------------------------------------------------------- /app/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/jess/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 | #} -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 12 | 13 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /app/src/main/ic_launcher-playstore.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/panyy/mvvm-jetpack-sample/6d22f7cb6f2954c2c590edeeca956a9b1895d7bd/app/src/main/ic_launcher-playstore.png -------------------------------------------------------------------------------- /app/src/main/java/com/common/sample/app/AppConfiguration.kt: -------------------------------------------------------------------------------- 1 | package com.common.sample.app 2 | 3 | import android.app.Application.ActivityLifecycleCallbacks 4 | import android.content.Context 5 | import androidx.fragment.app.FragmentManager 6 | import com.common.arms.base.delegate.AppLifecycles 7 | import com.common.arms.di.module.GlobalConfigModule 8 | import com.common.arms.integration.ConfigModule 9 | 10 | class AppConfiguration : ConfigModule { 11 | override fun applyOptions(context: Context, builder: GlobalConfigModule.Builder) { 12 | } 13 | 14 | override fun injectAppLifecycle(context: Context, lifecycles: MutableList) { 15 | lifecycles.add(AppLifecyclesImpl()) 16 | } 17 | 18 | override fun injectActivityLifecycle(context: Context, lifecycles: MutableList) { 19 | lifecycles.add(ActivityLifecycleCallbacksImpl()) 20 | } 21 | 22 | override fun injectFragmentLifecycle(context: Context, lifecycles: MutableList) { 23 | } 24 | } -------------------------------------------------------------------------------- /app/src/main/java/com/common/sample/app/AppLifecyclesImpl.kt: -------------------------------------------------------------------------------- 1 | package com.common.sample.app 2 | 3 | import android.app.Application 4 | import android.content.Context 5 | import com.common.arms.base.delegate.AppLifecycles 6 | import com.umeng.analytics.MobclickAgent 7 | import com.umeng.commonsdk.UMConfigure 8 | 9 | class AppLifecyclesImpl : AppLifecycles { 10 | 11 | override fun attachBaseContext(base: Context) { 12 | } 13 | 14 | override fun onCreate(application: Application) { 15 | //初始化友盟SDK 16 | UMConfigure.setLogEnabled(true) 17 | UMConfigure.init(application, "1234567890", "xxx", UMConfigure.DEVICE_TYPE_PHONE, "") 18 | MobclickAgent.setPageCollectionMode(MobclickAgent.PageMode.AUTO) 19 | } 20 | 21 | override fun onTerminate(application: Application) {} 22 | 23 | } -------------------------------------------------------------------------------- /app/src/main/java/com/common/sample/ui/activity/SplashActivity.kt: -------------------------------------------------------------------------------- 1 | package com.common.sample.ui.activity 2 | 3 | import android.os.Bundle 4 | import com.common.arms.base.BaseActivity 5 | import com.common.res.immersionbar.BindFullScreen 6 | import com.common.res.router.RouterHub 7 | import com.common.res.router.routerNavigation 8 | import com.common.res.utils.checkLogin 9 | import com.common.sample.databinding.ActivitySplashBinding 10 | 11 | class SplashActivity : BaseActivity(), BindFullScreen { 12 | 13 | override fun initData(savedInstanceState: Bundle?) { 14 | checkLogin { 15 | if (it) { 16 | routerNavigation(RouterHub.PUBLIC_MAIN) 17 | } else { 18 | routerNavigation(RouterHub.PUBLIC_LOGIN) 19 | } 20 | finish() 21 | } 22 | } 23 | 24 | } -------------------------------------------------------------------------------- /app/src/main/res/drawable/layer_splash_launch.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_splash.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/panyy/mvvm-jetpack-sample/6d22f7cb6f2954c2c590edeeca956a9b1895d7bd/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/panyy/mvvm-jetpack-sample/6d22f7cb6f2954c2c590edeeca956a9b1895d7bd/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/panyy/mvvm-jetpack-sample/6d22f7cb6f2954c2c590edeeca956a9b1895d7bd/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/panyy/mvvm-jetpack-sample/6d22f7cb6f2954c2c590edeeca956a9b1895d7bd/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/panyy/mvvm-jetpack-sample/6d22f7cb6f2954c2c590edeeca956a9b1895d7bd/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/panyy/mvvm-jetpack-sample/6d22f7cb6f2954c2c590edeeca956a9b1895d7bd/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/panyy/mvvm-jetpack-sample/6d22f7cb6f2954c2c590edeeca956a9b1895d7bd/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/panyy/mvvm-jetpack-sample/6d22f7cb6f2954c2c590edeeca956a9b1895d7bd/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/panyy/mvvm-jetpack-sample/6d22f7cb6f2954c2c590edeeca956a9b1895d7bd/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/panyy/mvvm-jetpack-sample/6d22f7cb6f2954c2c590edeeca956a9b1895d7bd/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/panyy/mvvm-jetpack-sample/6d22f7cb6f2954c2c590edeeca956a9b1895d7bd/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/panyy/mvvm-jetpack-sample/6d22f7cb6f2954c2c590edeeca956a9b1895d7bd/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/panyy/mvvm-jetpack-sample/6d22f7cb6f2954c2c590edeeca956a9b1895d7bd/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/panyy/mvvm-jetpack-sample/6d22f7cb6f2954c2c590edeeca956a9b1895d7bd/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/panyy/mvvm-jetpack-sample/6d22f7cb6f2954c2c590edeeca956a9b1895d7bd/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #85BF00 4 | #85BF00 5 | #85BF00 6 | #ffffff 7 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/values/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #85BF00 4 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | 10 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | apply from: './buildSrc/build_version.gradle' 2 | buildscript { 3 | 4 | ext.kotlin_version = '1.4.0' 5 | 6 | repositories { 7 | google() 8 | jcenter() 9 | maven { url 'https://maven.aliyun.com/nexus/content/groups/public/' } 10 | maven { url "https://jitpack.io" } 11 | maven { url 'https://dl.bintray.com/umsdk/release' } 12 | } 13 | dependencies { 14 | classpath 'com.android.tools.build:gradle:4.1.2' 15 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.4.20" 16 | //Gradle Android Maven plugin 17 | classpath 'com.github.dcendents:android-maven-gradle-plugin:2.1' 18 | //This plugin is available from Bintray's JCenter repository and from the Gradle Plugin Portal 19 | classpath "com.github.ben-manes:gradle-versions-plugin:0.36.0" 20 | } 21 | } 22 | 23 | allprojects { 24 | repositories { 25 | google() 26 | jcenter() 27 | maven { url 'https://maven.aliyun.com/nexus/content/groups/public/' } 28 | maven { url "https://jitpack.io" } 29 | maven { url 'https://dl.bintray.com/umsdk/release' } 30 | } 31 | } 32 | 33 | task clean(type: Delete) { 34 | delete rootProject.buildDir 35 | } -------------------------------------------------------------------------------- /buildSrc/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | /.gradle -------------------------------------------------------------------------------- /buildSrc/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | `kotlin-dsl` 3 | } 4 | repositories { 5 | google() 6 | jcenter() 7 | mavenCentral() 8 | } 9 | dependencies { 10 | /* Depend on the android gradle plugin, since we want to access it in our plugin */ 11 | implementation("com.android.tools.build:gradle:4.1.2") 12 | 13 | /* Depend on the kotlin plugin, since we want to access it in our plugin */ 14 | implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:1.4.20") 15 | 16 | /* Depend on the default Gradle API's since we want to build a custom plugin */ 17 | implementation(gradleApi()) 18 | implementation(localGroovy()) 19 | } -------------------------------------------------------------------------------- /buildSrc/build_version.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: "com.github.ben-manes.versions" 2 | 3 | def isNonStable = { ComponentSelection selection -> 4 | boolean rejected = ['release', 'final', 'alpha', 'beta', 'rc', 'ga'].any { qualifier -> 5 | selection.candidate.version ==~ /(?i).*[.-]${qualifier}[.\d-]*/ 6 | } 7 | return rejected 8 | } 9 | 10 | tasks.named("dependencyUpdates").configure { 11 | resolutionStrategy { 12 | componentSelection { 13 | all { ComponentSelection selection -> 14 | if (isNonStable(selection)) { 15 | selection.reject('Release candidate') 16 | } 17 | } 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /buildSrc/src/main/java/com/common/plugin/CommonDependencies.kt: -------------------------------------------------------------------------------- 1 | package com.common.plugin 2 | 3 | import Deps 4 | import com.android.build.gradle.api.AndroidBasePlugin 5 | import org.gradle.api.Project 6 | 7 | /** 8 | * desc :公共依赖 9 | * author:panyy 10 | * date:2021/04/22 11 | */ 12 | internal fun Project.configureDependencies() = dependencies.apply { 13 | add("implementation", (fileTree(mapOf("dir" to "libs", "include" to listOf("*.jar"))))) 14 | add("testImplementation", Deps.junit) 15 | 16 | if (project.containsAndroidPlugin()) { 17 | add("androidTestImplementation", Deps.extJunit) 18 | add("androidTestImplementation", Deps.espressoCore) 19 | } 20 | 21 | add("kapt", Deps.arouterCompiler) 22 | } 23 | 24 | internal fun Project.containsAndroidPlugin(): Boolean { 25 | return project.plugins.toList().any { plugin -> plugin is AndroidBasePlugin } 26 | } -------------------------------------------------------------------------------- /buildSrc/src/main/java/com/common/plugin/CommonPlugins.kt: -------------------------------------------------------------------------------- 1 | package com.common.plugin 2 | 3 | import isRunAlone 4 | import org.gradle.api.Project 5 | 6 | /** 7 | * desc :公共插件 8 | * author:panyy 9 | * date:2021/04/22 10 | */ 11 | internal fun Project.configurePlugins(isAppModule: Boolean) { 12 | if (isAppModule || isRunAlone) { 13 | plugins.apply("com.android.application") 14 | var options = mutableMapOf().apply { 15 | @Suppress("MISSING_DEPENDENCY_CLASS") 16 | put("from", "${project.rootDir}/build_app.gradle") 17 | } 18 | apply(options) 19 | } else { 20 | plugins.apply("com.android.library") 21 | } 22 | plugins.apply("kotlin-android") 23 | plugins.apply("kotlin-kapt") 24 | plugins.apply("kotlin-android-extensions") 25 | } -------------------------------------------------------------------------------- /buildSrc/src/main/java/com/common/plugin/PluginApp.kt: -------------------------------------------------------------------------------- 1 | package com.common.plugin 2 | 3 | import org.gradle.api.Plugin 4 | import org.gradle.api.Project 5 | 6 | /** 7 | * desc :插件配置 8 | * author:panyy 9 | * date:2021/04/22 10 | */ 11 | class PluginApp : Plugin { 12 | override fun apply(project: Project) { 13 | project.configurePlugins(true) 14 | project.configureAndroid(true) 15 | project.configureDependencies() 16 | } 17 | } -------------------------------------------------------------------------------- /buildSrc/src/main/java/com/common/plugin/PluginLib.kt: -------------------------------------------------------------------------------- 1 | package com.common.plugin 2 | 3 | import org.gradle.api.Plugin 4 | import org.gradle.api.Project 5 | 6 | /** 7 | * desc :插件配置 8 | * author:panyy 9 | * date:2021/04/22 10 | */ 11 | class PluginLib : Plugin { 12 | override fun apply(project: Project) { 13 | project.configurePlugins(false) 14 | project.configureAndroid(false) 15 | project.configureDependencies() 16 | } 17 | } -------------------------------------------------------------------------------- /buildSrc/src/main/resources/META-INF/gradle-plugins/com.common.plugin.app.properties: -------------------------------------------------------------------------------- 1 | implementation-class=com.common.plugin.PluginApp -------------------------------------------------------------------------------- /buildSrc/src/main/resources/META-INF/gradle-plugins/com.common.plugin.lib.properties: -------------------------------------------------------------------------------- 1 | implementation-class=com.common.plugin.PluginLib -------------------------------------------------------------------------------- /build_app.gradle: -------------------------------------------------------------------------------- 1 | android { 2 | productFlavors { 3 | sample_release { 4 | versionCode 2 5 | versionName "1.0.1" 6 | applicationId "com.common.sample" 7 | resValue "string", "app_name", "MVVMJetpack" 8 | } 9 | } 10 | } -------------------------------------------------------------------------------- /common-core/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /common-core/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /common-core/src/main/java/com/common/arms/base/App.java: -------------------------------------------------------------------------------- 1 | package com.common.arms.base; 2 | 3 | import androidx.annotation.NonNull; 4 | 5 | import com.common.arms.di.component.AppComponent; 6 | 7 | /** 8 | * ================================================ 9 | * 框架要求框架中的每个 {@link android.app.Application} 都需要实现此类, 以满足规范 10 | * ================================================ 11 | */ 12 | public interface App { 13 | @NonNull 14 | AppComponent getAppComponent(); 15 | } 16 | -------------------------------------------------------------------------------- /common-core/src/main/java/com/common/arms/base/BaseService.java: -------------------------------------------------------------------------------- 1 | package com.common.arms.base; 2 | 3 | import android.app.Service; 4 | import android.content.Intent; 5 | import android.os.IBinder; 6 | 7 | import androidx.annotation.Nullable; 8 | 9 | import io.reactivex.disposables.CompositeDisposable; 10 | import io.reactivex.disposables.Disposable; 11 | 12 | /** 13 | * ================================================ 14 | * 基类 {@link Service} 15 | * ================================================ 16 | */ 17 | public abstract class BaseService extends Service { 18 | protected final String TAG = this.getClass().getSimpleName(); 19 | protected CompositeDisposable mCompositeDisposable; 20 | 21 | @Nullable 22 | @Override 23 | public IBinder onBind(Intent intent) { 24 | return null; 25 | } 26 | 27 | @Override 28 | public void onCreate() { 29 | super.onCreate(); 30 | init(); 31 | } 32 | 33 | @Override 34 | public void onDestroy() { 35 | super.onDestroy(); 36 | unDispose();//解除订阅 37 | this.mCompositeDisposable = null; 38 | } 39 | 40 | protected void addDispose(Disposable disposable) { 41 | if (mCompositeDisposable == null) { 42 | mCompositeDisposable = new CompositeDisposable(); 43 | } 44 | mCompositeDisposable.add(disposable);//将所有 Disposable 放入容器集中处理 45 | } 46 | 47 | protected void unDispose() { 48 | if (mCompositeDisposable != null) { 49 | mCompositeDisposable.clear();//保证 Activity 结束时取消所有正在执行的订阅 50 | } 51 | } 52 | 53 | /** 54 | * 初始化 55 | */ 56 | abstract public void init(); 57 | } 58 | -------------------------------------------------------------------------------- /common-core/src/main/java/com/common/arms/base/delegate/ActivityDelegate.java: -------------------------------------------------------------------------------- 1 | package com.common.arms.base.delegate; 2 | 3 | import android.app.Activity; 4 | import android.os.Bundle; 5 | 6 | import androidx.annotation.NonNull; 7 | import androidx.annotation.Nullable; 8 | 9 | /** 10 | * ================================================ 11 | * {@link Activity} 代理类,用于框架内部在每个 {@link Activity} 的对应生命周期中插入需要的逻辑 12 | * ================================================ 13 | */ 14 | public interface ActivityDelegate { 15 | String LAYOUT_LINEARLAYOUT = "LinearLayout"; 16 | String LAYOUT_FRAMELAYOUT = "FrameLayout"; 17 | String LAYOUT_RELATIVELAYOUT = "RelativeLayout"; 18 | String ACTIVITY_DELEGATE = "ACTIVITY_DELEGATE"; 19 | 20 | void onCreate(@Nullable Bundle savedInstanceState); 21 | 22 | void onStart(); 23 | 24 | void onResume(); 25 | 26 | void onPause(); 27 | 28 | void onStop(); 29 | 30 | void onSaveInstanceState(@NonNull Bundle outState); 31 | 32 | void onDestroy(); 33 | } 34 | -------------------------------------------------------------------------------- /common-core/src/main/java/com/common/arms/base/delegate/ActivityDelegateImpl.java: -------------------------------------------------------------------------------- 1 | package com.common.arms.base.delegate; 2 | 3 | import android.app.Activity; 4 | import android.os.Bundle; 5 | 6 | import androidx.annotation.NonNull; 7 | import androidx.annotation.Nullable; 8 | 9 | /** 10 | * ================================================ 11 | * {@link ActivityDelegate} 默认实现类 12 | * ================================================ 13 | */ 14 | public class ActivityDelegateImpl implements ActivityDelegate { 15 | private Activity mActivity; 16 | private IActivity iActivity; 17 | 18 | public ActivityDelegateImpl(@NonNull Activity activity) { 19 | this.mActivity = activity; 20 | this.iActivity = (IActivity) activity; 21 | } 22 | 23 | @Override 24 | public void onCreate(@Nullable Bundle savedInstanceState) { 25 | 26 | } 27 | 28 | @Override 29 | public void onStart() { 30 | 31 | } 32 | 33 | @Override 34 | public void onResume() { 35 | 36 | } 37 | 38 | @Override 39 | public void onPause() { 40 | 41 | } 42 | 43 | @Override 44 | public void onStop() { 45 | 46 | } 47 | 48 | @Override 49 | public void onSaveInstanceState(@NonNull Bundle outState) { 50 | 51 | } 52 | 53 | @Override 54 | public void onDestroy() { 55 | this.iActivity = null; 56 | this.mActivity = null; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /common-core/src/main/java/com/common/arms/base/delegate/AppLifecycles.java: -------------------------------------------------------------------------------- 1 | package com.common.arms.base.delegate; 2 | 3 | import android.app.Application; 4 | import android.content.Context; 5 | 6 | import androidx.annotation.NonNull; 7 | 8 | /** 9 | * ================================================ 10 | * 用于代理 {@link Application} 的生命周期 11 | * ================================================ 12 | */ 13 | public interface AppLifecycles { 14 | void attachBaseContext(@NonNull Context base); 15 | 16 | void onCreate(@NonNull Application application); 17 | 18 | void onTerminate(@NonNull Application application); 19 | } 20 | -------------------------------------------------------------------------------- /common-core/src/main/java/com/common/arms/base/delegate/FragmentDelegate.java: -------------------------------------------------------------------------------- 1 | package com.common.arms.base.delegate; 2 | 3 | import android.content.Context; 4 | import android.os.Bundle; 5 | import android.view.View; 6 | 7 | import androidx.annotation.NonNull; 8 | import androidx.annotation.Nullable; 9 | import androidx.fragment.app.Fragment; 10 | 11 | /** 12 | * ================================================ 13 | * {@link Fragment} 代理类,用于框架内部在每个 {@link Fragment} 的对应生命周期中插入需要的逻辑 14 | * ================================================ 15 | */ 16 | public interface FragmentDelegate { 17 | String FRAGMENT_DELEGATE = "FRAGMENT_DELEGATE"; 18 | 19 | void onAttach(@NonNull Context context); 20 | 21 | void onCreate(@Nullable Bundle savedInstanceState); 22 | 23 | void onCreateView(@Nullable View view, @Nullable Bundle savedInstanceState); 24 | 25 | void onActivityCreate(@Nullable Bundle savedInstanceState); 26 | 27 | void onStart(); 28 | 29 | void onResume(); 30 | 31 | void onPause(); 32 | 33 | void onStop(); 34 | 35 | void onSaveInstanceState(@NonNull Bundle outState); 36 | 37 | void onDestroyView(); 38 | 39 | void onDestroy(); 40 | 41 | void onDetach(); 42 | 43 | /** 44 | * Return true if the fragment is currently added to its activity. 45 | */ 46 | boolean isAdded(); 47 | } 48 | -------------------------------------------------------------------------------- /common-core/src/main/java/com/common/arms/base/delegate/IActivity.java: -------------------------------------------------------------------------------- 1 | package com.common.arms.base.delegate; 2 | 3 | 4 | import android.app.Activity; 5 | import android.os.Bundle; 6 | 7 | import androidx.annotation.Nullable; 8 | import androidx.fragment.app.FragmentManager; 9 | 10 | import com.common.arms.integration.cache.Cache; 11 | import com.common.arms.integration.cache.LruCache; 12 | 13 | /** 14 | * ================================================ 15 | * 框架要求框架中的每个 {@link Activity} 都需要实现此类,以满足规范 16 | * ================================================ 17 | */ 18 | public interface IActivity { 19 | 20 | /** 21 | * 提供在 {@link Activity} 生命周期内的缓存容器, 可向此 {@link Activity} 存取一些必要的数据 22 | * 此缓存容器和 {@link Activity} 的生命周期绑定, 如果 {@link Activity} 在屏幕旋转或者配置更改的情况下 23 | * 重新创建, 那此缓存容器中的数据也会被清空, 如果你想避免此种情况请使用 LifecycleModel 24 | * 25 | * @return like {@link LruCache} 26 | */ 27 | Cache provideCache(); 28 | 29 | /** 30 | * 初始化数据 31 | * 32 | * @param savedInstanceState 33 | */ 34 | void initData(@Nullable Bundle savedInstanceState); 35 | 36 | /** 37 | * 这个 Activity 是否会使用 Fragment,框架会根据这个属性判断是否注册 {@link FragmentManager.FragmentLifecycleCallbacks} 38 | * 如果返回{@code false},那意味着这个 Activity 不需要绑定 Fragment,那你再在这个 Activity 中绑定继承于 BaseFragment 的 Fragment 将不起任何作用 39 | * 40 | * @return 41 | */ 42 | boolean useFragment(); 43 | } 44 | -------------------------------------------------------------------------------- /common-core/src/main/java/com/common/arms/base/delegate/IFragment.java: -------------------------------------------------------------------------------- 1 | package com.common.arms.base.delegate; 2 | 3 | import android.os.Bundle; 4 | import android.view.LayoutInflater; 5 | import android.view.ViewGroup; 6 | 7 | import androidx.annotation.NonNull; 8 | import androidx.annotation.Nullable; 9 | import androidx.fragment.app.Fragment; 10 | 11 | import com.common.arms.integration.cache.Cache; 12 | import com.common.arms.integration.cache.LruCache; 13 | 14 | /** 15 | * ================================================ 16 | * 框架要求框架中的每个 {@link Fragment} 都需要实现此类,以满足规范 17 | * ================================================ 18 | */ 19 | public interface IFragment { 20 | 21 | /** 22 | * 提供在 {@link Fragment} 生命周期内的缓存容器, 可向此 {@link Fragment} 存取一些必要的数据 23 | * 此缓存容器和 {@link Fragment} 的生命周期绑定, 如果 {@link Fragment} 在屏幕旋转或者配置更改的情况下 24 | * 重新创建, 那此缓存容器中的数据也会被清空, 如果你想避免此种情况请使用 LifecycleModel 25 | * 26 | * @return like {@link LruCache} 27 | */ 28 | @NonNull 29 | Cache provideCache(); 30 | 31 | /** 32 | * 初始化数据 33 | * 34 | * @param savedInstanceState 35 | */ 36 | void initData(@Nullable Bundle savedInstanceState); 37 | } 38 | -------------------------------------------------------------------------------- /common-core/src/main/java/com/common/arms/base/mvvm/BaseRepository.kt: -------------------------------------------------------------------------------- 1 | package com.common.arms.base.mvvm 2 | 3 | import com.common.arms.integration.AppManager 4 | import com.common.arms.utils.ArmsUtil 5 | 6 | /** 7 | * desc:Repository基类 8 | * author:panyy 9 | * date:2021/04/22 10 | */ 11 | abstract class BaseRepository { 12 | 13 | inline fun apiService(): T = 14 | ArmsUtil.obtainAppComponentFromContext(AppManager.getAppManager().application).repositoryManager().obtainRetrofitService(T::class.java) 15 | 16 | } -------------------------------------------------------------------------------- /common-core/src/main/java/com/common/arms/base/mvvm/BaseViewModel.kt: -------------------------------------------------------------------------------- 1 | package com.common.arms.base.mvvm 2 | 3 | import androidx.lifecycle.MutableLiveData 4 | import androidx.lifecycle.ViewModel 5 | import com.common.arms.base.state.State 6 | 7 | /** 8 | * desc:ViewModel基类 9 | * author:panyy 10 | * date:2021/04/22 11 | */ 12 | open class BaseViewModel : ViewModel() { 13 | 14 | val loadState by lazy { 15 | MutableLiveData() 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /common-core/src/main/java/com/common/arms/base/net/NetRequestExt.kt: -------------------------------------------------------------------------------- 1 | package com.common.arms.base.net 2 | 3 | import androidx.lifecycle.MutableLiveData 4 | import com.common.arms.base.state.State 5 | import com.common.arms.base.state.StateType 6 | 7 | /** 8 | * 发起网络请求 9 | */ 10 | suspend fun apiCall(call: suspend () -> BaseResponse): BaseResponse { 11 | return try { 12 | var response = call() 13 | if (response.errorCode == 0) { 14 | response.state = State(StateType.SUCCESS) 15 | } else { 16 | var message: String = response.errorMsg ?: "未知错误" 17 | response.state = State(StateType.ERROR, message) 18 | } 19 | response 20 | } catch (e: Exception) { 21 | e.printStackTrace() 22 | BaseResponse(state = State(StateType.ERROR, "网络出现问题啦")) 23 | } 24 | } 25 | 26 | /** 27 | * 发起网络请求并POST请求状态 28 | */ 29 | suspend fun apiCallWithState(call: suspend () -> BaseResponse, loadState: MutableLiveData? = null): T? { 30 | var result = apiCall(call) 31 | if (result.state?.code == StateType.SUCCESS) { 32 | return result.data 33 | } else { 34 | loadState?.postValue(result.state) 35 | } 36 | return null 37 | } 38 | 39 | /** 40 | * 发起上传请求 41 | */ 42 | suspend fun apiCallUpload(call: suspend () -> T, loadState: MutableLiveData? = null): T? { 43 | var result = try { 44 | var response: BaseResponse = BaseResponse(state = State(StateType.SUCCESS)) 45 | var result = call() 46 | response.data = result 47 | response 48 | } catch (e: Exception) { 49 | e.printStackTrace() 50 | BaseResponse(state = State(StateType.ERROR, "网络出现问题啦")) 51 | } 52 | if (result.state?.code == StateType.SUCCESS) { 53 | return result.data 54 | } else { 55 | loadState?.postValue(result.state) 56 | } 57 | return null 58 | } 59 | 60 | /** 61 | * 返回结果包装类 62 | */ 63 | class BaseResponse( 64 | var errorCode: Int? = -1, 65 | var errorMsg: String? = null, 66 | var data: T? = null, 67 | var state: State? = null, 68 | var isRefresh: Boolean = false, 69 | ) -------------------------------------------------------------------------------- /common-core/src/main/java/com/common/arms/base/state/State.kt: -------------------------------------------------------------------------------- 1 | package com.common.arms.base.state 2 | 3 | /** 4 | * desc:状态对象 5 | * author:panyy 6 | * date:2021/04/22 7 | */ 8 | data class State(var code: StateType, var message: String? = null, var showDialog: Boolean? = true) -------------------------------------------------------------------------------- /common-core/src/main/java/com/common/arms/base/state/StateType.kt: -------------------------------------------------------------------------------- 1 | package com.common.arms.base.state 2 | 3 | /** 4 | * desc:状态类型 5 | * author:panyy 6 | * date:2021/04/22 7 | */ 8 | enum class StateType { 9 | LOADING, 10 | EMPTY, 11 | ERROR, 12 | SUCCESS 13 | } 14 | -------------------------------------------------------------------------------- /common-core/src/main/java/com/common/arms/callback/EmptyCallBack.kt: -------------------------------------------------------------------------------- 1 | package com.common.arms.callback 2 | 3 | import com.common.arms.R 4 | import com.kingja.loadsir.callback.Callback 5 | 6 | class EmptyCallBack : Callback() { 7 | 8 | override fun onCreateView(): Int = R.layout.base_layout_empty 9 | 10 | } -------------------------------------------------------------------------------- /common-core/src/main/java/com/common/arms/callback/ErrorCallBack.kt: -------------------------------------------------------------------------------- 1 | package com.common.arms.callback 2 | 3 | import com.common.arms.R 4 | import com.kingja.loadsir.callback.Callback 5 | 6 | class ErrorCallBack : Callback() { 7 | 8 | override fun onCreateView(): Int = R.layout.base_layout_error 9 | 10 | } -------------------------------------------------------------------------------- /common-core/src/main/java/com/common/arms/callback/LoadingCallBack.kt: -------------------------------------------------------------------------------- 1 | package com.common.arms.callback 2 | 3 | import android.content.Context 4 | import android.view.View 5 | import com.common.arms.R 6 | import com.kingja.loadsir.callback.Callback 7 | 8 | class LoadingCallBack : Callback() { 9 | 10 | override fun onCreateView(): Int = R.layout.base_layout_loading 11 | 12 | override fun onReloadEvent(context: Context?, view: View?): Boolean { 13 | return true 14 | } 15 | 16 | } -------------------------------------------------------------------------------- /common-core/src/main/java/com/common/arms/glide/BlurTransformation.java: -------------------------------------------------------------------------------- 1 | package com.common.arms.glide; 2 | 3 | import android.graphics.Bitmap; 4 | 5 | import androidx.annotation.IntRange; 6 | import androidx.annotation.NonNull; 7 | 8 | import com.bumptech.glide.load.Key; 9 | import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool; 10 | import com.bumptech.glide.load.resource.bitmap.BitmapTransformation; 11 | import com.common.arms.utils.FastBlur; 12 | 13 | import java.security.MessageDigest; 14 | 15 | /** 16 | * ================================================ 17 | * 高斯模糊 18 | * ================================================ 19 | */ 20 | public class BlurTransformation extends BitmapTransformation { 21 | public static final int DEFAULT_RADIUS = 15; 22 | private static final String ID = BlurTransformation.class.getName(); 23 | private static final byte[] ID_BYTES = ID.getBytes(Key.CHARSET); 24 | private int mRadius; 25 | 26 | public BlurTransformation(@IntRange(from = 0) int radius) { 27 | mRadius = radius; 28 | } 29 | 30 | @Override 31 | public void updateDiskCacheKey(@NonNull MessageDigest messageDigest) { 32 | messageDigest.update(ID_BYTES); 33 | 34 | } 35 | 36 | @Override 37 | protected Bitmap transform(@NonNull BitmapPool pool, @NonNull Bitmap toTransform, int outWidth, int outHeight) { 38 | return FastBlur.doBlur(toTransform, mRadius, true); 39 | } 40 | 41 | @Override 42 | public boolean equals(Object o) { 43 | return o instanceof BlurTransformation; 44 | } 45 | 46 | @Override 47 | public int hashCode() { 48 | return ID.hashCode(); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /common-core/src/main/java/com/common/arms/glide/CacheStrategy.java: -------------------------------------------------------------------------------- 1 | package com.common.arms.glide; 2 | 3 | import androidx.annotation.IntDef; 4 | 5 | import java.lang.annotation.Retention; 6 | import java.lang.annotation.RetentionPolicy; 7 | 8 | 9 | /** 10 | * Incremental change is better than ambitious failure. 11 | * 12 | * @author : MysticCoder 13 | * @date : 2019/4/29 14 | * @desc :0对应DiskCacheStrategy.all,1对应DiskCacheStrategy.NONE,2对应DiskCacheStrategy.SOURCE,3对应DiskCacheStrategy.RESULT 15 | * see {@link com.bumptech.glide.load.engine.DiskCacheStrategy} 16 | */ 17 | 18 | public interface CacheStrategy { 19 | 20 | 21 | int ALL = 0; 22 | 23 | int NONE = 1; 24 | 25 | int RESOURCE = 2; 26 | 27 | int DATA = 3; 28 | 29 | int AUTOMATIC = 4; 30 | 31 | @IntDef({ALL, NONE, RESOURCE, DATA, AUTOMATIC}) 32 | @Retention(RetentionPolicy.SOURCE) 33 | @interface Strategy { 34 | } 35 | 36 | } -------------------------------------------------------------------------------- /common-core/src/main/java/com/common/arms/http/BaseUrl.java: -------------------------------------------------------------------------------- 1 | package com.common.arms.http; 2 | 3 | import androidx.annotation.NonNull; 4 | 5 | import okhttp3.HttpUrl; 6 | 7 | /** 8 | * ================================================ 9 | * 针对于 BaseUrl 在 App 启动时不能确定,需要请求服务器接口动态获取的应用场景 10 | * ================================================ 11 | */ 12 | public interface BaseUrl { 13 | /** 14 | * 在调用 Retrofit API 接口之前,使用 Okhttp 或其他方式,请求到正确的 BaseUrl 并通过此方法返回 15 | * 16 | * @return 17 | */ 18 | @NonNull 19 | HttpUrl url(); 20 | } 21 | -------------------------------------------------------------------------------- /common-core/src/main/java/com/common/arms/http/GlobalHttpHandler.java: -------------------------------------------------------------------------------- 1 | package com.common.arms.http; 2 | 3 | import androidx.annotation.NonNull; 4 | import androidx.annotation.Nullable; 5 | 6 | import com.common.arms.di.module.GlobalConfigModule; 7 | 8 | import okhttp3.Interceptor; 9 | import okhttp3.Request; 10 | import okhttp3.Response; 11 | 12 | /** 13 | * ================================================ 14 | * 处理 Http 请求和响应结果的处理类 15 | * 使用 {@link GlobalConfigModule.Builder#globalHttpHandler(GlobalHttpHandler)} 方法配置 16 | * ================================================ 17 | */ 18 | public interface GlobalHttpHandler { 19 | 20 | /** 21 | * 空实现 22 | */ 23 | GlobalHttpHandler EMPTY = new GlobalHttpHandler() { 24 | 25 | @NonNull 26 | @Override 27 | public Response onHttpResultResponse(@Nullable String httpResult, @NonNull Interceptor.Chain chain, @NonNull Response response) { 28 | //不管是否处理, 都必须将 response 返回出去 29 | return response; 30 | } 31 | 32 | @NonNull 33 | @Override 34 | public Request onHttpRequestBefore(@NonNull Interceptor.Chain chain, @NonNull Request request) { 35 | //不管是否处理, 都必须将 request 返回出去 36 | return request; 37 | } 38 | }; 39 | 40 | /** 41 | * 这里可以先客户端一步拿到每一次 Http 请求的结果, 可以先解析成 Json, 再做一些操作, 如检测到 token 过期后 42 | * 重新请求 token, 并重新执行请求 43 | * 44 | * @param httpResult 服务器返回的结果 (已被框架自动转换为字符串) 45 | * @param chain {@link okhttp3.Interceptor.Chain} 46 | * @param response {@link Response} 47 | * @return {@link Response} 48 | */ 49 | @NonNull 50 | Response onHttpResultResponse(@Nullable String httpResult, @NonNull Interceptor.Chain chain, @NonNull Response response); 51 | 52 | /** 53 | * 这里可以在请求服务器之前拿到 {@link Request}, 做一些操作比如给 {@link Request} 统一添加 token 或者 header 以及参数加密等操作 54 | * 55 | * @param chain {@link okhttp3.Interceptor.Chain} 56 | * @param request {@link Request} 57 | * @return {@link Request} 58 | */ 59 | @NonNull 60 | Request onHttpRequestBefore(@NonNull Interceptor.Chain chain, @NonNull Request request); 61 | } 62 | -------------------------------------------------------------------------------- /common-core/src/main/java/com/common/arms/http/imageloader/BaseImageLoaderStrategy.java: -------------------------------------------------------------------------------- 1 | package com.common.arms.http.imageloader; 2 | 3 | import android.content.Context; 4 | 5 | import androidx.annotation.Nullable; 6 | 7 | /** 8 | * ================================================ 9 | * 图片加载策略,实现 {@link BaseImageLoaderStrategy} 10 | * 并通过 {@link ImageLoader#setLoadImgStrategy(BaseImageLoaderStrategy)} 配置后,才可进行图片请求 11 | * ================================================ 12 | */ 13 | public interface BaseImageLoaderStrategy { 14 | 15 | /** 16 | * 加载图片 17 | * 18 | * @param ctx {@link Context} 19 | * @param config 图片加载配置信息 20 | */ 21 | void loadImage(@Nullable Context ctx, @Nullable T config); 22 | 23 | /** 24 | * 停止加载 25 | * 26 | * @param ctx {@link Context} 27 | * @param config 图片加载配置信息 28 | */ 29 | void clear(@Nullable Context ctx, @Nullable T config); 30 | } 31 | -------------------------------------------------------------------------------- /common-core/src/main/java/com/common/arms/http/imageloader/ImageConfig.java: -------------------------------------------------------------------------------- 1 | package com.common.arms.http.imageloader; 2 | 3 | import android.graphics.drawable.Drawable; 4 | import android.widget.ImageView; 5 | 6 | /** 7 | * ================================================ 8 | * 这里是图片加载配置信息的基类,定义一些所有图片加载框架都可以用的通用参数 9 | * 每个 {@link BaseImageLoaderStrategy} 应该对应一个 {@link ImageConfig} 实现类 10 | * ================================================ 11 | */ 12 | public class ImageConfig { 13 | protected String url; 14 | protected ImageView imageView; 15 | protected Drawable placeholder;//占位符 16 | protected Drawable errorPic;//错误占位符 17 | 18 | public String getUrl() { 19 | return url; 20 | } 21 | 22 | public ImageView getImageView() { 23 | return imageView; 24 | } 25 | 26 | public Drawable getPlaceholder() { 27 | return placeholder; 28 | } 29 | 30 | public Drawable getErrorPic() { 31 | return errorPic; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /common-core/src/main/java/com/common/arms/http/imageloader/glide/GlideAppliesOptions.java: -------------------------------------------------------------------------------- 1 | package com.common.arms.http.imageloader.glide; 2 | 3 | import android.content.Context; 4 | 5 | import androidx.annotation.NonNull; 6 | 7 | import com.bumptech.glide.Glide; 8 | import com.bumptech.glide.GlideBuilder; 9 | import com.bumptech.glide.Registry; 10 | import com.common.arms.http.imageloader.BaseImageLoaderStrategy; 11 | 12 | /** 13 | * ================================================ 14 | * 如果你想具有配置 @{@link Glide} 的权利,则需要让 {@link BaseImageLoaderStrategy} 15 | * 的实现类也必须实现 {@link GlideAppliesOptions} 16 | * ================================================ 17 | */ 18 | public interface GlideAppliesOptions { 19 | 20 | /** 21 | * 配置 @{@link Glide} 的自定义参数,此方法在 @{@link Glide} 初始化时执行(@{@link Glide} 在第一次被调用时初始化),只会执行一次 22 | * 23 | * @param context 24 | * @param builder {@link GlideBuilder} 此类被用来创建 Glide 25 | */ 26 | void applyGlideOptions(@NonNull Context context, @NonNull GlideBuilder builder); 27 | 28 | /** 29 | * 注册{@link Glide}的组件,参考{@link com.bumptech.glide.module.LibraryGlideModule} 30 | * 31 | * @param context Android context 32 | * @param glide {@link Glide} 33 | * @param registry {@link Registry} 34 | */ 35 | void registerComponents(@NonNull Context context, @NonNull Glide glide, @NonNull Registry registry); 36 | } 37 | -------------------------------------------------------------------------------- /common-core/src/main/java/com/common/arms/integration/ConfigModule.java: -------------------------------------------------------------------------------- 1 | package com.common.arms.integration; 2 | 3 | import android.app.Activity; 4 | import android.app.Application; 5 | import android.content.Context; 6 | 7 | import androidx.annotation.NonNull; 8 | import androidx.fragment.app.Fragment; 9 | import androidx.fragment.app.FragmentManager; 10 | 11 | import com.common.arms.base.delegate.AppLifecycles; 12 | import com.common.arms.di.module.GlobalConfigModule; 13 | 14 | import java.util.List; 15 | 16 | /** 17 | * ================================================ 18 | * {@link ConfigModule} 可以给框架配置一些参数,需要实现 {@link ConfigModule} 后,在 AndroidManifest 中声明该实现类 19 | * ================================================ 20 | */ 21 | public interface ConfigModule { 22 | /** 23 | * 使用 {@link GlobalConfigModule.Builder} 给框架配置一些配置参数 24 | * 25 | * @param context {@link Context} 26 | * @param builder {@link GlobalConfigModule.Builder} 27 | */ 28 | void applyOptions(@NonNull Context context, @NonNull GlobalConfigModule.Builder builder); 29 | 30 | /** 31 | * 使用 {@link AppLifecycles} 在 {@link Application} 的生命周期中注入一些操作 32 | * 33 | * @param context {@link Context} 34 | * @param lifecycles {@link Application} 的生命周期容器, 可向框架中添加多个 {@link Application} 的生命周期类 35 | */ 36 | void injectAppLifecycle(@NonNull Context context, @NonNull List lifecycles); 37 | 38 | /** 39 | * 使用 {@link Application.ActivityLifecycleCallbacks} 在 {@link Activity} 的生命周期中注入一些操作 40 | * 41 | * @param context {@link Context} 42 | * @param lifecycles {@link Activity} 的生命周期容器, 可向框架中添加多个 {@link Activity} 的生命周期类 43 | */ 44 | void injectActivityLifecycle(@NonNull Context context, @NonNull List lifecycles); 45 | 46 | /** 47 | * 使用 {@link FragmentManager.FragmentLifecycleCallbacks} 在 {@link Fragment} 的生命周期中注入一些操作 48 | * 49 | * @param context {@link Context} 50 | * @param lifecycles {@link Fragment} 的生命周期容器, 可向框架中添加多个 {@link Fragment} 的生命周期类 51 | */ 52 | void injectFragmentLifecycle(@NonNull Context context, @NonNull List lifecycles); 53 | } 54 | -------------------------------------------------------------------------------- /common-core/src/main/java/com/common/arms/integration/IRepositoryManager.java: -------------------------------------------------------------------------------- 1 | package com.common.arms.integration; 2 | 3 | import android.content.Context; 4 | 5 | import androidx.annotation.NonNull; 6 | import androidx.annotation.Nullable; 7 | 8 | import retrofit2.Retrofit; 9 | 10 | /** 11 | * ================================================ 12 | * 用来管理网络请求层,以及数据缓存层,以后可能添加数据库请求层 13 | * 提供必要的 Api 做数据处理 14 | * ================================================ 15 | */ 16 | public interface IRepositoryManager { 17 | 18 | /** 19 | * 根据传入的 Class 获取对应的 Retrofit service 20 | * 21 | * @param service Retrofit service class 22 | * @param Retrofit service 类型 23 | * @return Retrofit service 24 | */ 25 | @NonNull 26 | T obtainRetrofitService(@NonNull Class service); 27 | 28 | 29 | /** 30 | * 根据传入的 Class 获取对应的 RxCache service 31 | * 32 | * @param cache RxCache service class 33 | * @param RxCache service 类型 34 | * @return RxCache service 35 | */ 36 | @NonNull 37 | T obtainCacheService(@NonNull Class cache); 38 | 39 | /** 40 | * 清理所有缓存 41 | */ 42 | void clearAllCache(); 43 | 44 | /** 45 | * 获取 {@link Context} 46 | * 47 | * @return {@link Context} 48 | */ 49 | @NonNull 50 | Context getContext(); 51 | 52 | interface ObtainServiceDelegate { 53 | 54 | @Nullable 55 | T createRetrofitService(Retrofit retrofit, Class serviceClass); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /common-core/src/main/java/com/common/arms/integration/RetrofitServiceProxyHandler.java: -------------------------------------------------------------------------------- 1 | package com.common.arms.integration; 2 | 3 | import androidx.annotation.Nullable; 4 | 5 | import java.lang.reflect.InvocationHandler; 6 | import java.lang.reflect.Method; 7 | 8 | import io.reactivex.Observable; 9 | import io.reactivex.Single; 10 | import retrofit2.Retrofit; 11 | 12 | 13 | public class RetrofitServiceProxyHandler implements InvocationHandler { 14 | 15 | private Retrofit mRetrofit; 16 | private Class mServiceClass; 17 | private Object mRetrofitService; 18 | 19 | public RetrofitServiceProxyHandler(Retrofit retrofit, Class serviceClass) { 20 | mRetrofit = retrofit; 21 | mServiceClass = serviceClass; 22 | } 23 | 24 | @Override 25 | public Object invoke(Object proxy, Method method, @Nullable Object[] args) throws Throwable { 26 | 27 | // 根据 https://zhuanlan.zhihu.com/p/40097338 对 Retrofit 进行的优化 28 | 29 | if (method.getReturnType() == Observable.class) { 30 | // 如果方法返回值是 Observable 的话,则包一层再返回, 31 | // 只包一层 defer 由外部去控制耗时方法以及网络请求所处线程, 32 | // 如此对原项目的影响为 0,且更可控。 33 | return Observable.defer(() -> { 34 | // 执行真正的 Retrofit 动态代理的方法 35 | return (Observable) method.invoke(getRetrofitService(), args); 36 | }); 37 | } else if (method.getReturnType() == Single.class) { 38 | // 如果方法返回值是 Single 的话,则包一层再返回。 39 | return Single.defer(() -> { 40 | // 执行真正的 Retrofit 动态代理的方法 41 | return (Single) method.invoke(getRetrofitService(), args); 42 | }); 43 | } 44 | 45 | // 返回值不是 Observable 或 Single 的话不处理。 46 | return method.invoke(getRetrofitService(), args); 47 | } 48 | 49 | private Object getRetrofitService() { 50 | if (mRetrofitService == null) { 51 | mRetrofitService = mRetrofit.create(mServiceClass); 52 | } 53 | return mRetrofitService; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /common-core/src/main/java/com/common/arms/integration/lifecycle/ActivityLifecycleable.java: -------------------------------------------------------------------------------- 1 | package com.common.arms.integration.lifecycle; 2 | 3 | import android.app.Activity; 4 | 5 | import com.trello.rxlifecycle2.RxLifecycle; 6 | import com.trello.rxlifecycle2.android.ActivityEvent; 7 | 8 | /** 9 | * ================================================ 10 | * 让 {@link Activity} 实现此接口,即可正常使用 {@link RxLifecycle} 11 | * ================================================ 12 | */ 13 | public interface ActivityLifecycleable extends Lifecycleable { 14 | } 15 | -------------------------------------------------------------------------------- /common-core/src/main/java/com/common/arms/integration/lifecycle/FragmentLifecycleable.java: -------------------------------------------------------------------------------- 1 | package com.common.arms.integration.lifecycle; 2 | 3 | import androidx.fragment.app.Fragment; 4 | 5 | import com.trello.rxlifecycle2.RxLifecycle; 6 | import com.trello.rxlifecycle2.android.FragmentEvent; 7 | 8 | /** 9 | * ================================================ 10 | * 让 {@link Fragment} 实现此接口,即可正常使用 {@link RxLifecycle} 11 | * ================================================ 12 | */ 13 | public interface FragmentLifecycleable extends Lifecycleable { 14 | } 15 | -------------------------------------------------------------------------------- /common-core/src/main/java/com/common/arms/integration/lifecycle/Lifecycleable.java: -------------------------------------------------------------------------------- 1 | package com.common.arms.integration.lifecycle; 2 | 3 | import android.app.Activity; 4 | 5 | import androidx.annotation.NonNull; 6 | import androidx.fragment.app.Fragment; 7 | 8 | import com.trello.rxlifecycle2.RxLifecycle; 9 | 10 | import io.reactivex.subjects.Subject; 11 | 12 | /** 13 | * ================================================ 14 | * 让 {@link Activity}/{@link Fragment} 实现此接口,即可正常使用 {@link RxLifecycle} 15 | * 无需再继承 {@link RxLifecycle} 提供的 Activity/Fragment ,扩展性极强 16 | * ================================================ 17 | */ 18 | public interface Lifecycleable { 19 | @NonNull 20 | Subject provideLifecycleSubject(); 21 | } 22 | -------------------------------------------------------------------------------- /common-core/src/main/java/com/common/arms/utils/ClassUtil.kt: -------------------------------------------------------------------------------- 1 | package com.common.arms.utils 2 | 3 | import java.lang.reflect.ParameterizedType 4 | 5 | object ClassUtil { 6 | 7 | fun getClass(t: Any): Class { 8 | // 通过反射 获取父类泛型 (T) 对应 Class类 9 | return (t.javaClass.genericSuperclass as ParameterizedType) 10 | .actualTypeArguments[0] 11 | as Class 12 | } 13 | 14 | } -------------------------------------------------------------------------------- /common-core/src/main/java/com/common/arms/utils/DialogUtil.kt: -------------------------------------------------------------------------------- 1 | package com.common.arms.utils 2 | 3 | import android.app.Activity 4 | import androidx.fragment.app.Fragment 5 | import androidx.lifecycle.MutableLiveData 6 | import com.coder.zzq.smartshow.dialog.LoadingDialog 7 | import com.common.arms.base.mvvm.BaseVMActivity 8 | import com.common.arms.base.mvvm.BaseVMFragment 9 | import com.common.arms.base.state.State 10 | import com.common.arms.base.state.StateType 11 | 12 | fun showLoadingDialog(activity: Activity? = null, fragment: Fragment? = null, message: String? = ""): LoadingDialog? { 13 | return LoadingDialog().middle().message(message).apply { 14 | if (activity != null && !activity.isFinishing) { 15 | showInActivity(activity) 16 | } 17 | if (fragment != null) { 18 | showInFragment(fragment) 19 | } 20 | } 21 | } 22 | 23 | fun dismissLoadingDialog(dialog: LoadingDialog?) { 24 | dialog?.dismiss() 25 | } 26 | 27 | /** 28 | * 显示加载框状态 29 | */ 30 | fun showLoadingState(loadState: MutableLiveData, message: String? = "", showDialog: Boolean? = true) { 31 | loadState.postValue(State(StateType.LOADING, message, showDialog)) 32 | } 33 | 34 | /** 35 | * 隐藏加载框状态 36 | */ 37 | fun hideLoadingState(activity: Activity? = null, fragment: Fragment? = null) { 38 | if (activity != null && activity is BaseVMActivity<*, *>) { 39 | activity.loadService.showSuccess() 40 | dismissLoadingDialog(activity.loadingDialog) 41 | } 42 | if (fragment != null && fragment is BaseVMFragment<*, *>) { 43 | fragment.loadService.showSuccess() 44 | dismissLoadingDialog(fragment.loadingDialog) 45 | } 46 | } 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /common-core/src/main/java/com/common/arms/utils/UrlEncoderUtil.java: -------------------------------------------------------------------------------- 1 | package com.common.arms.utils; 2 | 3 | public class UrlEncoderUtil { 4 | 5 | private UrlEncoderUtil() { 6 | throw new IllegalStateException("you can't instantiate me!"); 7 | } 8 | 9 | /** 10 | * 判断 str 是否已经 URLEncoder.encode() 过 11 | * 经常遇到这样的情况, 拿到一个 URL, 但是搞不清楚到底要不要 URLEncoder.encode() 12 | * 不做 URLEncoder.encode() 吧, 担心出错, 做 URLEncoder.encode() 吧, 又怕重复了 13 | * 14 | * @param str 需要判断的内容 15 | * @return 返回 {@code true} 为被 URLEncoder.encode() 过 16 | */ 17 | public static boolean hasUrlEncoded(String str) { 18 | boolean encode = false; 19 | for (int i = 0; i < str.length(); i++) { 20 | char c = str.charAt(i); 21 | if (c == '%' && (i + 2) < str.length()) { 22 | // 判断是否符合urlEncode规范 23 | char c1 = str.charAt(i + 1); 24 | char c2 = str.charAt(i + 2); 25 | if (isValidHexChar(c1) && isValidHexChar(c2)) { 26 | encode = true; 27 | break; 28 | } else { 29 | break; 30 | } 31 | } 32 | } 33 | return encode; 34 | } 35 | 36 | /** 37 | * 判断 c 是否是 16 进制的字符 38 | * 39 | * @param c 需要判断的字符 40 | * @return 返回 {@code true} 为 16 进制的字符 41 | */ 42 | private static boolean isValidHexChar(char c) { 43 | return ('0' <= c && c <= '9') || ('a' <= c && c <= 'f') || ('A' <= c && c <= 'F'); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /common-core/src/main/res/layout/base_layout_empty.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 13 | 14 | 21 | 22 | -------------------------------------------------------------------------------- /common-core/src/main/res/layout/base_layout_error.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 13 | 14 | 22 | 23 | -------------------------------------------------------------------------------- /common-core/src/main/res/layout/base_layout_loading.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 16 | 17 | -------------------------------------------------------------------------------- /common-core/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #6452f0 4 | #40000000 5 | #ffa6a6a6 6 | 7 | -------------------------------------------------------------------------------- /common-core/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | arms 3 | 暂无数据~ 4 | 网络异常,点击空白处重试 5 | 6 | -------------------------------------------------------------------------------- /common-core/src/main/res/xml/network_security_config.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /common-res/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /common-res/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | apply plugin: 'kotlin-android' 3 | apply plugin: 'kotlin-kapt' 4 | apply plugin: 'kotlin-android-extensions' 5 | 6 | android { 7 | compileSdkVersion Versions.compileSdk 8 | defaultConfig { 9 | minSdkVersion Versions.minSdk 10 | targetSdkVersion Versions.targetSdk 11 | } 12 | compileOptions { 13 | targetCompatibility JavaVersion.VERSION_1_8 14 | sourceCompatibility JavaVersion.VERSION_1_8 15 | } 16 | buildFeatures { 17 | dataBinding = true 18 | viewBinding = true 19 | } 20 | defaultConfig { 21 | javaCompileOptions { 22 | annotationProcessorOptions { 23 | arguments = [AROUTER_MODULE_NAME: project.getName()] 24 | } 25 | } 26 | } 27 | } 28 | dependencies { 29 | api project(':common-core') 30 | api Deps.tbssdk 31 | api Deps.vlayout 32 | api Deps.smartkey 33 | api Deps.cardview 34 | api Deps.titlebar 35 | api Deps.autosize 36 | api Deps.easyFloat 37 | api Deps.rvAdapter 38 | api Deps.bgaQrcode 39 | api Deps.arouterApi 40 | api Deps.mmkvStatic 41 | api Deps.umengCommon 42 | api Deps.umengUtdid 43 | api Deps.immersionbar 44 | api Deps.umengAnalytics 45 | api Deps.ycbannerlib 46 | api Deps.labelsView 47 | api Deps.dropDownMenu 48 | api Deps.filedownloader 49 | api Deps.progressmanager 50 | api Deps.pictureSelector 51 | api Deps.androidPdfViewer 52 | api Deps.circleProgressbar 53 | api Deps.retrofitUrlManager 54 | api Deps.bottomNavigationViewEx 55 | api Deps.smartRefreshLayoutKernel 56 | api Deps.smartRefreshHeaderClassics 57 | api Deps.baseRecyclerViewAdapterHelper 58 | 59 | kapt Deps.arouterCompiler 60 | 61 | implementation Deps.xUpdate 62 | implementation Deps.okhttputils 63 | 64 | debugImplementation Deps.spidermanDebug 65 | releaseImplementation Deps.spidermanRelease 66 | //debugImplementation Deps.leakcanary 67 | } 68 | -------------------------------------------------------------------------------- /common-res/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /common-res/src/main/java/com/common/res/adapter/BaseBindingQuickAdapter.kt: -------------------------------------------------------------------------------- 1 | package com.common.res.adapter 2 | 3 | import android.view.View 4 | import android.view.ViewGroup 5 | import androidx.viewbinding.ViewBinding 6 | import com.chad.library.adapter.base.BaseQuickAdapter 7 | import com.chad.library.adapter.base.viewholder.BaseViewHolder 8 | import com.dylanc.viewbinding.base.inflateBindingWithGeneric 9 | 10 | abstract class BaseBindingQuickAdapter(layoutResId: Int = -1, 11 | data: MutableList? = null) : 12 | BaseQuickAdapter(layoutResId, data) { 13 | 14 | override fun onCreateDefViewHolder(parent: ViewGroup, viewType: Int) = 15 | BaseBindingHolder(inflateBindingWithGeneric(parent)) 16 | 17 | class BaseBindingHolder(private val binding: ViewBinding) : BaseViewHolder(binding.root) { 18 | constructor(itemView: View) : this(ViewBinding { itemView }) 19 | 20 | @Suppress("UNCHECKED_CAST") 21 | fun getViewBinding() = binding as VB 22 | } 23 | } -------------------------------------------------------------------------------- /common-res/src/main/java/com/common/res/api/Api.kt: -------------------------------------------------------------------------------- 1 | package com.common.res.api 2 | 3 | object Api { 4 | var H5_DOMAIN = "https://www.wanandroid.com/" 5 | var API_DOMAIN = "https://www.wanandroid.com/" 6 | } -------------------------------------------------------------------------------- /common-res/src/main/java/com/common/res/app/SSLSocketClient.java: -------------------------------------------------------------------------------- 1 | package com.common.res.app; 2 | 3 | import java.security.SecureRandom; 4 | import java.security.cert.CertificateException; 5 | import java.security.cert.X509Certificate; 6 | 7 | import javax.net.ssl.HostnameVerifier; 8 | import javax.net.ssl.SSLContext; 9 | import javax.net.ssl.SSLSession; 10 | import javax.net.ssl.TrustManager; 11 | import javax.net.ssl.X509TrustManager; 12 | 13 | public class SSLSocketClient { 14 | 15 | //获取这个SSLSocketFactory 16 | public static javax.net.ssl.SSLSocketFactory getSSLSocketFactory() { 17 | try { 18 | SSLContext sslContext = SSLContext.getInstance("SSL"); 19 | sslContext.init(null, getTrustManagers(), new SecureRandom()); 20 | return sslContext.getSocketFactory(); 21 | } catch (Exception e) { 22 | throw new RuntimeException(e); 23 | } 24 | } 25 | 26 | //获取TrustManager 27 | private static TrustManager[] getTrustManagers() { 28 | TrustManager[] trustAllCerts = new TrustManager[]{getTrustManager()}; 29 | return trustAllCerts; 30 | } 31 | 32 | //获取HostnameVerifier 33 | public static HostnameVerifier getHostnameVerifier() { 34 | HostnameVerifier hostnameVerifier = new HostnameVerifier() { 35 | @Override 36 | public boolean verify(String s, SSLSession sslSession) { 37 | return true; 38 | } 39 | }; 40 | return hostnameVerifier; 41 | } 42 | 43 | public static X509TrustManager getTrustManager() { 44 | return new MyTrustManager(); 45 | } 46 | 47 | private static final class MyTrustManager implements X509TrustManager { 48 | 49 | @Override 50 | public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { 51 | 52 | } 53 | 54 | @Override 55 | public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { 56 | 57 | } 58 | 59 | @Override 60 | public X509Certificate[] getAcceptedIssuers() { 61 | return new X509Certificate[0]; 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /common-res/src/main/java/com/common/res/config/AppConfig.kt: -------------------------------------------------------------------------------- 1 | package com.common.res.config 2 | 3 | import cn.vove7.smartkey.AConfig 4 | import cn.vove7.smartkey.annotation.Config 5 | import cn.vove7.smartkey.key.smartKey 6 | import com.common.res.smartkey.MmkvSettingsImpl 7 | 8 | @Config(implCls = MmkvSettingsImpl::class) 9 | object AppConfig : AConfig() { 10 | var login: Boolean by smartKey(false) 11 | var userName: String? by smartKey(null) 12 | var accessToken: String? by smartKey(null) 13 | 14 | fun clearUserData() { 15 | login = false 16 | accessToken = null 17 | } 18 | } -------------------------------------------------------------------------------- /common-res/src/main/java/com/common/res/entity/ListEntity.kt: -------------------------------------------------------------------------------- 1 | package com.common.res.entity 2 | 3 | data class ListEntity( 4 | var curPage: Int? = null, 5 | var offset: Int? = null, 6 | var over: Boolean? = null, 7 | var pageCount: Int? = null, 8 | var size: Int? = null, 9 | var total: Int? = null, 10 | var datas: MutableList? = null 11 | ) -------------------------------------------------------------------------------- /common-res/src/main/java/com/common/res/entity/SendEventEntity.kt: -------------------------------------------------------------------------------- 1 | package com.common.res.entity 2 | 3 | import java.io.Serializable 4 | 5 | /** 6 | * desc :发送事件实体类 7 | * author:panyy 8 | * data:2018/4/12 9 | */ 10 | class SendEventEntity : Serializable { 11 | var tag: String? = null 12 | var event: String? = null 13 | var args: Any? = null 14 | } -------------------------------------------------------------------------------- /common-res/src/main/java/com/common/res/entity/UpdateResultEntity.kt: -------------------------------------------------------------------------------- 1 | package com.common.res.entity 2 | 3 | /** 4 | * desc : 5 | * author:panyy 6 | * data:2020/12/4 7 | */ 8 | class UpdateResultEntity { 9 | var code: String? = null 10 | var message: String? = null 11 | var data: DataEntity? = null 12 | var sign: String? = null 13 | 14 | class DataEntity { 15 | var latestversion: LatestversionEntity? = null 16 | var updateitems: List? = null 17 | 18 | class LatestversionEntity { 19 | var productcode: Any? = null 20 | var code: Int = 0 21 | var name: String = "" 22 | var description: String? = null 23 | var versionid: String? = null 24 | var createtime: String? = null 25 | var mandatory = false 26 | var whole = false 27 | 28 | } 29 | 30 | class UpdateitemsEntity { 31 | var id = 0 32 | var versionid: String? = null 33 | var filename: String? = null 34 | var address: String? = null 35 | var location: String? = null 36 | var filetype = 0 37 | var filesize: Long = 0L 38 | var isreg = 0 39 | var deccompressfile = 0 40 | var createtime: Long = 0 41 | var decompressfile = 0 42 | 43 | } 44 | } 45 | } -------------------------------------------------------------------------------- /common-res/src/main/java/com/common/res/event/EventKeys.kt: -------------------------------------------------------------------------------- 1 | package com.common.res.event 2 | 3 | const val WEBFRAME_EVENT = "webframe_event" 4 | const val LIST_CLICK_EVENT = "list_click_event" -------------------------------------------------------------------------------- /common-res/src/main/java/com/common/res/ext/Boolean+Extension.kt: -------------------------------------------------------------------------------- 1 | package com.common.res.ext 2 | 3 | infix fun Boolean.then(value: T?) = if (this) value else null 4 | 5 | fun Boolean.then(value: T?, default: T) = if (this) value else default 6 | 7 | inline fun Boolean.then(function: () -> T, default: T) = if (this) function() else default 8 | 9 | inline fun Boolean.then(function: () -> T, default: () -> T) = if (this) function() else default() 10 | 11 | infix inline fun Boolean.then(function: () -> T) = if (this) function() else null -------------------------------------------------------------------------------- /common-res/src/main/java/com/common/res/ext/Bundle+Extension.kt: -------------------------------------------------------------------------------- 1 | package com.common.res.ext 2 | 3 | import android.os.Bundle 4 | import android.os.Parcelable 5 | import java.io.Serializable 6 | 7 | fun Bundle.put(params: Array>): Bundle { 8 | 9 | params.forEach { 10 | val key = it.first 11 | val value = it.second 12 | when (value) { 13 | is Int -> putInt(key, value) 14 | is IntArray -> putIntArray(key, value) 15 | is Long -> putLong(key, value) 16 | is LongArray -> putLongArray(key, value) 17 | is CharSequence -> putCharSequence(key, value) 18 | is String -> putString(key, value) 19 | is Float -> putFloat(key, value) 20 | is FloatArray -> putFloatArray(key, value) 21 | is Double -> putDouble(key, value) 22 | is DoubleArray -> putDoubleArray(key, value) 23 | is Char -> putChar(key, value) 24 | is CharArray -> putCharArray(key, value) 25 | is Short -> putShort(key, value) 26 | is ShortArray -> putShortArray(key, value) 27 | is Boolean -> putBoolean(key, value) 28 | is BooleanArray -> putBooleanArray(key, value) 29 | 30 | is Serializable -> putSerializable(key, value) 31 | is Parcelable -> putParcelable(key, value) 32 | is Bundle -> putAll(value) 33 | is Array<*> -> when { 34 | 35 | value.isArrayOf() -> putParcelableArray(key, value as Array?) 36 | } 37 | 38 | } 39 | } 40 | return this 41 | } -------------------------------------------------------------------------------- /common-res/src/main/java/com/common/res/ext/Exception+Extension.kt: -------------------------------------------------------------------------------- 1 | package com.common.res.ext 2 | 3 | import java.io.PrintWriter 4 | import java.io.StringWriter 5 | 6 | fun Throwable.getStackTraceText(): String { 7 | val sw = StringWriter() 8 | val pw = PrintWriter(sw) 9 | printStackTrace(pw) 10 | return sw.toString() 11 | } -------------------------------------------------------------------------------- /common-res/src/main/java/com/common/res/ext/IO+Extension.kt: -------------------------------------------------------------------------------- 1 | package com.common.res.ext 2 | 3 | import java.io.Closeable 4 | 5 | fun Closeable?.closeQuietly() { 6 | try { 7 | this?.close() 8 | } catch (e: Throwable) { 9 | // ignore 10 | } 11 | } 12 | 13 | inline fun T.use(block: (T) -> R): R { 14 | var closed = false 15 | try { 16 | return block(this) 17 | } catch (e: Exception) { 18 | closed = true 19 | try { 20 | this?.close() 21 | } catch (closeException: Exception) { 22 | } 23 | throw e 24 | } finally { 25 | if (!closed) { 26 | this?.close() 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /common-res/src/main/java/com/common/res/ext/Object+Extension.kt: -------------------------------------------------------------------------------- 1 | package com.common.res.ext 2 | 3 | fun T.TAG() = this::class.simpleName -------------------------------------------------------------------------------- /common-res/src/main/java/com/common/res/immersionbar/BindFullScreen.kt: -------------------------------------------------------------------------------- 1 | package com.common.res.immersionbar 2 | 3 | /** 4 | * desc :开启沉浸式全屏接口 5 | * author:panyy 6 | * date:2021/04/22 7 | */ 8 | interface BindFullScreen -------------------------------------------------------------------------------- /common-res/src/main/java/com/common/res/immersionbar/BindImmersionBar.kt: -------------------------------------------------------------------------------- 1 | package com.common.res.immersionbar 2 | 3 | /** 4 | * desc :开启沉浸式接口 5 | * author:panyy 6 | * date:2021/04/22 7 | */ 8 | interface BindImmersionBar -------------------------------------------------------------------------------- /common-res/src/main/java/com/common/res/router/RouterHub.kt: -------------------------------------------------------------------------------- 1 | package com.common.res.router 2 | 3 | object RouterHub { 4 | 5 | //服务组件, 用于给每个组件暴露特有的服务 6 | const val SERVICE = "/service" 7 | 8 | //login组件 9 | const val LOGIN: String = "/login" 10 | 11 | //main组件 12 | const val MAIN: String = "/main" 13 | 14 | //uniapp组件 15 | const val UNIAPP: String = "/uniapp" 16 | 17 | //webframe组件 18 | const val WEBFRAME: String = "/webframe" 19 | 20 | //login页 21 | const val PUBLIC_LOGIN: String = "$LOGIN/loginPage" 22 | 23 | //main页 24 | const val PUBLIC_MAIN: String = "$MAIN/mainPage" 25 | 26 | //web框架服务 27 | const val WEBFRAME_ERVICE: String = "$WEBFRAME$SERVICE/WebframeService" 28 | } -------------------------------------------------------------------------------- /common-res/src/main/java/com/common/res/router/RouterUtil.kt: -------------------------------------------------------------------------------- 1 | package com.common.res.router 2 | 3 | import android.content.Context 4 | import android.os.Bundle 5 | import android.text.TextUtils 6 | import com.alibaba.android.arouter.facade.template.IProvider 7 | import com.alibaba.android.arouter.launcher.ARouter 8 | 9 | fun routerNavigation(path: String?): Any? { 10 | return ARouter.getInstance().build(path).navigation() 11 | } 12 | 13 | fun routerNavigation(path: String?, bundle: Bundle?): Any? { 14 | return ARouter.getInstance().build(path).with(bundle).navigation() 15 | } 16 | 17 | fun routerNavigation(context: Context?, path: String?): Any? { 18 | return ARouter.getInstance().build(path).navigation(context) 19 | } 20 | 21 | fun routerNavigation(context: Context?, path: String?, bundle: Bundle?): Any? { 22 | return ARouter.getInstance().build(path).with(bundle).navigation(context) 23 | } 24 | 25 | inline fun routerProvide(path: String?): T? { 26 | if (TextUtils.isEmpty(path)) { 27 | return null 28 | } 29 | var provider: IProvider? = null 30 | try { 31 | provider = ARouter.getInstance() 32 | .build(path) 33 | .navigation() as IProvider 34 | } catch (e: Exception) { 35 | e.printStackTrace() 36 | } 37 | return provider as T? 38 | } 39 | 40 | inline fun routerProvide(): T? { 41 | var provider: IProvider? = null 42 | try { 43 | provider = ARouter.getInstance().navigation(T::class.java) 44 | } catch (e: Exception) { 45 | e.printStackTrace() 46 | } 47 | return provider as T? 48 | } -------------------------------------------------------------------------------- /common-res/src/main/java/com/common/res/router/service/IWebFrameService.kt: -------------------------------------------------------------------------------- 1 | package com.common.res.router.service 2 | 3 | import android.content.Context 4 | import androidx.fragment.app.Fragment 5 | import com.alibaba.android.arouter.facade.template.IProvider 6 | 7 | /** 8 | * desc :web框架服务接口 9 | * author:panyy 10 | * date:2021/04/22 11 | */ 12 | interface IWebFrameService : IProvider { 13 | 14 | /** 15 | * 打开web页面 16 | * @param context Context 17 | * @param url String? 18 | * @param title String? 19 | * @param isHideToolbar Boolean 20 | */ 21 | fun start(context: Context, url: String?, title: String? = "", isHideToolbar: Boolean = false) 22 | 23 | /** 24 | * 创建WebPageFragment 25 | * 26 | * @param url 27 | */ 28 | fun newWebPageFragment(url: String): Fragment 29 | 30 | /** 31 | * web框架回调通知H5 32 | * 33 | * @param data 34 | */ 35 | fun onCallBack(data: String?) 36 | 37 | } -------------------------------------------------------------------------------- /common-res/src/main/java/com/common/res/update/CustomUpdateParser.kt: -------------------------------------------------------------------------------- 1 | package com.common.res.update 2 | 3 | import com.common.res.entity.UpdateResultEntity 4 | import com.common.res.utils.GsonUtil 5 | import com.xuexiang.xupdate.entity.UpdateEntity 6 | import com.xuexiang.xupdate.listener.IUpdateParseCallback 7 | import com.xuexiang.xupdate.proxy.IUpdateParser 8 | 9 | class CustomUpdateParser : IUpdateParser { 10 | 11 | override fun parseJson(json: String): UpdateEntity { 12 | return getParseResult(json)!! 13 | } 14 | 15 | override fun parseJson(json: String, callback: IUpdateParseCallback) { 16 | //当isAsyncParser为 true时调用该方法, 所以当isAsyncParser为false可以不实现 17 | callback.onParseResult(getParseResult(json)) 18 | } 19 | 20 | private fun getParseResult(json: String): UpdateEntity? { 21 | val result = GsonUtil.fromJson(json, UpdateResultEntity::class.java) 22 | if (result != null) { 23 | val latestversion = result.data?.latestversion 24 | if (latestversion != null) { 25 | val updateitem = result.data?.updateitems?.get(0) 26 | return UpdateEntity() 27 | .setHasUpdate(true) 28 | .setIsIgnorable(false) 29 | .setVersionCode(latestversion.code) 30 | .setVersionName(latestversion.name) 31 | .setUpdateContent(latestversion.description) 32 | .setDownloadUrl(updateitem?.address) 33 | .setForce(latestversion.mandatory) 34 | .setSize(updateitem?.filesize!!) 35 | } 36 | } 37 | return UpdateEntity().setHasUpdate(false) 38 | } 39 | 40 | override fun isAsyncParser(): Boolean { 41 | return false 42 | } 43 | } -------------------------------------------------------------------------------- /common-res/src/main/java/com/common/res/update/UpdateUtil.kt: -------------------------------------------------------------------------------- 1 | package com.common.res.update 2 | 3 | import android.app.Activity 4 | import com.xuexiang.xupdate.XUpdate 5 | import com.xuexiang.xupdate.utils.UpdateUtils 6 | 7 | /** 8 | * desc :应用更新工具类 9 | * author:panyy 10 | * data:2020/12/4 11 | */ 12 | object UpdateUtil { 13 | 14 | private const val updateUrl = "http://www.baidu.com" 15 | 16 | fun checkUpdate(activity: Activity, isShowDialog: Boolean = false) { 17 | XUpdate.newBuild(activity) 18 | .updateUrl(updateUrl) 19 | .param("productType", "2") 20 | .param("productCode", activity.packageName) 21 | .param("versionCode", UpdateUtils.getVersionCode(activity)) 22 | .supportBackgroundUpdate(true) 23 | .promptWidthRatio(0.75F) 24 | .updateParser(CustomUpdateParser()) 25 | .updateChecker(CustomUpdateChecker(activity, isShowDialog)) 26 | .update() 27 | } 28 | 29 | } -------------------------------------------------------------------------------- /common-res/src/main/java/com/common/res/utils/AppUtil.kt: -------------------------------------------------------------------------------- 1 | package com.common.res.utils 2 | 3 | import android.os.Bundle 4 | import com.common.arms.integration.AppManager 5 | import com.common.res.config.AppConfig 6 | import com.common.res.router.RouterHub 7 | import com.common.res.router.routerNavigation 8 | 9 | /** 10 | * 登出 11 | */ 12 | fun appLogout() { 13 | checkLogin { 14 | if (it) { 15 | AppConfig.clearUserData() 16 | AppManager.getAppManager().killAll() 17 | } 18 | } 19 | } 20 | 21 | /** 22 | * 登出并跳转到登录页面 23 | */ 24 | fun appLogoutToLogin() { 25 | checkLogin { 26 | if (it) { 27 | appLogout() 28 | routerNavigation(RouterHub.PUBLIC_LOGIN) 29 | } 30 | } 31 | } 32 | 33 | /** 34 | * 登出并跳转到登录界面,并自动登录 35 | * @param username 36 | * @param password 37 | */ 38 | fun appLogoutAutoLogin(username: String?, password: String?) { 39 | checkLogin { 40 | if (it) { 41 | appLogout() 42 | var bundle = Bundle().apply { 43 | putString("username", username) 44 | putString("password", password) 45 | } 46 | routerNavigation(RouterHub.PUBLIC_LOGIN, bundle) 47 | } 48 | } 49 | } 50 | 51 | /** 52 | * 检查登录 53 | */ 54 | fun checkLogin(block: (it: Boolean) -> Unit) { 55 | block(AppConfig.login) 56 | } -------------------------------------------------------------------------------- /common-res/src/main/java/com/common/res/utils/EventBusUtil.kt: -------------------------------------------------------------------------------- 1 | package com.common.res.utils 2 | 3 | import androidx.lifecycle.LifecycleOwner 4 | import com.jeremyliao.liveeventbus.LiveEventBus 5 | 6 | fun eventBusPost(key: String, value: Any? = null) { 7 | LiveEventBus.get(key).post(value) 8 | } 9 | 10 | fun eventBusObserve(key: String, owner: LifecycleOwner, block: (it: Any?) -> Unit) { 11 | LiveEventBus.get(key).observe(owner, { 12 | block(it) 13 | }) 14 | } 15 | 16 | fun eventBusObserveForever(key: String, block: (it: Any?) -> Unit) { 17 | LiveEventBus.get(key).observeForever { 18 | block(it) 19 | } 20 | } 21 | 22 | fun eventBusRemoveObserver(key: String, block: (it: Any?) -> Unit) { 23 | if (block != null) { 24 | LiveEventBus.get(key).removeObserver(block) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /common-res/src/main/java/com/common/res/utils/FastClickUtil.kt: -------------------------------------------------------------------------------- 1 | package com.common.res.utils 2 | 3 | object FastClickUtil { 4 | // 两次点击按钮之间的点击间隔不能少于1000毫秒 5 | private const val MIN_CLICK_DELAY_TIME = 500 6 | private var lastClickTime: Long = 0 7 | val isFastClick: Boolean 8 | get() { 9 | var flag = false 10 | val curClickTime = System.currentTimeMillis() 11 | if (curClickTime - lastClickTime >= MIN_CLICK_DELAY_TIME) { 12 | flag = true 13 | } 14 | lastClickTime = curClickTime 15 | return flag 16 | } 17 | } -------------------------------------------------------------------------------- /common-res/src/main/java/com/common/res/utils/FileUtil.kt: -------------------------------------------------------------------------------- 1 | package com.common.res.utils 2 | 3 | import java.io.File 4 | import java.io.IOException 5 | 6 | fun exists(file: File?) = file != null && file.exists() 7 | 8 | /** 9 | * 判断是否文件 10 | * @param file 11 | * 12 | * @return 13 | */ 14 | fun isFile(file: File) = exists(file) && file.isFile 15 | 16 | /** 17 | * 判断是否目录 18 | * @param file 19 | * 20 | * @return 21 | */ 22 | fun isDirectory(file: File) = exists(file) && file.isDirectory 23 | 24 | /** 25 | * 判断目录是否存在,不存在则判断是否创建成功 26 | * 27 | * @param file 文件 28 | * @return boolean 29 | */ 30 | fun createOrExistsDir(file: File?) = (file != null) && if (file.exists()) file.isDirectory else file.mkdirs() 31 | 32 | /** 33 | * 判断文件是否存在,不存在则判断是否创建成功 34 | * 35 | * @param file 文件 36 | * @return boolean 37 | */ 38 | fun createOrExistsFile(file: File?): Boolean { 39 | if (file == null || !createOrExistsDir(file.parentFile)) { 40 | return false 41 | } 42 | if (file.exists()) { 43 | return file.isFile 44 | } 45 | try { 46 | return file.createNewFile() 47 | } catch (e: IOException) { 48 | e.printStackTrace() 49 | return false 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /common-res/src/main/java/com/common/res/utils/GsonUtil.kt: -------------------------------------------------------------------------------- 1 | package com.common.res.utils 2 | 3 | import com.google.gson.Gson 4 | import com.google.gson.GsonBuilder 5 | import java.lang.reflect.Type 6 | 7 | object GsonUtil { 8 | 9 | private var filterNullGson: Gson? = null 10 | private var nullableGson: Gson? = null 11 | 12 | init { 13 | nullableGson = GsonBuilder() 14 | .enableComplexMapKeySerialization() 15 | .serializeNulls() 16 | .setDateFormat("yyyy-MM-dd HH:mm:ss:SSS") 17 | .create() 18 | filterNullGson = GsonBuilder() 19 | .enableComplexMapKeySerialization() 20 | .setDateFormat("yyyy-MM-dd HH:mm:ss:SSS") 21 | .create() 22 | } 23 | 24 | /** 25 | * 根据对象返回json 不过滤空值字段 26 | */ 27 | fun toJson(obj: Any?): String { 28 | return nullableGson!!.toJson(obj) 29 | } 30 | 31 | /** 32 | * 根据对象返回json 过滤空值字段 33 | */ 34 | fun toJsonFilterNull(obj: Any?): String { 35 | return filterNullGson!!.toJson(obj) 36 | } 37 | 38 | /** 39 | * 将json转化为对应的实体对象 40 | */ 41 | fun fromJson(json: String?, classOfT: Class?): T { 42 | return nullableGson!!.fromJson(json, classOfT) 43 | } 44 | 45 | /** 46 | * 将json转化为对应的实体对象 47 | */ 48 | fun fromJson(json: String?, type: Type?): T { 49 | return nullableGson!!.fromJson(json, type) 50 | } 51 | 52 | /** 53 | * 将对象值赋值给目标对象 54 | * 55 | * @param source 源对象 56 | * @param 目标对象类型 57 | * @return 目标对象实例 58 | */ 59 | fun convert(source: Any?, clz: Class?): T { 60 | val json = toJsonFilterNull(source) 61 | return fromJson(json, clz) 62 | } 63 | 64 | } -------------------------------------------------------------------------------- /common-res/src/main/java/com/common/res/utils/HttpPartUtil.kt: -------------------------------------------------------------------------------- 1 | package com.common.res.utils 2 | 3 | import okhttp3.MediaType.Companion.toMediaTypeOrNull 4 | import okhttp3.MultipartBody 5 | import okhttp3.RequestBody 6 | import java.io.File 7 | 8 | /** 9 | * desc :http获取part 10 | * author:panyy 11 | * date:2021/04/22 12 | */ 13 | object HttpPartUtil { 14 | const val IMAGETYPE = "image/jpeg" 15 | const val AUDIOTYPE = "audio/wav" 16 | const val VIDEOTYPE = "video/mp4" 17 | 18 | /** 19 | * 获取图片part 20 | * 21 | * @param filepath 文件路径 22 | * @param paramName 参数名 23 | * @return 24 | */ 25 | fun getImagePart(filepath: String?, paramName: String?): MultipartBody.Part { 26 | val file = File(filepath) 27 | val requestBody = RequestBody.create(IMAGETYPE.toMediaTypeOrNull(), file) 28 | return MultipartBody.Part.createFormData(paramName!!, file.name, requestBody) 29 | } 30 | 31 | /** 32 | * 获取音频part 33 | * 34 | * @param filepath 文件路径 35 | * @param paramName 参数名 36 | * @return 37 | */ 38 | fun getAudioPart(filepath: String?, paramName: String?): MultipartBody.Part { 39 | val file = File(filepath) 40 | val requestBody = RequestBody.create(AUDIOTYPE.toMediaTypeOrNull(), file) 41 | return MultipartBody.Part.createFormData(paramName!!, file.name, requestBody) 42 | } 43 | 44 | /** 45 | * 获取视频part 46 | * 47 | * @param filepath 文件路径 48 | * @param paramName 参数名 49 | * @return 50 | */ 51 | fun getVideoPart(filepath: String?, paramName: String?): MultipartBody.Part { 52 | val file = File(filepath) 53 | val requestBody = RequestBody.create(VIDEOTYPE.toMediaTypeOrNull(), file) 54 | return MultipartBody.Part.createFormData(paramName!!, file.name, requestBody) 55 | } 56 | } -------------------------------------------------------------------------------- /common-res/src/main/java/com/common/res/utils/OnClickUtil.kt: -------------------------------------------------------------------------------- 1 | package com.common.res.utils 2 | 3 | import android.view.View 4 | 5 | /** 6 | * 批量设置控件点击事件。 7 | * 8 | * @param v 点击的控件 9 | * @param block 处理点击事件回调代码块 10 | */ 11 | fun bindViewClickListener(vararg v: View?, block: View.() -> Unit) { 12 | val listener = View.OnClickListener { it.block() } 13 | v.forEach { it?.setOnClickListener(listener) } 14 | } 15 | 16 | /** 17 | * 批量设置控件点击事件。 18 | * 19 | * @param v 点击的控件 20 | * @param listener 处理点击事件监听器 21 | */ 22 | fun bindViewClickListener(vararg v: View?, listener: View.OnClickListener) { 23 | v.forEach { it?.setOnClickListener(listener) } 24 | } 25 | 26 | 27 | -------------------------------------------------------------------------------- /common-res/src/main/java/com/common/res/utils/PlatformUtil.kt: -------------------------------------------------------------------------------- 1 | package com.common.res.utils 2 | 3 | import android.os.Build 4 | 5 | fun isFroyoOrHigher(): Boolean = versionOrHigher(8) 6 | 7 | fun isGingerbreadOrHigher(): Boolean = versionOrHigher(9) 8 | 9 | fun isHoneycombOrHigher(): Boolean = versionOrHigher(11) 10 | 11 | fun isICSOrHigher(): Boolean = versionOrHigher(14) 12 | 13 | fun isJellyBeanOrHigher(): Boolean = versionOrHigher(16) 14 | 15 | fun isJellyBeanMR1OrHigher(): Boolean = versionOrHigher(17) 16 | 17 | fun isJellyBeanMR2OrHigher(): Boolean = versionOrHigher(18) 18 | 19 | fun isKitkatOrHigher(): Boolean = versionOrHigher(19) 20 | 21 | fun isKitkatWatchOrHigher(): Boolean = versionOrHigher(20) 22 | 23 | fun isLOrHigher(): Boolean = versionOrHigher(21) 24 | 25 | fun isLMR1OrHigher(): Boolean = versionOrHigher(22) 26 | 27 | fun isMOrHigher(): Boolean = versionOrHigher(23) 28 | 29 | fun isNOrHigher(): Boolean = versionOrHigher(24) 30 | 31 | fun isNMR1OrHigher(): Boolean = versionOrHigher(25) 32 | 33 | fun isOOrHigher(): Boolean = versionOrHigher(26) 34 | 35 | fun isOMR1OrHigher(): Boolean = versionOrHigher(27) 36 | 37 | fun isPOrHigher(): Boolean = versionOrHigher(28) 38 | 39 | fun support(apiVersion: Int, block: () -> Unit) { 40 | 41 | if (versionOrHigher(apiVersion)) { 42 | 43 | block() 44 | } 45 | } 46 | 47 | fun support(apiVersion: Int, function: () -> T, default: () -> T): T = if (versionOrHigher(apiVersion)) function() else default() 48 | 49 | private fun versionOrHigher(version: Int) = Build.VERSION.SDK_INT >= version 50 | 51 | -------------------------------------------------------------------------------- /common-res/src/main/java/com/common/res/view/NoSlideViewPager.java: -------------------------------------------------------------------------------- 1 | package com.common.res.view; 2 | 3 | import android.content.Context; 4 | import android.util.AttributeSet; 5 | import android.view.MotionEvent; 6 | 7 | import androidx.viewpager.widget.ViewPager; 8 | 9 | public class NoSlideViewPager extends ViewPager { 10 | 11 | public NoSlideViewPager(Context context, AttributeSet attrs) { 12 | super(context, attrs); 13 | } 14 | 15 | public NoSlideViewPager(Context context) { 16 | super(context); 17 | } 18 | 19 | @Override 20 | public void scrollTo(int x, int y) { 21 | super.scrollTo(x, y); 22 | } 23 | 24 | @Override 25 | public boolean onTouchEvent(MotionEvent arg0) { 26 | return false; 27 | } 28 | 29 | @Override 30 | public boolean onInterceptTouchEvent(MotionEvent arg0) { 31 | return false; 32 | } 33 | 34 | @Override 35 | public void setCurrentItem(int item, boolean smoothScroll) { 36 | super.setCurrentItem(item, smoothScroll); 37 | } 38 | 39 | @Override 40 | public void setCurrentItem(int item) { 41 | super.setCurrentItem(item); 42 | } 43 | 44 | } -------------------------------------------------------------------------------- /common-res/src/main/res/drawable-xhdpi/res_ic_image_default.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/panyy/mvvm-jetpack-sample/6d22f7cb6f2954c2c590edeeca956a9b1895d7bd/common-res/src/main/res/drawable-xhdpi/res_ic_image_default.9.png -------------------------------------------------------------------------------- /common-res/src/main/res/drawable-xhdpi/res_ic_toolbar_back.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/panyy/mvvm-jetpack-sample/6d22f7cb6f2954c2c590edeeca956a9b1895d7bd/common-res/src/main/res/drawable-xhdpi/res_ic_toolbar_back.png -------------------------------------------------------------------------------- /common-res/src/main/res/layout/res_activity_qrcode.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 35 | -------------------------------------------------------------------------------- /common-res/src/main/res/layout/res_layout_refresh_header.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 14 | 15 | -------------------------------------------------------------------------------- /common-res/src/main/res/values/attrs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /common-res/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #ffffff 4 | #656565 5 | #333333 6 | #00000000 7 | -------------------------------------------------------------------------------- /common-res/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 50dp 5 | -------------------------------------------------------------------------------- /common-res/src/main/res/values/ids.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /common-res/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /common-res/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 17 | 18 | 24 | 25 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | ## Project-wide Gradle settings. 2 | # 3 | # For more details on how to configure your build environment visit 4 | # http://www.gradle.org/docs/current/userguide/build_environment.html 5 | # 6 | # Specifies the JVM arguments used for the daemon process. 7 | # The setting is particularly useful for tweaking memory settings. 8 | # Default value: -Xmx1024m -XX:MaxPermSize=256m 9 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 10 | # 11 | # When configured, Gradle will run in incubating parallel mode. 12 | # This option should only be used with decoupled projects. More details, visit 13 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 14 | # org.gradle.parallel=true 15 | #Thu May 25 20:59:18 CST 2017 16 | org.gradle.jvmargs=-Xmx1536m 17 | android.enableBuildCache=true 18 | android.useAndroidX=true 19 | android.enableJetifier=true 20 | android.injected.testOnly=false 21 | android.databinding.incremental=true 22 | android.lifecycleProcessor.incremental=true 23 | kapt.incremental.apt=true 24 | kapt.use.worker.api=true 25 | kapt.include.compile.classpath=false 26 | org.gradle.parallel=true 27 | org.gradle.caching=true 28 | org.gradle.configureondemand=true -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/panyy/mvvm-jetpack-sample/6d22f7cb6f2954c2c590edeeca956a9b1895d7bd/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Thu Oct 22 15:27:30 CST 2020 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-all.zip 7 | -------------------------------------------------------------------------------- /module-login/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /module-login/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id "com.common.plugin.lib" 3 | } 4 | dependencies { 5 | implementation project(':common-res') 6 | } 7 | -------------------------------------------------------------------------------- /module-login/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /module-login/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /module-login/src/main/java/com/common/login/api/LoginService.kt: -------------------------------------------------------------------------------- 1 | package com.common.login.api 2 | 3 | import com.common.arms.base.net.BaseResponse 4 | import com.common.login.entity.LoginEntity 5 | import io.reactivex.Observable 6 | import retrofit2.http.Field 7 | import retrofit2.http.FormUrlEncoded 8 | import retrofit2.http.POST 9 | 10 | interface LoginService { 11 | 12 | @FormUrlEncoded 13 | @POST("user/login") 14 | suspend fun userLogin( 15 | @Field("username") username: String?, 16 | @Field("password") password: String? 17 | ): BaseResponse 18 | } -------------------------------------------------------------------------------- /module-login/src/main/java/com/common/login/app/LoginConfiguration.kt: -------------------------------------------------------------------------------- 1 | package com.common.login.app 2 | 3 | import android.app.Application.ActivityLifecycleCallbacks 4 | import android.content.Context 5 | import androidx.fragment.app.FragmentManager 6 | import com.common.arms.base.delegate.AppLifecycles 7 | import com.common.arms.di.module.GlobalConfigModule 8 | import com.common.arms.integration.ConfigModule 9 | 10 | class LoginConfiguration : ConfigModule { 11 | override fun applyOptions(context: Context, builder: GlobalConfigModule.Builder) { 12 | } 13 | 14 | override fun injectAppLifecycle(context: Context, lifecycles: MutableList) { 15 | lifecycles.add(LoginLifecyclesImpl()) 16 | } 17 | 18 | override fun injectActivityLifecycle(context: Context, lifecycles: MutableList) { 19 | } 20 | 21 | override fun injectFragmentLifecycle(context: Context, lifecycles: MutableList) { 22 | } 23 | } -------------------------------------------------------------------------------- /module-login/src/main/java/com/common/login/app/LoginLifecyclesImpl.kt: -------------------------------------------------------------------------------- 1 | package com.common.login.app 2 | 3 | import android.app.Application 4 | import android.content.Context 5 | import com.common.arms.base.delegate.AppLifecycles 6 | import org.koin.androidx.viewmodel.dsl.viewModel 7 | import org.koin.core.context.loadKoinModules 8 | import org.koin.dsl.module 9 | import com.common.login.repository.LoginRepository 10 | import com.common.login.vm.LoginViewModel 11 | 12 | class LoginLifecyclesImpl : AppLifecycles { 13 | 14 | override fun attachBaseContext(base: Context) { 15 | } 16 | 17 | override fun onCreate(application: Application) { 18 | var modules = module { 19 | single { LoginRepository() } 20 | viewModel { LoginViewModel(get()) } 21 | } 22 | loadKoinModules(modules) 23 | } 24 | 25 | override fun onTerminate(application: Application) {} 26 | 27 | } -------------------------------------------------------------------------------- /module-login/src/main/java/com/common/login/entity/LoginEntity.kt: -------------------------------------------------------------------------------- 1 | package com.common.login.entity 2 | 3 | data class LoginEntity( 4 | var username: String? = null, 5 | var password: String? = null, 6 | var token: String? = null 7 | ) -------------------------------------------------------------------------------- /module-login/src/main/java/com/common/login/repository/LoginRepository.kt: -------------------------------------------------------------------------------- 1 | package com.common.login.repository 2 | 3 | import androidx.lifecycle.MutableLiveData 4 | import com.common.arms.base.mvvm.BaseRepository 5 | import com.common.arms.base.net.apiCallWithState 6 | import com.common.arms.base.state.State 7 | import com.common.login.api.LoginService 8 | import com.common.login.entity.LoginEntity 9 | import retrofit2.http.Field 10 | 11 | class LoginRepository : BaseRepository() { 12 | 13 | suspend fun userLogin( 14 | username: String?, 15 | password: String?, 16 | loadState: MutableLiveData? = null) = 17 | apiCallWithState({ 18 | apiService().userLogin(username, password) 19 | }, loadState) 20 | } -------------------------------------------------------------------------------- /module-login/src/main/java/com/common/login/ui/activity/LoginActivity.kt: -------------------------------------------------------------------------------- 1 | package com.common.login.ui.activity 2 | 3 | import android.os.Bundle 4 | import com.alibaba.android.arouter.facade.annotation.Route 5 | import com.coder.zzq.smartshow.dialog.LoadingDialog 6 | import com.common.arms.base.mvvm.BaseVMActivity 7 | import com.common.arms.utils.dismissLoadingDialog 8 | import com.common.login.databinding.ActivityLoginBinding 9 | import com.common.login.vm.LoginViewModel 10 | import com.common.res.router.RouterHub 11 | import com.common.res.router.routerNavigation 12 | import com.common.res.utils.bindViewClickListener 13 | import org.koin.androidx.viewmodel.ext.android.getViewModel 14 | 15 | @Route(path = RouterHub.PUBLIC_LOGIN) 16 | class LoginActivity : BaseVMActivity() { 17 | 18 | private var dialog: LoadingDialog? = null 19 | 20 | override fun initVM(): LoginViewModel = getViewModel() 21 | 22 | override fun initData(savedInstanceState: Bundle?) { 23 | 24 | } 25 | 26 | override fun bindViewClick() { 27 | vBinding.apply { 28 | bindViewClickListener(btnLogin) { 29 | when (this) { 30 | btnLogin -> { 31 | userLogin() 32 | } 33 | } 34 | } 35 | } 36 | } 37 | 38 | private fun userLogin() { 39 | vBinding.apply { 40 | var name = etMobile.text.toString() 41 | var password = etPassword.text.toString() 42 | viewModel.userLogin(name, password).observe(activity) { 43 | dismissLoadingDialog(dialog) 44 | routerNavigation(RouterHub.PUBLIC_MAIN) 45 | activity.finish() 46 | } 47 | } 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /module-login/src/main/java/com/common/login/vm/LoginViewModel.kt: -------------------------------------------------------------------------------- 1 | package com.common.login.vm 2 | 3 | import androidx.lifecycle.liveData 4 | import com.common.arms.base.mvvm.BaseViewModel 5 | import com.common.arms.utils.showLoadingState 6 | import com.common.login.entity.LoginEntity 7 | import com.common.login.repository.LoginRepository 8 | import com.common.res.config.AppConfig 9 | 10 | class LoginViewModel(private val repository: LoginRepository) : BaseViewModel() { 11 | 12 | fun userLogin(username: String, password: String) = liveData { 13 | showLoadingState(loadState, "正在登录") 14 | var result = repository.userLogin(username, password, loadState) 15 | if (result != null) { 16 | AppConfig.login = true 17 | emit(result) 18 | } 19 | } 20 | 21 | } -------------------------------------------------------------------------------- /module-login/src/main/res/drawable-xhdpi/ic_password.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/panyy/mvvm-jetpack-sample/6d22f7cb6f2954c2c590edeeca956a9b1895d7bd/module-login/src/main/res/drawable-xhdpi/ic_password.webp -------------------------------------------------------------------------------- /module-login/src/main/res/drawable-xhdpi/ic_username.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/panyy/mvvm-jetpack-sample/6d22f7cb6f2954c2c590edeeca956a9b1895d7bd/module-login/src/main/res/drawable-xhdpi/ic_username.webp -------------------------------------------------------------------------------- /module-login/src/main/res/drawable/selector_btn_bg_login.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /module-login/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | #ffffff 5 | #333333 6 | #9b9b9b 7 | #e7e7e7 8 | #cccccc 9 | #85bf00 10 | 11 | 12 | -------------------------------------------------------------------------------- /module-login/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /module-login/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /module-main/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /module-main/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id "com.common.plugin.lib" 3 | } 4 | dependencies { 5 | implementation project(':common-res') 6 | } 7 | -------------------------------------------------------------------------------- /module-main/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 10 | 11 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /module-main/src/main/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /module-main/src/main/java/com/common/main/api/MainService.kt: -------------------------------------------------------------------------------- 1 | package com.common.main.api 2 | 3 | import com.common.arms.base.net.BaseResponse 4 | import com.common.main.entity.ArticleEntity 5 | import com.common.res.entity.ListEntity 6 | import retrofit2.http.GET 7 | import retrofit2.http.Path 8 | 9 | interface MainService { 10 | 11 | /** 12 | * 首页文章列表 13 | * 参数:页码,拼接在连接中,从0开始。 14 | */ 15 | @GET("article/list/{page}/json") 16 | suspend fun getArticleList( 17 | @Path("page") page: Int 18 | ): BaseResponse> 19 | 20 | } -------------------------------------------------------------------------------- /module-main/src/main/java/com/common/main/app/MainConfiguration.kt: -------------------------------------------------------------------------------- 1 | package com.common.main.app 2 | 3 | import android.app.Application.ActivityLifecycleCallbacks 4 | import android.content.Context 5 | import androidx.fragment.app.FragmentManager 6 | import com.common.arms.base.delegate.AppLifecycles 7 | import com.common.arms.di.module.GlobalConfigModule 8 | import com.common.arms.integration.ConfigModule 9 | 10 | class MainConfiguration : ConfigModule { 11 | override fun applyOptions(context: Context, builder: GlobalConfigModule.Builder) { 12 | } 13 | 14 | override fun injectAppLifecycle(context: Context, lifecycles: MutableList) { 15 | lifecycles.add(MainLifecyclesImpl()) 16 | } 17 | 18 | override fun injectActivityLifecycle(context: Context, lifecycles: MutableList) { 19 | } 20 | 21 | override fun injectFragmentLifecycle(context: Context, lifecycles: MutableList) { 22 | } 23 | } -------------------------------------------------------------------------------- /module-main/src/main/java/com/common/main/app/MainLifecyclesImpl.kt: -------------------------------------------------------------------------------- 1 | package com.common.main.app 2 | 3 | import android.app.Application 4 | import android.content.Context 5 | import com.common.arms.base.delegate.AppLifecycles 6 | import org.koin.androidx.viewmodel.dsl.viewModel 7 | import org.koin.core.context.loadKoinModules 8 | import org.koin.dsl.module 9 | import com.common.main.repository.MainRepository 10 | import com.common.main.vm.MainViewModel 11 | 12 | class MainLifecyclesImpl : AppLifecycles { 13 | 14 | override fun attachBaseContext(base: Context) { 15 | } 16 | 17 | override fun onCreate(application: Application) { 18 | var modules = module { 19 | single { MainRepository() } 20 | viewModel { MainViewModel(get(), get()) } 21 | } 22 | loadKoinModules(modules) 23 | } 24 | 25 | override fun onTerminate(application: Application) {} 26 | 27 | } -------------------------------------------------------------------------------- /module-main/src/main/java/com/common/main/entity/ArticleEntity.kt: -------------------------------------------------------------------------------- 1 | package com.common.main.entity 2 | 3 | class ArticleEntity { 4 | val apkLink: String? = null 5 | var shareUser: String? = null 6 | var chapterId = 0 7 | var chapterName: String? = null 8 | var isCollect = false 9 | var courseId = 0 10 | var desc: String? = null 11 | var envelopePic: String? = null 12 | var isTop = false 13 | var isFresh = false 14 | var id = 0 15 | var link: String? = null 16 | var niceDate: String? = null 17 | var origin: String? = null 18 | var prefix: String? = null 19 | var projectLink: String? = null 20 | var publishTime: Long = 0 21 | var superChapterId = 0 22 | var superChapterName: String? = null 23 | var title: String? = null 24 | var type = 0 25 | var userId = 0 26 | var visible = 0 27 | var zan = 0 28 | var originId = 0 29 | var covImgUrl: String? = null 30 | } -------------------------------------------------------------------------------- /module-main/src/main/java/com/common/main/repository/MainRepository.kt: -------------------------------------------------------------------------------- 1 | package com.common.main.repository 2 | 3 | import com.common.arms.base.mvvm.BaseRepository 4 | import com.common.arms.base.net.apiCall 5 | import com.common.main.api.MainService 6 | 7 | class MainRepository : BaseRepository() { 8 | 9 | suspend fun getArticleList(page: Int) = 10 | apiCall { 11 | apiService().getArticleList(page) 12 | } 13 | 14 | } -------------------------------------------------------------------------------- /module-main/src/main/java/com/common/main/ui/adapter/ArticleAdapter.kt: -------------------------------------------------------------------------------- 1 | package com.common.main.ui.adapter 2 | 3 | import com.common.main.databinding.ItemArticleListLayoutBinding 4 | import com.common.main.entity.ArticleEntity 5 | import com.common.res.adapter.BaseBindingQuickAdapter 6 | import com.common.res.ext.load 7 | 8 | class ArticleAdapter : BaseBindingQuickAdapter() { 9 | 10 | override fun convert(holder: BaseBindingHolder, item: ArticleEntity) { 11 | holder.getViewBinding().apply { 12 | tvName.text = "${holder.adapterPosition + 1}.${item.title}" 13 | ivCover.load("https://www.wanandroid.com/blogimgs/62c1bd68-b5f3-4a3c-a649-7ca8c7dfabe6.png") 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /module-main/src/main/java/com/common/main/vm/MainViewModel.kt: -------------------------------------------------------------------------------- 1 | package com.common.main.vm 2 | 3 | import androidx.lifecycle.MutableLiveData 4 | import androidx.lifecycle.viewModelScope 5 | import com.common.arms.base.mvvm.BaseViewModel 6 | import com.common.arms.base.net.BaseResponse 7 | import com.common.main.entity.ArticleEntity 8 | import com.common.main.repository.MainRepository 9 | import com.common.res.entity.ListEntity 10 | import com.common.res.page.PageDataHelper 11 | import kotlinx.coroutines.launch 12 | 13 | class MainViewModel(private val repository: MainRepository, private val pageDataHelper: PageDataHelper) : BaseViewModel() { 14 | 15 | val articleListLiveData: MutableLiveData>> = MutableLiveData() 16 | 17 | fun getArticleList(isRefresh: Boolean) { 18 | viewModelScope.launch { 19 | pageDataHelper.pageDataFront(isRefresh, loadState) 20 | repository.getArticleList(pageDataHelper.currentPage).apply { 21 | articleListLiveData.postValue(pageDataHelper.pageDataBehind(isRefresh, this)) 22 | } 23 | } 24 | } 25 | 26 | } -------------------------------------------------------------------------------- /module-main/src/main/res/drawable/ic_avatar.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/panyy/mvvm-jetpack-sample/6d22f7cb6f2954c2c590edeeca956a9b1895d7bd/module-main/src/main/res/drawable/ic_avatar.webp -------------------------------------------------------------------------------- /module-main/src/main/res/drawable/ic_black_right_24.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /module-main/src/main/res/drawable/ic_black_settings_24.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /module-main/src/main/res/drawable/ic_white_settings_24.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /module-main/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 10 | 11 | 15 | 16 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /module-main/src/main/res/layout/item_article_list_layout.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 16 | 17 | 27 | 28 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /module-main/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #ffffff 4 | #000000 5 | 6 | -------------------------------------------------------------------------------- /module-main/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | %s.%s 4 | 5 | -------------------------------------------------------------------------------- /module-main/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /module-web/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /module-web/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id "com.common.plugin.lib" 3 | } 4 | dependencies { 5 | implementation project(':common-res') 6 | } 7 | -------------------------------------------------------------------------------- /module-web/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /module-web/src/main/assets/dsbridge.js: -------------------------------------------------------------------------------- 1 | var bridge={default:this,call:function(b,a,c){var e="";"function"==typeof a&&(c=a,a={});a={data:void 0===a?null:a};if("function"==typeof c){var g="dscb"+window.dscb++;window[g]=c;a._dscbstub=g}a=JSON.stringify(a);if(window._dsbridge)e=_dsbridge.call(b,a);else if(window._dswk||-1!=navigator.userAgent.indexOf("_dsbridge"))e=prompt("_dsbridge="+b,a);return JSON.parse(e||"{}").data},register:function(b,a,c){c=c?window._dsaf:window._dsf;window._dsInit||(window._dsInit=!0,setTimeout(function(){bridge.call("_dsb.dsinit")}, 2 | 0));"object"==typeof a?c._obs[b]=a:c[b]=a},registerAsyn:function(b,a){this.register(b,a,!0)},hasNativeMethod:function(b,a){return this.call("_dsb.hasNativeMethod",{name:b,type:a||"all"})},disableJavascriptDialogBlock:function(b){this.call("_dsb.disableJavascriptDialogBlock",{disable:!1!==b})}}; 3 | !function(){if(!window._dsf){var b={_dsf:{_obs:{}},_dsaf:{_obs:{}},dscb:0,dsBridge:bridge,close:function(){bridge.call("_dsb.closePage")},_handleMessageFromNative:function(a){var e=JSON.parse(a.data),b={id:a.callbackId,complete:!0},c=this._dsf[a.method],d=this._dsaf[a.method],h=function(a,c){b.data=a.apply(c,e);bridge.call("_dsb.returnValue",b)},k=function(a,c){e.push(function(a,c){b.data=a;b.complete=!1!==c;bridge.call("_dsb.returnValue",b)});a.apply(c,e)};if(c)h(c,this._dsf);else if(d)k(d,this._dsaf); 4 | else if(c=a.method.split("."),!(2>c.length)){a=c.pop();var c=c.join("."),d=this._dsf._obs,d=d[c]||{},f=d[a];f&&"function"==typeof f?h(f,d):(d=this._dsaf._obs,d=d[c]||{},(f=d[a])&&"function"==typeof f&&k(f,d))}}},a;for(a in b)window[a]=b[a];bridge.register("_hasJavascriptMethod",function(a,b){b=a.split(".");if(2>b.length)return!(!_dsf[b]&&!_dsaf[b]);a=b.pop();b=b.join(".");return(b=_dsf._obs[b]||_dsaf._obs[b])&&!!b[a]})}}();module.exports=bridge; -------------------------------------------------------------------------------- /module-web/src/main/java/com/common/webframe/app/WebConfiguration.kt: -------------------------------------------------------------------------------- 1 | package com.common.webframe.app 2 | 3 | import android.app.Application 4 | import android.content.Context 5 | import androidx.fragment.app.FragmentManager 6 | import com.common.arms.base.delegate.AppLifecycles 7 | import com.common.arms.di.module.GlobalConfigModule 8 | import com.common.arms.integration.ConfigModule 9 | 10 | class WebConfiguration : ConfigModule { 11 | 12 | override fun applyOptions(context: Context, builder: GlobalConfigModule.Builder) { 13 | 14 | } 15 | 16 | override fun injectAppLifecycle(context: Context, lifecycles: MutableList) { 17 | // AppLifecycles 的所有方法都会在基类 Application 的对应的生命周期中被调用,所以在对应的方法中可以扩展一些自己需要的逻辑 18 | // 可以根据不同的逻辑添加多个实现类 19 | lifecycles.add(WebLifecyclesImpl()) 20 | } 21 | 22 | override fun injectActivityLifecycle(context: Context, lifecycles: MutableList) { 23 | } 24 | 25 | override fun injectFragmentLifecycle(context: Context, lifecycles: MutableList) { 26 | 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /module-web/src/main/java/com/common/webframe/app/WebLifecyclesImpl.kt: -------------------------------------------------------------------------------- 1 | package com.common.webframe.app 2 | 3 | import android.app.Activity 4 | import android.app.ActivityManager 5 | import android.app.Application 6 | import android.content.Context 7 | import android.content.Intent 8 | import android.os.Handler 9 | import android.text.TextUtils 10 | import com.common.arms.base.delegate.AppLifecycles 11 | import com.common.arms.integration.AppManager 12 | import com.common.webframe.service.PreLoadX5Service 13 | import org.koin.core.context.loadKoinModules 14 | import org.koin.dsl.module 15 | 16 | 17 | class WebLifecyclesImpl : AppLifecycles { 18 | 19 | override fun attachBaseContext(base: Context) { 20 | } 21 | 22 | override fun onCreate(application: Application) { 23 | startPreLoadX5Service() 24 | } 25 | 26 | override fun onTerminate(application: Application) { 27 | } 28 | 29 | /** 30 | * 前台启动X5预加载服务 31 | */ 32 | private fun startPreLoadX5Service() { 33 | var handler = Handler() 34 | handler.postDelayed({ 35 | var activity = AppManager.getAppManager().currentActivity 36 | if (activity != null && isForeground(activity, activity.localClassName)) { 37 | activity.startService(Intent(activity, PreLoadX5Service::class.java)) 38 | } else { 39 | startPreLoadX5Service() 40 | } 41 | }, 1000) 42 | } 43 | 44 | private fun isForeground(context: Activity?, className: String): Boolean { 45 | if (context == null || TextUtils.isEmpty(className)) return false 46 | val am = context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager 47 | val list = am.getRunningTasks(1) 48 | if (list != null && list.size > 0) { 49 | val cpn = list[0].topActivity 50 | if (className == cpn!!.className) return true 51 | } 52 | return false 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /module-web/src/main/java/com/common/webframe/entity/BrowserEntity.kt: -------------------------------------------------------------------------------- 1 | package com.common.webframe.entity 2 | 3 | /** 4 | * desc :打开浏览器实体类 5 | * author:panyy 6 | * data:2018/4/12 7 | */ 8 | class BrowserEntity { 9 | var url: String? = null 10 | } -------------------------------------------------------------------------------- /module-web/src/main/java/com/common/webframe/entity/CloseNumPageEntity.kt: -------------------------------------------------------------------------------- 1 | package com.common.webframe.entity 2 | 3 | /** 4 | * desc :关闭指定数量页面实体类 5 | * author:panyy 6 | * data:2018/4/12 7 | */ 8 | class CloseNumPageEntity { 9 | var num = 0 10 | } -------------------------------------------------------------------------------- /module-web/src/main/java/com/common/webframe/entity/DialogEntity.kt: -------------------------------------------------------------------------------- 1 | package com.common.webframe.entity 2 | 3 | /** 4 | * desc : 5 | * author:panyy 6 | * data:2018/5/3 7 | */ 8 | class DialogEntity { 9 | var type: String? = null 10 | var title: String? = null 11 | var message: String? = null 12 | var messageDetial: String? = null 13 | var buttons: List? = null 14 | 15 | class ButtonEntity { 16 | var name: String? = null 17 | var data: String? = null 18 | var newpage: String? = null 19 | } 20 | } -------------------------------------------------------------------------------- /module-web/src/main/java/com/common/webframe/entity/NewPageEntity.kt: -------------------------------------------------------------------------------- 1 | package com.common.webframe.entity 2 | 3 | /** 4 | * desc :打开新页实体类 5 | * author:panyy 6 | * data:2018/4/12 7 | */ 8 | class NewPageEntity { 9 | var data: String? = null 10 | var title: String? = null 11 | var hidetoolbar = false 12 | var closenumpage = 0 13 | } -------------------------------------------------------------------------------- /module-web/src/main/java/com/common/webframe/entity/OpenAudioEntity.kt: -------------------------------------------------------------------------------- 1 | package com.common.webframe.entity 2 | 3 | /** 4 | * desc :打开音频实体类 5 | * author:panyy 6 | * data:2018/4/12 7 | */ 8 | class OpenAudioEntity { 9 | var url: String? = null 10 | } -------------------------------------------------------------------------------- /module-web/src/main/java/com/common/webframe/entity/OpenVideoEntity.kt: -------------------------------------------------------------------------------- 1 | package com.common.webframe.entity 2 | 3 | /** 4 | * desc :打开视频实体类 5 | * author:panyy 6 | * data:2018/4/12 7 | */ 8 | class OpenVideoEntity { 9 | var url: String? = null 10 | var title: String? = null 11 | } -------------------------------------------------------------------------------- /module-web/src/main/java/com/common/webframe/entity/PicturePreviewEntity.kt: -------------------------------------------------------------------------------- 1 | package com.common.webframe.entity 2 | 3 | /** 4 | * desc : 5 | * author:panyy 6 | * data:2018/5/3 7 | */ 8 | class PicturePreviewEntity { 9 | var position = 0 10 | var urls: String? = null 11 | } -------------------------------------------------------------------------------- /module-web/src/main/java/com/common/webframe/entity/RefreshTabRightBtnEntity.kt: -------------------------------------------------------------------------------- 1 | package com.common.webframe.entity 2 | 3 | /** 4 | * desc : 5 | * author:panyy 6 | * data:2018/4/12 7 | */ 8 | class RefreshTabRightBtnEntity { 9 | var btnrights: List? = null 10 | 11 | class BtnrightEntity { 12 | var name: String? = null 13 | var image: String? = null 14 | var data: String? = null 15 | } 16 | } -------------------------------------------------------------------------------- /module-web/src/main/java/com/common/webframe/entity/SetDataEntity.kt: -------------------------------------------------------------------------------- 1 | package com.common.webframe.entity 2 | 3 | /** 4 | * desc :保存本地数据实体类 5 | * author:panyy 6 | * data:2018/4/12 7 | */ 8 | class SetDataEntity { 9 | var key: String? = null 10 | var value: String? = null 11 | } -------------------------------------------------------------------------------- /module-web/src/main/java/com/common/webframe/entity/ShowToastEntity.kt: -------------------------------------------------------------------------------- 1 | package com.common.webframe.entity 2 | 3 | /** 4 | * desc :显示Toast实体类 5 | * author:panyy 6 | * data:2018/4/12 7 | */ 8 | class ShowToastEntity { 9 | var data: String? = null 10 | } -------------------------------------------------------------------------------- /module-web/src/main/java/com/common/webframe/entity/TabPageEntity.kt: -------------------------------------------------------------------------------- 1 | package com.common.webframe.entity 2 | 3 | import java.io.Serializable 4 | import java.util.* 5 | 6 | /** 7 | * desc : 8 | * author:panyy 9 | * data:2018/4/12 10 | */ 11 | class TabPageEntity : Serializable { 12 | var closenumpage = 0 13 | var tabs: ArrayList? = null 14 | 15 | class TabEntity : Serializable { 16 | var name: String? = null 17 | var url: String? = null 18 | } 19 | } -------------------------------------------------------------------------------- /module-web/src/main/java/com/common/webframe/entity/ToolBarEntity.kt: -------------------------------------------------------------------------------- 1 | package com.common.webframe.entity 2 | 3 | import java.util.* 4 | 5 | /** 6 | * desc :ToolBar实体类 7 | * author:panyy 8 | * data:2018/4/4 9 | */ 10 | class ToolBarEntity { 11 | var visible = false 12 | var bgcolor: String? = null 13 | var title: TitleEntity? = null 14 | var btnback: BtnbackEntity? = null 15 | var btnsearch: BtnsearchEntity? = null 16 | var btnleft: BtnLeftEntity? = null 17 | var btnright: BtnrightEntity? = null 18 | var btnmore: ArrayList? = null 19 | 20 | class TitleEntity { 21 | var content: String? = null 22 | var textsize: String? = null 23 | var textcolor: String? = null 24 | } 25 | 26 | class BtnbackEntity 27 | class BtnsearchEntity 28 | class BtnmoreEntity { 29 | var name: String? = null 30 | var data: String? = null 31 | var hidetoolbar = false 32 | var newpage = false 33 | } 34 | 35 | class BtnrightEntity { 36 | var name: String? = null 37 | var image: String? = null 38 | var data: String? = null 39 | } 40 | 41 | class BtnLeftEntity { 42 | var data: String? = null 43 | } 44 | } -------------------------------------------------------------------------------- /module-web/src/main/java/com/common/webframe/entity/WebPageEntity.kt: -------------------------------------------------------------------------------- 1 | package com.common.webframe.entity 2 | 3 | /** 4 | * desc : 5 | * author:panyy 6 | * data:2018/4/12 7 | */ 8 | class WebPageEntity { 9 | var toolbar: ToolBarEntity? = null 10 | } -------------------------------------------------------------------------------- /module-web/src/main/java/com/common/webframe/service/PreLoadX5Service.kt: -------------------------------------------------------------------------------- 1 | package com.common.webframe.service 2 | 3 | import android.app.Service 4 | import android.content.Intent 5 | import android.os.IBinder 6 | import android.util.Log 7 | import com.tencent.smtt.export.external.TbsCoreSettings 8 | import com.tencent.smtt.sdk.QbSdk 9 | import com.tencent.smtt.sdk.QbSdk.PreInitCallback 10 | import java.util.* 11 | 12 | class PreLoadX5Service : Service() { 13 | override fun onBind(intent: Intent): IBinder? { 14 | return null 15 | } 16 | 17 | override fun onCreate() { 18 | super.onCreate() 19 | initX5() 20 | preinitX5WebCore() 21 | } 22 | 23 | private fun initX5() { 24 | val settings: MutableMap = HashMap() 25 | settings[TbsCoreSettings.TBS_SETTINGS_USE_PRIVATE_CLASSLOADER] = true 26 | settings[TbsCoreSettings.TBS_SETTINGS_USE_SPEEDY_CLASSLOADER] = true 27 | settings[TbsCoreSettings.TBS_SETTINGS_USE_DEXLOADER_SERVICE] = true 28 | QbSdk.initTbsSettings(settings) 29 | QbSdk.initX5Environment(applicationContext, cb) 30 | } 31 | 32 | private val cb: PreInitCallback = object : PreInitCallback { 33 | override fun onViewInitFinished(arg0: Boolean) { 34 | Log.e("QbSdk", "onViewInitFinished is $arg0") 35 | } 36 | 37 | override fun onCoreInitFinished() { 38 | Log.e("QbSdk", "onCoreInitFinished") 39 | } 40 | } 41 | 42 | private fun preinitX5WebCore() { 43 | if (!QbSdk.isTbsCoreInited()) { 44 | QbSdk.preInit(applicationContext, null) 45 | } 46 | } 47 | } -------------------------------------------------------------------------------- /module-web/src/main/java/com/common/webframe/service/WebFrameServiceImpl.kt: -------------------------------------------------------------------------------- 1 | package com.common.webframe.service 2 | 3 | import android.app.Activity 4 | import android.content.Context 5 | import androidx.fragment.app.Fragment 6 | import com.alibaba.android.arouter.facade.annotation.Route 7 | import com.common.arms.integration.AppManager 8 | import com.common.res.router.RouterHub 9 | import com.common.res.router.service.IWebFrameService 10 | import com.common.webframe.ui.activity.WebPageActivity 11 | import com.common.webframe.ui.fragment.WebPageFrgment 12 | 13 | @Route(path = RouterHub.WEBFRAME_ERVICE, name = "web框架服务") 14 | class WebFrameServiceImpl : IWebFrameService { 15 | 16 | private var context: Context? = null 17 | 18 | override fun init(context: Context?) { 19 | this.context = context 20 | } 21 | 22 | /** 23 | * 打开web页面 24 | * @param context Context 25 | * @param url String? 26 | * @param title String? 27 | * @param isHideToolbar Boolean 28 | */ 29 | override fun start(context: Context, url: String?, title: String?, isHideToolbar: Boolean) { 30 | WebPageActivity.start(context, url, title, isHideToolbar) 31 | } 32 | 33 | /** 34 | * 创建WebPageFragment 35 | * 36 | * @param url 37 | */ 38 | override fun newWebPageFragment(url: String): Fragment { 39 | return WebPageFrgment.newInstance(url) 40 | } 41 | 42 | /** 43 | * web框架回调通知H5 44 | * @param data 45 | */ 46 | override fun onCallBack(data: String?) { 47 | val activityList: List = AppManager.getAppManager().activityList ?: return 48 | for (i in activityList.indices.reversed()) { 49 | val activity = activityList[i] 50 | if (activity != null && activity.javaClass == WebPageActivity::class.java) { 51 | val webPageActivity: WebPageActivity<*> = activity as WebPageActivity<*> 52 | webPageActivity.getWebPageFrgment()?.getJsApi()?.onProgressCallBack(data!!) 53 | } 54 | } 55 | } 56 | 57 | } -------------------------------------------------------------------------------- /module-web/src/main/java/com/common/webframe/ui/adapter/H5UrlAdapter.kt: -------------------------------------------------------------------------------- 1 | package com.common.webframe.ui.adapter 2 | 3 | import com.chad.library.adapter.base.BaseQuickAdapter 4 | import com.chad.library.adapter.base.viewholder.BaseViewHolder 5 | import com.common.webframe.R 6 | 7 | /** 8 | * desc :URL adapter 9 | * author:panyy 10 | * data:2018/12/5 11 | */ 12 | class H5UrlAdapter : BaseQuickAdapter(R.layout.layout_item_h5_url, null) { 13 | 14 | override fun convert(helper: BaseViewHolder, item: String) { 15 | helper.setText(R.id.tv_url, item) 16 | } 17 | 18 | } 19 | 20 | -------------------------------------------------------------------------------- /module-web/src/main/java/com/common/webframe/ui/adapter/TabPagerAdapter.kt: -------------------------------------------------------------------------------- 1 | package com.common.webframe.ui.adapter 2 | 3 | import androidx.fragment.app.Fragment 4 | import androidx.fragment.app.FragmentManager 5 | import androidx.fragment.app.FragmentPagerAdapter 6 | import com.common.webframe.ui.fragment.WebPageFrgment 7 | 8 | class TabPagerAdapter(fm: FragmentManager?, private val tabFragments: List) : FragmentPagerAdapter(fm!!) { 9 | override fun getItem(position: Int): Fragment { 10 | return tabFragments[position] 11 | } 12 | 13 | override fun getCount(): Int { 14 | return tabFragments.size 15 | } 16 | } -------------------------------------------------------------------------------- /module-web/src/main/java/com/common/webframe/view/BaseDWebView.java: -------------------------------------------------------------------------------- 1 | package com.common.webframe.view; 2 | 3 | public interface BaseDWebView { 4 | 5 | void addJavascriptObject(Object object, String namespace); 6 | 7 | void removeJavascriptObject(String namespace); 8 | 9 | void callHandler(String method, Object[] args); 10 | 11 | void callHandler(String method, OnReturnValue handler); 12 | 13 | } -------------------------------------------------------------------------------- /module-web/src/main/java/com/common/webframe/view/CommonIndicator.java: -------------------------------------------------------------------------------- 1 | package com.common.webframe.view; 2 | 3 | import android.content.Context; 4 | import android.util.AttributeSet; 5 | import android.view.View; 6 | import android.widget.FrameLayout; 7 | 8 | import androidx.annotation.Nullable; 9 | 10 | import com.common.webframe.view.agentweb.BaseIndicatorView; 11 | 12 | /** 13 | * Created by cenxiaozhong on 2017/5/26. 14 | * source code https://github.com/Justson/AgentWeb 15 | */ 16 | 17 | public class CommonIndicator extends BaseIndicatorView { 18 | public CommonIndicator(Context context) { 19 | super(context); 20 | } 21 | 22 | public CommonIndicator(Context context, @Nullable AttributeSet attrs) { 23 | super(context, attrs); 24 | } 25 | 26 | public CommonIndicator(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { 27 | super(context, attrs, defStyleAttr); 28 | } 29 | 30 | 31 | @Override 32 | public void show() { 33 | this.setVisibility(View.VISIBLE); 34 | } 35 | 36 | @Override 37 | public void hide() { 38 | this.setVisibility(View.GONE); 39 | } 40 | 41 | 42 | @Override 43 | public FrameLayout.LayoutParams offerLayoutParams() { 44 | return new FrameLayout.LayoutParams(-1, -1); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /module-web/src/main/java/com/common/webframe/view/CompletionHandler.java: -------------------------------------------------------------------------------- 1 | package com.common.webframe.view; 2 | 3 | public interface CompletionHandler { 4 | void complete(T retValue); 5 | 6 | void complete(); 7 | 8 | void setProgressData(T value); 9 | } -------------------------------------------------------------------------------- /module-web/src/main/java/com/common/webframe/view/OnReturnValue.java: -------------------------------------------------------------------------------- 1 | package com.common.webframe.view; 2 | 3 | public interface OnReturnValue { 4 | void onValue(T retValue); 5 | } -------------------------------------------------------------------------------- /module-web/src/main/java/com/common/webframe/view/agentweb/AgentWebFileProvider.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) Justson(https://github.com/Justson/AgentWeb) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.common.webframe.view.agentweb; 18 | 19 | import android.content.Context; 20 | import android.content.pm.ProviderInfo; 21 | 22 | import androidx.annotation.NonNull; 23 | import androidx.core.content.FileProvider; 24 | 25 | /** 26 | * @author cenxiaozhong 27 | * @since 2.0.0 28 | */ 29 | public class AgentWebFileProvider extends FileProvider { 30 | 31 | @Override 32 | public void attachInfo(@NonNull Context context, @NonNull ProviderInfo info) { 33 | super.attachInfo(context, info); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /module-web/src/main/java/com/common/webframe/view/agentweb/AgentWebPermissions.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) Justson(https://github.com/Justson/AgentWeb) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.common.webframe.view.agentweb; 18 | 19 | import android.Manifest; 20 | 21 | 22 | /** 23 | * @author cenxiaozhong 24 | * @since 1.0.0 25 | */ 26 | public class AgentWebPermissions { 27 | public static final String[] CAMERA; 28 | public static final String[] LOCATION; 29 | public static final String[] STORAGE; 30 | public static final String ACTION_CAMERA = "Camera"; 31 | public static final String ACTION_LOCATION = "Location"; 32 | public static final String ACTION_STORAGE = "Storage"; 33 | static { 34 | CAMERA = new String[]{ 35 | Manifest.permission.CAMERA}; 36 | LOCATION = new String[]{ 37 | Manifest.permission.ACCESS_FINE_LOCATION, 38 | Manifest.permission.ACCESS_COARSE_LOCATION}; 39 | STORAGE = new String[]{ 40 | Manifest.permission.READ_EXTERNAL_STORAGE, 41 | Manifest.permission.WRITE_EXTERNAL_STORAGE}; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /module-web/src/main/java/com/common/webframe/view/agentweb/BaseIndicatorSpec.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) Justson(https://github.com/Justson/AgentWeb) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.common.webframe.view.agentweb; 18 | 19 | 20 | 21 | /** 22 | * @author cenxiaozhong 23 | * @since 1.0.0 24 | */ 25 | public interface BaseIndicatorSpec { 26 | 27 | void show(); 28 | 29 | void hide(); 30 | 31 | void reset(); 32 | 33 | void setProgress(int newProgress); 34 | 35 | } 36 | -------------------------------------------------------------------------------- /module-web/src/main/java/com/common/webframe/view/agentweb/BaseIndicatorView.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) Justson(https://github.com/Justson/AgentWeb) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.common.webframe.view.agentweb; 18 | 19 | import android.content.Context; 20 | import android.util.AttributeSet; 21 | import android.widget.FrameLayout; 22 | 23 | import androidx.annotation.Nullable; 24 | 25 | 26 | /** 27 | * @author cenxiaozhong 28 | * @date 2017/5/12 29 | * @since 1.0.0 30 | */ 31 | public abstract class BaseIndicatorView extends FrameLayout implements BaseIndicatorSpec, LayoutParamsOffer { 32 | public BaseIndicatorView(Context context) { 33 | super(context); 34 | } 35 | 36 | public BaseIndicatorView(Context context, @Nullable AttributeSet attrs) { 37 | super(context, attrs); 38 | } 39 | 40 | public BaseIndicatorView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { 41 | super(context, attrs, defStyleAttr); 42 | } 43 | 44 | @Override 45 | public void reset() { 46 | } 47 | 48 | @Override 49 | public void setProgress(int newProgress) { 50 | } 51 | 52 | @Override 53 | public void show() { 54 | } 55 | 56 | @Override 57 | public void hide() { 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /module-web/src/main/java/com/common/webframe/view/agentweb/DefaultWebLifeCycleImpl.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) Justson(https://github.com/Justson/AgentWeb) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.common.webframe.view.agentweb; 18 | 19 | import android.os.Build; 20 | 21 | import com.tencent.smtt.sdk.WebView; 22 | 23 | /** 24 | * @author cenxiaozhong 25 | * @date 2017/6/3 26 | * @since 2.0.0 27 | */ 28 | public class DefaultWebLifeCycleImpl implements WebLifeCycle { 29 | private WebView mWebView; 30 | 31 | DefaultWebLifeCycleImpl(WebView webView) { 32 | this.mWebView = webView; 33 | } 34 | 35 | @Override 36 | public void onResume() { 37 | if (this.mWebView != null) { 38 | if (Build.VERSION.SDK_INT >= 11) { 39 | this.mWebView.onResume(); 40 | } 41 | this.mWebView.resumeTimers(); 42 | } 43 | } 44 | 45 | @Override 46 | public void onPause() { 47 | if (this.mWebView != null) { 48 | if (Build.VERSION.SDK_INT >= 11) { 49 | this.mWebView.onPause(); 50 | } 51 | this.mWebView.pauseTimers(); 52 | } 53 | } 54 | 55 | @Override 56 | public void onDestroy() { 57 | if (this.mWebView != null) { 58 | this.mWebView.resumeTimers(); 59 | } 60 | AgentWebUtils.clearWebView(this.mWebView); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /module-web/src/main/java/com/common/webframe/view/agentweb/EventHandlerImpl.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) Justson(https://github.com/Justson/AgentWeb) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.common.webframe.view.agentweb; 18 | 19 | import android.view.KeyEvent; 20 | 21 | import com.tencent.smtt.sdk.WebView; 22 | 23 | /** 24 | * IEventHandler 对事件的处理,主要是针对 25 | * 视屏状态进行了处理 , 如果当前状态为 视频状态 26 | * 则先退出视频。 27 | * 28 | * @author cenxiaozhong 29 | * @date 2017/6/3 30 | * @since 2.0.0 31 | */ 32 | public class EventHandlerImpl implements IEventHandler { 33 | private WebView mWebView; 34 | private EventInterceptor mEventInterceptor; 35 | 36 | public static final EventHandlerImpl getInstantce(WebView view, EventInterceptor eventInterceptor) { 37 | return new EventHandlerImpl(view, eventInterceptor); 38 | } 39 | 40 | public EventHandlerImpl(WebView webView, EventInterceptor eventInterceptor) { 41 | this.mWebView = webView; 42 | this.mEventInterceptor = eventInterceptor; 43 | } 44 | 45 | @Override 46 | public boolean onKeyDown(int keyCode, KeyEvent event) { 47 | if (keyCode == KeyEvent.KEYCODE_BACK) { 48 | return back(); 49 | } 50 | return false; 51 | } 52 | 53 | @Override 54 | public boolean back() { 55 | if (this.mEventInterceptor != null && this.mEventInterceptor.event()) { 56 | return true; 57 | } 58 | if (mWebView != null && mWebView.canGoBack()) { 59 | mWebView.goBack(); 60 | return true; 61 | } 62 | return false; 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /module-web/src/main/java/com/common/webframe/view/agentweb/EventInterceptor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) Justson(https://github.com/Justson/AgentWeb) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.common.webframe.view.agentweb; 18 | 19 | /** 20 | * @author cenxiaozhong 21 | * @date 2017/6/3 22 | * @since 1.0.0 23 | */ 24 | public interface EventInterceptor { 25 | boolean event(); 26 | } 27 | -------------------------------------------------------------------------------- /module-web/src/main/java/com/common/webframe/view/agentweb/HookManager.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) Justson(https://github.com/Justson/AgentWeb) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.common.webframe.view.agentweb; 18 | 19 | 20 | /** 21 | * @author cenxiaozhong 22 | * @since 1.0.0 23 | */ 24 | public class HookManager { 25 | 26 | public static AgentWeb hookAgentWeb(AgentWeb agentWeb, AgentWeb.AgentBuilder agentBuilder) { 27 | return agentWeb; 28 | } 29 | 30 | public static boolean permissionHook(String url, String[] permissions) { 31 | return true; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /module-web/src/main/java/com/common/webframe/view/agentweb/IAgentWebSettings.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) Justson(https://github.com/Justson/AgentWeb) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.common.webframe.view.agentweb; 18 | 19 | import com.tencent.smtt.sdk.WebView; 20 | 21 | /** 22 | * @author cenxiaozhong 23 | * @since 1.0.0 24 | */ 25 | 26 | public interface IAgentWebSettings { 27 | 28 | IAgentWebSettings toSetting(WebView webView); 29 | 30 | T getWebSettings(); 31 | 32 | } 33 | -------------------------------------------------------------------------------- /module-web/src/main/java/com/common/webframe/view/agentweb/IEventHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) Justson(https://github.com/Justson/AgentWeb) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.common.webframe.view.agentweb; 18 | 19 | import android.view.KeyEvent; 20 | 21 | /** 22 | * @author cenxiaozhong 23 | * @since 1.0.0 24 | */ 25 | public interface IEventHandler { 26 | 27 | boolean onKeyDown(int keyCode, KeyEvent event); 28 | 29 | boolean back(); 30 | } 31 | -------------------------------------------------------------------------------- /module-web/src/main/java/com/common/webframe/view/agentweb/IUrlLoader.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) Justson(https://github.com/Justson/AgentWeb) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.common.webframe.view.agentweb; 18 | 19 | import java.util.Map; 20 | 21 | /** 22 | * @author cenxiaozhong 23 | * @date 2017/6/3 24 | * @update 4.0.0 25 | * @since 2.0.0 26 | */ 27 | public interface IUrlLoader { 28 | 29 | 30 | void loadUrl(String url); 31 | 32 | void loadUrl(String url, Map headers); 33 | 34 | void reload(); 35 | 36 | void loadData(String data, String mimeType, String encoding); 37 | 38 | void stopLoading(); 39 | 40 | void loadDataWithBaseURL(String baseUrl, String data, 41 | String mimeType, String encoding, String historyUrl); 42 | 43 | void postUrl(String url, byte[] params); 44 | 45 | HttpHeaders getHttpHeaders(); 46 | } 47 | -------------------------------------------------------------------------------- /module-web/src/main/java/com/common/webframe/view/agentweb/IVideo.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) Justson(https://github.com/Justson/AgentWeb) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.common.webframe.view.agentweb; 18 | 19 | import android.view.View; 20 | 21 | import com.tencent.smtt.export.external.interfaces.IX5WebChromeClient; 22 | 23 | 24 | /** 25 | * @author cenxiaozhong 26 | * @date 2017/6/10 27 | * @since 2.0.0 28 | */ 29 | public interface IVideo { 30 | 31 | 32 | void onShowCustomView(View view, IX5WebChromeClient.CustomViewCallback callback); 33 | 34 | 35 | void onHideCustomView(); 36 | 37 | 38 | boolean isVideoState(); 39 | 40 | } 41 | -------------------------------------------------------------------------------- /module-web/src/main/java/com/common/webframe/view/agentweb/IWebIndicator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) Justson(https://github.com/Justson/AgentWeb) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.common.webframe.view.agentweb; 18 | 19 | /** 20 | * @author cenxiaozhong 21 | * @since 1.0.0 22 | */ 23 | 24 | 25 | public interface IWebIndicator { 26 | 27 | 28 | T offer(); 29 | } 30 | -------------------------------------------------------------------------------- /module-web/src/main/java/com/common/webframe/view/agentweb/IWebLayout.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) Justson(https://github.com/Justson/AgentWeb) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.common.webframe.view.agentweb; 18 | 19 | import android.view.ViewGroup; 20 | 21 | import androidx.annotation.NonNull; 22 | import androidx.annotation.Nullable; 23 | 24 | import com.tencent.smtt.sdk.WebView; 25 | 26 | /** 27 | * Created by cenxiaozhong on 2017/7/1. 28 | */ 29 | 30 | /** 31 | * @author cenxiaozhong 32 | * @date 2017/7/1 33 | * @update 4.0.0 34 | * @since 1.0.0 35 | */ 36 | public interface IWebLayout { 37 | 38 | /** 39 | * @return WebView 的父控件 40 | */ 41 | @NonNull 42 | V getLayout(); 43 | 44 | /** 45 | * @return 返回 WebView 或 WebView 的子View ,返回null AgentWeb 内部会创建适当 WebView 46 | */ 47 | @Nullable 48 | T getWebView(); 49 | } 50 | -------------------------------------------------------------------------------- /module-web/src/main/java/com/common/webframe/view/agentweb/IndicatorController.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) Justson(https://github.com/Justson/AgentWeb) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.common.webframe.view.agentweb; 18 | 19 | import com.tencent.smtt.sdk.WebView; 20 | 21 | /** 22 | * @author cenxiaozhong 23 | * @update 4.0.0 24 | * @since 1.0.0 25 | */ 26 | 27 | public interface IndicatorController { 28 | 29 | void progress(WebView v, int newProgress); 30 | 31 | BaseIndicatorSpec offerIndicator(); 32 | 33 | void showIndicator(); 34 | 35 | void setProgress(int newProgress); 36 | 37 | void finish(); 38 | } 39 | -------------------------------------------------------------------------------- /module-web/src/main/java/com/common/webframe/view/agentweb/JsAccessEntrace.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) Justson(https://github.com/Justson/AgentWeb) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.common.webframe.view.agentweb; 18 | 19 | import com.tencent.smtt.sdk.ValueCallback; 20 | 21 | /** 22 | * @author cenxiaozhong 23 | * @date 2017/5/14 24 | * @since 1.0.0 25 | */ 26 | public interface JsAccessEntrace extends QuickCallJs { 27 | 28 | 29 | void callJs(String js, ValueCallback callback); 30 | 31 | void callJs(String js); 32 | 33 | 34 | } 35 | -------------------------------------------------------------------------------- /module-web/src/main/java/com/common/webframe/view/agentweb/JsAccessEntraceImpl.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) Justson(https://github.com/Justson/AgentWeb) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.common.webframe.view.agentweb; 18 | 19 | import android.os.Handler; 20 | import android.os.Looper; 21 | 22 | import com.tencent.smtt.sdk.ValueCallback; 23 | import com.tencent.smtt.sdk.WebView; 24 | 25 | 26 | /** 27 | * @author cenxiaozhong 28 | * @date 2017/6/3 29 | * @since 1.0.0 30 | */ 31 | public class JsAccessEntraceImpl extends BaseJsAccessEntrace { 32 | 33 | private WebView mWebView; 34 | private Handler mHandler = new Handler(Looper.getMainLooper()); 35 | 36 | public static JsAccessEntraceImpl getInstance(WebView webView) { 37 | return new JsAccessEntraceImpl(webView); 38 | } 39 | 40 | private JsAccessEntraceImpl(WebView webView) { 41 | super(webView); 42 | this.mWebView = webView; 43 | } 44 | 45 | private void safeCallJs(final String s, final ValueCallback valueCallback) { 46 | mHandler.post(new Runnable() { 47 | @Override 48 | public void run() { 49 | callJs(s, valueCallback); 50 | } 51 | }); 52 | } 53 | 54 | @Override 55 | public void callJs(String params, final ValueCallback callback) { 56 | if (Thread.currentThread() != Looper.getMainLooper().getThread()) { 57 | safeCallJs(params, callback); 58 | return; 59 | } 60 | super.callJs(params,callback); 61 | } 62 | 63 | 64 | } 65 | -------------------------------------------------------------------------------- /module-web/src/main/java/com/common/webframe/view/agentweb/JsInterfaceHolder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) Justson(https://github.com/Justson/AgentWeb) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.common.webframe.view.agentweb; 18 | 19 | import java.util.Map; 20 | 21 | /** 22 | * @author cenxiaozhong 23 | * @date 2017/5/13 24 | * @since 1.0.0 25 | */ 26 | public interface JsInterfaceHolder { 27 | 28 | JsInterfaceHolder addJavaObjects(Map maps); 29 | 30 | JsInterfaceHolder addJavaObject(String k, Object v); 31 | 32 | boolean checkObject(Object v); 33 | 34 | } 35 | -------------------------------------------------------------------------------- /module-web/src/main/java/com/common/webframe/view/agentweb/JsInterfaceObjectException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) Justson(https://github.com/Justson/AgentWeb) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.common.webframe.view.agentweb; 18 | 19 | 20 | /** 21 | * @author cenxiaozhong 22 | * @date 2017/5/13 23 | * @since 1.0.0 24 | */ 25 | public class JsInterfaceObjectException extends RuntimeException { 26 | JsInterfaceObjectException(String msg){ 27 | super(msg); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /module-web/src/main/java/com/common/webframe/view/agentweb/LayoutParamsOffer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) Justson(https://github.com/Justson/AgentWeb) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.common.webframe.view.agentweb; 18 | 19 | import android.widget.FrameLayout; 20 | 21 | /** 22 | * @author cenxiaozhong 23 | * @date 2017/5/12 24 | * @since 1.0.0 25 | */ 26 | public interface LayoutParamsOffer { 27 | 28 | T offerLayoutParams(); 29 | 30 | } 31 | -------------------------------------------------------------------------------- /module-web/src/main/java/com/common/webframe/view/agentweb/LogUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) Justson(https://github.com/Justson/AgentWeb) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.common.webframe.view.agentweb; 18 | 19 | import android.util.Log; 20 | 21 | /** 22 | * @author cenxiaozhong 23 | * @date 2017/5/28 24 | * @since 1.0.0 25 | */ 26 | public class LogUtils { 27 | 28 | private static final String PREFIX = " agentweb - "; 29 | 30 | public static boolean isDebug() { 31 | return AgentWebConfig.DEBUG; 32 | } 33 | 34 | public static void i(String tag, String message) { 35 | 36 | if (isDebug()){ 37 | Log.i(PREFIX.concat(tag), message); 38 | } 39 | } 40 | 41 | public static void v(String tag, String message) { 42 | 43 | if (isDebug()){ 44 | Log.v(PREFIX.concat(tag), message); 45 | } 46 | 47 | } 48 | 49 | public static void safeCheckCrash(String tag, String msg, Throwable tr) { 50 | if (isDebug()) { 51 | throw new RuntimeException(PREFIX.concat(tag) + " " + msg, tr); 52 | } else { 53 | Log.e(PREFIX.concat(tag), msg, tr); 54 | } 55 | } 56 | 57 | public static void e(String tag, String msg, Throwable tr) { 58 | Log.e(tag, msg, tr); 59 | } 60 | 61 | public static void e(String tag, String message) { 62 | 63 | if (isDebug()){ 64 | Log.e(PREFIX.concat(tag), message); 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /module-web/src/main/java/com/common/webframe/view/agentweb/MiddlewareWebChromeBase.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) Justson(https://github.com/Justson/AgentWeb) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.common.webframe.view.agentweb; 18 | 19 | import com.tencent.smtt.sdk.WebChromeClient; 20 | 21 | /** 22 | * @author cenxiaozhong 23 | * @date 2017/12/16 24 | * @since 3.0.0 25 | */ 26 | public class MiddlewareWebChromeBase extends WebChromeClientDelegate { 27 | 28 | private MiddlewareWebChromeBase mMiddlewareWebChromeBase; 29 | 30 | protected MiddlewareWebChromeBase(WebChromeClient webChromeClient) { 31 | super(webChromeClient); 32 | } 33 | 34 | protected MiddlewareWebChromeBase() { 35 | super(null); 36 | } 37 | 38 | @Override 39 | final void setDelegate(WebChromeClient delegate) { 40 | super.setDelegate(delegate); 41 | } 42 | 43 | final MiddlewareWebChromeBase enq(MiddlewareWebChromeBase middlewareWebChromeBase) { 44 | setDelegate(middlewareWebChromeBase); 45 | this.mMiddlewareWebChromeBase = middlewareWebChromeBase; 46 | return this.mMiddlewareWebChromeBase; 47 | } 48 | 49 | 50 | final MiddlewareWebChromeBase next() { 51 | return this.mMiddlewareWebChromeBase; 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /module-web/src/main/java/com/common/webframe/view/agentweb/MiddlewareWebClientBase.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) Justson(https://github.com/Justson/AgentWeb) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.common.webframe.view.agentweb; 18 | 19 | import com.tencent.smtt.sdk.WebViewClient; 20 | 21 | /** 22 | * @author cenxiaozhong 23 | * @date 2017/12/15 24 | * @since 3.0.0 25 | */ 26 | public class MiddlewareWebClientBase extends WebViewClientDelegate { 27 | private MiddlewareWebClientBase mMiddleWrareWebClientBase; 28 | private static String TAG = MiddlewareWebClientBase.class.getSimpleName(); 29 | 30 | MiddlewareWebClientBase(MiddlewareWebClientBase client) { 31 | super(client); 32 | this.mMiddleWrareWebClientBase = client; 33 | } 34 | 35 | protected MiddlewareWebClientBase(WebViewClient client) { 36 | super(client); 37 | } 38 | 39 | protected MiddlewareWebClientBase() { 40 | super(null); 41 | } 42 | 43 | final MiddlewareWebClientBase next() { 44 | return this.mMiddleWrareWebClientBase; 45 | } 46 | 47 | @Override 48 | final void setDelegate(WebViewClient delegate) { 49 | super.setDelegate(delegate); 50 | 51 | } 52 | 53 | final MiddlewareWebClientBase enq(MiddlewareWebClientBase middleWrareWebClientBase) { 54 | setDelegate(middleWrareWebClientBase); 55 | this.mMiddleWrareWebClientBase = middleWrareWebClientBase; 56 | return middleWrareWebClientBase; 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /module-web/src/main/java/com/common/webframe/view/agentweb/PermissionInterceptor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) Justson(https://github.com/Justson/AgentWeb) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.common.webframe.view.agentweb; 18 | 19 | /** 20 | * @author cenxiaozhong 21 | * @since 3.0.0 22 | */ 23 | public interface PermissionInterceptor { 24 | boolean intercept(String url, String[] permissions, String action); 25 | } 26 | -------------------------------------------------------------------------------- /module-web/src/main/java/com/common/webframe/view/agentweb/Provider.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) Justson(https://github.com/Justson/AgentWeb) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.common.webframe.view.agentweb; 18 | 19 | /** 20 | * @author cenxiaozhong 21 | * @date 2017/7/5 22 | * @since 1.0.0 23 | */ 24 | public interface Provider { 25 | T provide(); 26 | } 27 | -------------------------------------------------------------------------------- /module-web/src/main/java/com/common/webframe/view/agentweb/QuickCallJs.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) Justson(https://github.com/Justson/AgentWeb) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.common.webframe.view.agentweb; 18 | 19 | import android.os.Build; 20 | 21 | import androidx.annotation.RequiresApi; 22 | 23 | import com.tencent.smtt.sdk.ValueCallback; 24 | 25 | 26 | /** 27 | * @author cenxiaozhong 28 | * @date 2017/5/29 29 | * @since 1.0.0 30 | */ 31 | public interface QuickCallJs { 32 | @RequiresApi(Build.VERSION_CODES.KITKAT) 33 | void quickCallJs(String method, ValueCallback callback, String... params); 34 | 35 | void quickCallJs(String method, String... params); 36 | 37 | void quickCallJs(String method); 38 | 39 | 40 | } 41 | -------------------------------------------------------------------------------- /module-web/src/main/java/com/common/webframe/view/agentweb/UrlCommonException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) Justson(https://github.com/Justson/AgentWeb) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.common.webframe.view.agentweb; 18 | /** 19 | * @author cenxiaozhong 20 | * @since 1.0.0 21 | */ 22 | public class UrlCommonException extends RuntimeException { 23 | 24 | public UrlCommonException() { 25 | } 26 | 27 | public UrlCommonException(String msg) { 28 | super(msg); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /module-web/src/main/java/com/common/webframe/view/agentweb/WebChromeClient.java: -------------------------------------------------------------------------------- 1 | package com.common.webframe.view.agentweb; 2 | 3 | /** 4 | * @author cenxiaozhong 5 | * @date 2019/4/13 6 | * @since 1.0.0 7 | */ 8 | public class WebChromeClient extends MiddlewareWebChromeBase { 9 | public WebChromeClient() { 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /module-web/src/main/java/com/common/webframe/view/agentweb/WebCreator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) Justson(https://github.com/Justson/AgentWeb) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.common.webframe.view.agentweb; 18 | 19 | import android.widget.FrameLayout; 20 | 21 | import com.tencent.smtt.sdk.WebView; 22 | 23 | /** 24 | * @author cenxiaozhong 25 | * @since 1.0.0 26 | */ 27 | public interface WebCreator extends IWebIndicator { 28 | WebCreator create(); 29 | 30 | WebView getWebView(); 31 | 32 | FrameLayout getWebParentLayout(); 33 | } 34 | -------------------------------------------------------------------------------- /module-web/src/main/java/com/common/webframe/view/agentweb/WebLifeCycle.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) Justson(https://github.com/Justson/AgentWeb) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.common.webframe.view.agentweb; 18 | 19 | /** 20 | * @author cenxiaozhong 21 | * @date 2017/5/30 22 | * @since 1.0.0 23 | */ 24 | public interface WebLifeCycle { 25 | void onResume(); 26 | void onPause(); 27 | void onDestroy(); 28 | } 29 | -------------------------------------------------------------------------------- /module-web/src/main/java/com/common/webframe/view/agentweb/WebListenerManager.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) Justson(https://github.com/Justson/AgentWeb) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.common.webframe.view.agentweb; 18 | 19 | import com.tencent.smtt.sdk.DownloadListener; 20 | import com.tencent.smtt.sdk.WebChromeClient; 21 | import com.tencent.smtt.sdk.WebView; 22 | import com.tencent.smtt.sdk.WebViewClient; 23 | 24 | /** 25 | * @author cenxiaozhong 26 | * @date 2017/5/13 27 | * @since 1.0.0 28 | */ 29 | public interface WebListenerManager { 30 | WebListenerManager setWebChromeClient(WebView webview, WebChromeClient webChromeClient); 31 | WebListenerManager setWebViewClient(WebView webView, WebViewClient webViewClient); 32 | WebListenerManager setDownloader(WebView webView, DownloadListener downloadListener); 33 | } 34 | -------------------------------------------------------------------------------- /module-web/src/main/java/com/common/webframe/view/agentweb/WebSecurityCheckLogic.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) Justson(https://github.com/Justson/AgentWeb) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.common.webframe.view.agentweb; 18 | 19 | import androidx.collection.ArrayMap; 20 | 21 | import com.tencent.smtt.sdk.WebView; 22 | 23 | 24 | /** 25 | * @author cenxiaozhong 26 | */ 27 | public interface WebSecurityCheckLogic { 28 | void dealHoneyComb(WebView view); 29 | 30 | void dealJsInterface(ArrayMap objects, AgentWeb.SecurityType securityType); 31 | } 32 | -------------------------------------------------------------------------------- /module-web/src/main/java/com/common/webframe/view/agentweb/WebSecurityController.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) Justson(https://github.com/Justson/AgentWeb) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.common.webframe.view.agentweb; 18 | 19 | /** 20 | * @author cenxiaozhong 21 | */ 22 | public interface WebSecurityController { 23 | void check(T t); 24 | } 25 | -------------------------------------------------------------------------------- /module-web/src/main/java/com/common/webframe/view/agentweb/WebSecurityControllerImpl.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) Justson(https://github.com/Justson/AgentWeb) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.common.webframe.view.agentweb; 18 | 19 | import android.os.Build; 20 | 21 | import androidx.collection.ArrayMap; 22 | 23 | import com.tencent.smtt.sdk.WebView; 24 | 25 | /** 26 | * @author cenxiaozhong 27 | */ 28 | public class WebSecurityControllerImpl implements WebSecurityController { 29 | 30 | private WebView mWebView; 31 | private ArrayMap mMap; 32 | private AgentWeb.SecurityType mSecurityType; 33 | 34 | public WebSecurityControllerImpl(WebView view, ArrayMap map, AgentWeb.SecurityType securityType) { 35 | this.mWebView = view; 36 | this.mMap = map; 37 | this.mSecurityType = securityType; 38 | } 39 | 40 | @Override 41 | public void check(WebSecurityCheckLogic webSecurityCheckLogic) { 42 | if (Build.VERSION.SDK_INT > Build.VERSION_CODES.HONEYCOMB) { 43 | webSecurityCheckLogic.dealHoneyComb(mWebView); 44 | } 45 | if (mMap != null && mSecurityType == AgentWeb.SecurityType.STRICT_CHECK && !mMap.isEmpty()) { 46 | webSecurityCheckLogic.dealJsInterface(mMap, mSecurityType); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /module-web/src/main/java/com/common/webframe/view/agentweb/WebViewClient.java: -------------------------------------------------------------------------------- 1 | package com.common.webframe.view.agentweb; 2 | 3 | /** 4 | * @author cenxiaozhong 5 | * @date 2019/4/13 6 | * @since 1.0.0 7 | */ 8 | public class WebViewClient extends MiddlewareWebClientBase { 9 | public WebViewClient() { 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /module-web/src/main/res/drawable-xhdpi/download.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/panyy/mvvm-jetpack-sample/6d22f7cb6f2954c2c590edeeca956a9b1895d7bd/module-web/src/main/res/drawable-xhdpi/download.png -------------------------------------------------------------------------------- /module-web/src/main/res/drawable-xhdpi/ic_load.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/panyy/mvvm-jetpack-sample/6d22f7cb6f2954c2c590edeeca956a9b1895d7bd/module-web/src/main/res/drawable-xhdpi/ic_load.png -------------------------------------------------------------------------------- /module-web/src/main/res/drawable-xhdpi/ic_load_fail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/panyy/mvvm-jetpack-sample/6d22f7cb6f2954c2c590edeeca956a9b1895d7bd/module-web/src/main/res/drawable-xhdpi/ic_load_fail.png -------------------------------------------------------------------------------- /module-web/src/main/res/drawable-xhdpi/ic_load_success.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/panyy/mvvm-jetpack-sample/6d22f7cb6f2954c2c590edeeca956a9b1895d7bd/module-web/src/main/res/drawable-xhdpi/ic_load_success.png -------------------------------------------------------------------------------- /module-web/src/main/res/drawable-xhdpi/ic_webframe_back_black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/panyy/mvvm-jetpack-sample/6d22f7cb6f2954c2c590edeeca956a9b1895d7bd/module-web/src/main/res/drawable-xhdpi/ic_webframe_back_black.png -------------------------------------------------------------------------------- /module-web/src/main/res/drawable-xhdpi/ic_webframe_back_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/panyy/mvvm-jetpack-sample/6d22f7cb6f2954c2c590edeeca956a9b1895d7bd/module-web/src/main/res/drawable-xhdpi/ic_webframe_back_white.png -------------------------------------------------------------------------------- /module-web/src/main/res/drawable/anim_progress.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /module-web/src/main/res/drawable/ic_add_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /module-web/src/main/res/drawable/ic_add_white_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /module-web/src/main/res/drawable/layer_progress_bar_states.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /module-web/src/main/res/drawable/selector_radio_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /module-web/src/main/res/drawable/selector_tab_text.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /module-web/src/main/res/drawable/shape_checked.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 8 | 9 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /module-web/src/main/res/drawable/shape_share_class_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 11 | 12 | -------------------------------------------------------------------------------- /module-web/src/main/res/drawable/shape_unchecked.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 8 | 9 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /module-web/src/main/res/drawable/shape_webframe_dialog_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /module-web/src/main/res/layout/activity_tabpage.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 10 | 11 | 15 | 16 | -------------------------------------------------------------------------------- /module-web/src/main/res/layout/activity_webpage.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 14 | 15 | -------------------------------------------------------------------------------- /module-web/src/main/res/layout/fragment_webpage.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 13 | -------------------------------------------------------------------------------- /module-web/src/main/res/layout/layout_agentweb_error_page.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /module-web/src/main/res/layout/layout_error_page.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /module-web/src/main/res/layout/layout_item_h5_url.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 17 | 18 | 23 | -------------------------------------------------------------------------------- /module-web/src/main/res/layout/layout_loading_view.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 14 | 15 | 20 | 21 | 29 | 30 | -------------------------------------------------------------------------------- /module-web/src/main/res/layout/layout_radiobutton.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | -------------------------------------------------------------------------------- /module-web/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #ffffff 4 | #000000 5 | 6 | #333333 7 | #666666 8 | #999999 9 | #939393 10 | #f0f2f5 11 | #1bb876 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /module-web/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 50dp 5 | -------------------------------------------------------------------------------- /module-web/src/main/res/values/ids.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /module-web/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 该任务已经存在 , 请勿重复点击下载! 3 | 提示 4 | 您正在使用手机流量 , 继续下载该文件吗? 5 | 下载 6 | 取消 7 | 下载失败! 8 | 当前进度:%s 9 | 已下载:%s 10 | 您有一条新通知 11 | 文件下载 12 | 点击打开 13 | 即将开始下载文件 14 | 相机 15 | 文件 16 | 加载中 ... 17 | 您需要离开%s前往其他应用吗? 18 | 离开 19 | 选择的文件不能大于%sMB 20 | 出错啦! 点击空白处刷新 ~ 21 | 22 | -------------------------------------------------------------------------------- /module-web/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 13 | 14 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /module-web/src/main/res/xml/web_files_public.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | include ':module-login' 3 | include ':module-main' 4 | include ':common-core' 5 | include ':common-res' 6 | include ':module-web' --------------------------------------------------------------------------------