├── .gitignore ├── .idea ├── .gitignore ├── codeStyles │ ├── Project.xml │ └── codeStyleConfig.xml ├── compiler.xml ├── gradle.xml ├── inspectionProfiles │ └── Project_Default.xml ├── jarRepositories.xml ├── kotlinc.xml ├── misc.xml └── vcs.xml ├── README.md ├── app ├── .gitignore ├── build.gradle ├── jks │ └── basicLibrary ├── proguard-rules.pro ├── release │ ├── app-release.apk │ └── output-metadata.json └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── peakmain │ │ └── basiclibary │ │ ├── App.kt │ │ ├── MainActivity.kt │ │ ├── activity │ │ └── BehaviorActivity.kt │ │ ├── adapter │ │ └── TestAdapter.kt │ │ ├── fragment │ │ ├── HomeFragment.kt │ │ └── MineFragment.kt │ │ ├── network │ │ ├── DataResponse.java │ │ ├── ProjectTree.java │ │ ├── WanAndroidApi.kt │ │ └── status │ │ │ ├── ApiBaseStatus.kt │ │ │ └── BaseEntityDataRetrofitData.kt │ │ ├── utils │ │ ├── AtPermissionUtils.kt │ │ └── PermissionUtils.kt │ │ └── viewModel │ │ ├── HomeFragmentViewModel.kt │ │ └── MainViewModel.kt │ └── res │ ├── drawable-v24 │ └── ic_launcher_foreground.xml │ ├── drawable │ ├── ic_bottom_navigation_home.xml │ ├── ic_bottom_navigation_me.xml │ ├── ic_launcher_background.xml │ ├── logo.jpg │ └── selector_tab_color.xml │ ├── layout │ ├── activity_behavior.xml │ ├── activity_main.xml │ ├── fragment_home.xml │ ├── fragment_mine.xml │ └── recycler_adpter_test.xml │ ├── menu │ └── bottom_navigation_main.xml │ ├── mipmap-anydpi-v26 │ ├── ic_launcher.xml │ └── ic_launcher_round.xml │ ├── mipmap-hdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ ├── mipmap-mdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ ├── mipmap-xhdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ ├── mipmap-xxhdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ ├── mipmap-xxxhdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ ├── values-night │ └── colors.xml │ └── values │ ├── colors.xml │ ├── strings.xml │ └── styles.xml ├── basicLibrary ├── .gitignore ├── build.gradle ├── consumer-rules.pro ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── peakmain │ │ └── basiclibrary │ │ ├── BasicLibraryProvider.kt │ │ ├── adapter │ │ ├── CommonRecyclerDataBindingAdapter.kt │ │ ├── holder │ │ │ ├── BaseLibraryFooterViewHolder.kt │ │ │ └── BaseLibraryViewHolder.kt │ │ └── listener │ │ │ ├── BaseLibraryOnScrollListener.kt │ │ │ ├── OnItemClickListener.kt │ │ │ └── OnLongClickListener.kt │ │ ├── ainimator │ │ ├── SimpleAnimationListener.kt │ │ └── SimpleAnimatorListener.kt │ │ ├── base │ │ ├── BaseSingleton.kt │ │ ├── IApp.kt │ │ ├── activity │ │ │ └── BaseActivity.kt │ │ ├── fragment │ │ │ └── BaseFragment.kt │ │ └── viewmodel │ │ │ └── BaseViewModel.kt │ │ ├── bean │ │ └── BasicLibraryBeanKt.kt │ │ ├── config │ │ ├── BaseAdapterFooterConfig.kt │ │ ├── BasicLibraryConfig.kt │ │ ├── DefaultAdapterFooterConfig.kt │ │ └── ImageRequestConfig.kt │ │ ├── constants │ │ ├── AndroidVersion.kt │ │ ├── ImageSelectConstants.kt │ │ ├── PermissionConstants.kt │ │ └── PermissionMapConstants.kt │ │ ├── dialog │ │ ├── CustomCenterDialog.kt │ │ └── SubmitLoading.kt │ │ ├── extend │ │ ├── CheckUtils.kt │ │ ├── ClickExtensions.kt │ │ ├── EmptyHandleUtils.kt │ │ ├── RxExtensions.kt │ │ ├── StringExtensions.kt │ │ ├── ThreadExtensions.kt │ │ ├── UtilsExtensions.kt │ │ └── ViewExtensions.kt │ │ ├── helper │ │ ├── AppManagerHelper.kt │ │ ├── BehaviorHelper.kt │ │ ├── ImageSelectorHelper.kt │ │ ├── PermissionHelper.kt │ │ └── RetrofitHelper.kt │ │ ├── image │ │ ├── ImageSelectorFragment.kt │ │ ├── PkImageSelector.kt │ │ ├── SimpleImageSelectorCallback.kt │ │ └── contract │ │ │ ├── SelectMultipleContract.kt │ │ │ ├── SelectSinglePhotoContract.kt │ │ │ └── TakePictureContract.kt │ │ ├── interfaces │ │ ├── IBehaviorHelperCallback.kt │ │ ├── IPermissionPopupListener.kt │ │ ├── IPermissionSetting.kt │ │ ├── OnImageSelectorCallback.kt │ │ └── OnPermissionCallback.kt │ │ ├── manager │ │ ├── AnimationManager.kt │ │ ├── PermissionHandlerManager.kt │ │ └── PhoneStateManager.kt │ │ ├── network │ │ ├── HttpDns.kt │ │ ├── MyX509.java │ │ ├── RetrofitManager.kt │ │ ├── entity │ │ │ └── BaseEntity.java │ │ ├── error │ │ │ └── ErrorEnum.kt │ │ ├── status │ │ │ ├── AbstractRetrofitData.kt │ │ │ ├── ApiStatus.kt │ │ │ ├── BaseApiStatus.kt │ │ │ └── CommonRetrofitData.kt │ │ └── strategy │ │ │ ├── CommonRetrofitStrategy.kt │ │ │ └── IRetrofitStrategy.kt │ │ ├── permission │ │ ├── PermissionSettingFactory.kt │ │ ├── PkPermission.kt │ │ ├── PkPermissionFragment.kt │ │ ├── RequestPermissionContract.kt │ │ ├── interfaces │ │ │ ├── ICall.kt │ │ │ └── IPermissionVersion.kt │ │ ├── setting │ │ │ ├── DefaultPermissionSetting.kt │ │ │ └── NotificationPermissionSetting.kt │ │ └── version │ │ │ ├── AndroidOtherPermissionVersion.kt │ │ │ ├── AndroidPermissionVersionImpl29.kt │ │ │ ├── AndroidPermissionVersionImpl30.kt │ │ │ ├── AndroidPermissionVersionImpl31.kt │ │ │ ├── AndroidPermissionVersionImpl33.kt │ │ │ ├── PermissionRequest.kt │ │ │ ├── RealPermissionVersionCall.kt │ │ │ └── RealPermissionVersionChain.kt │ │ ├── utils │ │ ├── ArithmeticUtils.kt │ │ ├── BasicLibraryUtils.kt │ │ ├── BitmapUtils.kt │ │ ├── FoldableDeviceUtils.kt │ │ ├── GlobalCoroutineExceptionHandler.kt │ │ ├── NotchScreenUtil.kt │ │ ├── OSUtils.kt │ │ ├── StatusBarUtils.java │ │ ├── SystemUtils.kt │ │ ├── ThreadUtils.kt │ │ ├── TimeUtils.kt │ │ ├── WindowUtils.kt │ │ ├── bus │ │ │ └── RxBus.kt │ │ ├── keyboard │ │ │ ├── KeyboardUtils.kt │ │ │ └── OnKeyboardListener.kt │ │ ├── log │ │ │ └── LogFileUtils.kt │ │ ├── mmkv │ │ │ ├── BaseSharedPreferences.kt │ │ │ ├── DefaultSharedPreferencesFactory.kt │ │ │ └── PreferencesUtils.kt │ │ ├── reflect │ │ │ └── ReflectUtils.kt │ │ └── toast │ │ │ ├── PkToastUtils.kt │ │ │ └── TopToastLinearLayout.kt │ │ ├── view │ │ └── BindingView.kt │ │ ├── viewmodel │ │ ├── EmptyViewModel.kt │ │ ├── ImageSelectViewModel.kt │ │ ├── PkPermissionViewModel.kt │ │ └── SameViewModel.kt │ │ └── viewpage │ │ ├── DepthPageTransformer.kt │ │ ├── DepthPageTransformer2.kt │ │ ├── ZoomOutPageTransformer.kt │ │ └── ZoomOutPageTransformer2.kt │ ├── res │ ├── anim │ │ ├── slide_in_from_top.xml │ │ └── slide_out_to_top.xml │ ├── drawable │ │ ├── library_clear_black_24dp.xml │ │ ├── library_done_black_24dp.xml │ │ ├── library_ic_left_black_back.xml │ │ └── library_rotate_progressbar.xml │ ├── layout-v21 │ │ └── layout_submit_loading.xml │ ├── layout │ │ ├── layout_submit_loading.xml │ │ ├── library_dialog_top_toast.xml │ │ ├── library_recycler_foot_layout.xml │ │ └── same_layout.xml │ ├── values │ │ ├── colors.xml │ │ ├── ids.xml │ │ ├── string.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── xml │ │ └── basic_library_provider_paths.xml │ └── resources │ └── META-INF.services │ └── kotlinx.coroutines.CoroutineExceptionHandler ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── jitpack.yml └── settings.gradle.kts /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/caches 5 | /.idea/libraries 6 | /.idea/modules.xml 7 | /.idea/workspace.xml 8 | /.idea/navEditor.xml 9 | /.idea/assetWizardSettings.xml 10 | .DS_Store 11 | /build 12 | /captures 13 | .externalNativeBuild 14 | .cxx 15 | -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | -------------------------------------------------------------------------------- /.idea/codeStyles/codeStyleConfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 19 | 20 | -------------------------------------------------------------------------------- /.idea/inspectionProfiles/Project_Default.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 76 | -------------------------------------------------------------------------------- /.idea/jarRepositories.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 10 | 14 | 15 | 19 | 20 | 24 | 25 | 29 | 30 | 34 | 35 | 39 | 40 | 44 | 45 | -------------------------------------------------------------------------------- /.idea/kotlinc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 9 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # BasicLibrary 2 | - BasicLibrary是基于kotlin+jetpack+mvvm封装的一套框架,提高Android开发效率 3 | - 项目地址:https://github.com/Peakmain/BasicLibrary 4 | - **使用文档链接:** https://github.com/Peakmain/BasicLibrary/wiki 5 | 6 | ### 功能介绍 7 | - Activity Results API实现权限封装 8 | - MMKV的封装 9 | - 防止多次事件的处理 10 | - Retrofit封装实现网络解耦 11 | - 线程的切换,View的抖动效果 12 | - LiveData实现事件分发总线 13 | 14 | 15 | ### 怎样使用 16 | #### Step 1. Add the JitPack repository to your build file 17 | 18 | Add it in your root build.gradle at the end of repositories: 19 | ``` 20 | allprojects { 21 | repositories { 22 | ... 23 | maven { url 'https://jitpack.io' } 24 | } 25 | } 26 | ``` 27 | but If it is a new version of Android studio,Add it in your root setting.gradle at the end of repositories: 28 | ``` 29 | dependencyResolutionManagement { 30 | repositories { 31 | ... 32 | maven { url 'https://jitpack.io' } 33 | } 34 | } 35 | ``` 36 | #### Step 2. Add the dependency 37 | ``` 38 | dependencies { 39 | implementation 'com.github.Peakmain:BasicLibrary:+' 40 | } 41 | ``` 42 | #### 混淆 43 | ``` 44 | -keep class com.peakmain.basiclibrary.permission.PkPermissionFragment { 45 | *; 46 | } 47 | 48 | -keep class com.peakmain.basiclibrary.image.ImageSelectorFragment { 49 | *; 50 | } 51 | ``` 52 | 53 | #### Screenshot 54 | 55 | ![demo](https://user-images.githubusercontent.com/26482737/197705839-b359236e-7e81-40f2-a8de-5d765fcbba22.gif) 56 | 57 | 58 | #### 关于我 59 | - 简书([https://www.jianshu.com/u/3ff32f5aea98](https://www.jianshu.com/u/3ff32f5aea98)) 60 | - 我的GitHub地址([https://github.com/Peakmain](https://links.jianshu.com/go?to=https%3A%2F%2Fgithub.com%2FPeakmain)) 61 | 62 | #### Donations 63 | 如果您觉得我的开源库帮您节省了大量的开发时间,请扫描下方的二维码随意打赏,您的支持将激励我不断前进 64 | ![微信](https://user-images.githubusercontent.com/26482737/184805287-0561a7e2-da13-4ef4-b367-c5e8672c121d.jpg) 65 | ![支付宝](https://user-images.githubusercontent.com/26482737/184805306-f44511a7-7660-4fe1-9f07-305005576c2c.jpg) 66 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | apply plugin: 'kotlin-android' 3 | apply plugin: 'kotlin-kapt' 4 | android { 5 | compileSdkVersion 33 6 | 7 | defaultConfig { 8 | applicationId "com.peakmain.basiclibary" 9 | minSdkVersion 16 10 | targetSdkVersion 33 11 | versionCode 1 12 | versionName "1.0" 13 | // 设置支持multidex 14 | multiDexEnabled true 15 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 16 | } 17 | 18 | buildTypes { 19 | release { 20 | minifyEnabled true 21 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 22 | } 23 | debug{ 24 | minifyEnabled false 25 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 26 | } 27 | } 28 | dataBinding { 29 | enabled = true 30 | } 31 | compileOptions { 32 | sourceCompatibility JavaVersion.VERSION_1_8 33 | targetCompatibility JavaVersion.VERSION_1_8 34 | } 35 | } 36 | 37 | dependencies { 38 | implementation fileTree(dir: "libs", include: ["*.jar"]) 39 | implementation 'androidx.core:core-ktx:1.8.0' 40 | implementation 'androidx.appcompat:appcompat:1.5.0' 41 | implementation 'androidx.constraintlayout:constraintlayout:2.1.4' 42 | implementation project(path: ':basicLibrary') 43 | implementation 'com.github.Peakmain:BasicUI:1.2.9' 44 | //implementation 'com.github.Peakmain:BasicLibrary:1.1.7' 45 | } 46 | -------------------------------------------------------------------------------- /app/jks/basicLibrary: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Peakmain/BasicLibrary/0a5979492abbada1e4802c2172f0286f1ddc072a/app/jks/basicLibrary -------------------------------------------------------------------------------- /app/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 | 23 | # ------------------------1.基本不用动区域-------------------------- 24 | # 保持哪些类不被混淆 25 | -keep public class * extends android.app.Fragment 26 | -keep public class * extends android.app.Activity 27 | -keep public class * extends android.app.Application 28 | -keep public class * extends android.app.Service 29 | -keep public class * extends android.content.BroadcastReceiver 30 | -keep public class * extends android.content.ContentProvider 31 | -keep public class * extends android.preference.Preference 32 | 33 | -keep class com.peakmain.basiclibrary.permission.PkPermissionFragment { 34 | *; 35 | } 36 | 37 | -keep class com.peakmain.basiclibrary.image.ImageSelectorFragment { 38 | *; 39 | } 40 | 41 | -assumenosideeffects class android.util.Log { 42 | public static boolean isLoggable(java.lang.String, int); 43 | public static int v(...); 44 | public static int i(...); 45 | public static int w(...); 46 | public static int d(...); 47 | public static int e(...); 48 | } 49 | # AndroidX 50 | -keep class com.google.android.material.**{*;} 51 | -keep class androidx.**{*;} 52 | -keep public class * extends androidx.** 53 | -keep interface androidx.**{*;} 54 | -keep @androidx.annotation.Keep class * 55 | -keepclassmembers class *{ 56 | @androidx.annotation.Keep *; 57 | } 58 | 59 | -dontwarn com.google.android.material.** 60 | -dontnote com.google.android.material.** 61 | -dontwarn androidx.** 62 | 63 | -------------------------------------------------------------------------------- /app/release/app-release.apk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Peakmain/BasicLibrary/0a5979492abbada1e4802c2172f0286f1ddc072a/app/release/app-release.apk -------------------------------------------------------------------------------- /app/release/output-metadata.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 1, 3 | "artifactType": { 4 | "type": "APK", 5 | "kind": "Directory" 6 | }, 7 | "applicationId": "com.peakmain.basiclibary", 8 | "variantName": "release", 9 | "elements": [ 10 | { 11 | "type": "SINGLE", 12 | "filters": [], 13 | "properties": [], 14 | "versionCode": 1, 15 | "versionName": "1.0", 16 | "enabled": true, 17 | "outputFile": "app-release.apk" 18 | } 19 | ] 20 | } -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 25 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /app/src/main/java/com/peakmain/basiclibary/App.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.basiclibary 2 | 3 | import android.app.Application 4 | import android.content.Context 5 | import androidx.multidex.MultiDex 6 | import com.peakmain.basiclibrary.helper.AppManagerHelper 7 | 8 | /** 9 | * author :Peakmain 10 | * createTime:2021/12/23 11 | * mail:2726449200@qq.com 12 | * describe: 13 | */ 14 | class App : Application() { 15 | override fun attachBaseContext(base: Context?) { 16 | super.attachBaseContext(base) 17 | MultiDex.install(this) 18 | } 19 | override fun onCreate() { 20 | super.onCreate() 21 | } 22 | 23 | } -------------------------------------------------------------------------------- /app/src/main/java/com/peakmain/basiclibary/adapter/TestAdapter.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.basiclibary.adapter 2 | 3 | import androidx.recyclerview.widget.LinearLayoutManager 4 | import com.peakmain.basiclibary.R 5 | import com.peakmain.basiclibary.databinding.RecyclerAdpterTestBinding 6 | import com.peakmain.basiclibrary.adapter.CommonRecyclerDataBindingAdapter 7 | import com.peakmain.basiclibrary.adapter.holder.BaseLibraryViewHolder 8 | import com.peakmain.basiclibrary.config.DefaultAdapterFooterConfig 9 | 10 | /** 11 | * author :Peakmain 12 | * createTime:2022/2/17 13 | * mail:2726449200@qq.com 14 | * describe: 15 | */ 16 | class TestAdapter(data: MutableList) : 17 | CommonRecyclerDataBindingAdapter( 18 | data, 19 | R.layout.recycler_adpter_test, 20 | null//DefaultAdapterFooterConfig(layoutManager).item 21 | ) { 22 | override fun convert( 23 | holder: BaseLibraryViewHolder, 24 | itemData: String, 25 | position: Int 26 | ) { 27 | val binding = holder.itemDataBinding 28 | binding.vm = itemData 29 | } 30 | 31 | } -------------------------------------------------------------------------------- /app/src/main/java/com/peakmain/basiclibary/fragment/MineFragment.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.basiclibary.fragment 2 | 3 | import android.view.View 4 | import com.peakmain.basiclibary.R 5 | import com.peakmain.basiclibary.databinding.FragmentMineBinding 6 | import com.peakmain.basiclibrary.base.fragment.BaseFragment 7 | import com.peakmain.basiclibrary.viewmodel.EmptyViewModel 8 | import com.peakmain.ui.navigationbar.DefaultNavigationBar 9 | 10 | /** 11 | * author :Peakmain 12 | * createTime:2020/3/9 13 | * mail:2726449200@qq.com 14 | * describe: 15 | */ 16 | class MineFragment(override val layoutId: Int = R.layout.fragment_mine) : 17 | BaseFragment() { 18 | override fun initView(fragmentView: View) { 19 | DefaultNavigationBar.Builder(context, fragmentView.findViewById(R.id.view_root)) 20 | .hideLeftText() 21 | .hideRightView() 22 | .setTitleText("我的") 23 | .setToolbarBackgroundColor(R.color.ui_color_01a8e3) 24 | .create() 25 | } 26 | } -------------------------------------------------------------------------------- /app/src/main/java/com/peakmain/basiclibary/network/DataResponse.java: -------------------------------------------------------------------------------- 1 | package com.peakmain.basiclibary.network; 2 | 3 | /** 4 | * @author :Peakmain 5 | * version :1.0 6 | * createTime :2018/10/20 0020 上午 10:28 7 | * mail : 2726449200@qq.com 8 | * describe : 9 | */ 10 | public class DataResponse { 11 | /** 12 | * data : ... 13 | * errorCode : 0 14 | * errorMsg : 15 | */ 16 | private T data; 17 | private int errorCode; 18 | private String errorMsg; 19 | 20 | public T getData() { 21 | return data; 22 | } 23 | 24 | public void setData(T data) { 25 | this.data = data; 26 | } 27 | 28 | public int getErrorCode() { 29 | return errorCode; 30 | } 31 | 32 | public void setErrorCode(int errorCode) { 33 | this.errorCode = errorCode; 34 | } 35 | 36 | public String getErrorMsg() { 37 | return errorMsg; 38 | } 39 | 40 | public void setErrorMsg(String errorMsg) { 41 | this.errorMsg = errorMsg; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /app/src/main/java/com/peakmain/basiclibary/network/ProjectTree.java: -------------------------------------------------------------------------------- 1 | package com.peakmain.basiclibary.network; 2 | 3 | import java.util.List; 4 | 5 | /** 6 | * author :Peakmain 7 | * createTime:2021/12/23 8 | * mail:2726449200@qq.com 9 | * describe: 10 | */ 11 | public class ProjectTree { 12 | 13 | /** 14 | * children : [] 15 | * courseId : 13 16 | * id : 294 17 | * name : 完整项目 18 | * order : 145000 19 | * parentChapterId : 293 20 | * userControlSetTop : false 21 | * visible : 0 22 | */ 23 | 24 | private int courseId; 25 | private int id; 26 | private String name; 27 | private int order; 28 | private int parentChapterId; 29 | private boolean userControlSetTop; 30 | private int visible; 31 | private List children; 32 | 33 | public int getCourseId() { 34 | return courseId; 35 | } 36 | 37 | public void setCourseId(int courseId) { 38 | this.courseId = courseId; 39 | } 40 | 41 | public int getId() { 42 | return id; 43 | } 44 | 45 | public void setId(int id) { 46 | this.id = id; 47 | } 48 | 49 | public String getName() { 50 | return name; 51 | } 52 | 53 | public void setName(String name) { 54 | this.name = name; 55 | } 56 | 57 | public int getOrder() { 58 | return order; 59 | } 60 | 61 | public void setOrder(int order) { 62 | this.order = order; 63 | } 64 | 65 | public int getParentChapterId() { 66 | return parentChapterId; 67 | } 68 | 69 | public void setParentChapterId(int parentChapterId) { 70 | this.parentChapterId = parentChapterId; 71 | } 72 | 73 | public boolean isUserControlSetTop() { 74 | return userControlSetTop; 75 | } 76 | 77 | public void setUserControlSetTop(boolean userControlSetTop) { 78 | this.userControlSetTop = userControlSetTop; 79 | } 80 | 81 | public int getVisible() { 82 | return visible; 83 | } 84 | 85 | public void setVisible(int visible) { 86 | this.visible = visible; 87 | } 88 | 89 | public List getChildren() { 90 | return children; 91 | } 92 | 93 | public void setChildren(List children) { 94 | this.children = children; 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /app/src/main/java/com/peakmain/basiclibary/network/WanAndroidApi.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.basiclibary.network 2 | 3 | import com.peakmain.basiclibrary.network.entity.BaseEntity 4 | import io.reactivex.Observable 5 | import kotlinx.coroutines.flow.Flow 6 | import retrofit2.http.GET 7 | 8 | /** 9 | * @author :Peakmain 10 | * version :1.0 11 | * createTime :2018/11/13 0013 下午 3:59 12 | * mail : 2726449200@qq.com 13 | * describe : 14 | */ 15 | interface WanAndroidApi { 16 | /** 17 | * https://www.wanandroid.com/project/tree/json 18 | */ 19 | @get:GET("project/tree/json") 20 | val projectTree: Observable> 21 | 22 | @get:GET("project/tree/json") 23 | val projectTree1: Observable> 24 | 25 | @get:GET("project/tree/json") 26 | val projectTree2: Flow> 27 | } -------------------------------------------------------------------------------- /app/src/main/java/com/peakmain/basiclibary/network/status/ApiBaseStatus.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.basiclibary.network.status 2 | 3 | import com.peakmain.basiclibrary.network.entity.BaseEntity 4 | import com.peakmain.basiclibrary.network.status.BaseApiStatus 5 | import io.reactivex.Observable 6 | 7 | /** 8 | * author :Peakmain 9 | * createTime:2021/12/23 10 | * mail:2726449200@qq.com 11 | * describe: 12 | */ 13 | abstract class ApiBaseStatus: BaseApiStatus { 14 | abstract fun baseData(entity: T) 15 | 16 | fun tokenError(observable: Observable>?, apiStatus: ApiBaseStatus>) { 17 | 18 | } 19 | } -------------------------------------------------------------------------------- /app/src/main/java/com/peakmain/basiclibary/network/status/BaseEntityDataRetrofitData.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.basiclibary.network.status 2 | 3 | import com.peakmain.basiclibrary.extend.ktxRunOnUiThread 4 | import com.peakmain.basiclibrary.network.entity.BaseEntity 5 | import com.peakmain.basiclibrary.network.error.ErrorEnum 6 | import com.peakmain.basiclibrary.network.status.AbstractRetrofitData 7 | import io.reactivex.Observable 8 | import io.reactivex.android.schedulers.AndroidSchedulers 9 | import io.reactivex.disposables.Disposable 10 | import io.reactivex.schedulers.Schedulers 11 | 12 | /** 13 | * author :Peakmain 14 | * createTime:2022/08/03 15 | * mail:2726449200@qq.com 16 | * describe: 17 | */ 18 | class BaseEntityDataRetrofitData(val apiStatus: ApiBaseStatus>) : 19 | AbstractRetrofitData>(apiStatus) { 20 | override fun createData(observable: Observable>): Disposable { 21 | apiStatus.before() 22 | return observable.subscribeOn(Schedulers.io()) 23 | .observeOn(AndroidSchedulers.mainThread()).subscribe({ t -> 24 | checkResult(observable, t, apiStatus) 25 | }, { exception -> 26 | checkError(exception, apiStatus) 27 | }) 28 | } 29 | 30 | private fun checkError(exception: Throwable, apiStatus: ApiBaseStatus>) { 31 | exception.printStackTrace() 32 | apiStatus.error(Exception(exception)) 33 | } 34 | 35 | private fun checkResult( 36 | observable: Observable>, 37 | t: BaseEntity, 38 | apiStatus: ApiBaseStatus> 39 | ) { 40 | apiStatus.baseData(t) 41 | when (t.result) { 42 | ErrorEnum.SUCCESS -> { 43 | if (t.data != null) { 44 | apiStatus.success(t) 45 | } else { 46 | apiStatus.isEmpty() 47 | } 48 | } 49 | ErrorEnum.TOKEN_ERROR -> { 50 | //token失效 51 | apiStatus.tokenError(observable, apiStatus) 52 | } 53 | else -> { 54 | apiStatus.ktxRunOnUiThread { 55 | error(Exception(t.detail)) 56 | } 57 | } 58 | 59 | } 60 | } 61 | 62 | } -------------------------------------------------------------------------------- /app/src/main/java/com/peakmain/basiclibary/utils/AtPermissionUtils.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.basiclibary.utils 2 | 3 | import android.app.Activity 4 | import com.peakmain.basiclibrary.interfaces.IPermissionPopupListener 5 | import com.peakmain.basiclibrary.utils.toast.PkToastUtils 6 | 7 | /** 8 | * author :Peakmain 9 | * createTime:2024/11/21 10 | * mail:2726449200@qq.com 11 | * describe: 12 | */ 13 | class AtPermissionUtils(val activity: Activity?) { 14 | 15 | val locationListener = createRequestListener( 16 | "位置权限使用说明", 17 | "开启定位权限,为您提供酒店推荐服务。" 18 | ) 19 | 20 | val photoListener = createRequestListener( 21 | "相册权限使用说明", 22 | "开启相册权限,为您提供个人信息头像上传、随手拍、竹居借书、在线客服上传照片与视频、申请差旅合作提供营业执照和联系人证件、上传酒店和零售商品点评照片服务。" 23 | ) 24 | val cameraListener = createRequestListener( 25 | "相机权限使用说明", 26 | "开启相机权限,为您提供个人信息头像上传、随手拍、竹居借书、在线客服上传照片与视频、申请差旅合作提供营业执照和联系人证件、上传酒店和零售商品点评照片服务。" 27 | ) 28 | val storageListener = createRequestListener( 29 | "存储权限说明", 30 | "开启存储权限,帮组您实现更换头像、上传图片、客服沟通服务" 31 | ) 32 | val blueListener = createRequestListener( 33 | "蓝牙权限使用说明", 34 | "开启蓝牙权限,为您识别您周围的门锁设备。" 35 | ) 36 | 37 | private fun createRequestListener(title: String, message: String): IPermissionPopupListener { 38 | return object : IPermissionPopupListener { 39 | private val utils by lazy { 40 | PkToastUtils.build(activity).apply { 41 | setTitle(title) 42 | .setMessage(message) 43 | } 44 | } 45 | 46 | override fun onShowPermissionPopup() { 47 | utils 48 | .show() 49 | } 50 | 51 | override fun onHidePermissionPopup() { 52 | utils.dismiss() 53 | } 54 | 55 | } 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /app/src/main/java/com/peakmain/basiclibary/viewModel/HomeFragmentViewModel.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.basiclibary.viewModel 2 | 3 | import android.util.Log 4 | import android.view.View 5 | import com.peakmain.basiclibary.network.DataResponse 6 | import com.peakmain.basiclibary.network.ProjectTree 7 | import com.peakmain.basiclibary.network.WanAndroidApi 8 | import com.peakmain.basiclibrary.base.viewmodel.BaseViewModel 9 | import com.peakmain.basiclibrary.network.RetrofitManager 10 | import com.peakmain.basiclibrary.network.entity.BaseEntity 11 | import com.peakmain.basiclibary.network.status.ApiBaseStatus 12 | import com.peakmain.basiclibrary.network.status.ApiStatus 13 | import com.peakmain.basiclibary.network.status.BaseEntityDataRetrofitData 14 | 15 | /** 16 | * author :Peakmain 17 | * createTime:2021/12/27 18 | * mail:2726449200@qq.com 19 | * describe: 20 | */ 21 | class HomeFragmentViewModel : BaseViewModel() { 22 | private lateinit var api: WanAndroidApi 23 | val REQUEST_BASE_URL = "https://wanandroid.com/" 24 | val delayTime = 1000L 25 | override fun initModel() { 26 | api = RetrofitManager.createService(WanAndroidApi::class.java, REQUEST_BASE_URL) 27 | } 28 | 29 | val isShow = false 30 | fun getProjectTree() { 31 | 32 | RetrofitManager.createData(api.projectTree, 33 | object : ApiStatus>() { 34 | 35 | override fun success(t: DataResponse) { 36 | Log.e("TAG", t.toString()) 37 | } 38 | 39 | override fun error(exception: Exception) { 40 | } 41 | 42 | 43 | }) 44 | /* RetrofitManager.createData(api.projectTree1, BaseEntityDataRetrofitData(object : 45 | ApiBaseStatus>(){ 46 | override fun baseData(entity: BaseEntity) { 47 | TODO("Not yet implemented") 48 | } 49 | 50 | override fun before() { 51 | TODO("Not yet implemented") 52 | } 53 | 54 | override fun success(t: BaseEntity) { 55 | TODO("Not yet implemented") 56 | } 57 | 58 | override fun isEmpty() { 59 | TODO("Not yet implemented") 60 | } 61 | 62 | override fun loadMore(t: BaseEntity, isRefresh: Boolean) { 63 | TODO("Not yet implemented") 64 | } 65 | 66 | override fun error(exception: java.lang.Exception) { 67 | TODO("Not yet implemented") 68 | } 69 | 70 | }) ) 71 | RetrofitManager.createData(api.projectTree, { 72 | //todo before() 73 | }, { 74 | //todo success( 75 | }, { 76 | //todo error() 77 | })*/ 78 | } 79 | 80 | 81 | fun clickListener(view: View) { 82 | } 83 | 84 | } -------------------------------------------------------------------------------- /app/src/main/java/com/peakmain/basiclibary/viewModel/MainViewModel.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.basiclibary.viewModel 2 | 3 | import com.peakmain.basiclibrary.base.viewmodel.BaseViewModel 4 | 5 | /** 6 | * author :Peakmain 7 | * createTime:2022/09/02 8 | * mail:2726449200@qq.com 9 | * describe: 10 | */ 11 | class MainViewModel:BaseViewModel() { 12 | override fun initModel() { 13 | 14 | } 15 | } -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 15 | 18 | 21 | 22 | 23 | 24 | 30 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_bottom_navigation_home.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_bottom_navigation_me.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/logo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Peakmain/BasicLibrary/0a5979492abbada1e4802c2172f0286f1ddc072a/app/src/main/res/drawable/logo.jpg -------------------------------------------------------------------------------- /app/src/main/res/drawable/selector_tab_color.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_behavior.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 11 | 12 | 21 | 22 | 23 | 32 | 33 | 39 | 40 | 49 | 50 | 59 | 60 | 69 | 70 | 87 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 12 | 13 | 20 | 21 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_home.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 10 | 11 | 12 | 17 | 18 | 25 | 26 | 37 | 38 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_mine.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 14 | 15 | 21 | 22 | 31 | 32 | 41 | 42 | 51 | 52 | -------------------------------------------------------------------------------- /app/src/main/res/layout/recycler_adpter_test.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 8 | 9 | 10 | 13 | 14 | 21 | 22 | -------------------------------------------------------------------------------- /app/src/main/res/menu/bottom_navigation_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 11 | 12 | -------------------------------------------------------------------------------- /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/Peakmain/BasicLibrary/0a5979492abbada1e4802c2172f0286f1ddc072a/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Peakmain/BasicLibrary/0a5979492abbada1e4802c2172f0286f1ddc072a/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Peakmain/BasicLibrary/0a5979492abbada1e4802c2172f0286f1ddc072a/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Peakmain/BasicLibrary/0a5979492abbada1e4802c2172f0286f1ddc072a/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Peakmain/BasicLibrary/0a5979492abbada1e4802c2172f0286f1ddc072a/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Peakmain/BasicLibrary/0a5979492abbada1e4802c2172f0286f1ddc072a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Peakmain/BasicLibrary/0a5979492abbada1e4802c2172f0286f1ddc072a/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Peakmain/BasicLibrary/0a5979492abbada1e4802c2172f0286f1ddc072a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Peakmain/BasicLibrary/0a5979492abbada1e4802c2172f0286f1ddc072a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Peakmain/BasicLibrary/0a5979492abbada1e4802c2172f0286f1ddc072a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/values-night/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #ffffff 4 | #ffffff 5 | #ffffff 6 | #ffffff 7 | #FFFFFF 8 | #ffffff 9 | #ffffff 10 | #ffffff 11 | #ffffff 12 | #ffffff 13 | -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #008577 4 | #00574B 5 | #921241 6 | #D81B60 7 | #FFFFFF 8 | #F117D4 9 | #d1d1d1 10 | #F5F5F5 11 | #7D7D7D 12 | #999999 13 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | BasicLibary 3 | Peakmain 4 | Github:https://github.com/Peakmain 5 | 简书:https://www.jianshu.com/u/3ff32f5aea98 6 | 7 | 首页 8 | 9 | 我的 10 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 10 | 11 | -------------------------------------------------------------------------------- /basicLibrary/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /basicLibrary/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | apply plugin: 'kotlin-android' 3 | apply plugin: 'kotlin-kapt' 4 | android { 5 | compileSdkVersion 33 6 | 7 | defaultConfig { 8 | minSdkVersion 16 9 | targetSdkVersion 33 10 | versionCode 1 11 | versionName "1.0" 12 | 13 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 14 | consumerProguardFiles "consumer-rules.pro" 15 | 16 | } 17 | 18 | buildTypes { 19 | release { 20 | minifyEnabled false 21 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 22 | } 23 | 24 | } 25 | buildFeatures { 26 | dataBinding true 27 | } 28 | packagingOptions { 29 | exclude 'AndroidManifest.xml' 30 | } 31 | } 32 | dependencies { 33 | implementation fileTree(dir: "libs", include: ["*.jar"]) 34 | implementation('androidx.core:core-ktx:1.8.0') { 35 | transitive false 36 | } 37 | implementation 'androidx.appcompat:appcompat:1.5.0' 38 | api('org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.1') { 39 | transitive false 40 | } 41 | api('org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.1') { 42 | transitive false 43 | } 44 | 45 | //OkHttp3 46 | api 'com.squareup.okhttp3:logging-interceptor:3.12.0' 47 | //Retrofit网络请求 48 | api("com.squareup.retrofit2:converter-gson:2.6.2") { 49 | exclude group: "com.squareup.okhttp3", module: "okhttp" 50 | } 51 | api('com.squareup.retrofit2:adapter-rxjava2:2.4.0') { 52 | exclude group: "com.squareup.retrofit2", module: "retrofit" 53 | } 54 | api("com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2") { 55 | transitive false 56 | } 57 | api "io.reactivex.rxjava2:rxandroid:2.1.1" 58 | api 'com.tencent:mmkv:1.2.11' 59 | implementation 'androidx.cardview:cardview:1.0.0' 60 | 61 | kapt "com.android.databinding:compiler:3.1.4" 62 | api 'androidx.recyclerview:recyclerview:1.2.1' 63 | api 'com.google.android.material:material:1.6.1' 64 | implementation 'com.github.Peakmain:BasicUI:1.2.11' 65 | api 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.4.0' 66 | implementation 'com.qiniu:happy-dns:0.2.13' 67 | 68 | } 69 | -------------------------------------------------------------------------------- /basicLibrary/consumer-rules.pro: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Peakmain/BasicLibrary/0a5979492abbada1e4802c2172f0286f1ddc072a/basicLibrary/consumer-rules.pro -------------------------------------------------------------------------------- /basicLibrary/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 -------------------------------------------------------------------------------- /basicLibrary/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 10 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /basicLibrary/src/main/java/com/peakmain/basiclibrary/BasicLibraryProvider.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.basiclibrary 2 | 3 | import android.app.Application 4 | import androidx.core.content.FileProvider 5 | import androidx.lifecycle.ViewModelStore 6 | import com.peakmain.basiclibrary.base.IApp 7 | import com.peakmain.basiclibrary.config.BasicLibraryConfig 8 | 9 | 10 | /** 11 | * author :Peakmain 12 | * createTime:2021/12/27 13 | * mail:2726449200@qq.com 14 | * describe: 15 | */ 16 | class BasicLibraryProvider : FileProvider(), IApp { 17 | private lateinit var viewModelStore: ViewModelStore 18 | override fun onCreate(): Boolean { 19 | BasicLibraryConfig.getInstance()?.setApp(this) 20 | viewModelStore = ViewModelStore() 21 | return true 22 | } 23 | 24 | override fun getApplication(): Application { 25 | return context?.applicationContext as Application 26 | } 27 | 28 | override fun getViewModelStore(): ViewModelStore { 29 | return viewModelStore 30 | } 31 | 32 | } -------------------------------------------------------------------------------- /basicLibrary/src/main/java/com/peakmain/basiclibrary/adapter/holder/BaseLibraryFooterViewHolder.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.basiclibrary.adapter.holder 2 | 3 | import androidx.databinding.ViewDataBinding 4 | 5 | /** 6 | * author :Peakmain 7 | * createTime:2022/2/17 8 | * mail:2726449200@qq.com 9 | * describe: 10 | */ 11 | open class BaseLibraryFooterViewHolder constructor(itemDataBinding: E) : 12 | BaseLibraryViewHolder(itemDataBinding) -------------------------------------------------------------------------------- /basicLibrary/src/main/java/com/peakmain/basiclibrary/adapter/holder/BaseLibraryViewHolder.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.basiclibrary.adapter.holder 2 | 3 | import androidx.databinding.ViewDataBinding 4 | import androidx.recyclerview.widget.RecyclerView 5 | 6 | /** 7 | * author :Peakmain 8 | * createTime:2022/2/17 9 | * mail:2726449200@qq.com 10 | * describe: 11 | */ 12 | open class BaseLibraryViewHolder constructor(var itemDataBinding: E) : 13 | RecyclerView.ViewHolder(itemDataBinding.root) -------------------------------------------------------------------------------- /basicLibrary/src/main/java/com/peakmain/basiclibrary/adapter/listener/BaseLibraryOnScrollListener.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.basiclibrary.adapter.listener 2 | 3 | import androidx.recyclerview.widget.LinearLayoutManager 4 | import androidx.recyclerview.widget.RecyclerView 5 | 6 | /** 7 | * author :Peakmain 8 | * createTime:2022/2/17 9 | * mail:2726449200@qq.com 10 | * describe: 11 | */ 12 | abstract class BaseLibraryOnScrollListener constructor() : RecyclerView.OnScrollListener(),OnScrollCallback { 13 | 14 | private var mLinearLayoutManager: LinearLayoutManager? = null 15 | 16 | constructor( 17 | linearLayoutManager: LinearLayoutManager 18 | ) : this() { 19 | this.mLinearLayoutManager = linearLayoutManager 20 | } 21 | 22 | override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) { 23 | super.onScrolled(recyclerView, dx, dy) 24 | if (dy > 0) { 25 | onScrolledUp() 26 | mLinearLayoutManager?.apply { 27 | val findLastVisibleItemPosition = findLastVisibleItemPosition() 28 | val itemCount = itemCount 29 | if(findLastVisibleItemPosition==itemCount-1){ 30 | onLoadMore() 31 | } 32 | } 33 | }else{ 34 | onScrolledDown() 35 | } 36 | } 37 | abstract fun onLoadMore() 38 | override fun onScrolledUp() { 39 | 40 | } 41 | 42 | override fun onScrolledDown() { 43 | 44 | } 45 | } 46 | 47 | interface OnScrollCallback { 48 | fun onScrolledUp() 49 | fun onScrolledDown() 50 | } -------------------------------------------------------------------------------- /basicLibrary/src/main/java/com/peakmain/basiclibrary/adapter/listener/OnItemClickListener.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.basiclibrary.adapter.listener 2 | 3 | /** 4 | * author :Peakmain 5 | * version : 1.0 6 | * createTime:2019/2/25 7 | * mail:2726449200@qq.com 8 | * describe:Adapter条目的点击事件 9 | */ 10 | interface OnItemClickListener { 11 | fun onItemClick(position: Int) 12 | } -------------------------------------------------------------------------------- /basicLibrary/src/main/java/com/peakmain/basiclibrary/adapter/listener/OnLongClickListener.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.basiclibrary.adapter.listener 2 | 3 | /** 4 | * author :Peakmain 5 | * version : 1.0 6 | * createTime:2019/2/25 7 | * mail:2726449200@qq.com 8 | * describe:Adapter条目的长按事件 9 | */ 10 | interface OnLongClickListener { 11 | fun onLongClick(position: Int): Boolean 12 | } -------------------------------------------------------------------------------- /basicLibrary/src/main/java/com/peakmain/basiclibrary/ainimator/SimpleAnimationListener.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.basiclibrary.ainimator 2 | 3 | import android.view.animation.Animation 4 | 5 | /** 6 | * author :Peakmain 7 | * createTime:2023/9/19 8 | * mail:2726449200@qq.com 9 | * describe: 10 | */ 11 | open class SimpleAnimationListener : Animation.AnimationListener { 12 | override fun onAnimationStart(animation: Animation?) { 13 | 14 | } 15 | 16 | override fun onAnimationEnd(animation: Animation?) { 17 | } 18 | 19 | override fun onAnimationRepeat(animation: Animation?) { 20 | } 21 | } -------------------------------------------------------------------------------- /basicLibrary/src/main/java/com/peakmain/basiclibrary/ainimator/SimpleAnimatorListener.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.basiclibrary.ainimator 2 | 3 | import android.animation.Animator 4 | 5 | /** 6 | * author :Peakmain 7 | * createTime:2023/9/19 8 | * mail:2726449200@qq.com 9 | * describe: 10 | */ 11 | open class SimpleAnimatorListener : Animator.AnimatorListener { 12 | override fun onAnimationStart(animation: Animator) { 13 | 14 | } 15 | 16 | override fun onAnimationEnd(animation: Animator) { 17 | } 18 | 19 | override fun onAnimationCancel(animation: Animator) { 20 | } 21 | 22 | override fun onAnimationRepeat(animation: Animator) { 23 | } 24 | } -------------------------------------------------------------------------------- /basicLibrary/src/main/java/com/peakmain/basiclibrary/base/BaseSingleton.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.basiclibrary.base 2 | 3 | /** 4 | * author :Peakmain 5 | * createTime:2022/4/22 6 | * mail:2726449200@qq.com 7 | * describe: 8 | */ 9 | 10 | abstract class BaseEmptySingleton { 11 | @Volatile 12 | private var sInstance: T? = null 13 | protected abstract val createSingleton :()->T 14 | fun getInstance(): T? { 15 | sInstance ?: synchronized(this) { 16 | sInstance ?: createSingleton().also { 17 | sInstance = it 18 | } 19 | } 20 | return sInstance 21 | } 22 | } 23 | 24 | abstract class BaseOneSingleton { 25 | @Volatile 26 | private var sInstance: T? = null 27 | protected abstract fun createSingleton(params:P):T 28 | fun getInstance(params: P): T? { 29 | sInstance ?: synchronized(this) { 30 | sInstance ?: createSingleton(params).also { 31 | sInstance = it 32 | } 33 | } 34 | return sInstance 35 | } 36 | } 37 | 38 | abstract class BaseTwoSingleton { 39 | @Volatile 40 | private var sInstance: T? = null 41 | protected abstract fun createSingleton(params1: P1, params2: P2): T? 42 | fun getInstance(params1: P1, params2: P2): T? { 43 | sInstance ?: synchronized(this) { 44 | sInstance ?: createSingleton(params1, params2).also { 45 | sInstance = it 46 | } 47 | } 48 | return sInstance 49 | } 50 | } -------------------------------------------------------------------------------- /basicLibrary/src/main/java/com/peakmain/basiclibrary/base/IApp.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.basiclibrary.base 2 | 3 | import android.app.Application 4 | import androidx.lifecycle.ViewModelProvider 5 | import androidx.lifecycle.ViewModelStore 6 | 7 | /** 8 | * author :Peakmain 9 | * createTime:2021/12/24 10 | * mail:2726449200@qq.com 11 | * describe: 12 | */ 13 | interface IApp { 14 | fun getViewModelProvider(): ViewModelProvider { 15 | val factory = ViewModelProvider.AndroidViewModelFactory.getInstance(getApplication()) 16 | return ViewModelProvider(getViewModelStore(), factory) 17 | } 18 | 19 | fun getApplication(): Application 20 | fun getViewModelStore(): ViewModelStore 21 | } -------------------------------------------------------------------------------- /basicLibrary/src/main/java/com/peakmain/basiclibrary/base/activity/BaseActivity.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.basiclibrary.base.activity 2 | 3 | import android.os.Bundle 4 | import androidx.appcompat.app.AppCompatActivity 5 | import androidx.databinding.DataBindingUtil 6 | import androidx.databinding.ViewDataBinding 7 | import androidx.lifecycle.ViewModel 8 | import com.peakmain.basiclibrary.BR 9 | import com.peakmain.basiclibrary.base.IApp 10 | import com.peakmain.basiclibrary.base.viewmodel.BaseViewModel 11 | import com.peakmain.basiclibrary.config.BasicLibraryConfig 12 | import java.lang.reflect.ParameterizedType 13 | 14 | /** 15 | * author :Peakmain 16 | * createTime:2021/12/24 17 | * mail:2726449200@qq.com 18 | * describe: 19 | */ 20 | abstract class BaseActivity : 21 | AppCompatActivity() { 22 | abstract val layoutId: Int 23 | protected lateinit var mBinding: T 24 | protected lateinit var mViewModel: E 25 | private var app: IApp? = BasicLibraryConfig.getInstance()?.getApp() 26 | 27 | 28 | override fun onCreate(savedInstanceState: Bundle?) { 29 | super.onCreate(savedInstanceState) 30 | initBefore() 31 | mBinding = DataBindingUtil.setContentView(this, layoutId) 32 | initViewModel() 33 | mViewModel.initModel() 34 | mBinding.setVariable(BR.vm, mViewModel) 35 | mBinding.lifecycleOwner = this 36 | initView() 37 | } 38 | 39 | private fun initViewModel() { 40 | val superClass = javaClass.genericSuperclass 41 | if (superClass is ParameterizedType) { 42 | val type = superClass.actualTypeArguments[1] 43 | val clazz = type as Class 44 | mViewModel = getViewModel(clazz) 45 | }else{ 46 | throw IllegalArgumentException("ParameterizedType error") 47 | } 48 | 49 | } 50 | 51 | 52 | abstract fun initView() 53 | 54 | 55 | open fun initBefore() { 56 | } 57 | 58 | protected fun getViewModel(modelClass: Class): E { 59 | if (app == null) { 60 | throw NullPointerException("app must not be null") 61 | } 62 | return app!!.getViewModelProvider()[modelClass] 63 | } 64 | } -------------------------------------------------------------------------------- /basicLibrary/src/main/java/com/peakmain/basiclibrary/base/fragment/BaseFragment.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.basiclibrary.base.fragment 2 | 3 | import android.os.Bundle 4 | import android.util.Log 5 | import android.view.LayoutInflater 6 | import android.view.View 7 | import android.view.ViewGroup 8 | import androidx.databinding.DataBindingUtil 9 | import androidx.databinding.ViewDataBinding 10 | import androidx.fragment.app.Fragment 11 | import androidx.lifecycle.ViewModel 12 | import com.peakmain.basiclibrary.BR 13 | import com.peakmain.basiclibrary.base.IApp 14 | import com.peakmain.basiclibrary.base.viewmodel.BaseViewModel 15 | import com.peakmain.basiclibrary.config.BasicLibraryConfig 16 | import java.lang.reflect.ParameterizedType 17 | 18 | /** 19 | * author :Peakmain 20 | * createTime:2021/12/27 21 | * mail:2726449200@qq.com 22 | * describe: 23 | */ 24 | abstract class BaseFragment : 25 | Fragment() { 26 | companion object { 27 | private val TAG = 28 | BaseFragment::class.java.superclass?.simpleName ?: BaseFragment::class.java.simpleName 29 | } 30 | 31 | protected lateinit var mViewModel: E 32 | protected lateinit var mBinding: T 33 | private var app: IApp? = BasicLibraryConfig.getInstance()?.getApp() 34 | override fun onCreateView( 35 | inflater: LayoutInflater, 36 | container: ViewGroup?, 37 | savedInstanceState: Bundle? 38 | ): View? { 39 | val fragmentView = inflater.inflate(layoutId, container, false) 40 | initViewModel(fragmentView) 41 | 42 | initView(fragmentView) 43 | return fragmentView 44 | } 45 | 46 | private fun initViewModel(fragmentView: View) { 47 | val genericSuperclass = javaClass.genericSuperclass 48 | var modelClass: Class? = null 49 | if (genericSuperclass is ParameterizedType) { 50 | val type = genericSuperclass.actualTypeArguments[1] 51 | modelClass = type as Class 52 | } else { 53 | Log.e(TAG, "initViewModel init error!!") 54 | } 55 | if (modelClass != null) { 56 | mViewModel = getViewModel(modelClass) 57 | mBinding = DataBindingUtil.bind(fragmentView)!! 58 | mBinding.setVariable(BR.vm, mViewModel) 59 | mBinding.lifecycleOwner=this 60 | mViewModel.initModel() 61 | } 62 | } 63 | 64 | protected fun getViewModel(modelClass: Class): T { 65 | if (app == null) { 66 | throw NullPointerException("app must not be null") 67 | } 68 | return app!!.getViewModelProvider()[modelClass] 69 | } 70 | 71 | abstract val layoutId: Int 72 | abstract fun initView(fragmentView: View) 73 | } -------------------------------------------------------------------------------- /basicLibrary/src/main/java/com/peakmain/basiclibrary/base/viewmodel/BaseViewModel.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.basiclibrary.base.viewmodel 2 | 3 | import androidx.lifecycle.ViewModel 4 | 5 | /** 6 | * author :Peakmain 7 | * createTime:2021/12/24 8 | * mail:2726449200@qq.com 9 | * describe: 10 | */ 11 | abstract class BaseViewModel: ViewModel() { 12 | abstract fun initModel() 13 | } -------------------------------------------------------------------------------- /basicLibrary/src/main/java/com/peakmain/basiclibrary/bean/BasicLibraryBeanKt.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.basiclibrary.bean 2 | 3 | import android.graphics.drawable.Drawable 4 | 5 | /** 6 | * author :Peakmain 7 | * createTime:2022/3/8 8 | * mail:2726449200@qq.com 9 | * describe: 10 | */ 11 | data class AppManagerBean( 12 | val packageName: String, 13 | val appName: String, 14 | val appIcon: Drawable, 15 | val firstRunName: String, 16 | val isSystemApp: Boolean 17 | ) -------------------------------------------------------------------------------- /basicLibrary/src/main/java/com/peakmain/basiclibrary/config/BaseAdapterFooterConfig.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.basiclibrary.config 2 | 3 | import android.view.ViewGroup 4 | import androidx.databinding.ViewDataBinding 5 | import androidx.recyclerview.widget.LinearLayoutManager 6 | import com.peakmain.basiclibrary.adapter.holder.BaseLibraryFooterViewHolder 7 | 8 | /** 9 | * author :Peakmain 10 | * createTime:2022/2/17 11 | * mail:2726449200@qq.com 12 | * describe:显示更多的Config 13 | */ 14 | interface BaseAdapterFooterConfig { 15 | fun footerDataBinding(parent: ViewGroup): E 16 | fun footerViewHolder(holder: BaseLibraryFooterViewHolder,data:MutableList,loadStatus:Int) 17 | fun layoutManager(): LinearLayoutManager 18 | } -------------------------------------------------------------------------------- /basicLibrary/src/main/java/com/peakmain/basiclibrary/config/BasicLibraryConfig.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.basiclibrary.config 2 | 3 | import com.peakmain.basiclibrary.base.BaseEmptySingleton 4 | import com.peakmain.basiclibrary.base.IApp 5 | 6 | /** 7 | * author :Peakmain 8 | * createTime:2021/12/27 9 | * mail:2726449200@qq.com 10 | * describe:全局的配置 11 | */ 12 | class BasicLibraryConfig private constructor() { 13 | private var mApp: IApp? = null 14 | 15 | companion object:BaseEmptySingleton(){ 16 | override val createSingleton=::BasicLibraryConfig 17 | } 18 | 19 | fun setApp(app: IApp) { 20 | this.mApp = app 21 | } 22 | 23 | fun getApp(): IApp? { 24 | return mApp 25 | } 26 | } -------------------------------------------------------------------------------- /basicLibrary/src/main/java/com/peakmain/basiclibrary/config/DefaultAdapterFooterConfig.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.basiclibrary.config 2 | 3 | import android.view.LayoutInflater 4 | import android.view.ViewGroup 5 | import androidx.databinding.DataBindingUtil 6 | import androidx.databinding.ViewDataBinding 7 | import androidx.recyclerview.widget.LinearLayoutManager 8 | import com.peakmain.basiclibrary.R 9 | import com.peakmain.basiclibrary.adapter.CommonRecyclerDataBindingAdapter 10 | import com.peakmain.basiclibrary.adapter.holder.BaseLibraryFooterViewHolder 11 | import com.peakmain.basiclibrary.databinding.LibraryRecyclerFootLayoutBinding 12 | 13 | /** 14 | * author :Peakmain 15 | * createTime:2022/2/17 16 | * mail:2726449200@qq.com 17 | * describe: 18 | */ 19 | class DefaultAdapterFooterConfig( 20 | var layoutManager: LinearLayoutManager, 21 | var loadContent: String = "正在加载中...", 22 | var loadCompleteContent: String = "加载完成", 23 | var loadNoMoreContent: String = "没有更多了", 24 | var emptyContent: String = "暂无内容" 25 | ) { 26 | 27 | val item = object : BaseAdapterFooterConfig { 28 | override fun footerDataBinding(parent: ViewGroup): E { 29 | return DataBindingUtil.inflate( 30 | LayoutInflater.from(parent.context), 31 | R.layout.library_recycler_foot_layout, 32 | parent, 33 | false 34 | ) 35 | } 36 | 37 | override fun footerViewHolder( 38 | holder: BaseLibraryFooterViewHolder, 39 | data: MutableList, 40 | loadStatus: Int 41 | ) { 42 | val dataBinding = holder.itemDataBinding as LibraryRecyclerFootLayoutBinding 43 | when (loadStatus) { 44 | CommonRecyclerDataBindingAdapter.STATUS_LOADING -> { 45 | dataBinding.progress = true 46 | dataBinding.content = loadContent 47 | } 48 | CommonRecyclerDataBindingAdapter.STATUS_COMPLETE -> { 49 | dataBinding.progress = false 50 | dataBinding.content = loadCompleteContent 51 | } 52 | CommonRecyclerDataBindingAdapter.STATUS_NO_MORE -> { 53 | dataBinding.progress = false 54 | dataBinding.content = if (data.isEmpty()) emptyContent else loadNoMoreContent 55 | } 56 | } 57 | } 58 | 59 | override fun layoutManager(): LinearLayoutManager { 60 | return layoutManager 61 | } 62 | } 63 | } -------------------------------------------------------------------------------- /basicLibrary/src/main/java/com/peakmain/basiclibrary/config/ImageRequestConfig.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.basiclibrary.config 2 | 3 | import androidx.fragment.app.Fragment 4 | import androidx.fragment.app.FragmentActivity 5 | import com.peakmain.basiclibrary.constants.ImageSelectConstants 6 | import com.peakmain.basiclibrary.interfaces.OnImageSelectorCallback 7 | import java.io.Serializable 8 | 9 | /** 10 | * author :Peakmain 11 | * createTime:2022/08/18 12 | * mail:2726449200@qq.com 13 | * describe: 14 | */ 15 | class ImageRequestConfig : Serializable { 16 | //最多选择图片的数量 17 | var maxNum: Int = 1 18 | 19 | //默认是单选 20 | var isSingle: Boolean = true 21 | 22 | //默认是图片类型 23 | var imageType: Int = ImageSelectConstants.IMAGE_TYPE 24 | } 25 | 26 | internal data class ImageContext( 27 | var fragment: Fragment? = null, 28 | var activity: FragmentActivity? = null, 29 | var onImageSelectorCallback: OnImageSelectorCallback? = null 30 | ) -------------------------------------------------------------------------------- /basicLibrary/src/main/java/com/peakmain/basiclibrary/constants/ImageSelectConstants.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.basiclibrary.constants 2 | 3 | import androidx.annotation.IntDef 4 | 5 | /** 6 | * author :Peakmain 7 | * createTime:2022/08/18 8 | * mail:2726449200@qq.com 9 | * describe: 10 | */ 11 | object ImageSelectConstants { 12 | const val REQUEST_CONFIG: String = "requestConfig" 13 | const val TAKE_PHOTO_TYPE = 0 14 | const val IMAGE_TYPE = 1 15 | const val VIDEO_TYPE = 2 16 | const val ALL_TYPE = 3 17 | 18 | @IntDef(TAKE_PHOTO_TYPE, IMAGE_TYPE, VIDEO_TYPE, ALL_TYPE) 19 | @Retention(AnnotationRetention.SOURCE) 20 | annotation class ImageSelectType 21 | 22 | 23 | } -------------------------------------------------------------------------------- /basicLibrary/src/main/java/com/peakmain/basiclibrary/constants/PermissionMapConstants.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.basiclibrary.constants 2 | 3 | import android.Manifest 4 | import androidx.annotation.StringDef 5 | 6 | /** 7 | * author :Peakmain 8 | * createTime:2024/11/21 9 | * mail:2726449200@qq.com 10 | * describe: 11 | */ 12 | object PermissionMapConstants { 13 | val dangerousPermissionTagMap = mapOf( 14 | // 日历权限 15 | Manifest.permission.READ_CALENDAR to "calendar", 16 | Manifest.permission.WRITE_CALENDAR to "calendar", 17 | 18 | // 相机权限 19 | Manifest.permission.CAMERA to "camera", 20 | 21 | // 联系人权限 22 | Manifest.permission.READ_CONTACTS to "contacts", 23 | Manifest.permission.WRITE_CONTACTS to "contacts", 24 | Manifest.permission.GET_ACCOUNTS to "contacts", 25 | 26 | // 位置权限 27 | Manifest.permission.ACCESS_FINE_LOCATION to "location", 28 | Manifest.permission.ACCESS_COARSE_LOCATION to "location", 29 | 30 | // 麦克风权限 31 | Manifest.permission.RECORD_AUDIO to "microphone", 32 | 33 | // 电话权限 34 | Manifest.permission.READ_PHONE_STATE to "phone", 35 | Manifest.permission.CALL_PHONE to "phone", 36 | Manifest.permission.READ_CALL_LOG to "phone", 37 | Manifest.permission.WRITE_CALL_LOG to "phone", 38 | Manifest.permission.ADD_VOICEMAIL to "phone", 39 | Manifest.permission.USE_SIP to "phone", 40 | Manifest.permission.PROCESS_OUTGOING_CALLS to "phone", 41 | 42 | // 传感器权限 43 | Manifest.permission.BODY_SENSORS to "sensors", 44 | 45 | // 短信权限 46 | Manifest.permission.SEND_SMS to "sms", 47 | Manifest.permission.RECEIVE_SMS to "sms", 48 | Manifest.permission.READ_SMS to "sms", 49 | Manifest.permission.RECEIVE_WAP_PUSH to "sms", 50 | Manifest.permission.RECEIVE_MMS to "sms", 51 | 52 | // 存储权限 53 | Manifest.permission.READ_EXTERNAL_STORAGE to "storage", 54 | Manifest.permission.WRITE_EXTERNAL_STORAGE to "storage", 55 | 56 | //蓝牙 57 | Manifest.permission.BLUETOOTH_CONNECT to "blue", 58 | Manifest.permission.BLUETOOTH_SCAN to "blue", 59 | ) 60 | 61 | @StringDef( 62 | PermissionTag.CALENDAR, 63 | PermissionTag.CAMERA, 64 | PermissionTag.CONTACTS, 65 | PermissionTag.LOCATION, 66 | PermissionTag.MICROPHONE, 67 | PermissionTag.PHONE, 68 | PermissionTag.SENSORS, 69 | PermissionTag.SMS, 70 | PermissionTag.STORAGE, 71 | PermissionTag.BLUE, 72 | ) 73 | @Retention(AnnotationRetention.SOURCE) 74 | annotation class PermissionTag { 75 | companion object { 76 | const val CALENDAR = "calendar" 77 | const val CAMERA = "camera" 78 | const val CONTACTS = "contacts" 79 | const val LOCATION = "location" 80 | const val MICROPHONE = "microphone" 81 | const val PHONE = "phone" 82 | const val SENSORS = "sensors" 83 | const val SMS = "sms" 84 | const val STORAGE = "storage" 85 | const val BLUE = "blue" 86 | } 87 | } 88 | 89 | 90 | } -------------------------------------------------------------------------------- /basicLibrary/src/main/java/com/peakmain/basiclibrary/dialog/CustomCenterDialog.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.basiclibrary.dialog 2 | 3 | import android.app.Dialog 4 | import android.content.Context 5 | import android.view.Gravity 6 | import android.view.View 7 | import com.peakmain.basiclibrary.R 8 | 9 | /** 10 | * author :Peakmain 11 | * createTime:2021/12/27 12 | * mail:2726449200@qq.com 13 | * describe: 14 | */ 15 | class CustomCenterDialog(context: Context, layout: View, style: Int=R.style.CustomDialogThemes) : Dialog(context, style) { 16 | 17 | init { 18 | 19 | setContentView(layout) 20 | 21 | val window = window 22 | 23 | val params = window!!.attributes 24 | 25 | params.gravity = Gravity.CENTER 26 | 27 | window.attributes = params 28 | } 29 | } -------------------------------------------------------------------------------- /basicLibrary/src/main/java/com/peakmain/basiclibrary/extend/CheckUtils.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.basiclibrary.extend 2 | 3 | /** 4 | * author :Peakmain 5 | * createTime:2023/9/8 6 | * mail:2726449200@qq.com 7 | * describe:检测工具 8 | */ 9 | fun List?.indexOfBound(index: Int): Boolean { 10 | if (this.isNullOrEmpty()) return true 11 | return index >= this.size 12 | } 13 | -------------------------------------------------------------------------------- /basicLibrary/src/main/java/com/peakmain/basiclibrary/extend/ClickExtensions.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.basiclibrary.extend 2 | 3 | import android.view.MotionEvent 4 | import android.view.View 5 | import android.widget.TextView 6 | 7 | /** 8 | * author :Peakmain 9 | * createTime:2021/12/27 10 | * mail:2726449200@qq.com 11 | * describe:点击事件的扩展类 12 | */ 13 | private var T.lastClickTime: Long 14 | get() = if (getTag(1638288000) != null) getTag(1638288000) as Long else -1 15 | set(value) { 16 | setTag(1638288000, value) 17 | } 18 | private var T.delayTime: Long 19 | get() = if (getTag(1638288600) != null) getTag(1638288600) as Long else -1 20 | set(value) { 21 | setTag(1638288600, value) 22 | } 23 | 24 | private fun T.clickEnable(): Boolean { 25 | var isClickEnable = false 26 | val currentTimeMillis = System.currentTimeMillis() 27 | if (currentTimeMillis - lastClickTime >= delayTime) { 28 | isClickEnable = true 29 | } 30 | lastClickTime = currentTimeMillis 31 | return isClickEnable 32 | } 33 | 34 | 35 | fun T.click(block: (T) -> Unit) = setOnClickListener { 36 | if (clickEnable()) { 37 | block(it as T) 38 | } 39 | } 40 | 41 | 42 | /** 43 | * @param time:延迟时间,默认750 44 | * @param block:事件处理函数 45 | */ 46 | fun T.clickViewDelay(time: Long = 750, block: (T) -> Unit) { 47 | delayTime = time 48 | setOnClickListener { 49 | if (clickEnable()) { 50 | block(it as T) 51 | } 52 | } 53 | } 54 | 55 | /** 56 | * TextView点击事件拆分 57 | */ 58 | fun T.clickClipListener( 59 | leftClick: (View) -> Unit = {}, 60 | rightClick: (View) -> Unit = {} 61 | ) { 62 | this.run { 63 | setOnTouchListener(object : View.OnTouchListener { 64 | override fun onTouch(v: View, event: MotionEvent): Boolean { 65 | when (event.action) { 66 | MotionEvent.ACTION_DOWN -> { 67 | val drawableLeft = compoundDrawables[0] 68 | if (drawableLeft != null && event.rawX <= left + drawableLeft.bounds.width()) { 69 | leftClick(this@run) 70 | return true 71 | } 72 | val drawableRight = compoundDrawables[2] 73 | return if (drawableRight != null && event.rawX >= width-paddingRight-drawableRight.intrinsicWidth) { // 增加了宽度,该方向+当前icon宽度 74 | rightClick(this@run) 75 | true 76 | } else { 77 | false 78 | } 79 | } 80 | else -> return false 81 | } 82 | } 83 | }) 84 | } 85 | } -------------------------------------------------------------------------------- /basicLibrary/src/main/java/com/peakmain/basiclibrary/extend/EmptyHandleUtils.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.basiclibrary.extend 2 | 3 | import android.content.Context 4 | import androidx.fragment.app.FragmentActivity 5 | 6 | /** 7 | * author :Peakmain 8 | * createTime:2024/11/14 9 | * mail:2726449200@qq.com 10 | * describe:空逻辑处理 11 | */ 12 | fun Context?.handleEmpty(block: ((Context) -> Unit)? = null) { 13 | this?.let { 14 | block?.invoke(it) 15 | } 16 | } 17 | fun FragmentActivity?.handleEmptyActivity(block: ((FragmentActivity) -> Unit)? = null) { 18 | this?.let { 19 | block?.invoke(it) 20 | } 21 | } -------------------------------------------------------------------------------- /basicLibrary/src/main/java/com/peakmain/basiclibrary/extend/RxExtensions.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.basiclibrary.extend 2 | 3 | import io.reactivex.disposables.Disposable 4 | 5 | /** 6 | * author :Peakmain 7 | * createTime:2022/10/24 8 | * mail:2726449200@qq.com 9 | * describe:Rx 扩展工具类 10 | */ 11 | /** 12 | * Rxjava Disposable取消 13 | */ 14 | fun Disposable?.cancel() { 15 | if (this == null) return 16 | if (!this.isDisposed) this.dispose() 17 | } -------------------------------------------------------------------------------- /basicLibrary/src/main/java/com/peakmain/basiclibrary/extend/StringExtensions.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.basiclibrary.extend 2 | 3 | import java.text.DecimalFormat 4 | 5 | /** 6 | * author :Peakmain 7 | * createTime:1/22/22 8 | * mail:2726449200@qq.com 9 | * describe: 10 | */ 11 | fun T.isSpace(): Boolean { 12 | if (this == null) return true 13 | var i = 0 14 | val len = length 15 | while (i < len) { 16 | if (!Character.isWhitespace(get(i))) { 17 | return false 18 | } 19 | i++ 20 | } 21 | return true 22 | } 23 | 24 | fun Number.formatToMoney(): String? { 25 | return DecimalFormat("#,###.00").format(this) 26 | } 27 | 28 | fun String?.replaceZero(): String? { 29 | if (this == null) return this 30 | var s = this 31 | s.replace("0+?$".toRegex(), "").also { s = it } 32 | s?.replace("[.]$".toRegex(), "").also { s = it } 33 | return s 34 | } 35 | /** 36 | * 判断两个字符是否改变 37 | */ 38 | fun CharSequence?.haveContentsChanged(str:CharSequence?):Boolean{ 39 | if (this == null != (str == null)) { 40 | return true 41 | } else if (this == null) { 42 | return false 43 | } 44 | val length: Int = this.length 45 | if (length != str?.length) { 46 | return true 47 | } 48 | for (i in 0 until length) { 49 | if (this[i] != str[i]) { 50 | return true 51 | } 52 | } 53 | return false 54 | } -------------------------------------------------------------------------------- /basicLibrary/src/main/java/com/peakmain/basiclibrary/extend/ThreadExtensions.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.basiclibrary.extend 2 | 3 | import android.os.Handler 4 | import android.os.Looper 5 | import io.reactivex.Observable 6 | import io.reactivex.android.schedulers.AndroidSchedulers 7 | import io.reactivex.disposables.Disposable 8 | import io.reactivex.schedulers.Schedulers 9 | import java.util.concurrent.ExecutorService 10 | import java.util.concurrent.Executors 11 | import java.util.concurrent.TimeUnit 12 | 13 | /** 14 | * author :Peakmain 15 | * createTime:2021/12/23 16 | * mail:2726449200@qq.com 17 | * describe:线程扩展类 18 | */ 19 | private val mHandler = Handler(Looper.getMainLooper()) 20 | 21 | private val mSingleService: ExecutorService = Executors.newSingleThreadExecutor() 22 | 23 | /** 24 | * 切换到主线程 25 | */ 26 | fun T.ktxRunOnUiThread(block: T.() -> Unit) { 27 | mHandler.post { 28 | block() 29 | } 30 | } 31 | 32 | /** 33 | * 延迟delayMills切换到主线程,默认是600ms 34 | */ 35 | fun T.ktxRunOnUiThreadDelay(delayMills: Long=600, block: T.() -> Unit) { 36 | mHandler.postDelayed({ 37 | block() 38 | }, delayMills) 39 | } 40 | 41 | /** 42 | * 子线程执行 43 | */ 44 | fun T.ktxRunOnThreadSingle(block: T.() -> Unit) { 45 | mSingleService.execute { 46 | block() 47 | } 48 | } 49 | 50 | /** 51 | * 延迟加载 52 | */ 53 | fun T.wait(delay: Long = 500L, block: T.() -> Unit): Disposable { 54 | return wait(delay, TimeUnit.MILLISECONDS, block) 55 | } 56 | /** 57 | * 延迟加载 58 | */ 59 | fun T.wait(delay: Long = 500L, unit: TimeUnit, block: T.() -> Unit): Disposable { 60 | return Observable.timer(delay, unit).subscribeOn(Schedulers.io()) 61 | .observeOn(AndroidSchedulers.mainThread()).subscribe { block() } 62 | } -------------------------------------------------------------------------------- /basicLibrary/src/main/java/com/peakmain/basiclibrary/extend/ViewExtensions.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.basiclibrary.extend 2 | 3 | import android.text.Spanned 4 | import android.view.View 5 | import android.view.animation.CycleInterpolator 6 | import android.view.animation.TranslateAnimation 7 | import android.widget.TextView 8 | 9 | /** 10 | * author :Peakmain 11 | * createTime:2022/1/5 12 | * mail:2726449200@qq.com 13 | * describe:View的扩展 14 | */ 15 | 16 | 17 | /** 18 | * View的抖动动画 19 | * @param fromXDelta Change in X coordinate to apply at the start of the 20 | * animation 21 | * @param toXDelta Change in X coordinate to apply at the end of the 22 | * animation 23 | * @param fromYDelta Change in Y coordinate to apply at the start of the 24 | * animation 25 | * @param toYDelta Change in Y coordinate to apply at the end of the 26 | * animation 27 | * @param duration durationMillis Duration in milliseconds 28 | */ 29 | fun T.shakeAnimation( 30 | fromXDelta: Float = 0f, 31 | toXDelta: Float = 5f, 32 | fromYDelta: Float = 0f, 33 | toYDelta: Float = 0f, 34 | duration: Long = 500 35 | ) { 36 | TranslateAnimation(fromXDelta, toXDelta, fromYDelta, toYDelta).also { 37 | it.duration = duration 38 | it.interpolator = CycleInterpolator(3f) 39 | startAnimation(it) 40 | } 41 | } 42 | 43 | fun View.visible() { 44 | visibility = View.VISIBLE 45 | } 46 | 47 | fun View.gone() { 48 | visibility = View.GONE 49 | } 50 | 51 | fun View.inVisible() { 52 | visibility = View.INVISIBLE 53 | } 54 | 55 | fun View.setPadding(left: Int, top: Int, right: Int, bottom: Int) { 56 | setPadding(left, top, right, bottom) 57 | } 58 | 59 | fun TextView.setText(text: CharSequence?) { 60 | val oldText = this.text 61 | if (text === oldText || text == null && oldText.isEmpty()) { 62 | return 63 | } 64 | if (text is Spanned) { 65 | if (text == oldText) { 66 | return // No change in the spans, so don't set anything. 67 | } 68 | } else if (!text.haveContentsChanged(oldText)) { 69 | return // No content changes, so don't set anything. 70 | } 71 | this.text = text 72 | } -------------------------------------------------------------------------------- /basicLibrary/src/main/java/com/peakmain/basiclibrary/helper/BehaviorHelper.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.basiclibrary.helper 2 | 3 | import android.graphics.Color 4 | import android.view.View 5 | import android.view.ViewGroup 6 | import android.widget.FrameLayout 7 | import androidx.annotation.ColorInt 8 | import com.google.android.material.bottomsheet.BottomSheetBehavior 9 | import com.peakmain.basiclibrary.R 10 | import com.peakmain.basiclibrary.interfaces.IBehaviorHelperCallback 11 | 12 | /** 13 | * author :Peakmain 14 | * createTime:2022/11/14 15 | * mail:2726449200@qq.com 16 | * describe: 17 | */ 18 | class BehaviorHelper 19 | /** 20 | * @param target 设置阴影的根布局 21 | * @param backgroundColor 阴影背景颜色 22 | * @param peekHeight 折叠的时候 底部显示高度 23 | * @param isHide false 表示用户将能通过向下滑动完全隐藏的BottomSheet ,默认无此状态 24 | * @param isCancelable 点击空白是否可以取消,false表示可以取消,true表示不可取消 25 | */ 26 | constructor( 27 | private val target: ViewGroup? = null, 28 | content: ViewGroup? = null, 29 | listener: IBehaviorHelperCallback? = null, 30 | @ColorInt val backgroundColor: Int = Color.parseColor("#66000000"), 31 | peekHeight: Int = 0, 32 | isHide: Boolean = false, 33 | private val isCancelable: Boolean = false 34 | ) { 35 | private var behavior: BottomSheetBehavior? = null 36 | 37 | init { 38 | content?.let { 39 | behavior = BottomSheetBehavior.from(it) 40 | behavior?.isHideable = isHide 41 | behavior?.peekHeight = peekHeight 42 | behavior?.addBottomSheetCallback(object : BottomSheetBehavior.BottomSheetCallback() { 43 | override fun onStateChanged(bottomSheet: View, newState: Int) { 44 | if (newState == BottomSheetBehavior.STATE_COLLAPSED) { 45 | removeShadow() 46 | listener?.close(bottomSheet, newState) 47 | } else if (newState == BottomSheetBehavior.STATE_EXPANDED) { 48 | listener?.open(bottomSheet, newState) 49 | } 50 | } 51 | 52 | override fun onSlide(bottomSheet: View, slideOffset: Float) { 53 | } 54 | 55 | }) 56 | } 57 | } 58 | 59 | fun toggle() { 60 | if (behavior?.state == BottomSheetBehavior.STATE_COLLAPSED) { 61 | behavior?.state = BottomSheetBehavior.STATE_EXPANDED 62 | showShadow() 63 | } else { 64 | behavior?.state = BottomSheetBehavior.STATE_COLLAPSED 65 | } 66 | } 67 | 68 | private fun showShadow() { 69 | if (target == null) return 70 | if (target.findViewById(R.id.basic_library_shadow) != null) return 71 | val shadow = FrameLayout(target.context) 72 | shadow.apply { 73 | layoutParams = FrameLayout.LayoutParams( 74 | FrameLayout.LayoutParams.MATCH_PARENT, 75 | FrameLayout.LayoutParams.MATCH_PARENT 76 | ) 77 | setBackgroundColor(backgroundColor) 78 | if (!isCancelable) { 79 | setOnClickListener { 80 | target.removeView(this) 81 | behavior?.state = BottomSheetBehavior.STATE_COLLAPSED 82 | } 83 | } 84 | id = R.id.basic_library_shadow 85 | } 86 | target.addView(shadow, 0) 87 | } 88 | 89 | fun removeShadow() { 90 | val shadowFrameLayout = target?.findViewById(R.id.basic_library_shadow) ?: return 91 | target.removeView(shadowFrameLayout) 92 | } 93 | 94 | fun getBehavior(): BottomSheetBehavior? { 95 | return behavior 96 | } 97 | } -------------------------------------------------------------------------------- /basicLibrary/src/main/java/com/peakmain/basiclibrary/helper/ImageSelectorHelper.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.basiclibrary.helper 2 | 3 | import android.os.Bundle 4 | import androidx.fragment.app.FragmentManager 5 | import com.peakmain.basiclibrary.config.ImageContext 6 | import com.peakmain.basiclibrary.image.PkImageSelector 7 | import com.peakmain.basiclibrary.image.ImageSelectorFragment 8 | import com.peakmain.basiclibrary.config.ImageRequestConfig 9 | import com.peakmain.basiclibrary.constants.ImageSelectConstants 10 | 11 | /** 12 | * author :Peakmain 13 | * createTime:2022/08/18 14 | * mail:2726449200@qq.com 15 | * describe: 16 | */ 17 | internal class ImageSelectorHelper private constructor() { 18 | companion object { 19 | val instance by lazy(LazyThreadSafetyMode.SYNCHRONIZED) { 20 | ImageSelectorHelper() 21 | } 22 | private val TAG = PkImageSelector::class.simpleName 23 | } 24 | 25 | fun getPictureSelectFragment( 26 | config: ImageRequestConfig, 27 | imageContext: ImageContext 28 | ): ImageSelectorFragment { 29 | val fragmentManager = getFragmentManager(imageContext) 30 | var imageSelectorFragment = findPictureSelectFragment(fragmentManager) 31 | if (imageSelectorFragment == null) { 32 | imageSelectorFragment = ImageSelectorFragment() 33 | val bundle = Bundle() 34 | bundle.putSerializable(ImageSelectConstants.REQUEST_CONFIG, config) 35 | imageSelectorFragment.arguments = bundle 36 | 37 | fragmentManager?.beginTransaction() 38 | ?.add(imageSelectorFragment, TAG) 39 | ?.commitAllowingStateLoss() 40 | } else 41 | initFragmentBundle(config, imageSelectorFragment) 42 | 43 | return imageSelectorFragment 44 | } 45 | 46 | private fun initFragmentBundle( 47 | config: ImageRequestConfig, 48 | imageSelectorFragment: ImageSelectorFragment 49 | ) { 50 | val bundle = Bundle() 51 | bundle.putSerializable(ImageSelectConstants.REQUEST_CONFIG, config) 52 | imageSelectorFragment.arguments = bundle 53 | } 54 | 55 | private fun findPictureSelectFragment(fragmentManager: FragmentManager?): ImageSelectorFragment? { 56 | return fragmentManager?.findFragmentByTag(TAG) as ImageSelectorFragment? 57 | } 58 | 59 | 60 | private fun getFragmentManager(imageContext: ImageContext): FragmentManager? { 61 | return if (imageContext.activity != null) { 62 | imageContext.activity!!.supportFragmentManager 63 | } else if (imageContext.fragment != null) { 64 | imageContext.fragment!!.childFragmentManager 65 | } else { 66 | null 67 | } 68 | } 69 | 70 | 71 | } -------------------------------------------------------------------------------- /basicLibrary/src/main/java/com/peakmain/basiclibrary/helper/RetrofitHelper.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.basiclibrary.helper 2 | 3 | import android.os.Build 4 | import com.peakmain.basiclibrary.network.HttpDns 5 | import com.peakmain.basiclibrary.network.MyX509 6 | import com.peakmain.basiclibrary.network.status.ApiStatus 7 | import com.peakmain.basiclibrary.network.status.CommonRetrofitData 8 | import okhttp3.OkHttpClient 9 | import okhttp3.logging.HttpLoggingInterceptor 10 | import java.util.concurrent.TimeUnit 11 | import javax.net.ssl.SSLContext 12 | import javax.net.ssl.SSLSocketFactory 13 | import javax.net.ssl.TrustManager 14 | import javax.net.ssl.X509ExtendedTrustManager 15 | 16 | /** 17 | * author :Peakmain 18 | * createTime:2022/08/04 19 | * mail:2726449200@qq.com 20 | * describe: 21 | */ 22 | object RetrofitHelper { 23 | //连接超时 24 | private const val CONNECT_TIMEOUT = 60L 25 | 26 | //阅读超时 27 | private const val READ_TIMEOUT = 10L 28 | 29 | //写入超时 30 | private const val WRITE_TIMEOUT = 10L 31 | private const val DNS_TIMEOUT = 5L 32 | 33 | /** 34 | * @param prevBuildOkHttpClient 在构建okHttpClient之前可设置一些参数 35 | */ 36 | fun buildOkHttpClient(prevBuildOkHttpClient: ((OkHttpClient.Builder) -> Unit)? = null): OkHttpClient { 37 | val builder = OkHttpClient.Builder() 38 | .connectTimeout(CONNECT_TIMEOUT, TimeUnit.SECONDS)//设置连接超时 39 | .dns(HttpDns(DNS_TIMEOUT, TimeUnit.MILLISECONDS)) 40 | .readTimeout(READ_TIMEOUT, TimeUnit.SECONDS)//读取超时 41 | .writeTimeout(WRITE_TIMEOUT, TimeUnit.SECONDS)//写入超时 42 | builder.addInterceptor(HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY)) 43 | .hostnameVerifier { _, _ -> true } 44 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { 45 | val x509 = MyX509() 46 | builder.sslSocketFactory(getSSLFactory(x509), x509) 47 | } 48 | prevBuildOkHttpClient?.invoke(builder) 49 | return builder.build() 50 | } 51 | 52 | private fun getSSLFactory(x509TrustManager: X509ExtendedTrustManager): SSLSocketFactory { 53 | val trustAllCerts = arrayOf(x509TrustManager) 54 | val sslContext = SSLContext.getInstance("SSL") 55 | sslContext.init(null, trustAllCerts, java.security.SecureRandom()) 56 | return sslContext.socketFactory 57 | } 58 | 59 | 60 | fun function2RetrofitData( 61 | before: () -> Unit, 62 | success: T.() -> Unit, 63 | error: (Exception) -> Unit 64 | ): CommonRetrofitData { 65 | return CommonRetrofitData(object : ApiStatus() { 66 | override fun before() { 67 | super.before() 68 | before() 69 | } 70 | 71 | override fun success(t: T) { 72 | success(t) 73 | } 74 | 75 | override fun error(exception: Exception) { 76 | error(exception) 77 | } 78 | 79 | }) 80 | } 81 | 82 | 83 | } -------------------------------------------------------------------------------- /basicLibrary/src/main/java/com/peakmain/basiclibrary/image/ImageSelectorFragment.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.basiclibrary.image 2 | 3 | import android.os.Bundle 4 | import androidx.fragment.app.Fragment 5 | import com.peakmain.basiclibrary.config.ImageRequestConfig 6 | import com.peakmain.basiclibrary.constants.AndroidVersion 7 | import com.peakmain.basiclibrary.constants.ImageSelectConstants 8 | import com.peakmain.basiclibrary.extend.launchImage 9 | import com.peakmain.basiclibrary.image.contract.SelectMultipleContract 10 | import com.peakmain.basiclibrary.image.contract.SelectSinglePhotoContract 11 | import com.peakmain.basiclibrary.image.contract.TakePictureContract 12 | import com.peakmain.basiclibrary.interfaces.OnImageSelectorCallback 13 | import com.peakmain.basiclibrary.viewmodel.ImageSelectViewModel 14 | 15 | /** 16 | * author :Peakmain 17 | * createTime:2022/08/18 18 | * mail:2726449200@qq.com 19 | * describe: 20 | */ 21 | internal class ImageSelectorFragment : Fragment() { 22 | 23 | private var mImageSelectViewModel: ImageSelectViewModel = ImageSelectViewModel() 24 | var selectMultipleContract = SelectMultipleContract() 25 | private val mSelectPhotoLauncher = 26 | registerForActivityResult(SelectSinglePhotoContract()) { uri -> 27 | mImageSelectViewModel.registerSingleLauncher(uri) 28 | } 29 | 30 | 31 | private val takePictureLauncher = 32 | registerForActivityResult(TakePictureContract()) { 33 | mImageSelectViewModel.registerTakePicture(it) 34 | } 35 | 36 | private val mSelectMultiPhotoLauncher = 37 | registerForActivityResult(selectMultipleContract) { lists -> 38 | mImageSelectViewModel.registerMultiLauncher(lists) 39 | } 40 | 41 | override fun onCreate(savedInstanceState: Bundle?) { 42 | super.onCreate(savedInstanceState) 43 | mImageSelectViewModel.mStart.observe( 44 | this, 45 | mImageSelectViewModel.imageSelectorObserver( { 46 | mSelectPhotoLauncher.launchImage(mImageSelectViewModel.mConfig) 47 | }, { 48 | mSelectMultiPhotoLauncher.launchImage(mImageSelectViewModel.mConfig) 49 | }) { 50 | takePictureLauncher.launch(null) 51 | } 52 | ) 53 | selectMultipleContract.maxNum = mImageSelectViewModel.mConfig?.maxNum ?: 9 54 | } 55 | 56 | 57 | fun start(onImageSelectorCallback: OnImageSelectorCallback?) { 58 | getConfig() 59 | mImageSelectViewModel.mStart.value = true 60 | mImageSelectViewModel.mOnImageSelectorCallback = onImageSelectorCallback 61 | } 62 | 63 | private fun getConfig() { 64 | mImageSelectViewModel.mConfig = if (AndroidVersion.isAndroid13()) { 65 | arguments?.getSerializable( 66 | ImageSelectConstants.REQUEST_CONFIG, 67 | ImageRequestConfig::class.java 68 | ) 69 | } else { 70 | arguments?.get(ImageSelectConstants.REQUEST_CONFIG) as ImageRequestConfig? 71 | } 72 | } 73 | 74 | override fun onDestroy() { 75 | super.onDestroy() 76 | mImageSelectViewModel.clearImage() 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /basicLibrary/src/main/java/com/peakmain/basiclibrary/image/PkImageSelector.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.basiclibrary.image 2 | 3 | import androidx.fragment.app.Fragment 4 | import androidx.fragment.app.FragmentActivity 5 | import com.peakmain.basiclibrary.config.ImageContext 6 | import com.peakmain.basiclibrary.helper.ImageSelectorHelper 7 | import com.peakmain.basiclibrary.config.ImageRequestConfig 8 | import com.peakmain.basiclibrary.constants.ImageSelectConstants 9 | import com.peakmain.basiclibrary.interfaces.OnImageSelectorCallback 10 | 11 | /** 12 | * author :Peakmain 13 | * createTime:2022/08/18 14 | * mail:2726449200@qq.com 15 | * describe: 16 | */ 17 | class PkImageSelector private constructor(mConfig: ImageRequestConfig, imageContext: ImageContext) { 18 | private var mPictureSelectorFragment: ImageSelectorFragment? = null 19 | 20 | init { 21 | mPictureSelectorFragment = ImageSelectorHelper.instance 22 | .getPictureSelectFragment(mConfig, imageContext) 23 | mPictureSelectorFragment?.start(imageContext.onImageSelectorCallback) 24 | } 25 | 26 | companion object { 27 | 28 | fun builder(fragment: Fragment): Builder { 29 | return Builder(fragment) 30 | } 31 | 32 | fun builder(activity: FragmentActivity): Builder { 33 | return Builder(activity) 34 | } 35 | 36 | class Builder private constructor() { 37 | private val mConfig: ImageRequestConfig = ImageRequestConfig() 38 | private val imageContext = ImageContext() 39 | 40 | constructor(activity: FragmentActivity) : this() { 41 | imageContext.activity = activity 42 | } 43 | 44 | constructor(fragment: Fragment) : this() { 45 | imageContext.fragment = fragment 46 | } 47 | 48 | 49 | fun setSingle(isSingle: Boolean): Builder { 50 | mConfig.isSingle = isSingle 51 | return this 52 | } 53 | 54 | /** 55 | * 设置多选最多的数量 56 | * android 13及以上才生效 57 | */ 58 | fun setMaxNum(num: Int = 1):Builder { 59 | mConfig.maxNum = num 60 | return this 61 | } 62 | 63 | fun setType(@ImageSelectConstants.ImageSelectType type: Int): Builder { 64 | mConfig.imageType = type 65 | return this 66 | } 67 | 68 | fun forResult(onImageSelectorCallback: OnImageSelectorCallback? = null): PkImageSelector { 69 | imageContext.onImageSelectorCallback = onImageSelectorCallback 70 | return PkImageSelector(mConfig, imageContext) 71 | } 72 | 73 | } 74 | } 75 | } -------------------------------------------------------------------------------- /basicLibrary/src/main/java/com/peakmain/basiclibrary/image/SimpleImageSelectorCallback.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.basiclibrary.image 2 | 3 | import android.graphics.Bitmap 4 | import com.peakmain.basiclibrary.interfaces.OnImageSelectorCallback 5 | 6 | /** 7 | * author :Peakmain 8 | * createTime:2022/08/22 9 | * mail:2726449200@qq.com 10 | * describe:接口适配器设计模式 11 | */ 12 | abstract class SimpleImageSelectorCallback : OnImageSelectorCallback { 13 | //拍照的空方法 14 | override fun onImageSelect(bitmap: Bitmap?) { 15 | 16 | } 17 | 18 | } -------------------------------------------------------------------------------- /basicLibrary/src/main/java/com/peakmain/basiclibrary/image/contract/SelectMultipleContract.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.basiclibrary.image.contract 2 | 3 | import android.app.Activity 4 | import android.content.Context 5 | import android.content.Intent 6 | import android.net.Uri 7 | import android.provider.MediaStore 8 | import androidx.activity.result.contract.ActivityResultContract 9 | import com.peakmain.basiclibrary.constants.AndroidVersion 10 | 11 | /** 12 | * author :Peakmain 13 | * createTime:2022/08/18 14 | * mail:2726449200@qq.com 15 | * describe: 16 | */ 17 | class SelectMultipleContract(var maxNum: Int = 9) : ActivityResultContract>() { 18 | override fun createIntent(context: Context, input: String): Intent { 19 | val intent = if (AndroidVersion.isAndroid13()) { 20 | Intent(MediaStore.ACTION_PICK_IMAGES) 21 | .putExtra(MediaStore.EXTRA_PICK_IMAGES_MAX, maxNum) 22 | .setType(input) 23 | } else { 24 | Intent(Intent.ACTION_GET_CONTENT) 25 | .addCategory(Intent.CATEGORY_OPENABLE) 26 | .setType(input) 27 | } 28 | if (AndroidVersion.isAndroid4_3()) { 29 | intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true) 30 | } 31 | return intent 32 | 33 | } 34 | 35 | override fun parseResult(resultCode: Int, intent: Intent?): List { 36 | return if (intent == null || resultCode != Activity.RESULT_OK) { 37 | emptyList() 38 | } else getClipDataUris(intent) 39 | } 40 | 41 | companion object { 42 | fun getClipDataUris(intent: Intent): List { 43 | // Use a LinkedHashSet to maintain any ordering that may be 44 | // present in the ClipData 45 | val resultSet = LinkedHashSet() 46 | if (intent.data != null) { 47 | resultSet.add(intent.data) 48 | } 49 | val clipData = intent.clipData 50 | if (clipData == null && resultSet.isEmpty()) { 51 | return emptyList() 52 | } else if (clipData != null) { 53 | for (i in 0 until clipData.itemCount) { 54 | val uri = clipData.getItemAt(i).uri 55 | if (uri != null) { 56 | resultSet.add(uri) 57 | } 58 | } 59 | } 60 | return ArrayList(resultSet) 61 | } 62 | } 63 | } -------------------------------------------------------------------------------- /basicLibrary/src/main/java/com/peakmain/basiclibrary/image/contract/SelectSinglePhotoContract.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.basiclibrary.image.contract 2 | 3 | import android.app.Activity 4 | import android.content.Context 5 | import android.content.Intent 6 | import android.net.Uri 7 | import androidx.activity.result.contract.ActivityResultContract 8 | import androidx.annotation.CallSuper 9 | 10 | /** 11 | * author :Peakmain 12 | * createTime:2022/08/18 13 | * mail:2726449200@qq.com 14 | * describe: 15 | */ 16 | class SelectSinglePhotoContract : ActivityResultContract() { 17 | @CallSuper 18 | override fun createIntent(context: Context, input: String?): Intent { 19 | return Intent(Intent.ACTION_PICK) 20 | .setType(input) 21 | } 22 | 23 | override fun parseResult(resultCode: Int, intent: Intent?): Uri? { 24 | return if (intent == null || resultCode != Activity.RESULT_OK) null else intent.data 25 | } 26 | } -------------------------------------------------------------------------------- /basicLibrary/src/main/java/com/peakmain/basiclibrary/image/contract/TakePictureContract.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.basiclibrary.image.contract 2 | 3 | import android.app.Activity 4 | import android.content.Context 5 | import android.content.Intent 6 | import android.graphics.Bitmap 7 | import android.net.Uri 8 | import android.provider.MediaStore 9 | import androidx.activity.result.contract.ActivityResultContract 10 | import androidx.annotation.CallSuper 11 | 12 | /** 13 | * author :Peakmain 14 | * createTime:2022/08/18 15 | * mail:2726449200@qq.com 16 | * describe: 17 | */ 18 | internal class TakePictureContract : ActivityResultContract>() { 19 | 20 | @CallSuper 21 | override fun createIntent(context: Context, input: Uri?): Intent { 22 | return Intent(MediaStore.ACTION_IMAGE_CAPTURE) 23 | .putExtra(MediaStore.EXTRA_OUTPUT, input) 24 | } 25 | 26 | override fun parseResult(resultCode: Int, intent: Intent?): Pair { 27 | val data=intent?.getParcelableExtra("data") 28 | return (resultCode == Activity.RESULT_OK) to data 29 | } 30 | } -------------------------------------------------------------------------------- /basicLibrary/src/main/java/com/peakmain/basiclibrary/interfaces/IBehaviorHelperCallback.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.basiclibrary.interfaces 2 | 3 | import android.view.View 4 | import com.google.android.material.bottomsheet.BottomSheetBehavior 5 | 6 | /** 7 | * author :Peakmain 8 | * createTime:2022/11/14 9 | * mail:2726449200@qq.com 10 | * describe: 11 | */ 12 | interface IBehaviorHelperCallback { 13 | fun open(bottomSheet: View?, @BottomSheetBehavior.State newState:Int) 14 | fun close(bottomSheet: View?, @BottomSheetBehavior.State newState:Int) 15 | } -------------------------------------------------------------------------------- /basicLibrary/src/main/java/com/peakmain/basiclibrary/interfaces/IPermissionPopupListener.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.basiclibrary.interfaces 2 | 3 | /** 4 | * author :Peakmain 5 | * createTime:2024/11/19 6 | * mail:2726449200@qq.com 7 | * describe: 8 | */ 9 | interface IPermissionPopupListener { 10 | fun onShowPermissionPopup() 11 | fun onHidePermissionPopup() 12 | } -------------------------------------------------------------------------------- /basicLibrary/src/main/java/com/peakmain/basiclibrary/interfaces/IPermissionSetting.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.basiclibrary.interfaces 2 | 3 | import android.content.Context 4 | import android.content.Intent 5 | 6 | /** 7 | * author :Peakmain 8 | * createTime:2022/08/12 9 | * mail:2726449200@qq.com 10 | * describe: 11 | */ 12 | internal interface IPermissionSetting { 13 | fun getAppSetting(context:Context): Intent 14 | } -------------------------------------------------------------------------------- /basicLibrary/src/main/java/com/peakmain/basiclibrary/interfaces/OnImageSelectorCallback.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.basiclibrary.interfaces 2 | 3 | import android.graphics.Bitmap 4 | import android.net.Uri 5 | 6 | /** 7 | * author :Peakmain 8 | * createTime:2022/08/18 9 | * mail:2726449200@qq.com 10 | * describe: 11 | */ 12 | interface OnImageSelectorCallback { 13 | //图片选择的回调 14 | fun onImageSelect(uris: List) 15 | //相机拍照的回调 16 | fun onImageSelect(bitmap: Bitmap?) 17 | } -------------------------------------------------------------------------------- /basicLibrary/src/main/java/com/peakmain/basiclibrary/interfaces/OnPermissionCallback.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.basiclibrary.interfaces 2 | 3 | /** 4 | * author :Peakmain 5 | * createTime:2022/08/11 6 | * mail:2726449200@qq.com 7 | * describe: 8 | */ 9 | interface OnPermissionCallback { 10 | /** 11 | * 权限被授予时回调 12 | * @param permissions 权限组 13 | */ 14 | fun onGranted(permissions: Array) 15 | 16 | /** 17 | * 权限被拒绝的时候回调 18 | * @param permissions 权限组 19 | * @param never 权限是否被永久拒绝 20 | */ 21 | fun onDenied(permissions: Array, never: Boolean) 22 | } -------------------------------------------------------------------------------- /basicLibrary/src/main/java/com/peakmain/basiclibrary/manager/AnimationManager.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.basiclibrary.manager 2 | 3 | import android.animation.Animator 4 | import android.animation.AnimatorListenerAdapter 5 | import android.view.View 6 | import com.peakmain.basiclibrary.config.BasicLibraryConfig 7 | 8 | /** 9 | * author :Peakmain 10 | * createTime:2022/1/27 11 | * mail:2726449200@qq.com 12 | * describe: 13 | */ 14 | object AnimationManager { 15 | /** 16 | * 显示淡入淡出动画 17 | */ 18 | fun showCrossFadeLoadingView(contentView: View, loadingView: View) { 19 | contentView.visibility = View.GONE 20 | loadingView.visibility = View.VISIBLE 21 | } 22 | 23 | /** 24 | * 隐藏淡入淡出动画 25 | */ 26 | fun hideCrossFadeLoadingView(contentView: View, loadingView: View) { 27 | if (BasicLibraryConfig.getInstance()?.getApp()?.getApplication() == null) { 28 | return 29 | } 30 | val animationDuration: Int = BasicLibraryConfig.getInstance()?.getApp() 31 | ?.getApplication()!!.resources.getInteger(android.R.integer.config_shortAnimTime) 32 | contentView.apply { 33 | alpha = 0f 34 | visibility = View.VISIBLE 35 | animate() 36 | .alpha(1f) 37 | .setDuration(animationDuration.toLong()) 38 | .setListener(null) 39 | } 40 | loadingView.animate() 41 | .alpha(0f) 42 | .setDuration(animationDuration.toLong()) 43 | .setListener(object : AnimatorListenerAdapter() { 44 | override fun onAnimationEnd(animation: Animator) { 45 | loadingView.visibility = View.GONE 46 | } 47 | }) 48 | } 49 | } -------------------------------------------------------------------------------- /basicLibrary/src/main/java/com/peakmain/basiclibrary/manager/PermissionHandlerManager.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.basiclibrary.manager 2 | 3 | import android.os.Handler 4 | import android.os.Looper 5 | import android.os.Message 6 | import com.peakmain.basiclibrary.constants.PermissionMapConstants 7 | import com.peakmain.basiclibrary.interfaces.IPermissionPopupListener 8 | 9 | /** 10 | * author :Peakmain 11 | * createTime:2024/11/19 12 | * mail:2726449200@qq.com 13 | * describe: 14 | */ 15 | class PermissionHandlerManager private constructor() { 16 | companion object { 17 | @JvmStatic 18 | val instance by lazy(LazyThreadSafetyMode.SYNCHRONIZED) { 19 | PermissionHandlerManager() 20 | } 21 | } 22 | 23 | // 使用弱引用的静态内部 Handler 类,防止内存泄漏 24 | private val mHandler = object : Handler(Looper.getMainLooper()) {} 25 | private val listeners = mutableMapOf>() 26 | private var permission: Array? = null 27 | 28 | // 权限与标签的映射表 29 | fun registerListener( 30 | @PermissionMapConstants.PermissionTag tag: String, 31 | listener: IPermissionPopupListener 32 | ) { 33 | val tagListeners = listeners[tag] ?: mutableListOf() 34 | if (!tagListeners.contains(listener)) { 35 | tagListeners.add(listener) 36 | listeners[tag] = tagListeners 37 | } 38 | } 39 | 40 | // 注销监听器 41 | fun unregisterListener( 42 | @PermissionMapConstants.PermissionTag tag: String, 43 | listener: IPermissionPopupListener 44 | ) { 45 | listeners[tag]?.remove(listener) 46 | if (listeners[tag]?.isEmpty() == true) { 47 | listeners.remove(tag) 48 | } 49 | } 50 | 51 | // 通知显示监听器(遍历所有监听器) 52 | private fun notifyShowListeners(permission: Array) { 53 | // 检查 permission 数组是否为空 54 | if (permission.isEmpty() || listeners.isEmpty()) return 55 | 56 | 57 | // 从映射表获取 tag 58 | val tag = PermissionMapConstants.dangerousPermissionTagMap[permission[0]] ?: return 59 | this.permission = permission 60 | // 安全获取 listeners[tag] 列表 61 | val listenerList = listeners[tag] 62 | if (listenerList.isNullOrEmpty()) return 63 | 64 | // 通知最后一个注册的监听器 65 | listenerList.last().onShowPermissionPopup() 66 | } 67 | 68 | private fun notifyHideListeners() { 69 | if (permission?.isEmpty() == true || listeners.isEmpty()) return 70 | this.permission?.let { 71 | if (it.isEmpty()) return 72 | val tag = PermissionMapConstants.dangerousPermissionTagMap[it[0]] ?: return 73 | val listenerList = listeners[tag] 74 | if (listenerList.isNullOrEmpty()) return 75 | 76 | // 通知最后一个注册的监听器 77 | listenerList.last().onHidePermissionPopup() 78 | } 79 | } 80 | 81 | /** 82 | * 发送延时消息 83 | */ 84 | fun sendMessage(permission: Array) { 85 | mHandler.sendMessageDelayed(createMessage { 86 | showPermissionPopup(permission) 87 | }, 100) 88 | } 89 | 90 | /** 91 | * 创建一个消息,封装 Runnable 动作 92 | */ 93 | private fun createMessage(action: () -> Unit): Message { 94 | return Message.obtain(this.mHandler) { 95 | action() 96 | } 97 | } 98 | 99 | /** 100 | * 展示权限弹窗说明 101 | */ 102 | private fun showPermissionPopup(permission: Array) { 103 | notifyShowListeners(permission) 104 | } 105 | 106 | /** 107 | * 移除所有消息和回调,防止任务继续执行 108 | */ 109 | fun removeAllMessages() { 110 | mHandler.removeCallbacksAndMessages(null) 111 | notifyHideListeners() 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /basicLibrary/src/main/java/com/peakmain/basiclibrary/manager/PhoneStateManager.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.basiclibrary.manager 2 | 3 | import android.content.Context 4 | import android.os.Build 5 | import android.telephony.PhoneStateListener 6 | import android.telephony.TelephonyCallback 7 | import android.telephony.TelephonyManager 8 | import androidx.annotation.RequiresApi 9 | import com.peakmain.basiclibrary.config.BasicLibraryConfig 10 | import com.peakmain.basiclibrary.constants.AndroidVersion 11 | import com.peakmain.basiclibrary.utils.ThreadUtils 12 | import java.util.concurrent.CopyOnWriteArrayList 13 | 14 | /** 15 | * author :Peakmain 16 | * createTime:1/25/22 17 | * mail:2726449200@qq.com 18 | * describe:电话状态工具类 19 | */ 20 | class PhoneStateManager private constructor() { 21 | companion object { 22 | val instance: PhoneStateManager by lazy(LazyThreadSafetyMode.SYNCHRONIZED) { 23 | PhoneStateManager() 24 | } 25 | } 26 | 27 | private var mStateCallbacks: MutableList = CopyOnWriteArrayList() 28 | private val phoneStateListener: PhoneStateListener = object : PhoneStateListener() { 29 | override fun onCallStateChanged(state: Int, incomingNumber: String) { 30 | super.onCallStateChanged(state, incomingNumber) 31 | for (callback in mStateCallbacks) { 32 | callback.onPhoneStateCallback(state, incomingNumber) 33 | } 34 | } 35 | } 36 | 37 | @RequiresApi(Build.VERSION_CODES.S) 38 | private class PhoneStateCallBack(stateCallbacks: MutableList) : 39 | TelephonyCallback(), TelephonyCallback.CallStateListener { 40 | private var mStateCallbacks: MutableList = stateCallbacks 41 | override fun onCallStateChanged(state: Int) { 42 | for (callback in mStateCallbacks) { 43 | callback.onPhoneStateCallback(state, "") 44 | } 45 | } 46 | 47 | } 48 | 49 | interface OnPhoneStateCallback { 50 | fun onPhoneStateCallback(state: Int, incomingPhoneNumber: String) 51 | } 52 | 53 | private var telephonyManager: TelephonyManager? = null 54 | 55 | 56 | init { 57 | val application = BasicLibraryConfig.getInstance()?.getApp()?.getApplication() 58 | application?.let { 59 | telephonyManager = 60 | it.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager? 61 | val mainExecutor = ThreadUtils.getMainExecutor() ?: return@let 62 | if (AndroidVersion.isAndroid12()) { 63 | telephonyManager?.registerTelephonyCallback( 64 | mainExecutor, 65 | PhoneStateCallBack(mStateCallbacks) 66 | ) 67 | } else { 68 | telephonyManager?.listen( 69 | phoneStateListener, 70 | PhoneStateListener.LISTEN_CALL_STATE 71 | ) 72 | } 73 | } 74 | 75 | } 76 | 77 | fun addStateCallback(phoneStateCallback: OnPhoneStateCallback) { 78 | if (!mStateCallbacks.contains(phoneStateCallback)) { 79 | mStateCallbacks.add(phoneStateCallback) 80 | } 81 | } 82 | 83 | fun removeStateCallback(phoneStateCallback: OnPhoneStateCallback) { 84 | if (mStateCallbacks.contains(phoneStateCallback)) { 85 | mStateCallbacks.remove(phoneStateCallback) 86 | } 87 | } 88 | 89 | 90 | @Throws(Throwable::class) 91 | protected fun finalize() { 92 | telephonyManager?.let { 93 | if (AndroidVersion.isAndroid12()) { 94 | it.unregisterTelephonyCallback( 95 | PhoneStateCallBack(mStateCallbacks) 96 | ) 97 | } else { 98 | it.listen(phoneStateListener, PhoneStateListener.LISTEN_NONE) 99 | } 100 | } 101 | } 102 | 103 | 104 | } -------------------------------------------------------------------------------- /basicLibrary/src/main/java/com/peakmain/basiclibrary/network/HttpDns.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.basiclibrary.network 2 | 3 | import android.os.Build 4 | import com.qiniu.android.dns.DnsManager 5 | import com.qiniu.android.dns.IResolver 6 | import com.qiniu.android.dns.NetworkInfo 7 | import com.qiniu.android.dns.local.Resolver 8 | import okhttp3.Dns 9 | import java.net.InetAddress 10 | import java.net.InterfaceAddress 11 | import java.net.UnknownHostException 12 | import java.util.* 13 | import java.util.concurrent.Callable 14 | import java.util.concurrent.CompletableFuture 15 | import java.util.concurrent.FutureTask 16 | import java.util.concurrent.TimeUnit 17 | import kotlin.collections.ArrayList 18 | 19 | /** 20 | * author :Peakmain 21 | * createTime:2023/06/15 22 | * mail:2726449200@qq.com 23 | * describe: 24 | */ 25 | class HttpDns constructor(val timeout: Long, val unit: TimeUnit) : Dns { 26 | private val mDnsManager: DnsManager 27 | 28 | init { 29 | val resolver = InetAddress.getByName("119.29.29.29") 30 | val resolvers = arrayOf(Resolver(resolver)) 31 | mDnsManager = DnsManager(NetworkInfo.normal, resolvers) 32 | } 33 | 34 | override fun lookup(hostname: String): MutableList { 35 | val future = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { 36 | CompletableFuture.supplyAsync { 37 | val ips = mDnsManager.query(hostname) 38 | if (ips == null || ips.isEmpty()) return@supplyAsync Dns.SYSTEM.lookup(hostname) 39 | val result = ArrayList() 40 | for (ip in ips) { 41 | try { 42 | result.add(InetAddress.getByName(ip)) 43 | } catch (e: UnknownHostException) { 44 | e.printStackTrace() 45 | } 46 | } 47 | return@supplyAsync result 48 | } 49 | } else { 50 | FutureTask(object : Callable> { 51 | override fun call(): List { 52 | val ips = mDnsManager.query(hostname) 53 | if (ips == null || ips.isEmpty()) return Dns.SYSTEM.lookup(hostname) 54 | val result = ArrayList() 55 | for (ip in ips) { 56 | try { 57 | result.add(InetAddress.getByName(ip)) 58 | } catch (e: UnknownHostException) { 59 | e.printStackTrace() 60 | } 61 | } 62 | return result 63 | } 64 | }) 65 | } 66 | return try { 67 | future.get(timeout, unit).toMutableList() 68 | } catch (e: Exception) { 69 | Dns.SYSTEM.lookup(hostname).toMutableList() 70 | } 71 | 72 | } 73 | } -------------------------------------------------------------------------------- /basicLibrary/src/main/java/com/peakmain/basiclibrary/network/MyX509.java: -------------------------------------------------------------------------------- 1 | package com.peakmain.basiclibrary.network; 2 | 3 | import android.annotation.SuppressLint; 4 | import android.os.Build; 5 | 6 | import androidx.annotation.RequiresApi; 7 | 8 | import java.net.Socket; 9 | import java.security.cert.CertificateException; 10 | import java.security.cert.X509Certificate; 11 | 12 | import javax.net.ssl.SSLEngine; 13 | import javax.net.ssl.X509ExtendedTrustManager; 14 | 15 | 16 | /** 17 | * author :Peakmain 18 | * createTime:2021/12/23 19 | * mail:2726449200@qq.com 20 | * describe: 21 | */ 22 | @RequiresApi(api = Build.VERSION_CODES.N) 23 | public class MyX509 extends X509ExtendedTrustManager { 24 | 25 | @SuppressLint("TrustAllX509TrustManager") 26 | @Override 27 | public void checkClientTrusted(X509Certificate[] chain, String authType, Socket socket) throws CertificateException { 28 | 29 | } 30 | 31 | @SuppressLint("TrustAllX509TrustManager") 32 | @Override 33 | public void checkServerTrusted(X509Certificate[] chain, String authType, Socket socket) { 34 | 35 | } 36 | 37 | @SuppressLint("TrustAllX509TrustManager") 38 | @Override 39 | public void checkClientTrusted(X509Certificate[] chain, String authType, SSLEngine engine) throws CertificateException { 40 | 41 | } 42 | 43 | @SuppressLint("TrustAllX509TrustManager") 44 | @Override 45 | public void checkServerTrusted(X509Certificate[] chain, String authType, SSLEngine engine) throws CertificateException { 46 | 47 | } 48 | 49 | @SuppressLint("TrustAllX509TrustManager") 50 | @Override 51 | public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { 52 | 53 | } 54 | 55 | @SuppressLint("TrustAllX509TrustManager") 56 | @Override 57 | public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { 58 | 59 | } 60 | 61 | @Override 62 | public X509Certificate[] getAcceptedIssuers() { 63 | return new X509Certificate[0]; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /basicLibrary/src/main/java/com/peakmain/basiclibrary/network/RetrofitManager.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.basiclibrary.network 2 | 3 | import android.text.TextUtils 4 | import com.peakmain.basiclibrary.network.status.AbstractRetrofitData 5 | import com.peakmain.basiclibrary.network.status.ApiStatus 6 | import com.peakmain.basiclibrary.network.status.CommonRetrofitData 7 | import com.peakmain.basiclibrary.network.strategy.CommonRetrofitStrategy 8 | import com.peakmain.basiclibrary.network.strategy.IRetrofitStrategy 9 | import com.peakmain.basiclibrary.helper.RetrofitHelper 10 | import io.reactivex.Observable 11 | import io.reactivex.disposables.Disposable 12 | import java.lang.NullPointerException 13 | 14 | /** 15 | * author :Peakmain 16 | * createTime:2021/12/23 17 | * mail:2726449200@qq.com 18 | * describe:Retrofit的管理类 19 | */ 20 | class RetrofitManager { 21 | companion object { 22 | private var mStrategy: IRetrofitStrategy = CommonRetrofitStrategy() 23 | private var mBaseUrl: String? = null 24 | 25 | fun setBaseUrl(baseUrl: String?): Companion { 26 | this.mBaseUrl = baseUrl 27 | return this 28 | } 29 | 30 | fun executeStrategy(strategy: IRetrofitStrategy) { 31 | this.mStrategy = strategy 32 | } 33 | 34 | fun createService(service: Class, block: (service: Class) -> T): T { 35 | return block(service) 36 | } 37 | 38 | fun createService(service: Class):T { 39 | if(TextUtils.isEmpty(mBaseUrl)){ 40 | throw NullPointerException("baseurl must not be null") 41 | } 42 | return createService(service, mBaseUrl!!) 43 | } 44 | 45 | fun createService(service: Class, baseUrl: String): T { 46 | return mStrategy.createService(service, baseUrl) 47 | } 48 | 49 | fun createData( 50 | observable: Observable, 51 | retrofitData: AbstractRetrofitData 52 | ): Disposable { 53 | return retrofitData.createData(observable) 54 | } 55 | 56 | fun createData( 57 | observable: Observable, 58 | apiStatus: ApiStatus, 59 | retrofitData: AbstractRetrofitData = CommonRetrofitData(apiStatus) 60 | ): Disposable { 61 | return retrofitData.createData(observable) 62 | } 63 | 64 | fun createData( 65 | observable: Observable, 66 | before: () -> Unit, 67 | success: T.() -> Unit, 68 | error: (Exception) -> Unit = {}, 69 | retrofitData: AbstractRetrofitData? = null 70 | ): Disposable { 71 | if (retrofitData == null) { 72 | val tempRetrofitData = RetrofitHelper.function2RetrofitData(before, success, error) 73 | return tempRetrofitData.createData(observable) 74 | } 75 | return retrofitData.createData(observable) 76 | } 77 | 78 | 79 | } 80 | } -------------------------------------------------------------------------------- /basicLibrary/src/main/java/com/peakmain/basiclibrary/network/entity/BaseEntity.java: -------------------------------------------------------------------------------- 1 | package com.peakmain.basiclibrary.network.entity; 2 | 3 | /** 4 | * author :Peakmain 5 | * createTime:2021/12/23 6 | * mail:2726449200@qq.com 7 | * describe: 8 | */ 9 | public class BaseEntity { 10 | private int result; 11 | private String detail; 12 | private T data; 13 | 14 | public String getDetail() { 15 | return detail; 16 | } 17 | 18 | public void setDetail(String detail) { 19 | this.detail = detail; 20 | } 21 | 22 | public T getData() { 23 | return data; 24 | } 25 | 26 | public void setData(T data) { 27 | this.data = data; 28 | } 29 | 30 | public int getResult() { 31 | return result; 32 | } 33 | 34 | public void setResult(int result) { 35 | this.result = result; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /basicLibrary/src/main/java/com/peakmain/basiclibrary/network/error/ErrorEnum.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.basiclibrary.network.error 2 | 3 | import androidx.annotation.IntDef 4 | 5 | /** 6 | * author :Peakmain 7 | * createTime:2021/12/23 8 | * mail:2726449200@qq.com 9 | * describe: 10 | */ 11 | class ErrorEnum{ 12 | companion object{ 13 | const val SUCCESS=0 14 | const val TOKEN_ERROR=401 15 | } 16 | @IntDef(value=[SUCCESS,TOKEN_ERROR]) 17 | @Retention(AnnotationRetention.SOURCE) 18 | annotation class Error 19 | 20 | } -------------------------------------------------------------------------------- /basicLibrary/src/main/java/com/peakmain/basiclibrary/network/status/AbstractRetrofitData.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.basiclibrary.network.status 2 | 3 | import io.reactivex.Observable 4 | import io.reactivex.android.schedulers.AndroidSchedulers 5 | import io.reactivex.disposables.Disposable 6 | import io.reactivex.schedulers.Schedulers 7 | 8 | /** 9 | * author :Peakmain 10 | * createTime:2022/08/02 11 | * mail:2726449200@qq.com 12 | * describe: 13 | */ 14 | abstract class AbstractRetrofitData(apiStatus: BaseApiStatus) { 15 | protected var mBaseApiStatus: BaseApiStatus = apiStatus 16 | abstract fun createData( 17 | observable: Observable 18 | ): Disposable 19 | 20 | open fun createData( 21 | observable: Observable, 22 | before: () -> Unit, 23 | success: T.() -> Unit, 24 | error: (Exception) -> Unit = {} 25 | ): Disposable { 26 | before() 27 | return observable.subscribeOn(Schedulers.io()) 28 | .observeOn(AndroidSchedulers.mainThread()).subscribe({ t -> 29 | success(t) 30 | }, { throwable -> 31 | error(Exception(throwable)) 32 | }) 33 | } 34 | } -------------------------------------------------------------------------------- /basicLibrary/src/main/java/com/peakmain/basiclibrary/network/status/ApiStatus.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.basiclibrary.network.status 2 | 3 | /** 4 | * author :Peakmain 5 | * createTime:2021/12/23 6 | * mail:2726449200@qq.com 7 | * describe: 8 | */ 9 | abstract class ApiStatus:BaseApiStatus{ 10 | override fun before() { 11 | } 12 | override fun isEmpty() { 13 | } 14 | 15 | override fun loadMore(t: T, isRefresh: Boolean) { 16 | } 17 | 18 | } -------------------------------------------------------------------------------- /basicLibrary/src/main/java/com/peakmain/basiclibrary/network/status/BaseApiStatus.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.basiclibrary.network.status 2 | 3 | import java.lang.Exception 4 | 5 | /** 6 | * author :Peakmain 7 | * createTime:2021/12/23 8 | * mail:2726449200@qq.com 9 | * describe: 10 | */ 11 | interface BaseApiStatus { 12 | fun before() 13 | 14 | fun success(t: T) 15 | 16 | fun isEmpty() 17 | 18 | fun loadMore(t: T, isRefresh: Boolean) 19 | 20 | fun error(exception: Exception) 21 | } -------------------------------------------------------------------------------- /basicLibrary/src/main/java/com/peakmain/basiclibrary/network/status/CommonRetrofitData.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.basiclibrary.network.status 2 | 3 | import io.reactivex.Observable 4 | import io.reactivex.android.schedulers.AndroidSchedulers 5 | import io.reactivex.disposables.Disposable 6 | import io.reactivex.schedulers.Schedulers 7 | 8 | /** 9 | * author :Peakmain 10 | * createTime:2022/08/02 11 | * mail:2726449200@qq.com 12 | * describe: 13 | */ 14 | class CommonRetrofitData(private val apiStatus: ApiStatus) : 15 | AbstractRetrofitData(apiStatus) { 16 | 17 | override fun createData(observable: Observable): Disposable { 18 | apiStatus.before() 19 | return observable.subscribeOn(Schedulers.io()) 20 | .observeOn(AndroidSchedulers.mainThread()).subscribe({ t -> 21 | apiStatus.success(t) 22 | }, { exception -> 23 | exception.printStackTrace() 24 | apiStatus.error(Exception(exception)) 25 | }) 26 | } 27 | } -------------------------------------------------------------------------------- /basicLibrary/src/main/java/com/peakmain/basiclibrary/network/strategy/CommonRetrofitStrategy.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.basiclibrary.network.strategy 2 | 3 | import com.peakmain.basiclibrary.helper.RetrofitHelper.buildOkHttpClient 4 | import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory 5 | import retrofit2.converter.gson.GsonConverterFactory 6 | 7 | /** 8 | * author :Peakmain 9 | * createTime:2022/08/02 10 | * mail:2726449200@qq.com 11 | * describe: 12 | */ 13 | class CommonRetrofitStrategy : IRetrofitStrategy { 14 | override fun createService(service: Class, baseUrl: String): T { 15 | val retrofit = retrofit2.Retrofit.Builder().baseUrl(baseUrl) 16 | .client(buildOkHttpClient()) 17 | .addConverterFactory(GsonConverterFactory.create()) 18 | .addCallAdapterFactory(RxJava2CallAdapterFactory.create()).build() 19 | return retrofit.create(service) 20 | } 21 | 22 | } -------------------------------------------------------------------------------- /basicLibrary/src/main/java/com/peakmain/basiclibrary/network/strategy/IRetrofitStrategy.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.basiclibrary.network.strategy 2 | 3 | /** 4 | * author :Peakmain 5 | * createTime:2022/08/02 6 | * mail:2726449200@qq.com 7 | * describe: 8 | */ 9 | interface IRetrofitStrategy { 10 | fun createService(service: Class, baseUrl: String): T 11 | } -------------------------------------------------------------------------------- /basicLibrary/src/main/java/com/peakmain/basiclibrary/permission/PermissionSettingFactory.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.basiclibrary.permission 2 | 3 | import android.content.Context 4 | import android.content.Intent 5 | import com.peakmain.basiclibrary.permission.setting.DefaultPermissionSetting 6 | import com.peakmain.basiclibrary.permission.setting.NotificationPermissionSetting 7 | 8 | 9 | /** 10 | * author :Peakmain 11 | * createTime:2022/08/12 12 | * mail:2726449200@qq.com 13 | * describe: 14 | */ 15 | internal object PermissionSettingFactory { 16 | /** 17 | * Build.MANUFACTURER 18 | */ 19 | private const val MANUFACTURER_HUAWEI = "HUAWEI" //华为 20 | 21 | private const val MANUFACTURER_MEIZU = "Meizu" //魅族 22 | 23 | private const val MANUFACTURER_XIAOMI = "Xiaomi" //小米 24 | 25 | private const val MANUFACTURER_SONY = "Sony" //索尼 26 | 27 | private const val MANUFACTURER_OPPO = "OPPO" //oppo 28 | 29 | private const val MANUFACTURER_LG = "LG" 30 | 31 | private const val MANUFACTURER_VIVO = "vivo" //vivo 32 | 33 | fun toAppSetting(context: Context?) { 34 | toAppSetting(context, false) 35 | } 36 | 37 | /** 38 | * @param isNotification 是否跳转系统的消息通知,true则表示想要跳转消息通知 39 | */ 40 | fun toAppSetting(context: Context?, isNotification: Boolean) { 41 | if (context == null) return 42 | if (!isNotification) { 43 | context.startActivity(getAppSettingIntent(context)) 44 | return 45 | } 46 | context.startActivity(NotificationPermissionSetting().getAppSetting(context)) 47 | } 48 | 49 | fun getAppSettingIntent(context: Context): Intent { 50 | /* return when (Build.MANUFACTURER) { 51 | MANUFACTURER_HUAWEI -> HuaWeiPermissionSetting().getAppSetting(context) 52 | MANUFACTURER_MEIZU -> MeiZuPermissionSetting().getAppSetting(context) 53 | MANUFACTURER_XIAOMI -> XiaomiPermissionSetting().getAppSetting(context) 54 | MANUFACTURER_SONY -> SonyPermissionSetting().getAppSetting(context) 55 | MANUFACTURER_OPPO -> OPPOPermissionSetting().getAppSetting(context) 56 | MANUFACTURER_VIVO -> VIVOPermissionSetting().getAppSetting(context) 57 | MANUFACTURER_LG -> LGPermissionSetting().getAppSetting(context) 58 | else -> DefaultPermissionSetting().getAppSetting(context) 59 | }*/ 60 | return DefaultPermissionSetting().getAppSetting(context) 61 | } 62 | 63 | 64 | } -------------------------------------------------------------------------------- /basicLibrary/src/main/java/com/peakmain/basiclibrary/permission/PkPermissionFragment.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.basiclibrary.permission 2 | 3 | import android.Manifest 4 | import android.os.Bundle 5 | import androidx.activity.result.contract.ActivityResultContracts 6 | import androidx.fragment.app.Fragment 7 | import com.peakmain.basiclibrary.constants.AndroidVersion 8 | import com.peakmain.basiclibrary.helper.PermissionHelper 9 | import com.peakmain.basiclibrary.interfaces.OnPermissionCallback 10 | import com.peakmain.basiclibrary.viewmodel.PkPermissionViewModel 11 | 12 | 13 | /** 14 | * author :Peakmain 15 | * createTime:2022/08/11 16 | * mail:2726449200@qq.com 17 | * describe: 18 | */ 19 | internal class PkPermissionFragment : Fragment() { 20 | 21 | private val mViewModel = PkPermissionViewModel() 22 | private var mSinglePermissionLauncher = 23 | registerForActivityResult(RequestPermissionContract()) { 24 | mViewModel.registerSingleForActivityResult( 25 | it, 26 | shouldShowRequestPermissionRationale(it.first) 27 | ) 28 | } 29 | private val mMultiPermissionLauncher = 30 | registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { 31 | mViewModel.registerMultiForActivityResult(it, { permission -> 32 | shouldShowRequestPermissionRationale(permission) 33 | }) { 34 | requestPermission( 35 | Manifest.permission.ACCESS_BACKGROUND_LOCATION, 36 | mViewModel.mOnPermissionCallback 37 | ) 38 | } 39 | 40 | } 41 | 42 | /** 43 | * 是否授予了某个权限 44 | */ 45 | fun isGranted(permission: String): Boolean { 46 | return PermissionHelper.instance.isGranted(permission) 47 | } 48 | 49 | fun isGranted(permissions: Array): Boolean { 50 | return PermissionHelper.instance.isGranted(permissions) 51 | } 52 | 53 | 54 | fun isRevoked(permission: String): Boolean { 55 | val fragmentActivity = activity ?: return false 56 | return !AndroidVersion.isAndroid6() || fragmentActivity.packageManager.isPermissionRevokedByPolicy( 57 | permission, 58 | fragmentActivity.packageName 59 | ) 60 | } 61 | 62 | override fun onCreate(savedInstanceState: Bundle?) { 63 | super.onCreate(savedInstanceState) 64 | mViewModel.mOnPermissionCallbackLiveData.observe(this, 65 | mViewModel.requestPermissionObserver( 66 | mSinglePermissionLauncher, 67 | mMultiPermissionLauncher 68 | ) { 69 | mViewModel.sBackgroundLocationPermission = true 70 | } 71 | ) 72 | } 73 | 74 | fun requestPermission(permission: String, block: OnPermissionCallback?) { 75 | mViewModel.mOnPermissionCallback = block 76 | mViewModel.mOnPermissionCallbackLiveData.value = arrayOf(permission) to block 77 | } 78 | 79 | /** 80 | * 申请权限 81 | */ 82 | fun requestPermissions(permissions: Array, block: OnPermissionCallback) { 83 | mViewModel.mOnPermissionCallback = block 84 | mViewModel.mOnPermissionCallbackLiveData.value = permissions to block 85 | } 86 | 87 | override fun onDestroy() { 88 | super.onDestroy() 89 | mViewModel.clearData() 90 | } 91 | 92 | } -------------------------------------------------------------------------------- /basicLibrary/src/main/java/com/peakmain/basiclibrary/permission/RequestPermissionContract.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.basiclibrary.permission 2 | 3 | import android.app.Activity 4 | import android.content.Context 5 | import android.content.Intent 6 | import android.content.pm.PackageManager 7 | import androidx.activity.result.contract.ActivityResultContract 8 | import androidx.activity.result.contract.ActivityResultContracts.RequestMultiplePermissions 9 | import androidx.activity.result.contract.ActivityResultContracts.RequestMultiplePermissions.Companion.ACTION_REQUEST_PERMISSIONS 10 | import androidx.activity.result.contract.ActivityResultContracts.RequestMultiplePermissions.Companion.EXTRA_PERMISSIONS 11 | import com.peakmain.basiclibrary.helper.PermissionHelper 12 | 13 | /** 14 | * author :Peakmain 15 | * createTime:2022/08/15 16 | * mail:2726449200@qq.com 17 | * describe: 18 | */ 19 | class RequestPermissionContract : ActivityResultContract>() { 20 | private var mPermission: String = "" 21 | override fun createIntent(context: Context, input: String): Intent { 22 | mPermission = input 23 | return Intent(ACTION_REQUEST_PERMISSIONS).putExtra(EXTRA_PERMISSIONS, arrayOf(input)) 24 | } 25 | 26 | override fun parseResult(resultCode: Int, intent: Intent?): Pair { 27 | if (intent == null || resultCode != Activity.RESULT_OK) return mPermission to false 28 | val grantResults = 29 | intent.getIntArrayExtra(RequestMultiplePermissions.EXTRA_PERMISSION_GRANT_RESULTS) 30 | return mPermission to 31 | if (grantResults == null || grantResults.isEmpty()) false 32 | else grantResults[0] == PackageManager.PERMISSION_GRANTED 33 | } 34 | 35 | override fun getSynchronousResult( 36 | context: Context, 37 | input: String 38 | ): SynchronousResult>? = when { 39 | PermissionHelper.instance.isGranted(input) -> SynchronousResult(input to true) 40 | else -> null 41 | } 42 | 43 | } -------------------------------------------------------------------------------- /basicLibrary/src/main/java/com/peakmain/basiclibrary/permission/interfaces/ICall.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.basiclibrary.permission.interfaces 2 | 3 | /** 4 | * author :Peakmain 5 | * createTime:2022/10/31 6 | * mail:2726449200@qq.com 7 | * describe: 8 | */ 9 | interface ICall: Cloneable { 10 | fun call() 11 | 12 | override fun clone():ICall 13 | } -------------------------------------------------------------------------------- /basicLibrary/src/main/java/com/peakmain/basiclibrary/permission/interfaces/IPermissionVersion.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.basiclibrary.permission.interfaces 2 | 3 | import com.peakmain.basiclibrary.permission.version.PermissionRequest 4 | 5 | /** 6 | * author :Peakmain 7 | * createTime:2022/10/31 8 | * mail:2726449200@qq.com 9 | * describe: 10 | */ 11 | interface IPermissionVersion { 12 | fun permissionVersion(chain: Chain): IPermissionVersion? 13 | interface Chain { 14 | fun request(): PermissionRequest 15 | fun proceed(request: PermissionRequest): IPermissionVersion 16 | } 17 | } -------------------------------------------------------------------------------- /basicLibrary/src/main/java/com/peakmain/basiclibrary/permission/setting/DefaultPermissionSetting.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.basiclibrary.permission.setting 2 | 3 | import android.content.Context 4 | import android.content.Intent 5 | import android.net.Uri 6 | import android.provider.Settings 7 | import com.peakmain.basiclibrary.interfaces.IPermissionSetting 8 | 9 | 10 | /** 11 | * author :Peakmain 12 | * createTime:2022/08/12 13 | * mail:2726449200@qq.com 14 | * describe: 15 | */ 16 | internal class DefaultPermissionSetting : IPermissionSetting { 17 | override fun getAppSetting(context: Context): Intent { 18 | try { 19 | val intent = Intent() 20 | intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) 21 | intent.action = Settings.ACTION_APPLICATION_DETAILS_SETTINGS 22 | intent.data = Uri.fromParts("package", context.packageName, null) 23 | return intent 24 | } catch (e: Exception) { 25 | e.printStackTrace() 26 | } 27 | //系统设置权限 28 | return Intent(Settings.ACTION_SETTINGS) 29 | } 30 | } -------------------------------------------------------------------------------- /basicLibrary/src/main/java/com/peakmain/basiclibrary/permission/setting/NotificationPermissionSetting.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.basiclibrary.permission.setting 2 | 3 | import android.content.Context 4 | import android.content.Intent 5 | import android.provider.Settings 6 | import com.peakmain.basiclibrary.constants.AndroidVersion 7 | import com.peakmain.basiclibrary.interfaces.IPermissionSetting 8 | 9 | /** 10 | * author :Peakmain 11 | * createTime:2022/10/25 12 | * mail:2726449200@qq.com 13 | * describe:android 13消息通知设置界面 14 | */ 15 | class NotificationPermissionSetting : IPermissionSetting { 16 | override fun getAppSetting(context: Context): Intent { 17 | if (AndroidVersion.isAndroid13()) { 18 | val applicationInfo = context.applicationInfo 19 | try { 20 | val intent = Intent() 21 | intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK 22 | intent.action = Settings.ACTION_APP_NOTIFICATION_SETTINGS 23 | intent.putExtra("app_package", applicationInfo.packageName) 24 | intent.putExtra(Settings.EXTRA_APP_PACKAGE, applicationInfo.packageName) 25 | intent.putExtra("app_uid", applicationInfo.uid) 26 | return intent 27 | } catch (t: Throwable) { 28 | t.printStackTrace() 29 | } 30 | } 31 | return DefaultPermissionSetting().getAppSetting(context) 32 | } 33 | } -------------------------------------------------------------------------------- /basicLibrary/src/main/java/com/peakmain/basiclibrary/permission/version/AndroidOtherPermissionVersion.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.basiclibrary.permission.version 2 | 3 | import android.Manifest 4 | import androidx.activity.result.ActivityResultLauncher 5 | import com.peakmain.basiclibrary.constants.AndroidVersion 6 | import com.peakmain.basiclibrary.extend.launchMulti 7 | import com.peakmain.basiclibrary.manager.PermissionHandlerManager 8 | import com.peakmain.basiclibrary.permission.interfaces.IPermissionVersion 9 | 10 | /** 11 | * author :Peakmain 12 | * createTime:2022/10/31 13 | * mail:2726449200@qq.com 14 | * describe: 15 | */ 16 | class AndroidOtherPermissionVersion( 17 | private val launcher: ActivityResultLauncher>, 18 | private val permissions: Array, 19 | private val block: (() -> Unit)? = null 20 | ) : 21 | IPermissionVersion { 22 | override fun permissionVersion(chain: IPermissionVersion.Chain): IPermissionVersion { 23 | val request = chain.request() 24 | val permissionList = request.permissionList 25 | if (!permissionList.contains(Manifest.permission.ACCESS_BACKGROUND_LOCATION)) { 26 | PermissionHandlerManager.instance.sendMessage(permissionList.toTypedArray()) 27 | launcher.launch(permissions) 28 | return this 29 | } 30 | if (permissionList.contains(Manifest.permission.ACCESS_COARSE_LOCATION) 31 | && !permissionList.contains(Manifest.permission.ACCESS_FINE_LOCATION) 32 | ) { 33 | permissionList.add(Manifest.permission.ACCESS_FINE_LOCATION) 34 | } 35 | //后台定位权限不要和其他权限一起申请 36 | for (permission in permissions) { 37 | if (permission != Manifest.permission.ACCESS_FINE_LOCATION || permission != Manifest.permission.ACCESS_COARSE_LOCATION || permission == Manifest.permission.ACCESS_BACKGROUND_LOCATION) { 38 | continue 39 | } 40 | throw IllegalArgumentException("因为有background location 权限, 请不要申请与位置无关的权限!!") 41 | } 42 | if (AndroidVersion.isAndroid10() && permissionList.size >= 2) { 43 | permissionList.remove(Manifest.permission.ACCESS_BACKGROUND_LOCATION) 44 | PermissionHandlerManager.instance.sendMessage(permissionList.toTypedArray()) 45 | launcher.launchMulti(permissionList.toTypedArray()) 46 | block?.invoke() 47 | return this 48 | } 49 | PermissionHandlerManager.instance.sendMessage(permissionList.toTypedArray()) 50 | launcher.launch(permissions) 51 | return this 52 | } 53 | } -------------------------------------------------------------------------------- /basicLibrary/src/main/java/com/peakmain/basiclibrary/permission/version/AndroidPermissionVersionImpl29.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.basiclibrary.permission.version 2 | 3 | import android.Manifest 4 | import android.os.Build 5 | import android.os.Environment 6 | import androidx.activity.result.ActivityResultLauncher 7 | import com.peakmain.basiclibrary.constants.AndroidVersion 8 | import com.peakmain.basiclibrary.permission.interfaces.IPermissionVersion 9 | 10 | /** 11 | * author :Peakmain 12 | * createTime:2022/10/31 13 | * mail:2726449200@qq.com 14 | * describe:android 10 15 | */ 16 | class AndroidPermissionVersionImpl29( 17 | ) : IPermissionVersion { 18 | override fun permissionVersion(chain: IPermissionVersion.Chain): IPermissionVersion? { 19 | val request = chain.request() 20 | if (Build.VERSION.SDK_INT == AndroidVersion.ANDROID_10) { 21 | val permissionList = request.permissionList 22 | if (permissionList.contains(Manifest.permission.MANAGE_EXTERNAL_STORAGE) 23 | && !Environment.isExternalStorageLegacy() 24 | ) { 25 | //有MANAGE_EXTERNAL_STORAGE权限,必须设置 android:requestLegacyExternalStorage="true" 26 | throw IllegalArgumentException("Application中必须设置android:requestLegacyExternalStorage=\"true\"") 27 | } 28 | } 29 | return chain.proceed(request) 30 | } 31 | } -------------------------------------------------------------------------------- /basicLibrary/src/main/java/com/peakmain/basiclibrary/permission/version/AndroidPermissionVersionImpl30.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.basiclibrary.permission.version 2 | 3 | import android.Manifest 4 | import androidx.activity.result.ActivityResultLauncher 5 | import com.peakmain.basiclibrary.constants.AndroidVersion 6 | import com.peakmain.basiclibrary.manager.PermissionHandlerManager 7 | import com.peakmain.basiclibrary.permission.interfaces.IPermissionVersion 8 | 9 | /** 10 | * author :Peakmain 11 | * createTime:2022/10/31 12 | * mail:2726449200@qq.com 13 | * describe:android 11 14 | */ 15 | class AndroidPermissionVersionImpl30( 16 | private val launcher: ActivityResultLauncher>, 17 | private val permissions: Array 18 | ) : IPermissionVersion { 19 | override fun permissionVersion(chain: IPermissionVersion.Chain): IPermissionVersion? { 20 | val request = chain.request() 21 | if (AndroidVersion.isAndroid11()) { 22 | val permissionList = request.permissionList 23 | if (permissionList.contains(Manifest.permission.MANAGE_EXTERNAL_STORAGE)) { 24 | PermissionHandlerManager.instance.sendMessage(permissionList.toTypedArray()) 25 | launcher.launch(permissions) 26 | return this 27 | } 28 | } 29 | return chain.proceed(request) 30 | } 31 | } -------------------------------------------------------------------------------- /basicLibrary/src/main/java/com/peakmain/basiclibrary/permission/version/AndroidPermissionVersionImpl31.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.basiclibrary.permission.version 2 | 3 | import android.Manifest 4 | import androidx.activity.result.ActivityResultLauncher 5 | import com.peakmain.basiclibrary.constants.AndroidVersion 6 | import com.peakmain.basiclibrary.manager.PermissionHandlerManager 7 | import com.peakmain.basiclibrary.permission.PkPermission 8 | import com.peakmain.basiclibrary.permission.interfaces.IPermissionVersion 9 | 10 | /** 11 | * author :Peakmain 12 | * createTime:2022/10/31 13 | * mail:2726449200@qq.com 14 | * describe:android 12 权限处理 15 | */ 16 | class AndroidPermissionVersionImpl31( 17 | private val launcher: ActivityResultLauncher>, 18 | private val permissions: Array 19 | ) : 20 | IPermissionVersion { 21 | override fun permissionVersion(chain: IPermissionVersion.Chain): IPermissionVersion { 22 | val request = chain.request() 23 | if (AndroidVersion.isAndroid12()) { 24 | val permissionList = request.permissionList 25 | if (permissionList.contains(Manifest.permission.ACCESS_FINE_LOCATION) && 26 | !permissionList.contains(Manifest.permission.ACCESS_COARSE_LOCATION) && !PkPermission.isGranted( 27 | Manifest.permission.ACCESS_COARSE_LOCATION 28 | ) 29 | ) { 30 | //Android 12必须添加ACCESS_COARSE_LOCATION 31 | //官方适配文档:https://developer.android.google.cn/about/versions/12/approximate-location 32 | throw IllegalArgumentException( 33 | "在android 12或更高的版本中,请勿单独请求ACCESS_FINE_LOCATION权限," + 34 | "而应在单个运行时请求中同时请求ACCESS_FINE_LOCATION和ACCESS_COARSE_LOCATION权限。" 35 | ) 36 | } 37 | if (permissionList.contains(Manifest.permission.BLUETOOTH_SCAN) 38 | || permissionList.contains(Manifest.permission.BLUETOOTH_CONNECT) 39 | || permissionList.contains(Manifest.permission.BLUETOOTH_ADVERTISE) 40 | ) { 41 | PermissionHandlerManager.instance.sendMessage(permissionList.toTypedArray()) 42 | launcher.launch(permissions) 43 | return this 44 | } 45 | } 46 | return chain.proceed(request) 47 | } 48 | } -------------------------------------------------------------------------------- /basicLibrary/src/main/java/com/peakmain/basiclibrary/permission/version/AndroidPermissionVersionImpl33.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.basiclibrary.permission.version 2 | 3 | import android.Manifest 4 | import androidx.activity.result.ActivityResultLauncher 5 | import com.peakmain.basiclibrary.constants.AndroidVersion 6 | import com.peakmain.basiclibrary.manager.PermissionHandlerManager 7 | import com.peakmain.basiclibrary.permission.interfaces.IPermissionVersion 8 | 9 | /** 10 | * author :Peakmain 11 | * createTime:2022/11/01 12 | * mail:2726449200@qq.com 13 | * describe:android 13权限 14 | */ 15 | class AndroidPermissionVersionImpl33( 16 | private val launcher: ActivityResultLauncher>, 17 | private val permissions: Array 18 | ) : 19 | IPermissionVersion { 20 | override fun permissionVersion(chain: IPermissionVersion.Chain): IPermissionVersion? { 21 | val request = chain.request() 22 | if (AndroidVersion.isAndroid13()) { 23 | val permissionList = request.permissionList 24 | if (permissionList.contains(Manifest.permission.POST_NOTIFICATIONS) 25 | || permissionList.contains(Manifest.permission.READ_MEDIA_IMAGES) 26 | || permissionList.contains(Manifest.permission.READ_MEDIA_AUDIO) 27 | || permissionList.contains(Manifest.permission.READ_MEDIA_VIDEO) 28 | || permissionList.contains(Manifest.permission.NEARBY_WIFI_DEVICES) 29 | ) { 30 | PermissionHandlerManager.instance.sendMessage(permissionList.toTypedArray()) 31 | launcher.launch(permissions) 32 | return this 33 | } 34 | } 35 | return chain.proceed(request) 36 | } 37 | } -------------------------------------------------------------------------------- /basicLibrary/src/main/java/com/peakmain/basiclibrary/permission/version/PermissionRequest.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.basiclibrary.permission.version 2 | 3 | /** 4 | * author :Peakmain 5 | * createTime:2022/10/31 6 | * mail:2726449200@qq.com 7 | * describe:权限的实体类 8 | */ 9 | class PermissionRequest constructor(var permissionList: MutableList) { 10 | 11 | } -------------------------------------------------------------------------------- /basicLibrary/src/main/java/com/peakmain/basiclibrary/permission/version/RealPermissionVersionCall.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.basiclibrary.permission.version 2 | 3 | import androidx.activity.result.ActivityResultLauncher 4 | import com.peakmain.basiclibrary.permission.interfaces.ICall 5 | import com.peakmain.basiclibrary.permission.interfaces.IPermissionVersion 6 | 7 | /** 8 | * author :Peakmain 9 | * createTime:2022/10/31 10 | * mail:2726449200@qq.com 11 | * describe: 12 | */ 13 | class RealPermissionVersionCall( 14 | private val permissions: Array, 15 | private val launcher: ActivityResultLauncher>, 16 | val block: (() -> Unit)? = null 17 | ) : ICall { 18 | 19 | override fun call() { 20 | val permissionVersionList = ArrayList() 21 | permissionVersionList.add(AndroidPermissionVersionImpl33(launcher, permissions)) 22 | permissionVersionList.add(AndroidPermissionVersionImpl31(launcher, permissions)) 23 | permissionVersionList.add(AndroidPermissionVersionImpl30(launcher, permissions)) 24 | permissionVersionList.add(AndroidPermissionVersionImpl29()) 25 | permissionVersionList.add(AndroidOtherPermissionVersion(launcher, permissions, block)) 26 | val permissionRequest = PermissionRequest(permissions.toMutableList()) 27 | val realPermissionVersionChain = RealPermissionVersionChain( 28 | permissionVersionList, 0, 29 | permissionRequest 30 | ) 31 | realPermissionVersionChain.proceed(permissionRequest) 32 | } 33 | 34 | override fun clone(): RealPermissionVersionCall { 35 | return RealPermissionVersionCall(permissions, launcher, block) 36 | } 37 | } -------------------------------------------------------------------------------- /basicLibrary/src/main/java/com/peakmain/basiclibrary/permission/version/RealPermissionVersionChain.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.basiclibrary.permission.version 2 | 3 | import com.peakmain.basiclibrary.permission.interfaces.IPermissionVersion 4 | 5 | /** 6 | * author :Peakmain 7 | * createTime:2022/10/31 8 | * mail:2726449200@qq.com 9 | * describe: 10 | */ 11 | class RealPermissionVersionChain( 12 | private val permissionVersionList: MutableList, 13 | private val index: Int, 14 | val request: PermissionRequest 15 | ) : IPermissionVersion.Chain { 16 | 17 | override fun request(): PermissionRequest { 18 | return request 19 | } 20 | 21 | override fun proceed(request: PermissionRequest): IPermissionVersion { 22 | if (index >= permissionVersionList.size) throw AssertionError() 23 | val realPermissionVersionChain = 24 | RealPermissionVersionChain(permissionVersionList, index + 1, request) 25 | val iPermissionVersion = permissionVersionList[index] 26 | return iPermissionVersion.permissionVersion(realPermissionVersionChain) 27 | ?: throw NullPointerException("permissionVersion returned null") 28 | } 29 | } -------------------------------------------------------------------------------- /basicLibrary/src/main/java/com/peakmain/basiclibrary/utils/ArithmeticUtils.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.basiclibrary.utils 2 | 3 | import android.text.TextUtils 4 | import java.math.BigDecimal 5 | 6 | /** 7 | * author :Peakmain 8 | * createTime:2022/3/1 9 | * mail:2726449200@qq.com 10 | * describe:算术工具类 11 | */ 12 | object ArithmeticUtils { 13 | fun add(d1: Double, d2: Double): Double { 14 | val str1 = d1.toString() 15 | val str2 = d2.toString() 16 | return add(str1, str2) 17 | } 18 | 19 | /** 20 | * 相加 21 | */ 22 | fun add(str1: String?, str2: String?): Double { 23 | val b1 = BigDecimal(str1) 24 | val b2 = BigDecimal(str2) 25 | return b1.add(b2).toDouble() 26 | } 27 | 28 | /** 29 | * 相减 30 | */ 31 | fun sub(d1: Double, d2: Double): Double { 32 | val str1 = d1.toString() 33 | val str2 = d2.toString() 34 | return sub(str1, str2) 35 | } 36 | 37 | /** 38 | * 相减 39 | */ 40 | fun sub(str1: String?, str2: String?): Double { 41 | val b1 = BigDecimal(str1) 42 | val b2 = BigDecimal(str2) 43 | return b1.subtract(b2).toDouble() 44 | } 45 | 46 | /** 47 | * 相乘 48 | */ 49 | fun mul(d1: Double, d2: Double): Double { 50 | val str1 = d1.toString() 51 | val str2 = d2.toString() 52 | return mul(str1, str2) 53 | } 54 | 55 | /** 56 | * 相乘 57 | */ 58 | fun mul(str1: String?, str2: String?): Double { 59 | val b1 = BigDecimal(str1) 60 | val b2 = BigDecimal(str2) 61 | return b1.multiply(b2).toDouble() 62 | } 63 | 64 | /** 65 | * 相除 66 | */ 67 | fun div(d1: Double, d2: Double): Double { 68 | return div(d1, d2, 10) 69 | } 70 | 71 | fun div(d1: Double, d2: Double, scale: Int): Double { 72 | require(scale >= 0) { "The scale must be a positive integer or zero" } 73 | val b1 = BigDecimal(d1.toString()) 74 | val b2 = BigDecimal(d2.toString()) 75 | return b1.divide(b2, scale, BigDecimal.ROUND_HALF_UP).toDouble() 76 | } 77 | 78 | /** 79 | * num.compareTo(BigDecimal.ZERO)结果: 80 | * num小于0 例如:num=-10.00 81 | * num等于0,例如num=0.00 82 | * num大于0 例如:num=10.00 83 | * 84 | * @param strValue 85 | * @return 浮点型是否大于0 86 | */ 87 | fun valueGreaterThanZero(strValue: String?): Boolean { 88 | // 为空时,认为大于0 89 | if (TextUtils.isEmpty(strValue)) { 90 | return false 91 | } 92 | val num = BigDecimal(strValue) 93 | val result = num.compareTo(BigDecimal.ZERO) 94 | return result == 1 95 | } 96 | 97 | /** 98 | * num.compareTo(BigDecimal.ZERO)结果: 99 | * num小于0 例如:num=-10.00 100 | * num等于0,例如num=0.00或 0 101 | * num大于0 例如:num=10.00 102 | * 103 | * @param strValue 104 | * @return 浮点型是否等于0 105 | */ 106 | fun valueEqualsZero(strValue: String?): Boolean { 107 | // 为空认为是0 108 | if (TextUtils.isEmpty(strValue)) { 109 | return true 110 | } 111 | val num = BigDecimal(strValue) 112 | val result = num.compareTo(BigDecimal.ZERO) 113 | return result == 0 114 | } 115 | } -------------------------------------------------------------------------------- /basicLibrary/src/main/java/com/peakmain/basiclibrary/utils/BasicLibraryUtils.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.basiclibrary.utils 2 | 3 | import android.app.Application 4 | import com.peakmain.basiclibrary.config.BasicLibraryConfig 5 | 6 | /** 7 | * author :Peakmain 8 | * createTime:2022/08/12 9 | * mail:2726449200@qq.com 10 | * describe: 11 | */ 12 | internal object BasicLibraryUtils { 13 | /** 14 | * 获取全局上下文 15 | */ 16 | @JvmStatic 17 | val application: Application? 18 | get() { 19 | return BasicLibraryConfig.getInstance()?.getApp()?.getApplication() 20 | } 21 | 22 | } -------------------------------------------------------------------------------- /basicLibrary/src/main/java/com/peakmain/basiclibrary/utils/BitmapUtils.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.basiclibrary.utils 2 | 3 | import android.graphics.Bitmap 4 | import android.graphics.BitmapFactory 5 | import android.net.Uri 6 | import java.io.File 7 | import java.io.FileOutputStream 8 | import kotlin.math.roundToInt 9 | 10 | /** 11 | * author :Peakmain 12 | * createTime:2022/09/02 13 | * mail:2726449200@qq.com 14 | * describe: 15 | */ 16 | object BitmapUtils { 17 | /** 18 | * Bitmap保存到sdk卡,并返回Uri 19 | */ 20 | fun bitmap2Uri(bitmap: Bitmap, savePath: String): Uri? { 21 | val file = File(savePath) 22 | if (!file.exists()) { 23 | file.mkdir() 24 | } 25 | val img = File(file.absolutePath + TimeUtils.getCurrentTime() + ".png") 26 | return try { 27 | val fos = FileOutputStream(img) 28 | bitmap.compress(Bitmap.CompressFormat.PNG, 90, fos) 29 | fos.flush() 30 | fos.close() 31 | Uri.fromFile(img) 32 | } catch (e: Exception) { 33 | e.printStackTrace() 34 | null 35 | } 36 | } 37 | 38 | /** 39 | * Bitmap保存到SD卡上,得到一个绝对路径 40 | */ 41 | fun getBitmapPath(bitmap: Bitmap, savePath: String): String? { 42 | val file = File(savePath) 43 | if (!file.exists()) { 44 | file.mkdir() 45 | } 46 | val img = File(file.absolutePath + TimeUtils.getCurrentTime() + ".png") 47 | return try { 48 | val fos = FileOutputStream(img) 49 | bitmap.compress(Bitmap.CompressFormat.PNG, 90, fos) 50 | fos.flush() 51 | fos.close() 52 | img.canonicalPath 53 | } catch (e: Exception) { 54 | e.printStackTrace() 55 | null 56 | } 57 | } 58 | 59 | /** 60 | * 计算图片的缩放值 61 | */ 62 | fun calculateInSampleSize(options: BitmapFactory.Options, reqWidth: Int, reqHeight: Int): Int { 63 | val height: Int = options.outHeight 64 | val width: Int = options.outWidth 65 | var inSampleSize = 1 66 | if (height > reqHeight || width > reqWidth) { 67 | val heightRatio = (height.toFloat() / reqHeight.toFloat()).roundToInt() 68 | val widthRatio = (width.toFloat() / reqWidth.toFloat()).roundToInt() 69 | inSampleSize = if (heightRatio < widthRatio) heightRatio else widthRatio 70 | } 71 | return inSampleSize 72 | } 73 | } -------------------------------------------------------------------------------- /basicLibrary/src/main/java/com/peakmain/basiclibrary/utils/FoldableDeviceUtils.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.basiclibrary.utils 2 | 3 | 4 | /** 5 | * author :Peakmain 6 | * createTime:2023/9/12 7 | * mail:2726449200@qq.com 8 | * describe: 9 | */ 10 | object FoldableDeviceUtils { 11 | /** 12 | * true表示是折叠状态 13 | * false表示展开状态 14 | */ 15 | fun isFold(): Boolean { 16 | val screenWidth: Int? = 17 | BasicLibraryUtils.application?.resources?.displayMetrics?.widthPixels 18 | 19 | if (SystemUtils.isSamsungFold()) { 20 | return screenWidth != 1768 21 | } 22 | if (SystemUtils.isHuaWeiFoldDevice()||SystemUtils.isGoogleFoldDevice()) { 23 | return screenWidth != 2200 24 | } 25 | if (SystemUtils.isVivoFoldDevice()||SystemUtils.isXiaomiFoldDevice()) { 26 | return screenWidth != 1916 27 | } 28 | return true 29 | } 30 | 31 | 32 | } -------------------------------------------------------------------------------- /basicLibrary/src/main/java/com/peakmain/basiclibrary/utils/GlobalCoroutineExceptionHandler.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.basiclibrary.utils 2 | 3 | import kotlinx.coroutines.CoroutineExceptionHandler 4 | import kotlin.coroutines.CoroutineContext 5 | 6 | /** 7 | * author :Peakmain 8 | * createTime:2022/2/15 9 | * mail:2726449200@qq.com 10 | * describe: 11 | */ 12 | class GlobalCoroutineExceptionHandler : CoroutineExceptionHandler { 13 | override val key = CoroutineExceptionHandler 14 | 15 | var coroutineExceptionCallback: ((context: CoroutineContext, exception: Throwable) -> Unit)? = 16 | null 17 | 18 | override fun handleException(context: CoroutineContext, exception: Throwable) { 19 | coroutineExceptionCallback?.let { 20 | it(context, exception) 21 | } 22 | } 23 | 24 | } -------------------------------------------------------------------------------- /basicLibrary/src/main/java/com/peakmain/basiclibrary/utils/ThreadUtils.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.basiclibrary.utils 2 | 3 | import android.os.Handler 4 | import android.os.Looper 5 | import com.peakmain.basiclibrary.config.BasicLibraryConfig 6 | import com.peakmain.basiclibrary.constants.AndroidVersion 7 | import java.util.concurrent.Executor 8 | import java.util.concurrent.RejectedExecutionException 9 | 10 | /** 11 | * author :Peakmain 12 | * createTime:2022/10/31 13 | * mail:2726449200@qq.com 14 | * describe:线程工具类 15 | */ 16 | object ThreadUtils { 17 | private val handler: Handler = object : Handler(Looper.getMainLooper()) { 18 | } 19 | private var mExecutor = HandlerExecutor(handler) 20 | 21 | /** 22 | * 获得主线程的线程池 23 | */ 24 | fun getMainExecutor(): Executor? { 25 | val application = BasicLibraryConfig.getInstance()?.getApp()?.getApplication() 26 | return if (AndroidVersion.isAndroid9()) 27 | application?.mainExecutor 28 | else 29 | mExecutor 30 | } 31 | 32 | class HandlerExecutor(private val mHandler: Handler) : Executor { 33 | override fun execute(command: Runnable?) { 34 | if (command != null && !mHandler.post(command)) { 35 | throw RejectedExecutionException("$mHandler is shutting down") 36 | } 37 | } 38 | 39 | } 40 | 41 | fun assertMainThread(methodName: String) { 42 | check(!isMainThread()) { 43 | ("Cannot invoke " + methodName + " on a background" 44 | + " thread") 45 | } 46 | } 47 | 48 | fun isMainThread(): Boolean { 49 | return Looper.getMainLooper().thread === Thread.currentThread() 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /basicLibrary/src/main/java/com/peakmain/basiclibrary/utils/TimeUtils.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.basiclibrary.utils 2 | 3 | import com.peakmain.basiclibrary.constants.AndroidVersion 4 | import java.text.SimpleDateFormat 5 | import java.util.* 6 | 7 | /** 8 | * author :Peakmain 9 | * createTime:2021/12/24 10 | * mail:2726449200@qq.com 11 | * describe: 12 | */ 13 | object TimeUtils { 14 | const val yyyy_MM_dd = "yyyy-MM-dd" 15 | private const val yyyy_MM_dd_HH_mm_ss = "yyyy-MM-dd HH:mm:ss" 16 | 17 | fun getCurrentTime(pattern: String=yyyy_MM_dd_HH_mm_ss): String { 18 | val currentTime = Date() 19 | val formatter = if (AndroidVersion.isAndroid7()) { 20 | SimpleDateFormat(pattern,Locale.getDefault(Locale.Category.FORMAT)) 21 | } else { 22 | SimpleDateFormat(pattern,Locale.CHINA) 23 | } 24 | return formatter.format(currentTime) 25 | } 26 | /** 27 | * 返回几就是周几 28 | */ 29 | fun getDayOfWeek(date: Date): Int { 30 | val c = Calendar.getInstance().also { 31 | it.time = date 32 | } 33 | val weekDay = c.get(Calendar.DAY_OF_WEEK) 34 | val day = (weekDay - 1) 35 | return if (day == 0) 7 else day 36 | } 37 | /** 38 | * 将指定的毫秒数转换为 以pattern参数自定义的格式返回 39 | */ 40 | fun ms2Date(_ms: Long, pattern: String): String { 41 | val date = Date(_ms) 42 | val format = SimpleDateFormat(pattern, Locale.getDefault()) 43 | return format.format(date) 44 | } 45 | /** 46 | * 将指定以pattern参数自定义的格式的时间转换为毫秒值 47 | */ 48 | fun date2Ms(_data: String, pattern: String): Long { 49 | val format = if(AndroidVersion.isAndroid7()){ 50 | SimpleDateFormat(pattern,Locale.getDefault(Locale.Category.FORMAT)) 51 | }else{ 52 | SimpleDateFormat(pattern,Locale.CHINA) 53 | } 54 | return try { 55 | val date = format.parse(_data) 56 | date?.time ?: 0 57 | } catch (e: Exception) { 58 | 0 59 | } 60 | } 61 | /** 62 | * 获取当前时间段 63 | * [h] 小时数,24小时制 64 | */ 65 | fun getCurrentTimeRange(h: String): String { 66 | var hour: Int 67 | try { 68 | hour = h.toInt() 69 | } catch (e: Exception) { 70 | hour = 0 71 | e.printStackTrace() 72 | } 73 | return when (hour) { 74 | 23, 0, 1 -> "半夜" 75 | in 2..5 -> "凌晨" 76 | in 6..9 -> "早上" 77 | in 9 until 12 -> "上午" 78 | in 12..13 -> "中午" 79 | in 14..18 -> "下午" 80 | in 19..22 -> "晚上" 81 | else -> "" 82 | } 83 | } 84 | 85 | /** 86 | * 获取[date2]比[date1]多的天数 87 | */ 88 | fun dateDifference(date1: Date, date2: Date): Int { 89 | val cal1 = Calendar.getInstance() 90 | cal1.time = date1 91 | val cal2 = Calendar.getInstance() 92 | cal2.time = date2 93 | val day1 = cal1[Calendar.DAY_OF_YEAR] 94 | val day2 = cal2[Calendar.DAY_OF_YEAR] 95 | val year1 = cal1[Calendar.YEAR] 96 | val year2 = cal2[Calendar.YEAR] 97 | return if (year1 != year2) { 98 | var timeDistance = 0 99 | for (i in year1 until year2) { 100 | timeDistance += if (i % 4 == 0 && i % 100 != 0 || i % 400 == 0) { 101 | //闰年 102 | 366 103 | } else {//不是闰年 104 | 365 105 | } 106 | } 107 | timeDistance + (day2 - day1) 108 | } else { 109 | day2 - day1 110 | } 111 | } 112 | 113 | } -------------------------------------------------------------------------------- /basicLibrary/src/main/java/com/peakmain/basiclibrary/utils/bus/RxBus.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.basiclibrary.utils.bus 2 | 3 | import androidx.lifecycle.* 4 | import com.peakmain.basiclibrary.utils.ThreadUtils 5 | import java.util.concurrent.ConcurrentHashMap 6 | import kotlin.collections.set 7 | 8 | /** 9 | * author :Peakmain 10 | * createTime:2021/5/12 11 | * mail:2726449200@qq.com 12 | * describe:LiveData实现事件分发总线 13 | */ 14 | class RxBus private constructor() { 15 | 16 | companion object { 17 | private val eventMap = ConcurrentHashMap>() 18 | val instance: RxBus by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) { 19 | RxBus() 20 | } 21 | } 22 | 23 | /** 24 | * register bus 25 | */ 26 | fun register(eventName: String): StickyLiveData { 27 | var liveData = eventMap[eventName] 28 | if (liveData == null) { 29 | liveData = 30 | StickyLiveData( 31 | eventName 32 | ) 33 | eventMap[eventName] = liveData 34 | } 35 | return liveData as StickyLiveData 36 | } 37 | 38 | class StickyLiveData(private val eventName: String) : LiveData() { 39 | internal var mData: T? = null 40 | internal var mVersion = 0 41 | private var mSticky: Boolean = false 42 | fun setData(data: T) { 43 | setValue(data) 44 | } 45 | 46 | fun postData(data: T) { 47 | super.postValue(data) 48 | } 49 | 50 | /** 51 | * @param sticky true表示是粘性事件,默认是false 52 | */ 53 | fun isSticky(sticky: Boolean) { 54 | mSticky = sticky 55 | } 56 | 57 | override fun setValue(value: T) { 58 | mData = value 59 | mVersion++ 60 | super.setValue(value) 61 | } 62 | 63 | override fun observe(owner: LifecycleOwner, observer: Observer) { 64 | observerSticky(owner, mSticky, observer) 65 | } 66 | 67 | private fun observerSticky( 68 | owner: LifecycleOwner, 69 | sticky: Boolean, 70 | observer: Observer 71 | ) { 72 | owner.lifecycle.addObserver(LifecycleEventObserver { _, event -> 73 | if (event == Lifecycle.Event.ON_DESTROY) { 74 | eventMap.remove(eventName) 75 | } 76 | }) 77 | super.observe( 78 | owner, 79 | StickyObserver( 80 | this, 81 | sticky, 82 | observer 83 | ) 84 | ) 85 | } 86 | } 87 | 88 | /** 89 | * sticky不等于true,只能接收到注册之后发送的消息,如果想接受先发送后注册的消息需要设置sticky为true 90 | */ 91 | class StickyObserver( 92 | private val stickyLiveData: StickyLiveData, 93 | private val sticky: Boolean, 94 | private val observer: Observer 95 | ) : Observer { 96 | private var lastVersion = stickyLiveData.mVersion 97 | override fun onChanged(t: T) { 98 | if (lastVersion >= stickyLiveData.mVersion) { 99 | if (sticky && stickyLiveData.mData != null) { 100 | observer.onChanged(t) 101 | } 102 | return 103 | } 104 | lastVersion = stickyLiveData.mVersion 105 | observer.onChanged(t) 106 | } 107 | 108 | } 109 | 110 | } 111 | -------------------------------------------------------------------------------- /basicLibrary/src/main/java/com/peakmain/basiclibrary/utils/keyboard/OnKeyboardListener.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.basiclibrary.utils.keyboard 2 | 3 | /** 4 | * author :Peakmain 5 | * createTime:1/22/22 6 | * mail:2726449200@qq.com 7 | * describe: 8 | */ 9 | interface OnKeyboardListener { 10 | /** 11 | * 键盘变化 12 | * @param isPopup the is popup 是否弹出 13 | * @param keyboardHeight the keyboard height 软键盘高度 14 | */ 15 | fun onKeyboardChange(isPopup: Boolean, keyboardHeight: Int) 16 | } -------------------------------------------------------------------------------- /basicLibrary/src/main/java/com/peakmain/basiclibrary/utils/mmkv/DefaultSharedPreferencesFactory.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.basiclibrary.utils.mmkv 2 | 3 | import android.content.Context 4 | 5 | /** 6 | * author :Peakmain 7 | * createTime:2021/12/23 8 | * mail:2726449200@qq.com 9 | * describe: 10 | */ 11 | class DefaultSharedPreferencesFactory(context: Context, override val key: String="basic_sp_key") : 12 | BaseSharedPreferencesFactory(context) -------------------------------------------------------------------------------- /basicLibrary/src/main/java/com/peakmain/basiclibrary/utils/mmkv/PreferencesUtils.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.basiclibrary.utils.mmkv 2 | 3 | import android.content.Context 4 | import java.lang.ref.WeakReference 5 | 6 | /** 7 | * author :Peakmain 8 | * createTime:2021/12/23 9 | * mail:2726449200@qq.com 10 | * describe: 11 | */ 12 | 13 | class PreferencesUtils private constructor(private val contextRef: WeakReference) { 14 | companion object { 15 | @Volatile 16 | private var instance: PreferencesUtils? = null 17 | 18 | @JvmStatic 19 | fun getInstance(context: Context): PreferencesUtils? { 20 | instance ?: synchronized(this) { 21 | instance ?: PreferencesUtils(WeakReference(context)).also { 22 | instance = it 23 | } 24 | } 25 | return instance 26 | } 27 | } 28 | 29 | private lateinit var mSharedPreferences: DefaultSharedPreferencesFactory 30 | fun getSharedPreferences(): DefaultSharedPreferencesFactory? { 31 | if (this::mSharedPreferences.isInitialized) { 32 | return mSharedPreferences 33 | } else { 34 | val context = contextRef.get() 35 | if (context != null) { 36 | return init(context) 37 | } 38 | } 39 | return null 40 | } 41 | 42 | private fun init(context: Context): DefaultSharedPreferencesFactory { 43 | mSharedPreferences = 44 | DefaultSharedPreferencesFactory( 45 | context 46 | ) 47 | return mSharedPreferences 48 | } 49 | 50 | fun saveParams(key: String, objects: Any) { 51 | getSharedPreferences()?.saveParams(key, objects) 52 | } 53 | 54 | fun getParam(key: String, defaultObject: Any?): Any? { 55 | return getSharedPreferences()?.getParam(key, defaultObject) 56 | } 57 | 58 | fun clearData() { 59 | getSharedPreferences()?.clearData() 60 | } 61 | } 62 | 63 | -------------------------------------------------------------------------------- /basicLibrary/src/main/java/com/peakmain/basiclibrary/utils/reflect/ReflectUtils.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.basiclibrary.utils.reflect 2 | 3 | import android.util.Log 4 | import java.lang.Exception 5 | import java.lang.reflect.Field 6 | 7 | /** 8 | * author :Peakmain 9 | * createTime:2022/3/1 10 | * mail:2726449200@qq.com 11 | * describe: 12 | */ 13 | object ReflectUtils { 14 | private const val TAG = "ReflectUtil" 15 | @JvmStatic 16 | fun invokeStaticMethod( 17 | clzName: String?, 18 | methodName: String?, 19 | methodParamTypes: Array?>, 20 | vararg methodParamValues: Any? 21 | ): Any? { 22 | if(clzName==null||methodName==null)return null 23 | try { 24 | val clz = Class.forName(clzName) 25 | val med = clz.getDeclaredMethod(methodName, *methodParamTypes) 26 | med.isAccessible = true 27 | return med.invoke(null, *methodParamValues) 28 | } catch (e: Exception) { 29 | Log.e(TAG, "invokeStaticMethod got Exception:", e) 30 | } 31 | return null 32 | } 33 | 34 | fun invokeMethod( 35 | clzName: String?, 36 | methodName: String?, 37 | methodReceiver: Any?, 38 | methodParamTypes: Array?>, 39 | vararg methodParamValues: Any? 40 | ): Any? { 41 | try { 42 | if (methodReceiver == null||clzName==null||methodName==null) { 43 | return null 44 | } 45 | val clz = Class.forName(clzName) 46 | val med = clz.getDeclaredMethod(methodName, *methodParamTypes) 47 | med.isAccessible = true 48 | return med.invoke(methodReceiver, *methodParamValues) 49 | } catch (e: Exception) { 50 | Log.e(TAG, "invokeStaticMethod got Exception:", e) 51 | } 52 | return null 53 | } 54 | 55 | fun getStaticField(clzName: String?, filedName: String?): Any? { 56 | if(clzName==null||filedName==null)return null 57 | try { 58 | var field: Field? = null 59 | val clz = Class.forName(clzName) 60 | field = clz.getField(filedName) 61 | if (field != null) { 62 | return field[""] 63 | } 64 | } catch (e: Exception) { 65 | Log.e(TAG, "getStaticField got Exception:", e) 66 | } 67 | return null 68 | } 69 | 70 | fun getField(clzName: String?, obj: Any?, filedName: String?): Any? { 71 | try { 72 | if (obj == null||clzName==null||filedName==null) { 73 | return null 74 | } 75 | val clz = Class.forName(clzName) 76 | val field = clz.getField(filedName) 77 | return field[obj] 78 | } catch (e: Exception) { 79 | Log.e(TAG, "getStaticField got Exception:", e) 80 | } 81 | return null 82 | } 83 | } -------------------------------------------------------------------------------- /basicLibrary/src/main/java/com/peakmain/basiclibrary/view/BindingView.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.basiclibrary.view 2 | 3 | import android.view.MotionEvent 4 | import android.view.View 5 | import android.widget.TextView 6 | import androidx.databinding.BindingAdapter 7 | import com.peakmain.basiclibrary.extend.clickViewDelay 8 | 9 | /** 10 | * author :Peakmain 11 | * createTime:2021/12/29 12 | * mail:2726449200@qq.com 13 | * describe: 14 | */ 15 | object BindingView { 16 | 17 | /** 18 | * 设置view的visibility 19 | */ 20 | @BindingAdapter(value = ["visibilityOrGone"]) 21 | @JvmStatic 22 | fun setViewVisibleOrGone(view: View, showVisibility: Boolean) { 23 | view.visibility = if (showVisibility) View.VISIBLE else View.GONE 24 | } 25 | 26 | @BindingAdapter(value = ["visibilityOrInVisible"]) 27 | @JvmStatic 28 | fun setViewVisibleOrInvisible(view: View, showVisibility: Boolean) { 29 | view.visibility = if (showVisibility) View.VISIBLE else View.INVISIBLE 30 | } 31 | 32 | /** 33 | * 防止多次重复点击 34 | */ 35 | @BindingAdapter(value = ["clickDelayTime", "click"], requireAll = false) 36 | @JvmStatic 37 | fun setViewClick(view: View, delayTime: Long = 0, block: View.OnClickListener? = null) { 38 | if (delayTime == 0L) { 39 | view.setOnClickListener(block) 40 | } else { 41 | view.clickViewDelay(delayTime) {v-> 42 | block?.let { 43 | block.onClick(v) 44 | } 45 | } 46 | } 47 | } 48 | 49 | /** 50 | * textView的drawableLeft和drawableRight的点击事件 51 | */ 52 | @BindingAdapter(value = ["drawableLeftClick", "drawableRightClick"], requireAll = false) 53 | @JvmStatic 54 | fun setTextViewDrawableClick( 55 | view: TextView, 56 | drawableLeftClick: View.OnClickListener? = null, 57 | drawableRightClick: View.OnClickListener? = null 58 | ) { 59 | view.run { 60 | setOnTouchListener(object : View.OnTouchListener { 61 | override fun onTouch(v: View, event: MotionEvent): Boolean { 62 | when (event.action) { 63 | MotionEvent.ACTION_DOWN -> { 64 | val drawableLeft = compoundDrawables[0] 65 | if (drawableLeft != null && event.rawX <= left + drawableLeft.bounds.width()) { 66 | drawableLeftClick?.let { 67 | drawableLeftClick.onClick(view) 68 | } 69 | return true 70 | } 71 | val drawableRight = compoundDrawables[2] 72 | return if (drawableRight != null && event.rawX >= width-paddingRight-drawableRight.intrinsicWidth) { // 增加了宽度,该方向+当前icon宽度 73 | drawableRightClick?.let { 74 | drawableRightClick.onClick(view) 75 | } 76 | true 77 | } else { 78 | false 79 | } 80 | } 81 | else -> return false 82 | } 83 | } 84 | }) 85 | } 86 | } 87 | } -------------------------------------------------------------------------------- /basicLibrary/src/main/java/com/peakmain/basiclibrary/viewmodel/EmptyViewModel.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.basiclibrary.viewmodel 2 | 3 | import com.peakmain.basiclibrary.base.viewmodel.BaseViewModel 4 | 5 | /** 6 | * author :Peakmain 7 | * createTime:2022/09/02 8 | * mail:2726449200@qq.com 9 | * describe: 10 | */ 11 | class EmptyViewModel:BaseViewModel() { 12 | override fun initModel() { 13 | 14 | } 15 | } -------------------------------------------------------------------------------- /basicLibrary/src/main/java/com/peakmain/basiclibrary/viewmodel/ImageSelectViewModel.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.basiclibrary.viewmodel 2 | 3 | import android.graphics.Bitmap 4 | import android.net.Uri 5 | import androidx.lifecycle.MutableLiveData 6 | import androidx.lifecycle.Observer 7 | import com.peakmain.basiclibrary.base.viewmodel.BaseViewModel 8 | import com.peakmain.basiclibrary.config.ImageRequestConfig 9 | import com.peakmain.basiclibrary.interfaces.OnImageSelectorCallback 10 | 11 | /** 12 | * author :Peakmain 13 | * createTime:2022/08/18 14 | * mail:2726449200@qq.com 15 | * describe: 16 | */ 17 | internal class ImageSelectViewModel : BaseViewModel() { 18 | var mStart = MutableLiveData(false) 19 | var mOnImageSelectorCallback: OnImageSelectorCallback? = null 20 | var mConfig: ImageRequestConfig? = null 21 | override fun initModel() { 22 | 23 | } 24 | 25 | fun clearImage() { 26 | mStart.value = null 27 | mOnImageSelectorCallback = null 28 | mConfig = null 29 | } 30 | 31 | fun registerSingleLauncher(uri: Uri?) { 32 | mStart.value = false 33 | mOnImageSelectorCallback?.onImageSelect(arrayListOf(uri)) 34 | } 35 | 36 | fun registerMultiLauncher(lists: List) { 37 | mStart.value = false 38 | mOnImageSelectorCallback?.onImageSelect(lists) 39 | } 40 | 41 | fun registerTakePicture(pair: Pair) { 42 | if (pair.first) { 43 | val bitmap = pair.second 44 | mOnImageSelectorCallback?.onImageSelect(bitmap) 45 | } 46 | mOnImageSelectorCallback = null 47 | } 48 | 49 | fun imageSelectorObserver( 50 | selectPhotoLauncher: ((ImageRequestConfig) -> Unit)? = null, 51 | selectMultiPhotoLauncher: ((ImageRequestConfig) -> Unit)? = null, 52 | takePictureLauncher: (() -> Unit)? = null 53 | ) 54 | : Observer = Observer { start -> 55 | mConfig?.also { 56 | if (!start) return@Observer 57 | if (it.imageType != 0 && it.isSingle) { 58 | selectPhotoLauncher?.invoke(it) 59 | } else if (it.imageType == 0) { 60 | takePictureLauncher?.invoke() 61 | } else { 62 | selectMultiPhotoLauncher?.invoke(it) 63 | } 64 | } 65 | } 66 | } -------------------------------------------------------------------------------- /basicLibrary/src/main/java/com/peakmain/basiclibrary/viewmodel/SameViewModel.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.basiclibrary.viewmodel 2 | 3 | import com.peakmain.basiclibrary.base.viewmodel.BaseViewModel 4 | 5 | /** 6 | * author :Peakmain 7 | * createTime:2021/12/27 8 | * mail:2726449200@qq.com 9 | * describe: 10 | */ 11 | internal abstract class SameViewModel:BaseViewModel(){ 12 | val content ="test" 13 | 14 | } -------------------------------------------------------------------------------- /basicLibrary/src/main/java/com/peakmain/basiclibrary/viewpage/DepthPageTransformer.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.basiclibrary.viewpage 2 | 3 | import android.view.View 4 | import androidx.viewpager.widget.ViewPager 5 | import kotlin.math.abs 6 | 7 | /** 8 | * author :Peakmain 9 | * createTime:2022/1/27 10 | * mail:2726449200@qq.com 11 | * describe:深度页面转换器 12 | */ 13 | 14 | class DepthPageTransformer : ViewPager.PageTransformer { 15 | companion object{ 16 | private const val MIN_SCALE = 0.75f 17 | 18 | } 19 | override fun transformPage(view: View, position: Float) { 20 | view.apply { 21 | val pageWidth = width 22 | when { 23 | position < -1 -> { // [-Infinity,-1) 24 | // This page is way off-screen to the left. 25 | alpha = 0f 26 | } 27 | position <= 0 -> { // [-1,0] 28 | // Use the default slide transition when moving to the left page 29 | alpha = 1f 30 | translationX = 0f 31 | scaleX = 1f 32 | scaleY = 1f 33 | } 34 | position <= 1 -> { // (0,1] 35 | visibility=View.VISIBLE 36 | // Fade the page out. 37 | alpha = 1 - position 38 | 39 | // Counteract the default slide transition 40 | translationX = pageWidth * -position 41 | 42 | // Scale the page down (between MIN_SCALE and 1) 43 | val scaleFactor = (MIN_SCALE + (1 - MIN_SCALE) * (1 - abs(position))) 44 | scaleX = scaleFactor 45 | scaleY = scaleFactor 46 | if(position==1f){ 47 | visibility=View.INVISIBLE 48 | } 49 | } 50 | else -> { // (1,+Infinity] 51 | // This page is way off-screen to the right. 52 | alpha = 0f 53 | } 54 | } 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /basicLibrary/src/main/java/com/peakmain/basiclibrary/viewpage/DepthPageTransformer2.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.basiclibrary.viewpage 2 | 3 | import android.view.View 4 | import androidx.viewpager2.widget.ViewPager2 5 | import kotlin.math.abs 6 | 7 | /** 8 | * author :Peakmain 9 | * createTime:2022/1/27 10 | * mail:2726449200@qq.com 11 | * describe:viewPager2->深度页面转换器 12 | */ 13 | 14 | class DepthPageTransformer2 : ViewPager2.PageTransformer { 15 | companion object{ 16 | private const val MIN_SCALE = 0.75f 17 | 18 | } 19 | override fun transformPage(view: View, position: Float) { 20 | view.apply { 21 | val pageWidth = width 22 | when { 23 | position < -1 -> { // [-Infinity,-1) 24 | // This page is way off-screen to the left. 25 | alpha = 0f 26 | } 27 | position <= 0 -> { // [-1,0] 28 | // Use the default slide transition when moving to the left page 29 | alpha = 1f 30 | translationX = 0f 31 | scaleX = 1f 32 | scaleY = 1f 33 | } 34 | position <= 1 -> { // (0,1] 35 | visibility=View.VISIBLE 36 | // Fade the page out. 37 | alpha = 1 - position 38 | 39 | // Counteract the default slide transition 40 | translationX = pageWidth * -position 41 | 42 | // Scale the page down (between MIN_SCALE and 1) 43 | val scaleFactor = (MIN_SCALE + (1 - MIN_SCALE) * (1 - abs(position))) 44 | scaleX = scaleFactor 45 | scaleY = scaleFactor 46 | if(position==1f){ 47 | visibility=View.INVISIBLE 48 | } 49 | } 50 | else -> { // (1,+Infinity] 51 | // This page is way off-screen to the right. 52 | alpha = 0f 53 | } 54 | } 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /basicLibrary/src/main/java/com/peakmain/basiclibrary/viewpage/ZoomOutPageTransformer.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.basiclibrary.viewpage 2 | 3 | import android.view.View 4 | import androidx.viewpager.widget.ViewPager 5 | import kotlin.math.abs 6 | 7 | /** 8 | * author :Peakmain 9 | * createTime:2022/1/27 10 | * mail:2726449200@qq.com 11 | * describe:缩小页面转换器 12 | */ 13 | class ZoomOutPageTransformer : ViewPager.PageTransformer { 14 | companion object { 15 | private const val MIN_SCALE = 0.85f 16 | private const val MIN_ALPHA = 0.5f 17 | } 18 | 19 | override fun transformPage(view: View, position: Float) { 20 | view.apply { 21 | val pageWidth = width 22 | val pageHeight = height 23 | when { 24 | position < -1 -> { 25 | alpha = 0f 26 | } 27 | position <= 1 -> { 28 | val scaleFactor = MIN_SCALE.coerceAtLeast(1 - abs(position)) 29 | val vertMargin = pageHeight * (1 - scaleFactor) / 2 30 | val horzMargin = pageWidth * (1 - scaleFactor) / 2 31 | translationX = if (position < 0) { 32 | horzMargin - vertMargin / 2 33 | } else { 34 | horzMargin + vertMargin / 2 35 | } 36 | scaleX = scaleFactor 37 | scaleY = scaleFactor 38 | alpha = MIN_ALPHA + 39 | (((scaleFactor - MIN_SCALE) / (1 - MIN_SCALE)) * (1 - MIN_ALPHA)) 40 | } 41 | else -> { 42 | alpha = 0f 43 | } 44 | } 45 | } 46 | } 47 | } -------------------------------------------------------------------------------- /basicLibrary/src/main/java/com/peakmain/basiclibrary/viewpage/ZoomOutPageTransformer2.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.basiclibrary.viewpage 2 | 3 | import android.view.View 4 | import androidx.viewpager2.widget.ViewPager2 5 | import kotlin.math.abs 6 | 7 | /** 8 | * author :Peakmain 9 | * createTime:2022/1/27 10 | * mail:2726449200@qq.com 11 | * describe:ViewPager2->缩小页面转换器 12 | */ 13 | class ZoomOutPageTransformer2 : ViewPager2.PageTransformer { 14 | companion object { 15 | private const val MIN_SCALE = 0.85f 16 | private const val MIN_ALPHA = 0.5f 17 | } 18 | 19 | override fun transformPage(view: View, position: Float) { 20 | view.apply { 21 | val pageWidth = width 22 | val pageHeight = height 23 | when { 24 | position < -1 -> { 25 | alpha = 0f 26 | } 27 | position <= 1 -> { 28 | val scaleFactor = MIN_SCALE.coerceAtLeast(1 - abs(position)) 29 | val vertMargin = pageHeight * (1 - scaleFactor) / 2 30 | val horzMargin = pageWidth * (1 - scaleFactor) / 2 31 | translationX = if (position < 0) { 32 | horzMargin - vertMargin / 2 33 | } else { 34 | horzMargin + vertMargin / 2 35 | } 36 | scaleX = scaleFactor 37 | scaleY = scaleFactor 38 | alpha = MIN_ALPHA + 39 | (((scaleFactor - MIN_SCALE) / (1 - MIN_SCALE)) * (1 - MIN_ALPHA)) 40 | } 41 | else -> { 42 | alpha = 0f 43 | } 44 | } 45 | } 46 | } 47 | } -------------------------------------------------------------------------------- /basicLibrary/src/main/res/anim/slide_in_from_top.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /basicLibrary/src/main/res/anim/slide_out_to_top.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /basicLibrary/src/main/res/drawable/library_clear_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /basicLibrary/src/main/res/drawable/library_done_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /basicLibrary/src/main/res/drawable/library_ic_left_black_back.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /basicLibrary/src/main/res/drawable/library_rotate_progressbar.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 12 | 17 | 18 | -------------------------------------------------------------------------------- /basicLibrary/src/main/res/layout-v21/layout_submit_loading.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 10 | 11 | 16 | 17 | 24 | 25 | 29 | 30 | 35 | 36 | 42 | 43 | 44 | 45 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /basicLibrary/src/main/res/layout/layout_submit_loading.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 10 | 11 | 15 | 16 | 23 | 24 | 28 | 29 | 34 | 35 | 41 | 42 | 43 | 44 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /basicLibrary/src/main/res/layout/library_dialog_top_toast.xml: -------------------------------------------------------------------------------- 1 | 2 | 14 | 15 | 24 | 25 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /basicLibrary/src/main/res/layout/library_recycler_foot_layout.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 10 | 11 | 14 | 15 | 16 | 17 | 18 | 25 | 26 | 31 | 32 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /basicLibrary/src/main/res/layout/same_layout.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 9 | 10 | 11 | 15 | 16 | 20 | 21 | -------------------------------------------------------------------------------- /basicLibrary/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #f3f3f3 4 | #77000000 5 | -------------------------------------------------------------------------------- /basicLibrary/src/main/res/values/ids.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /basicLibrary/src/main/res/values/string.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 加载中… 4 | 5 | 6 | 7 | 8 | com.android.vending 9 | 10 | com.tencent.android.qqdownloader 11 | 12 | com.qihoo.appstore 13 | 14 | com.baidu.appsearch 15 | 16 | com.xiaomi.market 17 | 18 | com.wandoujia.phoenix2 19 | 20 | com.huawei.appmarket 21 | 22 | com.taobao.appcenter 23 | 24 | com.hiapk.marketpho 25 | 26 | cn.goapk.market 27 | 28 | 29 | -------------------------------------------------------------------------------- /basicLibrary/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | MEIZU_FLAG_DARK_STATUS_BAR_ICON 4 | meizuFlags 5 | -------------------------------------------------------------------------------- /basicLibrary/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 21 | -------------------------------------------------------------------------------- /basicLibrary/src/main/res/xml/basic_library_provider_paths.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 9 | 12 | 13 | 16 | 17 | 20 | 21 | 24 | 25 | 28 | -------------------------------------------------------------------------------- /basicLibrary/src/main/resources/META-INF.services/kotlinx.coroutines.CoroutineExceptionHandler: -------------------------------------------------------------------------------- 1 | com.peakmain.basiclibrary.utils.GlobalCoroutineExceptionHandler -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | buildscript { 3 | ext.kotlin_version = '1.6.10' 4 | repositories { 5 | google() 6 | mavenCentral() 7 | maven { 8 | url "https://plugins.gradle.org/m2/" 9 | } 10 | } 11 | dependencies { 12 | classpath 'com.android.tools.build:gradle:4.2.2' 13 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 14 | // NOTE: Do not place your application dependencies here; they belong 15 | // in the individual module build.gradle files 16 | } 17 | } 18 | 19 | allprojects { 20 | repositories { 21 | google() 22 | mavenCentral() 23 | maven { url "https://jitpack.io" } 24 | maven { 25 | url "https://plugins.gradle.org/m2/" 26 | } 27 | } 28 | } 29 | task clean(type: Delete) { 30 | delete rootProject.buildDir 31 | } -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | # IDE (e.g. Android Studio) users: 3 | # Gradle settings configured through the IDE *will override* 4 | # any settings specified in this file. 5 | # For more details on how to configure your build environment visit 6 | # http://www.gradle.org/docs/current/userguide/build_environment.html 7 | # Specifies the JVM arguments used for the daemon process. 8 | # The setting is particularly useful for tweaking memory settings. 9 | org.gradle.jvmargs=-Xmx2048m 10 | # When configured, Gradle will run in incubating parallel mode. 11 | # This option should only be used with decoupled projects. More details, visit 12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 13 | # org.gradle.parallel=true 14 | # AndroidX package structure to make it clearer which packages are bundled with the 15 | # Android operating system, and which are packaged with your app"s APK 16 | # https://developer.android.com/topic/libraries/support-library/androidx-rn 17 | android.useAndroidX=true 18 | # Automatically convert third-party libraries to use AndroidX 19 | android.enableJetifier=true 20 | # Kotlin code style for this project: "official" or "obsolete": 21 | kotlin.code.style=official 22 | 23 | android.useNewApkCreator=false 24 | android.injected.testOnly=false 25 | kapt.use.worker.api=false 26 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Peakmain/BasicLibrary/0a5979492abbada1e4802c2172f0286f1ddc072a/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Thu Dec 23 10:17:40 CST 2021 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.7.1-all.zip 7 | -------------------------------------------------------------------------------- /jitpack.yml: -------------------------------------------------------------------------------- 1 | jdk: 2 | - openjdk11 -------------------------------------------------------------------------------- /settings.gradle.kts: -------------------------------------------------------------------------------- 1 | include (":app") 2 | include (":basicLibrary") 3 | rootProject.name = "BasicLibrary" 4 | rootProject.buildFileName="build.gradle" 5 | --------------------------------------------------------------------------------