├── .gitattributes ├── .github └── workflows │ └── android.yml ├── .gitignore ├── LICENSE ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── omarea │ │ └── filter │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── assets │ │ ├── for_atom.json │ │ ├── for_cepheus.json │ │ ├── for_cmi.json │ │ ├── for_perseus.json │ │ ├── for_pyxis.json │ │ ├── for_raphael.json │ │ ├── for_tucana.json │ │ ├── for_vela.json │ │ ├── lcd.json │ │ ├── oled.json │ │ └── ref.json │ ├── java │ │ └── com │ │ │ └── omarea │ │ │ └── filter │ │ │ ├── DynamicOptimize.kt │ │ │ ├── FilterApp.kt │ │ │ ├── FilterSample.kt │ │ │ ├── FilterView.kt │ │ │ ├── FilterViewConfig.kt │ │ │ ├── FilterViewManager.kt │ │ │ ├── GlobalStatus.kt │ │ │ ├── HelpActivity.kt │ │ │ ├── MainActivity.kt │ │ │ ├── NotificationHelper.kt │ │ │ ├── PopupBrightnessController.kt │ │ │ ├── ReceiverLock.kt │ │ │ ├── SampleData.kt │ │ │ ├── SampleDataView.kt │ │ │ ├── SampleEditActivity.kt │ │ │ ├── ScreenCapActivity.kt │ │ │ ├── ScreenEventHandler.kt │ │ │ ├── ScreenState.kt │ │ │ ├── SpfConfig.java │ │ │ ├── Utils.kt │ │ │ ├── broadcast │ │ │ ├── BrightnessControlerBroadcast.java │ │ │ └── ControllerClickedReceiver.kt │ │ │ ├── common │ │ │ ├── FileWrite.kt │ │ │ ├── KeepShell.kt │ │ │ ├── KeepShellPublic.kt │ │ │ ├── RadioGroupSimulator.kt │ │ │ ├── ScreenShotHelper.java │ │ │ ├── SystemProperty.java │ │ │ ├── UITools.java │ │ │ └── ViewHelper.kt │ │ │ ├── light │ │ │ ├── LightHandler.java │ │ │ ├── LightHistory.kt │ │ │ ├── LightSensorManager.java │ │ │ └── LightSensorWatcher.kt │ │ │ └── service │ │ │ ├── FilterAccessibilityService.kt │ │ │ ├── QuickSettingService.java │ │ │ ├── ScreenShotService.java │ │ │ ├── SwitchBrightnessModeService.java │ │ │ └── WindowAnalyzer.kt │ └── res │ │ ├── anim │ │ ├── dialog_enter.xml │ │ └── dialog_exit.xml │ │ ├── drawable │ │ ├── add.png │ │ ├── alpha_gradient.xml │ │ ├── bg_gradient.xml │ │ ├── blue_gradient.xml │ │ ├── brightness_auto.png │ │ ├── card_bg.xml │ │ ├── card_bg_dark.xml │ │ ├── dialog.png │ │ ├── dialog_icon_bg.xml │ │ ├── filter.png │ │ ├── glass.png │ │ ├── green_gradient.xml │ │ ├── ic_lightbulb.png │ │ ├── ic_settings.png │ │ ├── icon_brightness_auto.png │ │ ├── icon_brightness_manual.png │ │ ├── icon_power_off.png │ │ ├── icon_power_on.png │ │ ├── icon_question.png │ │ ├── icon_settings.png │ │ ├── icon_tuner.png │ │ ├── in_card_item.xml │ │ ├── light_sensor.png │ │ ├── minus.png │ │ ├── off.png │ │ ├── on.png │ │ ├── plus.png │ │ ├── power_off.png │ │ ├── power_on.png │ │ ├── power_switch_off.xml │ │ ├── power_switch_on.xml │ │ ├── power_switch_style.xml │ │ ├── progress_color.xml │ │ ├── progress_shape.xml │ │ ├── red_gradient.xml │ │ ├── seekbar_thumb_solid.xml │ │ ├── texture_paper1.png │ │ ├── texture_paper2.png │ │ ├── texture_sand1.png │ │ ├── texture_sand2.png │ │ ├── texture_sand3.png │ │ ├── texture_stripe1.png │ │ └── texture_stripe2.png │ │ ├── layout │ │ ├── activity_help.xml │ │ ├── activity_main.xml │ │ ├── activity_sample_edit.xml │ │ ├── content_main.xml │ │ ├── dialog_guide.xml │ │ ├── dialog_help_info.xml │ │ ├── dialog_loading.xml │ │ ├── filter.xml │ │ ├── filter_color_picker.xml │ │ ├── notification.xml │ │ ├── popup_controller.xml │ │ └── sample_edit.xml │ │ ├── menu │ │ └── menu_main.xml │ │ ├── mipmap │ │ └── ic_launcher.png │ │ ├── values │ │ ├── attrs.xml │ │ ├── attrs_my_view.xml │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── strings.xml │ │ └── styles.xml │ │ ├── xml-v25 │ │ └── shortcuts.xml │ │ └── xml │ │ └── filter_accessibility.xml │ └── test │ └── java │ └── com │ └── omarea │ └── filter │ └── ExampleUnitTest.java ├── build.gradle ├── common ├── .classpath ├── .gitignore ├── .project ├── .settings │ └── org.eclipse.buildship.core.prefs ├── build.gradle ├── libs │ ├── fastscroll_v1.2_20160903.jar │ └── overscroll-release-v1.1-20160904.jar ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── omarea │ │ └── common │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── omarea │ │ │ └── common │ │ │ ├── model │ │ │ └── SelectItem.kt │ │ │ ├── shared │ │ │ ├── BitmapUtil.java │ │ │ ├── FilePathResolver.java │ │ │ ├── FileWrite.kt │ │ │ ├── MagiskExtend.java │ │ │ ├── ObjectStorage.kt │ │ │ ├── RawText.kt │ │ │ └── RootFileInfo.kt │ │ │ ├── shell │ │ │ ├── AsynSuShellUnit.kt │ │ │ ├── KeepShell.kt │ │ │ ├── KeepShellAsync.kt │ │ │ ├── KeepShellPublic.kt │ │ │ ├── KernelProrp.kt │ │ │ ├── RootFile.kt │ │ │ ├── ShellEvents.kt │ │ │ └── ShellExecutor.java │ │ │ └── ui │ │ │ ├── AdapterAppChooser.kt │ │ │ ├── AdapterItemChooser.kt │ │ │ ├── AdapterItemChooser2.kt │ │ │ ├── BlurBackground.kt │ │ │ ├── DialogAppChooser.kt │ │ │ ├── DialogFullScreen.kt │ │ │ ├── DialogHelper.kt │ │ │ ├── DialogItemChooser.kt │ │ │ ├── DialogItemChooser2.kt │ │ │ ├── DialogItemChooserMini.kt │ │ │ ├── FastBlurUtility.java │ │ │ ├── OverScrollGridView.java │ │ │ ├── OverScrollListView.java │ │ │ ├── OverScrollView.java │ │ │ ├── ProgressBarDialog.kt │ │ │ ├── ProgressCircle.kt │ │ │ └── ThemeMode.kt │ └── res │ │ ├── anim │ │ ├── activity_close_enter.xml │ │ ├── activity_close_exit.xml │ │ ├── activity_open_enter.xml │ │ ├── activity_open_exit.xml │ │ ├── dialog_enter.xml │ │ ├── dialog_exit.xml │ │ ├── dialog_fade_in.xml │ │ ├── dialog_fade_out.xml │ │ ├── input_method_enter.xml │ │ ├── input_method_exit.xml │ │ ├── task_close_enter.xml │ │ ├── task_close_exit.xml │ │ ├── task_open_enter.xml │ │ ├── task_open_exit.xml │ │ ├── toast_enter.xml │ │ └── toast_exit.xml │ │ ├── drawable │ │ ├── btn_bg.xml │ │ ├── btn_bg_active.xml │ │ ├── btn_bg_active_large.xml │ │ ├── btn_bg_disabled.xml │ │ ├── btn_bg_disabled_large.xml │ │ ├── btn_bg_inactive.xml │ │ ├── btn_bg_inactive_large.xml │ │ ├── btn_bg_inactive_large_secondary.xml │ │ ├── btn_bg_inactive_large_warning.xml │ │ ├── btn_bg_large.xml │ │ ├── btn_bg_large_secondary.xml │ │ ├── btn_bg_large_warning.xml │ │ ├── checkbox_false.xml │ │ ├── checkbox_style.xml │ │ ├── checkbox_true.xml │ │ ├── confirm_dialog_bg.xml │ │ ├── dialog_search_bg.xml │ │ ├── dialog_search_clear.png │ │ ├── in_card_item_inactive.xml │ │ ├── radio_false.xml │ │ ├── radio_style.xml │ │ ├── radio_true.xml │ │ ├── seekbar_big_thumb.xml │ │ ├── seekbar_progress_big_drawable.xml │ │ ├── seekbar_progress_drawable.xml │ │ ├── seekbar_progress_icon.xml │ │ ├── seekbar_thumb.xml │ │ ├── switch_thumb.xml │ │ ├── switch_track.xml │ │ ├── switch_track_close.xml │ │ ├── switch_track_disabled.xml │ │ └── switch_track_open.xml │ │ ├── layout │ │ ├── app_multiple_chooser_item.xml │ │ ├── app_single_chooser_item.xml │ │ ├── dialog_alert.xml │ │ ├── dialog_app_chooser.xml │ │ ├── dialog_confirm.xml │ │ ├── dialog_confirm_custom.xml │ │ ├── dialog_help_info.xml │ │ ├── dialog_item_chooser.xml │ │ ├── dialog_item_chooser_small.xml │ │ ├── dialog_loading.xml │ │ ├── dialog_loading_accurate.xml │ │ ├── dialog_warning.xml │ │ ├── item_multiple_chooser_item.xml │ │ └── item_single_chooser_item.xml │ │ ├── values-v23 │ │ └── styles.xml │ │ └── values │ │ ├── attrs.xml │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── omarea │ └── common │ └── ExampleUnitTest.java ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.github/workflows/android.yml: -------------------------------------------------------------------------------- 1 | name: Android CI 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | pull_request: 7 | branches: [ master ] 8 | 9 | jobs: 10 | build: 11 | 12 | runs-on: ubuntu-latest 13 | 14 | steps: 15 | - uses: actions/checkout@v2 16 | - name: set up JDK 11 17 | uses: actions/setup-java@v2 18 | with: 19 | java-version: '11' 20 | distribution: 'adopt' 21 | cache: gradle 22 | 23 | - name: Grant execute permission for gradlew 24 | run: chmod +x gradlew 25 | - name: Build with Gradle 26 | run: ./gradlew build 27 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .idea 3 | .gradle 4 | .DS_Store 5 | build 6 | app/build/* 7 | app/release/* 8 | *.log 9 | local.properties 10 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | apply plugin: 'kotlin-android' 3 | apply plugin: 'kotlin-android-extensions' 4 | android { 5 | signingConfigs { 6 | omarea_Signing { 7 | keyAlias 'omarea.com' 8 | keyPassword 'asdf1234' 9 | storeFile file('D:/omoarea.jks') 10 | storePassword 'asdf1234' 11 | } 12 | } 13 | compileSdkVersion 28 14 | defaultConfig { 15 | resConfigs "zh" 16 | applicationId "com.omarea.filter" 17 | minSdkVersion 21 18 | targetSdkVersion 28 19 | versionCode 224 20 | versionName "2.0.0 Beta4" 21 | testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner' 22 | } 23 | buildTypes { 24 | release { 25 | shrinkResources true 26 | minifyEnabled true 27 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 28 | debuggable = false 29 | } 30 | debug { 31 | // signingConfig signingConfigs.omarea_Signing 32 | minifyEnabled false 33 | debuggable = true 34 | } 35 | } 36 | } 37 | 38 | dependencies { 39 | implementation fileTree(include: ['*.jar'], dir: 'libs') 40 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 41 | implementation 'androidx.appcompat:appcompat:1.2.0' 42 | implementation 'androidx.constraintlayout:constraintlayout:2.0.4' 43 | implementation 'com.google.android.material:material:1.2.1' 44 | implementation project(':common') 45 | // testImplementation 'junit:junit:4.12' 46 | // androidTestImplementation 'com.android.support.test:runner:1.0.2' 47 | // androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' 48 | } 49 | -------------------------------------------------------------------------------- /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 | -keepclassmembers class com.omarea.filter.ScreenCapActivity 24 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/omarea/filter/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.omarea.filter; 2 | 3 | import android.content.Context; 4 | import android.support.test.InstrumentationRegistry; 5 | import android.support.test.runner.AndroidJUnit4; 6 | 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | 10 | import static org.junit.Assert.assertEquals; 11 | 12 | /** 13 | * Instrumented test, which will execute on an Android device. 14 | * 15 | * @see Testing documentation 16 | */ 17 | @RunWith(AndroidJUnit4.class) 18 | public class ExampleInstrumentedTest { 19 | @Test 20 | public void useAppContext() { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getTargetContext(); 23 | 24 | assertEquals("com.example.filter", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/assets/for_atom.json: -------------------------------------------------------------------------------- 1 | { 2 | "samples": { 3 | "0": 10, 4 | "1": 85, 5 | "14": 113, 6 | "49": 160, 7 | "250": 200, 8 | "350": 250, 9 | "1500": 450, 10 | "3000": 500, 11 | "4000": 870, 12 | "10000": 900, 13 | "20000": 1000 14 | }, 15 | "screenMinLightDC": 251, 16 | "screenMinLight": 10, 17 | "filterColor": -16777216 18 | } 19 | -------------------------------------------------------------------------------- /app/src/main/assets/for_cepheus.json: -------------------------------------------------------------------------------- 1 | { 2 | "samples": { 3 | "0": 25, 4 | "1": 85, 5 | "49": 160, 6 | "250": 200, 7 | "350": 250, 8 | "1500": 450, 9 | "3000": 500, 10 | "10000": 900, 11 | "20000": 1000 12 | }, 13 | "screenMinLightDC": 300, 14 | "screenMinLight": 10 15 | } -------------------------------------------------------------------------------- /app/src/main/assets/for_cmi.json: -------------------------------------------------------------------------------- 1 | { 2 | "samples": { 3 | "0": 50, 4 | "15": 80, 5 | "23": 110, 6 | "93": 150, 7 | "171": 169, 8 | "336": 200, 9 | "415": 240, 10 | "1500": 450, 11 | "3000": 500, 12 | "10000": 900, 13 | "20000": 1000 14 | }, 15 | "screenMinLightDC": 220, 16 | "screenMinLight": 10 17 | } -------------------------------------------------------------------------------- /app/src/main/assets/for_perseus.json: -------------------------------------------------------------------------------- 1 | { 2 | "samples": { 3 | "0": 25, 4 | "1": 85, 5 | "49": 160, 6 | "250": 200, 7 | "350": 250, 8 | "1500": 450, 9 | "3000": 500, 10 | "10000": 900, 11 | "20000": 1000 12 | }, 13 | "screenMinLightDC": 300, 14 | "screenMinLight": 10 15 | } -------------------------------------------------------------------------------- /app/src/main/assets/for_pyxis.json: -------------------------------------------------------------------------------- 1 | { 2 | "samples": { 3 | "0": 25, 4 | "1": 85, 5 | "49": 160, 6 | "250": 200, 7 | "350": 250, 8 | "1500": 450, 9 | "3000": 500, 10 | "10000": 900, 11 | "20000": 1000 12 | }, 13 | "screenMinLightDC": 300, 14 | "screenMinLight": 10 15 | } -------------------------------------------------------------------------------- /app/src/main/assets/for_raphael.json: -------------------------------------------------------------------------------- 1 | { 2 | "samples": { 3 | "0": 25, 4 | "1": 85, 5 | "49": 160, 6 | "250": 200, 7 | "350": 250, 8 | "1500": 450, 9 | "3000": 500, 10 | "10000": 900, 11 | "20000": 1000 12 | }, 13 | "screenMinLightDC": 300, 14 | "screenMinLight": 10 15 | } -------------------------------------------------------------------------------- /app/src/main/assets/for_tucana.json: -------------------------------------------------------------------------------- 1 | { 2 | "desc": "配置格式为[lux]:[brightness],亮度值(brightness)范围是5~1000,环境光(lux)值范围是0~40000", 3 | "samples": { 4 | "0": 80, 5 | "4": 85, 6 | "5": 110, 7 | "6": 117, 8 | "45": 124, 9 | "100": 130, 10 | "102": 140, 11 | "150": 210, 12 | "1163": 532, 13 | "4000": 772, 14 | "6695": 1000 15 | }, 16 | "screenMinLightDC": 700, 17 | "screenMinLight": 10 18 | } -------------------------------------------------------------------------------- /app/src/main/assets/for_vela.json: -------------------------------------------------------------------------------- 1 | { 2 | "samples": { 3 | "0": 25, 4 | "1": 85, 5 | "49": 160, 6 | "250": 200, 7 | "350": 250, 8 | "1500": 450, 9 | "3000": 500, 10 | "10000": 900, 11 | "20000": 1000 12 | }, 13 | "screenMinLightDC": 300, 14 | "screenMinLight": 10 15 | } -------------------------------------------------------------------------------- /app/src/main/assets/lcd.json: -------------------------------------------------------------------------------- 1 | { 2 | "samples": { 3 | "0": 25, 4 | "1": 85, 5 | "49": 160, 6 | "250": 200, 7 | "350": 250, 8 | "1500": 450, 9 | "3000": 500, 10 | "10000": 900, 11 | "20000": 1000 12 | }, 13 | "screenMinLight": 10 14 | } -------------------------------------------------------------------------------- /app/src/main/assets/oled.json: -------------------------------------------------------------------------------- 1 | { 2 | "desc": "配置格式为[lux]:[brightness],亮度值(brightness)范围是5~1000,环境光(lux)值范围是0~40000", 3 | "samples": { 4 | "0": 25, 5 | "1": 85, 6 | "49": 160, 7 | "250": 200, 8 | "350": 250, 9 | "1500": 450, 10 | "3000": 500, 11 | "10000": 900, 12 | "20000": 1000 13 | }, 14 | "screenMinLight": "1000" 15 | } -------------------------------------------------------------------------------- /app/src/main/assets/ref.json: -------------------------------------------------------------------------------- 1 | [[1000,0.9923076923076923],[995,0.9846153846153847],[990,0.9738461538461538],[985,0.9661538461538461],[980,0.9569230769230769],[975,0.9476923076923077],[970,0.9292307692307692],[965,0.9215384615384615],[960,0.9123076923076923],[955,0.9030769230769231],[950,0.8938461538461538],[945,0.8769230769230769],[940,0.8692307692307693],[935,0.86],[930,0.8523076923076923],[925,0.8384615384615385],[920,0.8215384615384616],[915,0.8153846153846154],[910,0.8061538461538461],[905,0.7984615384615384],[900,0.7938461538461539],[895,0.7753846153846153],[890,0.7692307692307693],[885,0.7630769230769231],[880,0.7523076923076923],[875,0.7476923076923077],[870,0.74],[865,0.7215384615384616],[860,0.7153846153846154],[855,0.7061538461538461],[850,0.703076923076923],[845,0.6938461538461539],[840,0.6846153846153846],[835,0.6784615384615384],[830,0.6707692307692308],[825,0.6646153846153846],[820,0.6584615384615384],[815,0.6446153846153846],[810,0.6384615384615384],[805,0.6323076923076923],[800,0.6246153846153846],[795,0.6215384615384615],[790,0.6076923076923076],[785,0.6015384615384616],[780,0.5938461538461538],[775,0.5876923076923077],[770,0.58],[765,0.5738461538461539],[760,0.56],[755,0.5538461538461539],[750,0.5476923076923077],[745,0.5415384615384615],[740,0.5338461538461539],[735,0.5215384615384615],[730,0.5153846153846153],[725,0.5092307692307693],[720,0.5030769230769231],[715,0.4969230769230769],[710,0.4876923076923077],[705,0.48],[600,0.48],[695,0.4753846153846154],[690,0.46923076923076923],[685,0.45692307692307693],[680,0.4523076923076923],[675,0.4461538461538462],[670,0.44153846153846155],[665,0.4338461538461538],[660,0.4276923076923077],[655,0.41846153846153844],[650,0.4169230769230769],[645,0.4107692307692308],[640,0.4046153846153846],[635,0.4015384615384615],[630,0.3923076923076923],[625,0.38769230769230767],[620,0.38153846153846155],[615,0.3769230769230769],[610,0.3707692307692308],[605,0.36153846153846153],[600,0.3569230769230769],[595,0.34923076923076923],[590,0.34615384615384615],[585,0.3415384615384615],[580,0.33076923076923076],[575,0.3261538461538461],[570,0.32153846153846155],[565,0.31846153846153846],[560,0.31384615384615383],[555,0.31076923076923074],[550,0.29846153846153844],[545,0.2953846153846154],[540,0.2907692307692308],[535,0.28615384615384615],[530,0.2815384615384615],[525,0.27076923076923076],[520,0.2676923076923077],[515,0.26153846153846155],[510,0.25846153846153846],[505,0.25384615384615383],[500,0.24461538461538462],[495,0.24153846153846154],[490,0.23692307692307693],[485,0.2323076923076923],[480,0.2276923076923077],[475,0.22],[470,0.2169230769230769],[465,0.2123076923076923],[460,0.20923076923076922],[455,0.2076923076923077],[450,0.20153846153846153],[445,0.19538461538461538],[440,0.19384615384615383],[435,0.18769230769230769],[430,0.18461538461538463],[425,0.18153846153846154],[420,0.17384615384615384],[415,0.17076923076923076],[410,0.1676923076923077],[405,0.16615384615384615],[400,0.16307692307692306],[395,0.15538461538461537],[390,0.1523076923076923],[385,0.14923076923076922],[380,0.14615384615384616],[375,0.14153846153846153],[370,0.14],[365,0.13538461538461538],[360,0.13230769230769232],[355,0.12923076923076923],[350,0.12307692307692308],[345,0.12],[340,0.11384615384615385],[335,0.1123076923076923],[330,0.10923076923076923],[325,0.10615384615384615],[320,0.10307692307692308],[315,0.09846153846153846],[310,0.09538461538461539],[305,0.09384615384615384],[300,0.09076923076923077],[295,0.0876923076923077],[290,0.08307692307692308],[285,0.08153846153846153],[280,0.07846153846153846],[275,0.07692307692307693],[270,0.07692307692307693],[265,0.07076923076923076],[260,0.06923076923076923],[255,0.06769230769230769],[250,0.06461538461538462],[245,0.06307692307692307],[240,0.06153846153846154],[235,0.055384615384615386],[230,0.05384615384615385],[225,0.052307692307692305],[220,0.05076923076923077],[215,0.04923076923076923],[210,0.046153846153846156],[205,0.04461538461538461],[200,0.043076923076923075],[195,0.04],[190,0.038461538461538464],[185,0.033846153846153845],[180,0.03230769230769231],[175,0.03076923076923077],[170,0.027692307692307693],[165,0.018461538461538463],[160,0.013846153846153847],[35,0.010769230769230769],[30,0.009230769230769232],[25,0.006153846153846154],[20,0.003076923076923077],[15,0]] -------------------------------------------------------------------------------- /app/src/main/java/com/omarea/filter/DynamicOptimize.kt: -------------------------------------------------------------------------------- 1 | package com.omarea.filter 2 | 3 | import android.content.SharedPreferences 4 | import java.util.* 5 | 6 | class DynamicOptimize { 7 | private val enableLuxOptimize = false 8 | private fun luxOptimization(lux: Float): Float { 9 | if (!enableLuxOptimize) { 10 | return lux 11 | } 12 | 13 | val calendar = Calendar.getInstance() 14 | val hour = calendar.get(Calendar.HOUR_OF_DAY) 15 | // 日间传感器数值补偿 16 | if (hour in 7..20) { 17 | if (lux <= 2f) { 18 | // 不在深夜时段,且光线传感器数值小于2,返回2,避免正常使用时间误入暗光模式,导致屏幕太暗 19 | return 2f 20 | } 21 | } else if (lux < 1f) { 22 | return 0f 23 | } 24 | 25 | return lux 26 | } 27 | 28 | private val nightTime = 20 * 60 + 50 // 夜晚时间 20:50 29 | private val lateNightTime = 22 * 60 // 深夜时间 22:00 30 | private val morningTime = 7 * 60 + 30 // 早晨 7:30 31 | private val dawnTime = 6 * 60 // 黎明 6:00 32 | private fun brightnessOptimization(): Double { 33 | var offsetValue: Double = 0.toDouble() 34 | val calendar = Calendar.getInstance() 35 | val value = calendar.get(Calendar.HOUR_OF_DAY) * 60 + calendar.get(Calendar.MINUTE) 36 | 37 | // 在深夜光线极暗的情况下 38 | if (value >= nightTime || value < morningTime) { 39 | if (value >= nightTime) { 40 | offsetValue -= ((value - nightTime) / 10.0 / 23) // 24:00 - 20:30 = 210 , 210 / 10.0 / 23 ≈ 0.9 41 | } else if (value < dawnTime) { 42 | offsetValue -= 0.9 43 | } else if (value < morningTime) { 44 | offsetValue -= ((morningTime - value) / 10.0 / 10) // 7:30 - 6:00 = 90 , 90 / 10.0 / 10 ≈ 0.9 45 | } 46 | } 47 | 48 | return offsetValue * 0.7 49 | } 50 | 51 | fun optimizedBrightness(lux: Float, config: SharedPreferences): Int? { 52 | val luxValue = if (lux < 0) 0f else lux 53 | val optimizedLux = luxOptimization(luxValue) 54 | 55 | // 亮度微调 56 | val staticOffset = config.getInt(SpfConfig.BRIGTHNESS_OFFSET, SpfConfig.BRIGTHNESS_OFFSET_DEFAULT) / 100.0 57 | var offsetPractical = 0.0 58 | 59 | // 夜间微调 60 | if (config.getBoolean(SpfConfig.DYNAMIC_OPTIMIZE, SpfConfig.DYNAMIC_OPTIMIZE_DEFAULT)) { 61 | val dynamicOptimizeLux = config.getFloat(SpfConfig.DYNAMIC_OPTIMIZE_LIMIT, SpfConfig.DYNAMIC_OPTIMIZE_LIMIT_DEFAULT) 62 | if (luxValue <= dynamicOptimizeLux) { 63 | offsetPractical += brightnessOptimization() 64 | } 65 | } 66 | 67 | 68 | val sampleValue = GlobalStatus.sampleData?.getVitualSample(optimizedLux) 69 | sampleValue?.run { 70 | val value = (((sampleValue) * (1 + offsetPractical)) + (FilterViewConfig.FILTER_BRIGHTNESS_MAX * staticOffset)).toInt() 71 | 72 | return (if (value > FilterViewConfig.FILTER_BRIGHTNESS_MAX) { 73 | FilterViewConfig.FILTER_BRIGHTNESS_MAX 74 | } else if (value < FilterViewConfig.FILTER_BRIGHTNESS_MIN) { 75 | FilterViewConfig.FILTER_BRIGHTNESS_MIN 76 | } else { 77 | value 78 | }) 79 | } 80 | return null 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /app/src/main/java/com/omarea/filter/FilterApp.kt: -------------------------------------------------------------------------------- 1 | package com.omarea.filter 2 | 3 | import android.app.Application 4 | import android.content.Context 5 | import android.os.Handler 6 | import android.os.Looper 7 | 8 | class FilterApp : Application() { 9 | companion object { 10 | lateinit var context: Context 11 | val handler = Handler(Looper.getMainLooper()) 12 | } 13 | 14 | override fun attachBaseContext(base: Context?) { 15 | super.attachBaseContext(base) 16 | context = this 17 | } 18 | } -------------------------------------------------------------------------------- /app/src/main/java/com/omarea/filter/FilterSample.kt: -------------------------------------------------------------------------------- 1 | package com.omarea.filter 2 | 3 | import org.json.JSONArray 4 | import java.nio.charset.Charset 5 | import java.util.* 6 | import kotlin.collections.LinkedHashMap 7 | 8 | class FilterSample { 9 | companion object { 10 | // 样本数据(lux, Sample) 11 | private var samples = TreeMap() 12 | } 13 | 14 | private fun init() { 15 | val customConfig = FilterApp.context.assets.open("ref.json").readBytes() 16 | 17 | val originData = JSONArray(String(customConfig, Charset.defaultCharset())) 18 | val temp = LinkedHashMap() 19 | for (index in 0 until originData.length()) { 20 | val sample = originData.getJSONArray(index) 21 | val filter = sample.getInt(0) 22 | val ratio = sample.getDouble(1) 23 | 24 | if (!temp.containsKey(ratio)) { 25 | temp.put(ratio, filter) 26 | } 27 | } 28 | temp.keys.sorted().forEach { 29 | temp.get(it)?.let { it1 -> samples.put(it, it1) } 30 | } 31 | } 32 | 33 | fun getFilterAlpha(targetRatio: Int): Int? { 34 | return getFilterAlpha(if (targetRatio > FilterViewConfig.FILTER_MAX_ALPHA) { 35 | 1.0 36 | } else if (targetRatio < 1) { 37 | 0.001 38 | } else { 39 | targetRatio.toDouble() / FilterViewConfig.FILTER_MAX_ALPHA 40 | }) 41 | } 42 | 43 | fun getFilterAlpha(targetRatio: Double): Int? { 44 | if (samples.isEmpty()) { 45 | init() 46 | } 47 | 48 | val ratio: Double = if (targetRatio > 1) { 49 | 1.0 50 | } else if (targetRatio < 0.001) { 51 | 0.001 52 | } else { 53 | targetRatio 54 | } 55 | 56 | if (samples.size > 1) { 57 | // 如果有现成的样本 直接获取样本值 58 | if (samples.containsKey(ratio)) { 59 | return FilterViewConfig.FILTER_MAX_ALPHA - (samples.get(ratio) as Int) 60 | } else { 61 | // 计算生成虚拟样本 62 | var rangeMin = samples.keys.first() 63 | var rangeMax = samples.keys.last() 64 | 65 | val alpha = FilterViewConfig.FILTER_MAX_ALPHA - (if (ratio < rangeMin) { 66 | samples[rangeMin]!! 67 | } else if (ratio > rangeMax) { 68 | samples[rangeMax]!! 69 | } else { 70 | for (sampleKey in samples.keys) { 71 | if (ratio > sampleKey) { 72 | rangeMin = sampleKey 73 | } else { 74 | rangeMax = sampleKey 75 | break 76 | } 77 | } 78 | val rangeLeftBrightness = samples.get(rangeMin)!! 79 | val rangeRightBrightness = samples.get(rangeMax)!! 80 | if (rangeLeftBrightness == rangeRightBrightness || rangeMin == rangeMax) { 81 | return rangeLeftBrightness 82 | } 83 | (rangeLeftBrightness + ((rangeRightBrightness - rangeLeftBrightness) * (ratio - rangeMin) / (rangeMax - rangeMin)).toInt()) 84 | } 85 | ) 86 | return alpha 87 | } 88 | } 89 | return null 90 | } 91 | } -------------------------------------------------------------------------------- /app/src/main/java/com/omarea/filter/FilterViewConfig.kt: -------------------------------------------------------------------------------- 1 | package com.omarea.filter 2 | 3 | class FilterViewConfig { 4 | // 0 - 1000 // 1000表示全黑,0 表示不使用滤镜 5 | internal var filterAlpha = 0 6 | 7 | // 0 - 1000,1000 表示最大亮度 8 | internal var filterBrightness = FILTER_BRIGHTNESS_MAX 9 | 10 | // 是否平滑变更 11 | internal var smoothChange = true 12 | 13 | /** 14 | * 获取亮度的比率(0.00 ~ 1.00) 15 | */ 16 | internal fun getFilterBrightnessRatio(): Float { 17 | return (filterBrightness.toFloat() / FILTER_BRIGHTNESS_MAX) 18 | } 19 | 20 | companion object { 21 | var FILTER_BRIGHTNESS_MAX = 1000 22 | var FILTER_BRIGHTNESS_MIN = 1 23 | var FILTER_MAX_ALPHA = 1000 24 | private val filterSample = FilterSample() 25 | 26 | fun getDefault(): FilterViewConfig { 27 | return FilterViewConfig() 28 | } 29 | 30 | /** 31 | * 根据所需的亮度值获取滤镜配置 32 | */ 33 | fun getConfigByBrightness(brightness: Int, screenMinLight: Int = FILTER_BRIGHTNESS_MAX): FilterViewConfig { 34 | val brightnessValue = if (brightness < FILTER_BRIGHTNESS_MIN) { 35 | FILTER_BRIGHTNESS_MIN 36 | } else if (brightness > FILTER_BRIGHTNESS_MAX) { 37 | FILTER_BRIGHTNESS_MAX 38 | } else { 39 | brightness 40 | } 41 | 42 | if (screenMinLight == FILTER_BRIGHTNESS_MAX) { 43 | val config = getDefault() 44 | config.filterBrightness = FILTER_BRIGHTNESS_MAX 45 | config.filterAlpha = filterSample.getFilterAlpha(brightnessValue)!! 46 | return config 47 | } else { 48 | return getConfigByRatio(getBrightnessRatio(brightnessValue), screenMinLight) 49 | } 50 | } 51 | 52 | /** 53 | * 根据亮度值获取亮度比率(0.01~1) 54 | */ 55 | fun getBrightnessRatio(brightness: Int): Float { 56 | if (brightness > 1000) { 57 | return 1f 58 | } else if (brightness < 1) { 59 | return 0.01f 60 | } 61 | return (brightness / 1000.0).toFloat() 62 | } 63 | 64 | fun getConfigByRatio(ratio: Float, screenMinLight: Int): FilterViewConfig { 65 | val config = getDefault() 66 | var avalibRatio = ratio 67 | if (ratio > 1) { 68 | avalibRatio = 1f 69 | } else if (ratio < 0f) { 70 | avalibRatio = 0.01f 71 | } 72 | 73 | if (screenMinLight == FILTER_BRIGHTNESS_MAX) { 74 | config.filterAlpha = filterSample.getFilterAlpha(avalibRatio.toDouble())!! 75 | config.filterBrightness = FILTER_BRIGHTNESS_MAX 76 | } else { 77 | // 如果亮度还没低于屏幕最低亮度限制 78 | if (avalibRatio >= screenMinLight.toFloat() / FILTER_BRIGHTNESS_MAX) { 79 | config.filterAlpha = 0 80 | config.filterBrightness = (avalibRatio * FILTER_BRIGHTNESS_MAX).toInt() 81 | } else { 82 | val filterAlpha = filterSample.getFilterAlpha(avalibRatio.toDouble() * FILTER_BRIGHTNESS_MAX / screenMinLight)!! 83 | config.filterAlpha = filterAlpha 84 | config.filterBrightness = screenMinLight 85 | } 86 | } 87 | return config 88 | } 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /app/src/main/java/com/omarea/filter/GlobalStatus.kt: -------------------------------------------------------------------------------- 1 | package com.omarea.filter 2 | 3 | object GlobalStatus { 4 | var filterEnabled = false 5 | 6 | var currentLux: Float = 0F 7 | var avgLux: Float = 0F 8 | var currentFilterBrightness: Int = 0 9 | var currentFilterAlpah: Int = 0 10 | var sampleData: SampleData? = null 11 | 12 | var filterOpen: Runnable? = null 13 | var filterUpdateTexture: Runnable? = null 14 | var filterClose: Runnable? = null 15 | var filterRefresh: Runnable? = null 16 | var filterManualUpdate: Runnable? = null 17 | var filterManualBrightness: Int = -1 18 | var screenCap: Runnable? = null 19 | var isLandscape = false 20 | } 21 | -------------------------------------------------------------------------------- /app/src/main/java/com/omarea/filter/HelpActivity.kt: -------------------------------------------------------------------------------- 1 | package com.omarea.filter 2 | 3 | import android.os.Bundle 4 | import android.widget.Toast 5 | import androidx.appcompat.app.AppCompatActivity 6 | import androidx.appcompat.widget.Toolbar 7 | 8 | class HelpActivity : AppCompatActivity() { 9 | private var filterEnabled = GlobalStatus.filterEnabled 10 | override fun onCreate(savedInstanceState: Bundle?) { 11 | super.onCreate(savedInstanceState) 12 | 13 | val intent = this.intent 14 | if (intent != null && intent.action != null) { 15 | val action = intent.action 16 | if (action == "open") { 17 | if (!GlobalStatus.filterEnabled && GlobalStatus.filterOpen != null) { 18 | GlobalStatus.filterOpen?.run() 19 | } 20 | Toast.makeText(this, "滤镜已开启", Toast.LENGTH_SHORT).show() 21 | finish() 22 | return 23 | } else if (action == "close") { 24 | if (GlobalStatus.filterEnabled && GlobalStatus.filterClose != null) { 25 | GlobalStatus.filterClose?.run() 26 | } 27 | Toast.makeText(this, "滤镜已关闭", Toast.LENGTH_SHORT).show() 28 | finish() 29 | return 30 | } 31 | } 32 | 33 | setTheme(if (filterEnabled) R.style.AppTheme_Default else R.style.AppTheme_OFF) 34 | 35 | setContentView(R.layout.activity_help) 36 | val toolbar = findViewById(R.id.toolbar) 37 | setSupportActionBar(toolbar) 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /app/src/main/java/com/omarea/filter/ReceiverLock.kt: -------------------------------------------------------------------------------- 1 | package com.omarea.filter 2 | 3 | import android.content.BroadcastReceiver 4 | import android.content.Context 5 | import android.content.Intent 6 | import android.content.IntentFilter 7 | import android.os.Build 8 | import android.os.Handler 9 | 10 | /** 11 | * 监听屏幕开关事件 12 | * Created by Hello on 2018/01/23. 13 | */ 14 | 15 | class ReceiverLock(private var callbacks: Handler) : BroadcastReceiver() { 16 | override fun onReceive(p0: Context?, p1: Intent?) { 17 | if (p1 == null) { 18 | return 19 | } 20 | when (p1.action) { 21 | Intent.ACTION_SCREEN_OFF -> { 22 | try { 23 | callbacks.sendMessage(callbacks.obtainMessage(8)) 24 | } catch (ex: Exception) { 25 | } 26 | } 27 | Intent.ACTION_USER_PRESENT, 28 | Intent.ACTION_USER_UNLOCKED, 29 | Intent.ACTION_SCREEN_ON -> { 30 | try { 31 | callbacks.sendMessage(callbacks.obtainMessage(7)) 32 | } catch (ex: Exception) { 33 | } 34 | } 35 | } 36 | } 37 | 38 | companion object { 39 | private var receiver: ReceiverLock? = null 40 | fun autoRegister(context: Context, callbacks: Handler): ReceiverLock? { 41 | if (receiver != null) { 42 | unRegister(context) 43 | } 44 | 45 | receiver = ReceiverLock(callbacks) 46 | 47 | context.applicationContext.registerReceiver(receiver, IntentFilter(Intent.ACTION_SCREEN_OFF)) 48 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { 49 | context.applicationContext.registerReceiver(receiver, IntentFilter(Intent.ACTION_USER_UNLOCKED)) 50 | } 51 | context.applicationContext.registerReceiver(receiver, IntentFilter(Intent.ACTION_SCREEN_ON)) 52 | context.applicationContext.registerReceiver(receiver, IntentFilter(Intent.ACTION_USER_PRESENT)) 53 | 54 | 55 | 56 | return receiver 57 | } 58 | 59 | fun unRegister(context: Context) { 60 | if (receiver == null) { 61 | return 62 | } 63 | try { 64 | context.applicationContext.unregisterReceiver(receiver) 65 | receiver = null 66 | } catch (ex: java.lang.Exception) { 67 | } 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /app/src/main/java/com/omarea/filter/ScreenCapActivity.kt: -------------------------------------------------------------------------------- 1 | package com.omarea.filter 2 | 3 | import android.app.Activity 4 | import android.os.Bundle 5 | import android.widget.Toast 6 | 7 | class ScreenCapActivity : Activity() { 8 | 9 | override fun onCreate(savedInstanceState: Bundle?) { 10 | super.onCreate(savedInstanceState) 11 | 12 | val screenCap = GlobalStatus.screenCap 13 | if (screenCap != null) { 14 | screenCap.run() 15 | } else { 16 | Toast.makeText(this, "滤镜服务未启动", Toast.LENGTH_LONG).show() 17 | } 18 | 19 | finish() 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /app/src/main/java/com/omarea/filter/ScreenEventHandler.kt: -------------------------------------------------------------------------------- 1 | package com.omarea.filter 2 | 3 | import android.os.Handler 4 | import android.os.Looper 5 | import android.os.Message 6 | 7 | /** 8 | * 处理屏幕开关事件的Handler 9 | * Created by Hello on 2018/01/23. 10 | */ 11 | 12 | internal class ScreenEventHandler(private var onSceenOff: () -> Unit, private var onSceenOn: () -> Unit) : Handler(Looper.getMainLooper()) { 13 | override fun handleMessage(msg: Message?) { 14 | super.handleMessage(msg) 15 | if (msg == null) { 16 | return 17 | } 18 | 19 | when (msg.what) { 20 | 7 -> onSceenOn() //屏幕已解锁 21 | 8 -> onSceenOff() //屏幕已关闭 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /app/src/main/java/com/omarea/filter/ScreenState.kt: -------------------------------------------------------------------------------- 1 | package com.omarea.filter 2 | 3 | import android.app.KeyguardManager 4 | import android.content.Context 5 | import android.os.Build 6 | import android.view.Display 7 | import android.view.WindowManager 8 | 9 | class ScreenState(private var context: Context) { 10 | fun isScreenLocked(): Boolean { 11 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT_WATCH) { 12 | val windowManager = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager 13 | val display = windowManager.defaultDisplay 14 | if (display.state == Display.STATE_OFF) { 15 | return true 16 | } 17 | } 18 | 19 | val mKeyguardManager = context.getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager 20 | return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { 21 | mKeyguardManager.isDeviceLocked || mKeyguardManager.isKeyguardLocked 22 | } else { 23 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) { 24 | mKeyguardManager.inKeyguardRestrictedInputMode() || mKeyguardManager.isDeviceLocked || mKeyguardManager.isKeyguardLocked 25 | } else { 26 | mKeyguardManager.inKeyguardRestrictedInputMode() || mKeyguardManager.isKeyguardLocked 27 | } 28 | } 29 | } 30 | 31 | fun isScreenOn(): Boolean { 32 | return !isScreenLocked() 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /app/src/main/java/com/omarea/filter/SpfConfig.java: -------------------------------------------------------------------------------- 1 | package com.omarea.filter; 2 | 3 | public class SpfConfig { 4 | public static String FILTER_SPF = "FILTER_SPF"; 5 | 6 | // 亮度偏移量(1表示1%,100表示100%) 7 | public static String BRIGTHNESS_OFFSET = "BRIGTHNESS_OFFSET_V3"; 8 | public static int BRIGTHNESS_OFFSET_DEFAULT = 0; 9 | public static int BRIGTHNESS_OFFSET_LEVELS = 50; 10 | 11 | // 平滑亮度 12 | public static String SMOOTH_ADJUSTMENT = "SMOOTH_ADJUSTMENT"; 13 | public static boolean SMOOTH_ADJUSTMENT_DEFAULT = true; 14 | 15 | // 息屏暂停 16 | public static String SCREEN_OFF_PAUSE = "SCREEN_OFF_PAUSE"; 17 | public static boolean SCREEN_OFF_PAUSE_DEFAULT = true; 18 | 19 | // 息屏关闭滤镜 20 | public static String SCREEN_OFF_CLOSE = "SCREEN_OFF_CLOSE"; 21 | public static boolean SCREEN_OFF_CLOSE_DEFAULT = false; 22 | 23 | // 横屏优化 24 | public static String LANDSCAPE_OPTIMIZE = "LANDSCAPE_OPTIMIZE"; 25 | public static boolean LANDSCAPE_OPTIMIZE_DEFAULT = true; 26 | 27 | // 自动启动服务 28 | public static String FILTER_AUTO_START = "FILTER_AUTO_START"; 29 | public static boolean FILTER_AUTO_START_DEFAULT = false; 30 | 31 | public static String FILTER_ALIGN_START = "FILTER_ALIGN_START"; 32 | public static boolean FILTER_ALIGN_START_DEFAULT = false; 33 | 34 | // 屏幕最大亮度数值(通常是1-255,但是也有发现最大值可到2047甚至4095的) 35 | public static String SCREENT_MAX_LIGHT = "SCREENT_MAX_LIGHT"; 36 | public static int SCREENT_MAX_LIGHT_DEFAULT = 255; 37 | 38 | // 目标设备 39 | public static String TARGET_DEVICE = "TARGET_DEVICE"; 40 | public static int TARGET_DEVICE_AMOLED = 1; 41 | public static int TARGET_DEVICE_LCD = 2; 42 | 43 | // 屏幕最小亮度 44 | public static String SCREENT_MIN_LIGHT = "SCREENT_MAX_LIGHT"; 45 | public static int SCREENT_MIN_LIGHT_DEFAULT = 255; 46 | 47 | // 动态优化(虚拟环境) 48 | public static String DYNAMIC_OPTIMIZE = "DYNAMIC_OPTIMIZE"; 49 | public static boolean DYNAMIC_OPTIMIZE_DEFAULT = false; 50 | 51 | // 动态优化(虚拟环境) 亮度限制(Lux) 52 | public static String DYNAMIC_OPTIMIZE_LIMIT = "DYNAMIC_OPTIMIZE_LIMIT"; 53 | public static float DYNAMIC_OPTIMIZE_LIMIT_DEFAULT = 10; 54 | 55 | // 通知中心显示亮度控制器 56 | public static String BRIGHTNESS_CONTROLLER = "BRIGHTNESS_CONTROLLER"; 57 | public static boolean BRIGHTNESS_CONTROLLER_DEFAULT = false; 58 | 59 | // 纹理素材 60 | public static String TEXTURE = "TEXTURE"; 61 | public static int TEXTURE_DEFAULT = 0; 62 | } 63 | -------------------------------------------------------------------------------- /app/src/main/java/com/omarea/filter/Utils.kt: -------------------------------------------------------------------------------- 1 | package com.omarea.filter 2 | 3 | import android.content.Context 4 | import android.provider.Settings 5 | 6 | object Utils { 7 | internal fun getSystemBrightness(context: Context): Int { 8 | var systemBrightness = 0 9 | try { 10 | systemBrightness = Settings.System.getInt(context.contentResolver, Settings.System.SCREEN_BRIGHTNESS) 11 | } catch (e: Settings.SettingNotFoundException) { 12 | e.printStackTrace() 13 | } 14 | return systemBrightness 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /app/src/main/java/com/omarea/filter/broadcast/ControllerClickedReceiver.kt: -------------------------------------------------------------------------------- 1 | package com.omarea.filter.broadcast 2 | 3 | import android.content.BroadcastReceiver 4 | import android.content.Context 5 | import android.content.Intent 6 | import android.net.Uri 7 | import android.os.Build 8 | import android.provider.Settings 9 | import android.widget.Toast 10 | import com.omarea.filter.PopupBrightnessController 11 | 12 | class ControllerClickedReceiver : BroadcastReceiver() { 13 | 14 | override fun onReceive(context: Context, intent: Intent) { 15 | if (Build.VERSION.SDK_INT >= 23 && !Settings.canDrawOverlays(context)) { 16 | //若没有权限,提示获取 17 | //val intent = Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION); 18 | //startActivity(intent); 19 | val overlayPermission = Intent().addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) 20 | overlayPermission.action = "android.settings.APPLICATION_DETAILS_SETTINGS" 21 | overlayPermission.data = Uri.fromParts("package", context.packageName, null) 22 | Toast.makeText(context, "为[屏幕滤镜]授权显示悬浮窗权限,从而使用更便捷的亮度控制器!", Toast.LENGTH_LONG).show(); 23 | } else { 24 | PopupBrightnessController(context).open() 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /app/src/main/java/com/omarea/filter/common/KeepShellPublic.kt: -------------------------------------------------------------------------------- 1 | package com.omarea.filter.common 2 | 3 | /** 4 | * Created by Hello on 2018/01/23. 5 | */ 6 | object KeepShellPublic { 7 | private var keepShell: KeepShell? = null 8 | 9 | //执行脚本 10 | fun doCmdSync(cmd: String): String { 11 | if (keepShell == null) { 12 | keepShell = KeepShell() 13 | } 14 | return keepShell!!.doCmdSync(cmd) 15 | } 16 | 17 | //执行脚本 18 | fun checkRoot(): Boolean { 19 | if (keepShell == null) { 20 | keepShell = KeepShell() 21 | } 22 | return keepShell!!.checkRoot() 23 | } 24 | 25 | fun tryExit() { 26 | if (keepShell != null) { 27 | keepShell!!.tryExit() 28 | keepShell = null 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /app/src/main/java/com/omarea/filter/common/RadioGroupSimulator.kt: -------------------------------------------------------------------------------- 1 | package com.omarea.filter.common 2 | 3 | import android.widget.CompoundButton 4 | 5 | class RadioGroupSimulator { 6 | val radios = ArrayList() 7 | 8 | constructor(vararg items: CompoundButton) { 9 | items.iterator().forEach { 10 | radios.add(it) 11 | 12 | it.setOnClickListener { 13 | val isChecked = (it as CompoundButton).isChecked 14 | if (isChecked) { 15 | this.autoUnChecked(it) 16 | } else { 17 | this.autoCheck(it) 18 | } 19 | } 20 | it.setOnCheckedChangeListener { compoundButton, b -> 21 | if (b) { 22 | autoUnChecked(compoundButton) 23 | } 24 | } 25 | } 26 | 27 | // 如果发现有多个选中,自动取消多余的选中(只保留最后一个) 28 | val checkedItems = radios.filter { it.isChecked } 29 | if (checkedItems.size > 0) { 30 | val last = checkedItems.last() 31 | checkedItems.forEach { 32 | if (it != last) { 33 | it.isChecked = false 34 | } 35 | } 36 | } 37 | } 38 | 39 | private fun autoCheck(current: CompoundButton) { 40 | if (radios.filter { it.isChecked && it != current }.isEmpty()) { 41 | current.isChecked = true 42 | } 43 | } 44 | 45 | private fun autoUnChecked(current: CompoundButton) { 46 | radios.forEach { 47 | if (it != current) { 48 | it.isChecked = false 49 | } 50 | } 51 | } 52 | 53 | val checked: CompoundButton? 54 | get() { 55 | return radios.find { it.isChecked } 56 | } 57 | 58 | fun setCheckedByTag(value: Any) { 59 | val radio = radios.find { it.tag == value } 60 | radio?.isChecked = true 61 | } 62 | } -------------------------------------------------------------------------------- /app/src/main/java/com/omarea/filter/common/ScreenShotHelper.java: -------------------------------------------------------------------------------- 1 | package com.omarea.filter.common; 2 | 3 | import android.content.Context; 4 | import android.content.Intent; 5 | import android.content.res.Resources; 6 | import android.graphics.Bitmap; 7 | import android.graphics.PixelFormat; 8 | import android.hardware.display.DisplayManager; 9 | import android.hardware.display.VirtualDisplay; 10 | import android.media.Image; 11 | import android.media.ImageReader; 12 | import android.media.projection.MediaProjection; 13 | import android.media.projection.MediaProjectionManager; 14 | import android.os.AsyncTask; 15 | import android.os.Build; 16 | import android.os.Handler; 17 | 18 | import androidx.annotation.RequiresApi; 19 | 20 | import java.lang.ref.SoftReference; 21 | import java.nio.ByteBuffer; 22 | 23 | @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) 24 | public class ScreenShotHelper { 25 | 26 | private final SoftReference mRefContext; 27 | private final OnScreenShotListener mOnScreenShotListener; 28 | 29 | private final ImageReader mImageReader; 30 | private final MediaProjection mMediaProjection; 31 | private VirtualDisplay mVirtualDisplay; 32 | 33 | public ScreenShotHelper(Context context, int resultCode, Intent data, OnScreenShotListener onScreenShotListener) { 34 | this.mOnScreenShotListener = onScreenShotListener; 35 | this.mRefContext = new SoftReference(context); 36 | 37 | mMediaProjection = getMediaProjectionManager().getMediaProjection(resultCode, data); 38 | mImageReader = ImageReader.newInstance(getScreenWidth(), getScreenHeight(), PixelFormat.RGBA_8888, 1); 39 | } 40 | 41 | public static int getScreenWidth() { 42 | return Resources.getSystem().getDisplayMetrics().widthPixels; 43 | } 44 | 45 | public static int getScreenHeight() { 46 | return Resources.getSystem().getDisplayMetrics().heightPixels; 47 | } 48 | 49 | public void startScreenShot() { 50 | createVirtualDisplay(); 51 | 52 | Handler handler = new Handler(); 53 | handler.postDelayed(new Runnable() { 54 | @Override 55 | public void run() { 56 | new CreateBitmapTask().execute(); 57 | } 58 | }, 1000); 59 | } 60 | 61 | private MediaProjectionManager getMediaProjectionManager() { 62 | return (MediaProjectionManager) getContext().getSystemService( 63 | Context.MEDIA_PROJECTION_SERVICE); 64 | } 65 | 66 | private void createVirtualDisplay() { 67 | mVirtualDisplay = mMediaProjection.createVirtualDisplay( 68 | "screen-mirror", 69 | getScreenWidth(), 70 | getScreenHeight(), 71 | Resources.getSystem().getDisplayMetrics().densityDpi, 72 | DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR, 73 | mImageReader.getSurface(), 74 | null, 75 | null 76 | ); 77 | } 78 | 79 | private Context getContext() { 80 | return mRefContext.get(); 81 | } 82 | 83 | interface OnScreenShotListener { 84 | void onFinish(Bitmap bitmap); 85 | } 86 | 87 | public class CreateBitmapTask extends AsyncTask { 88 | 89 | @Override 90 | protected Bitmap doInBackground(Image... params) { 91 | Image image = mImageReader.acquireLatestImage(); 92 | int width = image.getWidth(); 93 | int height = image.getHeight(); 94 | final Image.Plane[] planes = image.getPlanes(); 95 | final ByteBuffer buffer = planes[0].getBuffer(); 96 | 97 | int pixelStride = planes[0].getPixelStride(); 98 | 99 | int rowStride = planes[0].getRowStride(); 100 | int rowPadding = rowStride - pixelStride * width; 101 | Bitmap bitmap = Bitmap.createBitmap(width + rowPadding / pixelStride, height, Bitmap.Config.ARGB_8888); 102 | bitmap.copyPixelsFromBuffer(buffer); 103 | bitmap = Bitmap.createBitmap(bitmap, 0, 0, width, height); 104 | image.close(); 105 | 106 | return bitmap; 107 | } 108 | 109 | @Override 110 | protected void onPostExecute(Bitmap bitmap) { 111 | super.onPostExecute(bitmap); 112 | mVirtualDisplay.release(); 113 | mMediaProjection.stop(); 114 | 115 | if (mOnScreenShotListener != null) { 116 | mOnScreenShotListener.onFinish(bitmap); 117 | } 118 | } 119 | } 120 | } -------------------------------------------------------------------------------- /app/src/main/java/com/omarea/filter/common/SystemProperty.java: -------------------------------------------------------------------------------- 1 | package com.omarea.filter.common; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.InputStreamReader; 5 | import java.util.Objects; 6 | 7 | public class SystemProperty { 8 | public String get(String propName) { 9 | String line; 10 | BufferedReader input = null; 11 | try { 12 | Process p = Runtime.getRuntime().exec("getprop " + propName); 13 | input = new BufferedReader(new InputStreamReader(p.getInputStream()), 1024); 14 | line = input.readLine(); 15 | input.close(); 16 | p.destroy(); 17 | } catch (Exception ex) { 18 | return null; 19 | } finally { 20 | if (input != null) { 21 | try { 22 | input.close(); 23 | } catch (Exception ignored) { 24 | } 25 | } 26 | } 27 | return line; 28 | } 29 | 30 | public boolean isOLED () { 31 | try { 32 | // 反射调用私有接口,被Google封杀了 33 | // Object result = Class.forName("android.os.Systemproperties").getMethod("get").invoke(null, "ro.miui.ui.version.name", ""); 34 | // return "V12".equals(result.toString()); 35 | return Objects.equals(get("ro.vendor.display.type"), "oled"); 36 | } catch (Exception ex) { 37 | return false; 38 | } 39 | } 40 | 41 | public boolean isMiui12() { 42 | try { 43 | // 反射调用私有接口,被Google封杀了 44 | // Object result = Class.forName("android.os.Systemproperties").getMethod("get").invoke(null, "ro.miui.ui.version.name", ""); 45 | // return "V12".equals(result.toString()); 46 | return Objects.equals(get("ro.miui.ui.version.name"), "V12"); 47 | } catch (Exception ex) { 48 | return false; 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /app/src/main/java/com/omarea/filter/common/UITools.java: -------------------------------------------------------------------------------- 1 | package com.omarea.filter.common; 2 | 3 | import android.content.Context; 4 | 5 | public class UITools { 6 | /** 7 | * dp转换成px 8 | */ 9 | public static int dp2px(Context context, float dpValue) { 10 | float scale = context.getResources().getDisplayMetrics().density; 11 | int value = (int) (dpValue * scale + 0.5f); 12 | if (value < 1) { 13 | return 1; 14 | } 15 | return value; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /app/src/main/java/com/omarea/filter/common/ViewHelper.kt: -------------------------------------------------------------------------------- 1 | package com.omarea.filter.common 2 | 3 | import android.content.Context 4 | 5 | class ViewHelper(private var context: Context) { 6 | /** 7 | * dp转换成px 8 | */ 9 | private fun dp2px(context: Context, dpValue: Float): Int { 10 | val scale = context.resources.displayMetrics.density 11 | return (dpValue * scale + 0.5f).toInt() 12 | } 13 | 14 | /** 15 | * 获取导航栏高度 16 | * @param context 17 | * @return 18 | */ 19 | fun getNavBarHeight(): Int { 20 | val height = context.resources.getDimensionPixelSize(context.resources.getIdentifier("navigation_bar_height", "dimen", "android")) 21 | if (height < 1) { 22 | return dp2px(context, 55f) 23 | } 24 | return height 25 | } 26 | 27 | /** 28 | * 获取状态栏高度 29 | */ 30 | fun getStatusHeight(): Int { 31 | var result = 0 32 | val resourceId = context.resources.getIdentifier("status_bar_height", "dimen", "android") 33 | if (resourceId > 0) { 34 | result = context.resources.getDimensionPixelSize(resourceId) 35 | } 36 | return result 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /app/src/main/java/com/omarea/filter/light/LightHandler.java: -------------------------------------------------------------------------------- 1 | package com.omarea.filter.light; 2 | 3 | public interface LightHandler { 4 | void onLuxChange(float lux); 5 | 6 | void onBrightnessChange(int brightness); 7 | 8 | void onModeChange(boolean auto); 9 | } 10 | -------------------------------------------------------------------------------- /app/src/main/java/com/omarea/filter/light/LightHistory.kt: -------------------------------------------------------------------------------- 1 | package com.omarea.filter.light 2 | 3 | class LightHistory { 4 | internal var time: Long = 0 5 | internal var lux: Float = 0F 6 | } 7 | -------------------------------------------------------------------------------- /app/src/main/java/com/omarea/filter/light/LightSensorManager.java: -------------------------------------------------------------------------------- 1 | package com.omarea.filter.light; 2 | 3 | import android.content.Context; 4 | import android.hardware.Sensor; 5 | import android.hardware.SensorEventListener; 6 | import android.hardware.SensorManager; 7 | 8 | public class LightSensorManager { 9 | private static LightSensorManager instance; 10 | private SensorManager mSensorManager; 11 | private SensorEventListener mLightSensorListener; 12 | private boolean mHasStarted = false; 13 | 14 | public LightSensorManager() { 15 | } 16 | 17 | public static LightSensorManager getInstance() { 18 | if (instance == null) { 19 | instance = new LightSensorManager(); 20 | } 21 | return instance; 22 | } 23 | 24 | public void start(Context context, SensorEventListener sensorEventListener) { 25 | if (mHasStarted) { 26 | stop(); 27 | } 28 | mHasStarted = true; 29 | mSensorManager = (SensorManager) context.getApplicationContext().getSystemService(Context.SENSOR_SERVICE); 30 | Sensor lightSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_LIGHT); // 获取光线传感器 31 | if (lightSensor != null) { // 光线传感器存在时 32 | mLightSensorListener = sensorEventListener; 33 | mSensorManager.registerListener(mLightSensorListener, lightSensor, 34 | SensorManager.SENSOR_DELAY_NORMAL); // 注册事件监听 35 | } 36 | } 37 | 38 | public void stop() { 39 | if (!mHasStarted || mSensorManager == null) { 40 | return; 41 | } 42 | mHasStarted = false; 43 | mSensorManager.unregisterListener(mLightSensorListener); 44 | mLightSensorListener = null; 45 | } 46 | } -------------------------------------------------------------------------------- /app/src/main/java/com/omarea/filter/service/QuickSettingService.java: -------------------------------------------------------------------------------- 1 | package com.omarea.filter.service; 2 | 3 | import android.content.Context; 4 | import android.content.Intent; 5 | import android.content.SharedPreferences; 6 | import android.os.Build; 7 | import android.provider.Settings; 8 | import android.service.quicksettings.Tile; 9 | import android.service.quicksettings.TileService; 10 | import android.widget.Toast; 11 | 12 | import androidx.annotation.RequiresApi; 13 | 14 | import com.omarea.filter.GlobalStatus; 15 | import com.omarea.filter.R; 16 | import com.omarea.filter.SpfConfig; 17 | 18 | @RequiresApi(api = Build.VERSION_CODES.N) 19 | public class QuickSettingService extends TileService { 20 | 21 | //当用户从Edit栏添加到快速设定中调用 22 | @Override 23 | public void onTileAdded() { 24 | } 25 | 26 | //当用户从快速设定栏中移除的时候调用 27 | @Override 28 | public void onTileRemoved() { 29 | } 30 | 31 | // 点击的时候 32 | @Override 33 | public void onClick() { 34 | SharedPreferences config = getSharedPreferences(SpfConfig.FILTER_SPF, Context.MODE_PRIVATE); 35 | 36 | int toggleState = getQsTile().getState(); 37 | 38 | // 如果磁贴为激活状态 被点击 则动作为关闭滤镜 39 | if (toggleState == Tile.STATE_ACTIVE) { 40 | Runnable close = GlobalStatus.INSTANCE.getFilterClose(); 41 | if (close != null) { 42 | close.run(); 43 | config.edit().putBoolean(SpfConfig.FILTER_AUTO_START, false).apply(); 44 | 45 | Toast.makeText(this, R.string.quick_tile_off, Toast.LENGTH_SHORT).show(); 46 | } 47 | getQsTile().setState(Tile.STATE_INACTIVE); 48 | } 49 | // 如果磁贴为未激活状态 被点击 则动作为开启滤镜 50 | else if (toggleState == Tile.STATE_INACTIVE) { 51 | Runnable open = GlobalStatus.INSTANCE.getFilterOpen(); 52 | // 如果服务没启动 53 | if (open == null) { 54 | Toast.makeText(this, R.string.accessibility_service_required, Toast.LENGTH_SHORT).show(); 55 | try { 56 | Intent intent = new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS); 57 | startActivity(intent); 58 | } catch (java.lang.Exception ignored) { 59 | } 60 | } 61 | // 正常开启滤镜 62 | else { 63 | open.run(); 64 | config.edit().putBoolean(SpfConfig.FILTER_AUTO_START, true).apply(); 65 | 66 | getQsTile().setState(Tile.STATE_ACTIVE); 67 | 68 | Toast.makeText(this, R.string.quick_tile_on, Toast.LENGTH_SHORT).show(); 69 | } 70 | } 71 | 72 | // Icon icon = Icon.createWithResource(getApplicationContext(), R.drawable.filter); 73 | // getQsTile().setIcon(icon); //设置图标 74 | getQsTile().updateTile(); //更新Tile 75 | } 76 | 77 | // 打开下拉菜单的时候调用,当快速设置按钮并没有在编辑栏拖到设置栏中不会调用 78 | //在TleAdded之后会调用一次 79 | @Override 80 | public void onStartListening() { 81 | getQsTile().setState(GlobalStatus.INSTANCE.getFilterEnabled() ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE); 82 | getQsTile().updateTile(); //更新Tile 83 | } 84 | 85 | // 关闭下拉菜单的时候调用,当快速设置按钮并没有在编辑栏拖到设置栏中不会调用 86 | // 在onTileRemoved移除之前也会调用移除 87 | @Override 88 | public void onStopListening() { 89 | } 90 | } -------------------------------------------------------------------------------- /app/src/main/java/com/omarea/filter/service/ScreenShotService.java: -------------------------------------------------------------------------------- 1 | package com.omarea.filter.service; 2 | 3 | import android.content.Intent; 4 | import android.os.Build; 5 | import android.service.quicksettings.TileService; 6 | import android.util.Log; 7 | 8 | import androidx.annotation.RequiresApi; 9 | 10 | import com.omarea.filter.ScreenCapActivity; 11 | 12 | @RequiresApi(api = Build.VERSION_CODES.N) 13 | public class ScreenShotService extends TileService { 14 | // 点击的时候 15 | @Override 16 | public void onClick() { 17 | try { 18 | Intent intent = new Intent(this, ScreenCapActivity.class); 19 | intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 20 | intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK); 21 | startActivityAndCollapse(intent); 22 | } catch (Exception ex) { 23 | Log.e("ScreenCapActivity", "!!!" + ex.getMessage()); 24 | } 25 | } 26 | 27 | @Override 28 | public void onStartListening() { 29 | getQsTile().updateTile(); //更新Tile 30 | } 31 | } -------------------------------------------------------------------------------- /app/src/main/java/com/omarea/filter/service/SwitchBrightnessModeService.java: -------------------------------------------------------------------------------- 1 | package com.omarea.filter.service; 2 | 3 | import android.content.ContentResolver; 4 | import android.content.Context; 5 | import android.content.SharedPreferences; 6 | import android.os.Build; 7 | import android.provider.Settings; 8 | import android.service.quicksettings.Tile; 9 | import android.service.quicksettings.TileService; 10 | import android.widget.Toast; 11 | 12 | import androidx.annotation.RequiresApi; 13 | 14 | import com.omarea.filter.R; 15 | import com.omarea.filter.SpfConfig; 16 | 17 | @RequiresApi(api = Build.VERSION_CODES.N) 18 | public class SwitchBrightnessModeService extends TileService { 19 | 20 | //当用户从Edit栏添加到快速设定中调用 21 | @Override 22 | public void onTileAdded() { 23 | } 24 | 25 | //当用户从快速设定栏中移除的时候调用 26 | @Override 27 | public void onTileRemoved() { 28 | } 29 | 30 | // 点击的时候 31 | @Override 32 | public void onClick() { 33 | SharedPreferences config = getSharedPreferences(SpfConfig.FILTER_SPF, Context.MODE_PRIVATE); 34 | 35 | int toggleState = getQsTile().getState(); 36 | 37 | // 如果磁贴为激活状态 被点击 则动作为关闭滤镜 38 | if (toggleState == Tile.STATE_ACTIVE) { 39 | if (Settings.System.canWrite(getApplicationContext())) { 40 | ContentResolver contentResolver = getApplicationContext().getContentResolver(); 41 | Settings.System.putInt(contentResolver, Settings.System.SCREEN_BRIGHTNESS_MODE, Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL); 42 | getQsTile().setState(Tile.STATE_INACTIVE); 43 | getQsTile().updateTile(); //更新Tile 44 | } else { 45 | Toast.makeText(this, getString(R.string.write_settings_unallowed), Toast.LENGTH_LONG).show(); 46 | } 47 | } 48 | // 如果磁贴为未激活状态 被点击 则动作为开启滤镜 49 | else if (toggleState == Tile.STATE_INACTIVE) { 50 | if (Settings.System.canWrite(getApplicationContext())) { 51 | ContentResolver contentResolver = getApplicationContext().getContentResolver(); 52 | Settings.System.putInt(contentResolver, Settings.System.SCREEN_BRIGHTNESS_MODE, Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC); 53 | getQsTile().setState(Tile.STATE_ACTIVE); 54 | getQsTile().updateTile(); //更新Tile 55 | } else { 56 | Toast.makeText(this, getString(R.string.write_settings_unallowed), Toast.LENGTH_LONG).show(); 57 | } 58 | } 59 | 60 | // Icon icon = Icon.createWithResource(getApplicationContext(), R.drawable.filter); 61 | // getQsTile().setIcon(icon); //设置图标 62 | getQsTile().updateTile(); //更新Tile 63 | } 64 | 65 | // 打开下拉菜单的时候调用,当快速设置按钮并没有在编辑栏拖到设置栏中不会调用 66 | //在TleAdded之后会调用一次 67 | @Override 68 | public void onStartListening() { 69 | try { 70 | ContentResolver contentResolver = getApplicationContext().getContentResolver(); 71 | if (Settings.System.getInt(contentResolver, Settings.System.SCREEN_BRIGHTNESS_MODE) == Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC) { 72 | getQsTile().setState(Tile.STATE_ACTIVE); 73 | } else { 74 | getQsTile().setState(Tile.STATE_INACTIVE); 75 | } 76 | getQsTile().updateTile(); //更新Tile 77 | } catch (Exception ex) { 78 | } 79 | } 80 | 81 | // 关闭下拉菜单的时候调用,当快速设置按钮并没有在编辑栏拖到设置栏中不会调用 82 | // 在onTileRemoved移除之前也会调用移除 83 | @Override 84 | public void onStopListening() { 85 | } 86 | } -------------------------------------------------------------------------------- /app/src/main/res/anim/dialog_enter.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 10 | 19 | 23 | -------------------------------------------------------------------------------- /app/src/main/res/anim/dialog_exit.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 10 | 19 | 23 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/add.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/helloklf/ScreenFilter/780ffb7b9fd626c150aa625ead6b1d1b5b04676b/app/src/main/res/drawable/add.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/alpha_gradient.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_gradient.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/blue_gradient.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/brightness_auto.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/helloklf/ScreenFilter/780ffb7b9fd626c150aa625ead6b1d1b5b04676b/app/src/main/res/drawable/brightness_auto.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/card_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/card_bg_dark.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/dialog.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/helloklf/ScreenFilter/780ffb7b9fd626c150aa625ead6b1d1b5b04676b/app/src/main/res/drawable/dialog.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/dialog_icon_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 14 | 15 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/filter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/helloklf/ScreenFilter/780ffb7b9fd626c150aa625ead6b1d1b5b04676b/app/src/main/res/drawable/filter.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/glass.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/helloklf/ScreenFilter/780ffb7b9fd626c150aa625ead6b1d1b5b04676b/app/src/main/res/drawable/glass.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/green_gradient.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_lightbulb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/helloklf/ScreenFilter/780ffb7b9fd626c150aa625ead6b1d1b5b04676b/app/src/main/res/drawable/ic_lightbulb.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/helloklf/ScreenFilter/780ffb7b9fd626c150aa625ead6b1d1b5b04676b/app/src/main/res/drawable/ic_settings.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/icon_brightness_auto.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/helloklf/ScreenFilter/780ffb7b9fd626c150aa625ead6b1d1b5b04676b/app/src/main/res/drawable/icon_brightness_auto.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/icon_brightness_manual.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/helloklf/ScreenFilter/780ffb7b9fd626c150aa625ead6b1d1b5b04676b/app/src/main/res/drawable/icon_brightness_manual.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/icon_power_off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/helloklf/ScreenFilter/780ffb7b9fd626c150aa625ead6b1d1b5b04676b/app/src/main/res/drawable/icon_power_off.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/icon_power_on.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/helloklf/ScreenFilter/780ffb7b9fd626c150aa625ead6b1d1b5b04676b/app/src/main/res/drawable/icon_power_on.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/icon_question.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/helloklf/ScreenFilter/780ffb7b9fd626c150aa625ead6b1d1b5b04676b/app/src/main/res/drawable/icon_question.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/icon_settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/helloklf/ScreenFilter/780ffb7b9fd626c150aa625ead6b1d1b5b04676b/app/src/main/res/drawable/icon_settings.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/icon_tuner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/helloklf/ScreenFilter/780ffb7b9fd626c150aa625ead6b1d1b5b04676b/app/src/main/res/drawable/icon_tuner.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/in_card_item.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/light_sensor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/helloklf/ScreenFilter/780ffb7b9fd626c150aa625ead6b1d1b5b04676b/app/src/main/res/drawable/light_sensor.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/minus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/helloklf/ScreenFilter/780ffb7b9fd626c150aa625ead6b1d1b5b04676b/app/src/main/res/drawable/minus.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/helloklf/ScreenFilter/780ffb7b9fd626c150aa625ead6b1d1b5b04676b/app/src/main/res/drawable/off.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/on.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/helloklf/ScreenFilter/780ffb7b9fd626c150aa625ead6b1d1b5b04676b/app/src/main/res/drawable/on.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/plus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/helloklf/ScreenFilter/780ffb7b9fd626c150aa625ead6b1d1b5b04676b/app/src/main/res/drawable/plus.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/power_off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/helloklf/ScreenFilter/780ffb7b9fd626c150aa625ead6b1d1b5b04676b/app/src/main/res/drawable/power_off.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/power_on.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/helloklf/ScreenFilter/780ffb7b9fd626c150aa625ead6b1d1b5b04676b/app/src/main/res/drawable/power_on.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/power_switch_off.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/power_switch_on.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/power_switch_style.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/progress_color.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/progress_shape.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/red_gradient.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/seekbar_thumb_solid.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/texture_paper1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/helloklf/ScreenFilter/780ffb7b9fd626c150aa625ead6b1d1b5b04676b/app/src/main/res/drawable/texture_paper1.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/texture_paper2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/helloklf/ScreenFilter/780ffb7b9fd626c150aa625ead6b1d1b5b04676b/app/src/main/res/drawable/texture_paper2.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/texture_sand1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/helloklf/ScreenFilter/780ffb7b9fd626c150aa625ead6b1d1b5b04676b/app/src/main/res/drawable/texture_sand1.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/texture_sand2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/helloklf/ScreenFilter/780ffb7b9fd626c150aa625ead6b1d1b5b04676b/app/src/main/res/drawable/texture_sand2.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/texture_sand3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/helloklf/ScreenFilter/780ffb7b9fd626c150aa625ead6b1d1b5b04676b/app/src/main/res/drawable/texture_sand3.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/texture_stripe1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/helloklf/ScreenFilter/780ffb7b9fd626c150aa625ead6b1d1b5b04676b/app/src/main/res/drawable/texture_stripe1.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/texture_stripe2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/helloklf/ScreenFilter/780ffb7b9fd626c150aa625ead6b1d1b5b04676b/app/src/main/res/drawable/texture_stripe2.png -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 16 | 17 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /app/src/main/res/layout/dialog_help_info.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 15 | 16 | 22 | 23 | -------------------------------------------------------------------------------- /app/src/main/res/layout/dialog_loading.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 17 | 18 | 25 | 26 | -------------------------------------------------------------------------------- /app/src/main/res/layout/filter.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 14 | -------------------------------------------------------------------------------- /app/src/main/res/layout/notification.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 20 | 21 | 28 | 29 | 39 | 40 | 44 | 52 | 53 | 62 | 63 | 64 | 74 | 75 | 84 | 85 | 86 | -------------------------------------------------------------------------------- /app/src/main/res/layout/popup_controller.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 22 | 23 | 32 | 33 | 38 | 39 | 42 | 43 | 50 | 51 | 60 | 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /app/src/main/res/menu/menu_main.xml: -------------------------------------------------------------------------------- 1 | 5 | 12 | 18 | 25 | 26 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/helloklf/ScreenFilter/780ffb7b9fd626c150aa625ead6b1d1b5b04676b/app/src/main/res/mipmap/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/values/attrs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/values/attrs_my_view.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #8BC34A 4 | #8BC34A 5 | #4CAF50 6 | 7 | #FF9800 8 | #FF9800 9 | #FF5722 10 | 11 | #66000000 12 | #66888888 13 | #88888888 14 | 15 | -------------------------------------------------------------------------------- /app/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 16dp 3 | 4 | -------------------------------------------------------------------------------- /app/src/main/res/xml-v25/shortcuts.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 10 | 14 | 15 | 22 | 26 | 27 | -------------------------------------------------------------------------------- /app/src/main/res/xml/filter_accessibility.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /app/src/test/java/com/omarea/filter/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package com.omarea.filter; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.assertEquals; 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * @see Testing documentation 11 | */ 12 | public class ExampleUnitTest { 13 | @Test 14 | public void addition_isCorrect() { 15 | assertEquals(4, 2 + 2); 16 | } 17 | } -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | ext.kotlin_version = '1.4.10' 5 | repositories { 6 | google() 7 | jcenter() 8 | 9 | } 10 | dependencies { 11 | classpath 'com.android.tools.build:gradle:4.0.2' 12 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 13 | 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 | jcenter() 23 | } 24 | } 25 | 26 | task clean(type: Delete) { 27 | delete rootProject.buildDir 28 | } 29 | -------------------------------------------------------------------------------- /common/.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /common/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /common/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | common 4 | Project common created by Buildship. 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | org.eclipse.buildship.core.gradleprojectbuilder 15 | 16 | 17 | 18 | 19 | 20 | org.eclipse.jdt.core.javanature 21 | org.eclipse.buildship.core.gradleprojectnature 22 | 23 | 24 | -------------------------------------------------------------------------------- /common/.settings/org.eclipse.buildship.core.prefs: -------------------------------------------------------------------------------- 1 | connection.project.dir=.. 2 | eclipse.preferences.version=1 3 | -------------------------------------------------------------------------------- /common/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | apply plugin: 'kotlin-android-extensions' 3 | apply plugin: 'kotlin-android' 4 | 5 | android { 6 | compileSdkVersion 28 7 | 8 | defaultConfig { 9 | minSdkVersion 21 10 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 11 | } 12 | 13 | buildTypes { 14 | release { 15 | minifyEnabled false 16 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 17 | } 18 | release_mini { 19 | minifyEnabled = true 20 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 21 | } 22 | } 23 | 24 | } 25 | 26 | dependencies { 27 | implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.9" 28 | // implementation fileTree(include: ['*.jar'], dir: 'libs') 29 | implementation 'androidx.appcompat:appcompat:1.2.0' 30 | // testImplementation 'junit:junit:4.13-beta-3' 31 | // androidTestImplementation 'androidx.test.ext:junit:1.1.1' 32 | // androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' 33 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 34 | api files('libs/overscroll-release-v1.1-20160904.jar') 35 | // implementation files('libs/fastscroll_v1.2_20160903.jar') 36 | } 37 | repositories { 38 | mavenCentral() 39 | } 40 | -------------------------------------------------------------------------------- /common/libs/fastscroll_v1.2_20160903.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/helloklf/ScreenFilter/780ffb7b9fd626c150aa625ead6b1d1b5b04676b/common/libs/fastscroll_v1.2_20160903.jar -------------------------------------------------------------------------------- /common/libs/overscroll-release-v1.1-20160904.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/helloklf/ScreenFilter/780ffb7b9fd626c150aa625ead6b1d1b5b04676b/common/libs/overscroll-release-v1.1-20160904.jar -------------------------------------------------------------------------------- /common/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /common/src/androidTest/java/com/omarea/common/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.omarea.common; 2 | 3 | import android.content.Context; 4 | 5 | import androidx.test.ext.junit.runners.AndroidJUnit4; 6 | import androidx.test.platform.app.InstrumentationRegistry; 7 | 8 | import org.junit.Test; 9 | import org.junit.runner.RunWith; 10 | 11 | import static org.junit.Assert.assertEquals; 12 | 13 | /** 14 | * Instrumented test, which will execute on an Android device. 15 | * 16 | * @see Testing documentation 17 | */ 18 | @RunWith(AndroidJUnit4.class) 19 | public class ExampleInstrumentedTest { 20 | @Test 21 | public void useAppContext() { 22 | // Context of the app under test. 23 | Context appContext = InstrumentationRegistry.getTargetContext(); 24 | 25 | assertEquals("com.omarea.common.test", appContext.getPackageName()); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /common/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /common/src/main/java/com/omarea/common/model/SelectItem.kt: -------------------------------------------------------------------------------- 1 | package com.omarea.common.model 2 | 3 | 4 | /* 5 | 示例1: 用于Spinner 6 | ArrayAdapter(context, R.layout.kr_spinner_default, R.id.text, options).apply { 7 | setDropDownViewResource(R.layout.kr_spinner_dropdown) 8 | } 9 | */ 10 | 11 | class SelectItem { 12 | var title: String? = null 13 | // var desc: String = "" 14 | var value: String? = null 15 | var selected: Boolean = false 16 | 17 | override fun toString(): String { 18 | if (!title.isNullOrEmpty()) { 19 | return title!! 20 | } else if (!value.isNullOrEmpty()) { 21 | return value!! 22 | } else { 23 | return "" // super.toString() 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /common/src/main/java/com/omarea/common/shared/BitmapUtil.java: -------------------------------------------------------------------------------- 1 | package com.omarea.common.shared; 2 | 3 | import android.graphics.Bitmap; 4 | import android.graphics.BitmapFactory; 5 | import android.graphics.Canvas; 6 | import android.graphics.Matrix; 7 | import android.graphics.PixelFormat; 8 | import android.graphics.drawable.BitmapDrawable; 9 | import android.graphics.drawable.Drawable; 10 | 11 | import java.io.File; 12 | import java.io.FileInputStream; 13 | import java.io.FileOutputStream; 14 | import java.io.InputStream; 15 | import java.io.OutputStream; 16 | 17 | public class BitmapUtil { 18 | public Bitmap temp; 19 | 20 | /** 21 | * 根据指定的高度进行缩放(source是bitmap) 22 | */ 23 | public Bitmap bitmapZoomByHeight(Bitmap srcBitmap, float newHeight) { 24 | float scale = newHeight / (((float) srcBitmap.getHeight())); 25 | return bitmapZoomByScale(srcBitmap, scale, scale); 26 | } 27 | 28 | /** 29 | * 根据指定的高度进行缩放(source是drawable) 30 | */ 31 | public Bitmap bitmapZoomByHeight(Drawable drawable, float newHeight) { 32 | Bitmap bitmap = drawableToBitmap(drawable); 33 | float scale = newHeight / (((float) bitmap.getHeight())); 34 | return bitmapZoomByScale(bitmap, scale, scale); 35 | } 36 | 37 | /** 38 | * 根据指定的宽度比例值和高度比例值进行缩放 39 | */ 40 | public Bitmap bitmapZoomByScale(Bitmap srcBitmap, float scaleWidth, float scaleHeight) { 41 | int width = srcBitmap.getWidth(); 42 | int height = srcBitmap.getHeight(); 43 | Matrix matrix = new Matrix(); 44 | matrix.postScale(scaleWidth, scaleHeight); 45 | Bitmap bitmap = Bitmap.createBitmap(srcBitmap, 0, 0, width, height, matrix, true); 46 | if (bitmap != null) { 47 | return bitmap; 48 | } else { 49 | return srcBitmap; 50 | } 51 | } 52 | 53 | /** 54 | * 将drawable对象转成bitmap对象 55 | */ 56 | public Bitmap drawableToBitmap(Drawable drawable) { 57 | int width = drawable.getIntrinsicWidth(); 58 | int height = drawable.getIntrinsicHeight(); 59 | Bitmap.Config config = drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565; 60 | Bitmap bitmap = Bitmap.createBitmap(width, height, config); 61 | Canvas canvas = new Canvas(bitmap); 62 | drawable.setBounds(0, 0, width, height); 63 | drawable.draw(canvas); 64 | return bitmap; 65 | } 66 | 67 | /** 68 | * 将drawable对象转成bitmap对象 69 | */ 70 | public Bitmap drawableToBitmap2(Drawable drawable) { 71 | BitmapDrawable bd = (BitmapDrawable) drawable; 72 | Bitmap bm = bd.getBitmap(); 73 | return bm; 74 | } 75 | 76 | /** 77 | * 将bitmap对象保存成图片到sd卡中 78 | */ 79 | public void saveBitmapToSDCard(Bitmap bitmap, String path) { 80 | File file = new File(path); 81 | if (file.exists()) { 82 | file.delete(); 83 | } 84 | try { 85 | FileOutputStream fileOutputStream = new FileOutputStream(file); 86 | bitmap.compress(Bitmap.CompressFormat.PNG, 100, ((OutputStream) fileOutputStream));//设置PNG的话,透明区域不会变成黑色 87 | 88 | fileOutputStream.close(); 89 | System.out.println("----------save success-------------------"); 90 | } catch (Exception v0) { 91 | v0.printStackTrace(); 92 | } 93 | } 94 | 95 | /** 96 | * 从sd卡中获取图片的bitmap对象 97 | */ 98 | public Bitmap getBitmapFromSDCard(String path) { 99 | Bitmap bitmap = null; 100 | try { 101 | FileInputStream fileInputStream = new FileInputStream(path); 102 | if (fileInputStream != null) { 103 | BitmapFactory.Options options = new BitmapFactory.Options(); 104 | options.inSampleSize = 2; //当图片资源太大的适合,会出现内存溢出。图片宽高都为原来的二分之一,即图片为原来的四分一 105 | bitmap = BitmapFactory.decodeStream(((InputStream) fileInputStream), null, options); 106 | } 107 | } catch (Exception e) { 108 | return null; 109 | } 110 | 111 | return bitmap; 112 | } 113 | } -------------------------------------------------------------------------------- /common/src/main/java/com/omarea/common/shared/ObjectStorage.kt: -------------------------------------------------------------------------------- 1 | package com.omarea.common.shared 2 | 3 | import android.content.Context 4 | import android.widget.Toast 5 | import java.io.* 6 | 7 | open class ObjectStorage(private val context: Context) { 8 | private val objectStorageDir = "objects/" 9 | protected fun getSaveDir(configFile: String): String { 10 | return FileWrite.getPrivateFilePath(context, objectStorageDir + configFile) 11 | } 12 | 13 | public open fun load(configFile: String): T? { 14 | val file = File(getSaveDir(configFile)) 15 | if (file.exists()) { 16 | var fileInputStream: FileInputStream? = null; 17 | var objectInputStream: ObjectInputStream? = null; 18 | try { 19 | fileInputStream = FileInputStream(file) 20 | objectInputStream = ObjectInputStream(fileInputStream) 21 | return objectInputStream.readObject() as T? 22 | } catch (ex: Exception) { 23 | } finally { 24 | try { 25 | if (objectInputStream != null) { 26 | objectInputStream.close() 27 | } 28 | if (fileInputStream != null) { 29 | fileInputStream.close() 30 | } 31 | } catch (ex: Exception) { 32 | } 33 | } 34 | } 35 | return null 36 | } 37 | 38 | public open fun save(obj: T?, configFile: String): Boolean { 39 | val file = File(getSaveDir(configFile)) 40 | val parentFile = file.parentFile 41 | if (!parentFile.exists()) { 42 | parentFile.mkdirs() 43 | } 44 | if (obj != null) { 45 | var fileOutputStream: FileOutputStream? = null 46 | var objectOutputStream: ObjectOutputStream? = null 47 | try { 48 | fileOutputStream = FileOutputStream(file) 49 | objectOutputStream = ObjectOutputStream(fileOutputStream) 50 | objectOutputStream.writeObject(obj) 51 | return true 52 | } catch (ex: Exception) { 53 | Toast.makeText(context, "存储配置失败!", Toast.LENGTH_SHORT).show() 54 | return false 55 | } finally { 56 | try { 57 | if (objectOutputStream != null) { 58 | objectOutputStream.close() 59 | } 60 | if (fileOutputStream != null) { 61 | fileOutputStream.close() 62 | } 63 | } catch (ex: Exception) { 64 | } 65 | } 66 | } else { 67 | if (file.exists()) { 68 | file.delete() 69 | } 70 | } 71 | return true 72 | } 73 | 74 | public open fun remove(configFile: String) { 75 | val file = File(getSaveDir(configFile)) 76 | if (file.exists()) { 77 | file.delete() 78 | } 79 | } 80 | 81 | public open fun exists(configFile: String): Boolean { 82 | return File(getSaveDir(configFile)).exists() 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /common/src/main/java/com/omarea/common/shared/RawText.kt: -------------------------------------------------------------------------------- 1 | package com.omarea.common.shared 2 | 3 | import android.content.Context 4 | import java.nio.charset.Charset 5 | 6 | object RawText { 7 | fun getRawText(context: Context, id: Int): String { 8 | try { 9 | return String(context.resources.openRawResource(id).readBytes(), Charset.defaultCharset()).replace(Regex("\r\n"), "\n").replace(Regex("\r\t"), "\t").replace(Regex("\r"), "\n") 10 | } catch (ex: Exception) { 11 | return "" 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /common/src/main/java/com/omarea/common/shared/RootFileInfo.kt: -------------------------------------------------------------------------------- 1 | package com.omarea.common.shared 2 | 3 | import com.omarea.common.shell.RootFile 4 | 5 | class RootFileInfo { 6 | constructor() 7 | constructor(path: String) { 8 | val file = RootFile.fileInfo(path) 9 | if (file != null) { 10 | this.parentDir = file.parentDir 11 | this.filePath = file.filePath 12 | this.isDirectory = file.isDirectory 13 | } 14 | } 15 | 16 | var parentDir: String = "" 17 | var filePath: String = "" 18 | var isDirectory: Boolean = false 19 | var fileSize: Long = 0; 20 | 21 | val fileName: String 22 | get() { 23 | if (filePath.endsWith("/")) { 24 | return filePath.substring(0, filePath.length - 1) 25 | } 26 | return filePath 27 | } 28 | 29 | val absolutePath: String 30 | get() = parentDir + "/" + fileName 31 | 32 | 33 | public fun exists(): Boolean { 34 | return RootFile.itemExists(this.absolutePath) 35 | } 36 | 37 | public fun isFile(): Boolean { 38 | return !isDirectory 39 | } 40 | 41 | public fun getParent(): String { 42 | return this.parentDir 43 | } 44 | 45 | public fun getName(): String { 46 | return this.fileName 47 | } 48 | 49 | public fun listFiles(): ArrayList { 50 | if (this.isDirectory) { 51 | return RootFile.list(this.absolutePath) 52 | } 53 | return ArrayList() 54 | } 55 | 56 | fun length(): Long { 57 | return this.fileSize 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /common/src/main/java/com/omarea/common/shell/AsynSuShellUnit.kt: -------------------------------------------------------------------------------- 1 | package com.omarea.common.shell 2 | 3 | import android.os.Handler 4 | import java.nio.charset.Charset 5 | 6 | /** 7 | * Created by helloklf on 2017/12/01. 8 | */ 9 | 10 | class AsynSuShellUnit(var handler: Handler) { 11 | var process: Process? = null 12 | 13 | private fun start(): AsynSuShellUnit { 14 | try { 15 | if (process == null) 16 | process = ShellExecutor.getSuperUserRuntime() 17 | 18 | Thread(Runnable { 19 | try { 20 | var line: String 21 | val reader = process!!.inputStream.bufferedReader() 22 | while (true) { 23 | line = reader.readLine() 24 | if (line != null) { 25 | line = line.trim() 26 | if (line.isNotEmpty()) 27 | handler.sendMessage(handler.obtainMessage(1, line)) 28 | } else { 29 | destroy() 30 | break 31 | } 32 | } 33 | } catch (ex: Exception) { 34 | print(ex.message) 35 | } 36 | }).start() 37 | Thread(Runnable { 38 | try { 39 | var line: String 40 | val reader = process!!.errorStream.bufferedReader() 41 | while (true) { 42 | line = reader.readLine().trim() 43 | if (line.isNotEmpty()) 44 | handler.sendMessage(handler.obtainMessage(5, line)) 45 | } 46 | } catch (ex: Exception) { 47 | print(ex.message) 48 | } 49 | }).start() 50 | handler.sendMessage(handler.obtainMessage(0, true)) 51 | } catch (ex: Exception) { 52 | handler.sendMessage(handler.obtainMessage(0, false)) 53 | } 54 | return this 55 | } 56 | 57 | fun destroy() { 58 | try { 59 | if (process != null) { 60 | process!!.outputStream.close() 61 | process!!.destroy() 62 | } 63 | } catch (ex: Exception) { 64 | 65 | } 66 | } 67 | 68 | fun exec(cmd: String): AsynSuShellUnit { 69 | if (process == null) { 70 | start() 71 | } 72 | if (process == null) { 73 | handler.handleMessage(handler.obtainMessage(-1)) 74 | return this 75 | } 76 | val outputStream = process!!.outputStream 77 | outputStream.write("\n\n".toByteArray(Charset.forName("UTF-8"))) 78 | outputStream.write(cmd.toByteArray(Charset.forName("UTF-8"))) 79 | outputStream.write("\n\n".toByteArray(Charset.forName("UTF-8"))) 80 | outputStream.flush() 81 | return this 82 | } 83 | 84 | fun waitFor() { 85 | if (process == null) 86 | return 87 | 88 | val outputStream = process!!.outputStream 89 | val writer = outputStream.bufferedWriter() 90 | writer.write("exit\nexit\nexit\n") 91 | writer.write("\n\n") 92 | writer.flush() 93 | Thread(Runnable { 94 | if (process!!.waitFor() == 0) { 95 | handler.sendMessage(handler.obtainMessage(10, true)) 96 | } else { 97 | handler.sendMessage(handler.obtainMessage(10, false)) 98 | } 99 | destroy() 100 | }).start() 101 | } 102 | 103 | fun waitFor(next: Runnable) { 104 | if (process == null) 105 | return 106 | 107 | val outputStream = process!!.outputStream 108 | val writer = outputStream.bufferedWriter() 109 | writer.write("exit\nexit\nexit\n") 110 | writer.write("\n\n") 111 | writer.flush() 112 | Thread(Runnable { 113 | process!!.waitFor() 114 | destroy() 115 | handler.sendMessage(handler.obtainMessage(10, true)) 116 | next.run() 117 | }).start() 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /common/src/main/java/com/omarea/common/shell/KeepShellPublic.kt: -------------------------------------------------------------------------------- 1 | package com.omarea.common.shell 2 | 3 | import android.util.Log 4 | 5 | /** 6 | * Created by Hello on 2018/01/23. 7 | */ 8 | object KeepShellPublic { 9 | private val keepShells = HashMap() 10 | 11 | fun getInstance(key: String, rootMode: Boolean): KeepShell { 12 | synchronized(keepShells) { 13 | if (!keepShells.containsKey(key)) { 14 | keepShells.put(key, KeepShell(rootMode)) 15 | } 16 | return keepShells.get(key)!! 17 | } 18 | } 19 | 20 | fun destoryInstance(key: String) { 21 | synchronized(keepShells) { 22 | if (!keepShells.containsKey(key)) { 23 | return 24 | } else { 25 | val keepShell = keepShells.get(key)!! 26 | keepShells.remove(key) 27 | keepShell.tryExit() 28 | } 29 | } 30 | } 31 | 32 | fun destoryAll() { 33 | synchronized(keepShells) { 34 | while (keepShells.isNotEmpty()) { 35 | val key = keepShells.keys.first() 36 | val keepShell = keepShells.get(key)!! 37 | keepShells.remove(key) 38 | keepShell.tryExit() 39 | } 40 | } 41 | } 42 | 43 | private var defaultKeepShell: KeepShell? = null 44 | 45 | fun getDefaultInstance(): KeepShell { 46 | if (defaultKeepShell == null) { 47 | defaultKeepShell = KeepShell() 48 | } 49 | return defaultKeepShell!! 50 | } 51 | 52 | fun doCmdSync(commands: List): Boolean { 53 | val stringBuilder = StringBuilder() 54 | 55 | for (cmd in commands) { 56 | stringBuilder.append(cmd) 57 | stringBuilder.append("\n\n") 58 | } 59 | 60 | return doCmdSync(stringBuilder.toString()) != "error" 61 | } 62 | 63 | //执行脚本 64 | fun doCmdSync(cmd: String): String { 65 | return getDefaultInstance().doCmdSync(cmd) 66 | } 67 | 68 | //执行脚本 69 | fun checkRoot(): Boolean { 70 | return getDefaultInstance().checkRoot() 71 | } 72 | 73 | fun tryExit() { 74 | if (defaultKeepShell != null) { 75 | defaultKeepShell!!.tryExit() 76 | defaultKeepShell = null 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /common/src/main/java/com/omarea/common/shell/KernelProrp.kt: -------------------------------------------------------------------------------- 1 | package com.omarea.common.shell 2 | 3 | /** 4 | * 操作内核参数节点 5 | * Created by Hello on 2017/11/01. 6 | */ 7 | object KernelProrp { 8 | /** 9 | * 获取属性 10 | * @param propName 属性名称 11 | * @return 12 | */ 13 | fun getProp(propName: String): String { 14 | return KeepShellPublic.doCmdSync("if [[ -e \"$propName\" ]]; then cat \"$propName\"; fi;") 15 | } 16 | 17 | fun getProp(propName: String, grep: String): String { 18 | return KeepShellPublic.doCmdSync("if [[ -e \"$propName\" ]]; then cat \"$propName\" | grep \"$grep\"; fi;") 19 | } 20 | 21 | /** 22 | * 保存属性 23 | * @param propName 属性名称(要永久保存,请以persist.开头) 24 | * @param value 属性值,值尽量是简单的数字或字母,避免出现错误 25 | */ 26 | fun setProp(propName: String, value: String): Boolean { 27 | return KeepShellPublic.doCmdSync( 28 | "chmod 664 \"$propName\" 2 > /dev/null\n" + 29 | "echo \"$value\" > \"$propName\"" 30 | ) != "error" 31 | } 32 | } -------------------------------------------------------------------------------- /common/src/main/java/com/omarea/common/shell/ShellEvents.kt: -------------------------------------------------------------------------------- 1 | package com.omarea.common.shell 2 | 3 | import android.os.Handler 4 | 5 | /** 6 | * Created by Hello on 2018/06/30. 7 | */ 8 | 9 | open class ShellEvents { 10 | protected var processHandler: Handler? = null 11 | public var PROCESS_EVENT_STAR = 0; 12 | public var PROCESS_EVENT_CONTENT = 1; 13 | public var PROCESS_EVENT_ERROR_CONTENT = 2; 14 | public var PROCESS_EVENT_EXIT = -1; 15 | } 16 | -------------------------------------------------------------------------------- /common/src/main/java/com/omarea/common/shell/ShellExecutor.java: -------------------------------------------------------------------------------- 1 | package com.omarea.common.shell; 2 | 3 | import java.io.IOException; 4 | import java.io.InputStream; 5 | import java.io.OutputStream; 6 | 7 | public class ShellExecutor { 8 | private static String extraEnvPath = ""; 9 | private static String defaultEnvPath = ""; // /sbin:/system/sbin:/system/bin:/system/xbin:/odm/bin:/vendor/bin:/vendor/xbin 10 | 11 | public static void setExtraEnvPath(String extraEnvPath) { 12 | ShellExecutor.extraEnvPath = extraEnvPath; 13 | } 14 | 15 | private static String getEnvPath() { 16 | // FIXME:非root模式下,默认的 TMPDIR=/data/local/tmp 变量可能会导致某些需要写缓存的场景(例如使用source指令)脚本执行失败! 17 | if (extraEnvPath != null && !extraEnvPath.isEmpty()) { 18 | if (defaultEnvPath.isEmpty()) { 19 | try { 20 | Process process = Runtime.getRuntime().exec("sh"); 21 | OutputStream outputStream = process.getOutputStream(); 22 | outputStream.write("echo $PATH".getBytes()); 23 | outputStream.flush(); 24 | outputStream.close(); 25 | 26 | InputStream inputStream = process.getInputStream(); 27 | byte[] cache = new byte[16384]; 28 | int length = inputStream.read(cache); 29 | inputStream.close(); 30 | process.destroy(); 31 | 32 | String path = new String(cache, 0, length).trim(); 33 | if (path.length() > 0) { 34 | defaultEnvPath = path; 35 | } else { 36 | throw new RuntimeException("未能获取到$PATH参数"); 37 | } 38 | } catch (Exception ex) { 39 | defaultEnvPath = "/sbin:/system/sbin:/system/bin:/system/xbin:/odm/bin:/vendor/bin:/vendor/xbin"; 40 | } 41 | } 42 | 43 | String path = defaultEnvPath; 44 | 45 | return ( "PATH=" + path + ":" + extraEnvPath); 46 | } 47 | 48 | return null; 49 | } 50 | 51 | private static Process getProcess(String run) throws IOException { 52 | String env = getEnvPath(); 53 | Runtime runtime = Runtime.getRuntime(); 54 | /* 55 | // 部分机型会有Aborted错误 56 | if (env != null) { 57 | return runtime.exec(run, new String[]{ 58 | env 59 | }); 60 | } 61 | */ 62 | Process process = runtime.exec(run); 63 | if (env != null) { 64 | OutputStream outputStream = process.getOutputStream(); 65 | outputStream.write("export ".getBytes()); 66 | outputStream.write(env.getBytes()); 67 | outputStream.write("\n".getBytes()); 68 | outputStream.flush(); 69 | } 70 | return process; 71 | } 72 | 73 | public static Process getSuperUserRuntime() throws IOException { 74 | return getProcess("su"); 75 | } 76 | 77 | public static Process getRuntime() throws IOException { 78 | return getProcess("sh"); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /common/src/main/java/com/omarea/common/ui/BlurBackground.kt: -------------------------------------------------------------------------------- 1 | package com.omarea.common.ui 2 | 3 | import android.app.Activity 4 | import android.app.Dialog 5 | import android.graphics.Bitmap 6 | import android.os.Handler 7 | import android.os.Looper 8 | import android.renderscript.Allocation 9 | import android.renderscript.Element 10 | import android.renderscript.RenderScript 11 | import android.renderscript.ScriptIntrinsicBlur 12 | import android.view.View 13 | import android.view.Window 14 | import android.view.WindowManager 15 | import android.widget.ImageView 16 | 17 | class BlurBackground(private val activity: Activity) { 18 | private var dialogBg: ImageView? = null 19 | private var originalW = 0 20 | private var originalH = 0 21 | private var mHandler: Handler = Handler(Looper.getMainLooper()) 22 | 23 | private fun captureScreen(activity: Activity): Bitmap? { 24 | activity.window.decorView.destroyDrawingCache() //先清理屏幕绘制缓存(重要) 25 | activity.window.decorView.isDrawingCacheEnabled = true 26 | var bmp: Bitmap = activity.window.decorView.drawingCache 27 | //获取原图尺寸 28 | originalW = bmp.getWidth() 29 | originalH = bmp.getHeight() 30 | //对原图进行缩小,提高下一步高斯模糊的效率 31 | bmp = Bitmap.createScaledBitmap(bmp, originalW / 4, originalH / 4, false) 32 | return bmp 33 | } 34 | 35 | private fun asyncRefresh(`in`: Boolean) { 36 | //淡出淡入效果的实现 37 | if (`in`) { //淡入效果 38 | Thread { 39 | var i = 0 40 | while (i < 256) { 41 | refreshUI(i) //在UI线程刷新视图 42 | try { 43 | Thread.sleep(4) 44 | } catch (e: InterruptedException) { 45 | e.printStackTrace() 46 | } 47 | i += 5 48 | } 49 | }.start() 50 | } else { //淡出效果 51 | Thread { 52 | var i = 255 53 | while (i >= 0) { 54 | refreshUI(i) //在UI线程刷新视图 55 | try { 56 | Thread.sleep(4) 57 | } catch (e: InterruptedException) { 58 | e.printStackTrace() 59 | } 60 | i -= 5 61 | } 62 | //当淡出效果完毕后发送消息给mHandler把对话框背景设为不可见 63 | mHandler.sendEmptyMessage(0) 64 | }.start() 65 | } 66 | } 67 | 68 | private fun runOnUiThread(runnable: Runnable) { 69 | mHandler.post(runnable) 70 | } 71 | 72 | private fun refreshUI(i: Int) { 73 | runOnUiThread(Runnable { dialogBg?.setImageAlpha(i) }) 74 | } 75 | 76 | private fun hideBlur() { 77 | //把对话框背景隐藏 78 | asyncRefresh(false) 79 | System.gc() 80 | } 81 | 82 | private fun blur(bitmap: Bitmap): Bitmap? { 83 | //使用RenderScript对图片进行高斯模糊处理 84 | val output = Bitmap.createBitmap(bitmap) // 创建输出图片 85 | val rs: RenderScript = RenderScript.create(activity) // 构建一个RenderScript对象 86 | val gaussianBlue: ScriptIntrinsicBlur = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs)) // 87 | // 创建高斯模糊脚本 88 | val allIn: Allocation = Allocation.createFromBitmap(rs, bitmap) // 开辟输入内存 89 | val allOut: Allocation = Allocation.createFromBitmap(rs, output) // 开辟输出内存 90 | val radius = 10f //设置模糊半径 91 | gaussianBlue.setRadius(radius) // 设置模糊半径,范围0f=23则使用rs.releaseAllContexts() 97 | return output 98 | } 99 | 100 | private fun handleBlur() { 101 | dialogBg?.run { 102 | var bp = captureScreen(activity) 103 | if (bp == null) { 104 | return 105 | } 106 | 107 | bp = blur(bp) //对屏幕截图模糊处理 108 | //将模糊处理后的图恢复到原图尺寸并显示出来 109 | bp = Bitmap.createScaledBitmap(bp, originalW, originalH, false) 110 | setImageBitmap(bp) 111 | setVisibility(View.VISIBLE) 112 | //防止UI线程阻塞,在子线程中让背景实现淡入效果 113 | asyncRefresh(true) 114 | } 115 | } 116 | 117 | fun setScreenBgLight(dialog: Dialog) { 118 | val window: Window? = dialog.getWindow() 119 | val lp: WindowManager.LayoutParams 120 | if (window != null) { 121 | lp = window.getAttributes() 122 | lp.dimAmount = 0.2f 123 | window.setAttributes(lp) 124 | } 125 | handleBlur() 126 | } 127 | 128 | } -------------------------------------------------------------------------------- /common/src/main/java/com/omarea/common/ui/DialogAppChooser.kt: -------------------------------------------------------------------------------- 1 | package com.omarea.common.ui 2 | 3 | import android.content.DialogInterface 4 | import android.os.Bundle 5 | import android.text.Editable 6 | import android.text.TextWatcher 7 | import android.view.View 8 | import android.widget.AbsListView 9 | import android.widget.EditText 10 | import android.widget.Filterable 11 | import com.omarea.common.R 12 | 13 | class DialogAppChooser( 14 | private val darkMode: Boolean, 15 | private var packages: ArrayList, 16 | private val multiple: Boolean = false, 17 | private var callback: Callback? = null) : DialogFullScreen(R.layout.dialog_app_chooser, darkMode) { 18 | override fun onViewCreated(view: View, savedInstanceState: Bundle?) { 19 | super.onViewCreated(view, savedInstanceState) 20 | 21 | val absListView = view.findViewById(R.id.app_list) 22 | setup(absListView) 23 | 24 | view.findViewById(R.id.btn_cancel).setOnClickListener { 25 | dismiss() 26 | } 27 | view.findViewById(R.id.btn_confirm).setOnClickListener { 28 | this.onConfirm(absListView) 29 | } 30 | val clearBtn = view.findViewById(R.id.search_box_clear) 31 | val searchBox = view.findViewById(R.id.search_box).apply { 32 | addTextChangedListener(object : TextWatcher { 33 | override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {} 34 | override fun afterTextChanged(s: Editable?) { 35 | if (s != null) { 36 | clearBtn.visibility = if (s.length > 0) View.VISIBLE else View.GONE 37 | } 38 | } 39 | override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) { 40 | (absListView.adapter as Filterable).getFilter().filter(if (s == null) "" else s.toString()) 41 | } 42 | }) 43 | } 44 | clearBtn.visibility = if (searchBox.text.isNullOrEmpty()) View.GONE else View.VISIBLE 45 | clearBtn.setOnClickListener { 46 | searchBox.text = null 47 | } 48 | } 49 | 50 | private fun setup(gridView: AbsListView) { 51 | gridView.adapter = AdapterAppChooser(gridView.context, packages, multiple) 52 | } 53 | 54 | interface Callback { 55 | fun onConfirm(apps: List) 56 | } 57 | 58 | private fun onConfirm(gridView: AbsListView) { 59 | val apps = (gridView.adapter as AdapterAppChooser).getSelectedItems() 60 | 61 | callback?.onConfirm(apps) 62 | 63 | this.dismiss() 64 | } 65 | 66 | override fun onActivityCreated(savedInstanceState: Bundle?) { 67 | super.onActivityCreated(savedInstanceState) 68 | } 69 | 70 | override fun onDismiss(dialog: DialogInterface) { 71 | super.onDismiss(dialog) 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /common/src/main/java/com/omarea/common/ui/DialogFullScreen.kt: -------------------------------------------------------------------------------- 1 | package com.omarea.common.ui 2 | 3 | import android.app.Dialog 4 | import android.os.Build 5 | import android.os.Bundle 6 | import android.view.LayoutInflater 7 | import android.view.View 8 | import android.view.ViewGroup 9 | import android.view.WindowManager 10 | import com.omarea.common.R 11 | 12 | 13 | /* 14 | 继承使用示例: 15 | 16 | class DialogAppChooser(private val darkMode: Boolean): DialogFullScreen(R.layout.dialog_app_chooser, darkMode) { 17 | 18 | override fun onViewCreated(view: View, savedInstanceState: Bundle?) { 19 | super.onViewCreated(view, savedInstanceState) 20 | 21 | } 22 | 23 | override fun onActivityCreated(savedInstanceState: Bundle?) { 24 | super.onActivityCreated(savedInstanceState) 25 | } 26 | 27 | override fun onDismiss(dialog: DialogInterface) { 28 | super.onDismiss(dialog) 29 | } 30 | } 31 | */ 32 | 33 | open class DialogFullScreen(private val layout: Int, private val darkMode: Boolean) : androidx.fragment.app.DialogFragment() { 34 | override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { 35 | currentView = inflater.inflate(layout, container) 36 | return currentView 37 | } 38 | 39 | private var themeResId: Int = 0 40 | private lateinit var currentView: View 41 | 42 | override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { 43 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { 44 | return Dialog(activity!!, if (themeResId != 0) themeResId else R.style.dialog_full_screen_light) 45 | } else { 46 | return Dialog(activity!!, -1) 47 | } 48 | } 49 | 50 | override fun onViewCreated(view: View, savedInstanceState: Bundle?) { 51 | super.onViewCreated(view, savedInstanceState) 52 | 53 | val activity = this.activity 54 | if (activity != null) { 55 | dialog?.window?.run { 56 | if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { 57 | setWindowAnimations(android.R.style.Animation_Translucent) 58 | } 59 | 60 | DialogHelper.setWindowBlurBg(this, activity) 61 | } 62 | } 63 | } 64 | 65 | override fun onActivityCreated(savedInstanceState: Bundle?) { 66 | super.onActivityCreated(savedInstanceState) 67 | } 68 | 69 | public fun closeView() { 70 | try { 71 | dismiss() 72 | } catch (ex: java.lang.Exception) { 73 | } 74 | } 75 | 76 | init { 77 | themeResId = if (darkMode) R.style.dialog_full_screen_dark else R.style.dialog_full_screen_light 78 | } 79 | } -------------------------------------------------------------------------------- /common/src/main/java/com/omarea/common/ui/OverScrollGridView.java: -------------------------------------------------------------------------------- 1 | package com.omarea.common.ui; 2 | 3 | import android.content.Context; 4 | import android.util.AttributeSet; 5 | import android.widget.GridView; 6 | 7 | public class OverScrollGridView extends GridView { 8 | private int mMaxOverScrollY = 400;//默认200 9 | 10 | public OverScrollGridView(Context context) { 11 | super(context); 12 | } 13 | 14 | public OverScrollGridView(Context context, AttributeSet attrs) { 15 | super(context, attrs); 16 | } 17 | 18 | public OverScrollGridView(Context context, AttributeSet attrs, int defStyleAttr) { 19 | super(context, attrs, defStyleAttr); 20 | } 21 | 22 | 23 | /** 24 | * 设置最大的回弹距离 25 | * 26 | * @param maxOverScrollY 27 | */ 28 | public void setMaxOverScrollY(int maxOverScrollY) { 29 | this.mMaxOverScrollY = maxOverScrollY; 30 | } 31 | 32 | /** 33 | * @param deltaX 继续滑动x方向的距离 34 | * @param deltaY 继续滑动y方向的距离 负:表示顶部到头 正:表示底部到头 35 | * @param scrollX x方向滑动的距离 36 | * @param scrollY y方法滑动的距离 37 | * @param scrollRangeX 38 | * @param scrollRangeY 39 | * @param maxOverScrollX x方向最大可以滚动的距离 40 | * @param maxOverScrollY y方向最大可以滚动的距离 41 | * @param isTouchEvent 是手指拖动滑动 false:表示fling靠惯性滑动; 42 | * @return 43 | */ 44 | @Override 45 | protected boolean overScrollBy(int deltaX, int deltaY, int scrollX, int scrollY, int scrollRangeX, int scrollRangeY, int maxOverScrollX, int maxOverScrollY, boolean isTouchEvent) { 46 | return super.overScrollBy(deltaX, deltaY, scrollX, scrollY, scrollRangeX, scrollRangeY, 47 | maxOverScrollX, mMaxOverScrollY, isTouchEvent); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /common/src/main/java/com/omarea/common/ui/OverScrollListView.java: -------------------------------------------------------------------------------- 1 | package com.omarea.common.ui; 2 | 3 | import android.content.Context; 4 | import android.util.AttributeSet; 5 | 6 | public class OverScrollListView extends com.mixiaoxiao.overscroll.OverScrollListView { 7 | public OverScrollListView(Context context) { 8 | super(context); 9 | } 10 | 11 | public OverScrollListView(Context context, AttributeSet attrs) { 12 | super(context, attrs); 13 | } 14 | 15 | public OverScrollListView(Context context, AttributeSet attrs, int defStyleAttr) { 16 | super(context, attrs, defStyleAttr); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /common/src/main/java/com/omarea/common/ui/OverScrollView.java: -------------------------------------------------------------------------------- 1 | package com.omarea.common.ui; 2 | 3 | import android.annotation.TargetApi; 4 | import android.content.Context; 5 | import android.os.Build; 6 | import android.util.AttributeSet; 7 | 8 | import com.mixiaoxiao.overscroll.OverScrollScrollView; 9 | 10 | public class OverScrollView extends OverScrollScrollView { 11 | public OverScrollView(Context context) { 12 | super(context); 13 | } 14 | 15 | public OverScrollView(Context context, AttributeSet attrs) { 16 | super(context, attrs); 17 | } 18 | 19 | public OverScrollView(Context context, AttributeSet attrs, int defStyle) { 20 | super(context, attrs, defStyle); 21 | } 22 | 23 | @TargetApi(Build.VERSION_CODES.LOLLIPOP) 24 | public OverScrollView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { 25 | super(context, attrs, defStyleAttr, defStyleRes); 26 | } 27 | } -------------------------------------------------------------------------------- /common/src/main/java/com/omarea/common/ui/ProgressBarDialog.kt: -------------------------------------------------------------------------------- 1 | package com.omarea.common.ui 2 | 3 | import android.annotation.SuppressLint 4 | import android.app.Activity 5 | import android.os.Handler 6 | import android.os.Looper 7 | import android.os.Message 8 | import android.view.LayoutInflater 9 | import android.widget.TextView 10 | import android.widget.Toast 11 | import com.omarea.common.R 12 | import com.omarea.common.shell.AsynSuShellUnit 13 | import java.util.LinkedHashSet 14 | 15 | open class ProgressBarDialog(private var context: Activity, private var uniqueId: String? = null) { 16 | private var alert: DialogHelper.DialogWrap? = null 17 | private var textView: TextView? = null 18 | 19 | companion object { 20 | private val dialogs = LinkedHashMap() 21 | } 22 | 23 | init { 24 | hideDialog() 25 | } 26 | 27 | class DefaultHandler(private var alertDialog: DialogHelper.DialogWrap?) : Handler(Looper.myLooper()!!) { 28 | override fun handleMessage(msg: Message) { 29 | super.handleMessage(msg) 30 | 31 | try { 32 | if (alertDialog == null) { 33 | return 34 | } 35 | if (msg.what == 10) { 36 | alertDialog!!.dismiss() 37 | alertDialog!!.hide() 38 | if (msg.obj == true) { 39 | Toast.makeText(alertDialog!!.context, R.string.execute_success, Toast.LENGTH_SHORT).show() 40 | } else { 41 | Toast.makeText(alertDialog!!.context, R.string.execute_fail, Toast.LENGTH_LONG).show() 42 | } 43 | } else if (msg.what == -1) { 44 | Toast.makeText(alertDialog!!.context, R.string.execute_fail, Toast.LENGTH_LONG).show() 45 | } else if (msg.what == 0 && msg.obj == false) { 46 | alertDialog!!.dismiss() 47 | alertDialog!!.hide() 48 | Toast.makeText(alertDialog!!.context, R.string.execute_fail, Toast.LENGTH_LONG).show() 49 | } 50 | } catch (ex: Exception) { 51 | } 52 | } 53 | } 54 | 55 | @SuppressLint("InflateParams") 56 | public fun execShell(cmd: String, handler: Handler? = null) { 57 | hideDialog() 58 | 59 | val layoutInflater = LayoutInflater.from(context) 60 | val dialog = layoutInflater.inflate(R.layout.dialog_loading, null) 61 | val textView = (dialog.findViewById(R.id.dialog_text) as TextView) 62 | textView.text = context.getString(R.string.execute_wait) 63 | alert = DialogHelper.customDialog(context, dialog, false) 64 | // AlertDialog.Builder(context).setView(dialog).setCancelable(false).create() 65 | if (handler == null) { 66 | AsynSuShellUnit(DefaultHandler(alert)).exec(cmd).waitFor() 67 | } else { 68 | AsynSuShellUnit(handler).exec(cmd).waitFor() 69 | } 70 | } 71 | 72 | public fun execShell(sb: StringBuilder, handler: Handler? = null) { 73 | execShell(sb.toString(), handler) 74 | } 75 | 76 | public fun isDialogShow(): Boolean { 77 | return this.alert != null 78 | } 79 | 80 | public fun hideDialog() { 81 | try { 82 | if (alert != null) { 83 | alert!!.dismiss() 84 | alert!!.hide() 85 | alert = null 86 | } 87 | } catch (ex: Exception) { 88 | } 89 | 90 | uniqueId?.run { 91 | if (dialogs.containsKey(this)) { 92 | dialogs.remove(this) 93 | } 94 | } 95 | } 96 | 97 | @SuppressLint("InflateParams") 98 | public fun showDialog(text: String = "正在加载,请稍等..."): ProgressBarDialog { 99 | if (textView != null && alert != null) { 100 | textView!!.text = text 101 | } else { 102 | hideDialog() 103 | val layoutInflater = LayoutInflater.from(context) 104 | val dialog = layoutInflater.inflate(R.layout.dialog_loading, null) 105 | textView = (dialog.findViewById(R.id.dialog_text) as TextView) 106 | textView!!.text = text 107 | alert = DialogHelper.customDialog(context, dialog, false) 108 | // AlertDialog.Builder(context).setView(dialog).setCancelable(false).create() 109 | } 110 | 111 | uniqueId?.run { 112 | if (dialogs.containsKey(this)) { 113 | dialogs.remove(this) 114 | } 115 | if (alert != null) { 116 | dialogs.put(this, alert!!) 117 | } 118 | } 119 | 120 | return this 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /common/src/main/java/com/omarea/common/ui/ThemeMode.kt: -------------------------------------------------------------------------------- 1 | package com.omarea.common.ui 2 | 3 | class ThemeMode { 4 | var isDarkMode: Boolean = false 5 | var isLightStatusBar: Boolean = false 6 | } 7 | -------------------------------------------------------------------------------- /common/src/main/res/anim/activity_close_enter.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 10 | 14 | -------------------------------------------------------------------------------- /common/src/main/res/anim/activity_close_exit.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 10 | 18 | 22 | -------------------------------------------------------------------------------- /common/src/main/res/anim/activity_open_enter.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 10 | 14 | -------------------------------------------------------------------------------- /common/src/main/res/anim/activity_open_exit.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 10 | 18 | 22 | -------------------------------------------------------------------------------- /common/src/main/res/anim/dialog_enter.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 10 | 19 | 23 | -------------------------------------------------------------------------------- /common/src/main/res/anim/dialog_exit.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 10 | 19 | 23 | -------------------------------------------------------------------------------- /common/src/main/res/anim/dialog_fade_in.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 13 | 18 | -------------------------------------------------------------------------------- /common/src/main/res/anim/dialog_fade_out.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 15 | 24 | 29 | -------------------------------------------------------------------------------- /common/src/main/res/anim/input_method_enter.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 10 | 19 | 23 | -------------------------------------------------------------------------------- /common/src/main/res/anim/input_method_exit.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 10 | 19 | 23 | -------------------------------------------------------------------------------- /common/src/main/res/anim/task_close_enter.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 10 | 14 | -------------------------------------------------------------------------------- /common/src/main/res/anim/task_close_exit.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 10 | 18 | 22 | -------------------------------------------------------------------------------- /common/src/main/res/anim/task_open_enter.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 10 | 14 | -------------------------------------------------------------------------------- /common/src/main/res/anim/task_open_exit.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 10 | 18 | 22 | -------------------------------------------------------------------------------- /common/src/main/res/anim/toast_enter.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 10 | 19 | 23 | -------------------------------------------------------------------------------- /common/src/main/res/anim/toast_exit.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 10 | 19 | 23 | -------------------------------------------------------------------------------- /common/src/main/res/drawable/btn_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /common/src/main/res/drawable/btn_bg_active.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 8 | 9 | 10 | 13 | 14 | 15 | 16 | 17 | 18 | 23 | -------------------------------------------------------------------------------- /common/src/main/res/drawable/btn_bg_active_large.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 15 | -------------------------------------------------------------------------------- /common/src/main/res/drawable/btn_bg_disabled.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 10 | 11 | 12 | 13 | 14 | 15 | 20 | -------------------------------------------------------------------------------- /common/src/main/res/drawable/btn_bg_disabled_large.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 10 | 11 | 12 | 13 | 14 | 15 | 20 | -------------------------------------------------------------------------------- /common/src/main/res/drawable/btn_bg_inactive.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 8 | 9 | 10 | 13 | 14 | 15 | 16 | 17 | 18 | 23 | -------------------------------------------------------------------------------- /common/src/main/res/drawable/btn_bg_inactive_large.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 15 | -------------------------------------------------------------------------------- /common/src/main/res/drawable/btn_bg_inactive_large_secondary.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 15 | -------------------------------------------------------------------------------- /common/src/main/res/drawable/btn_bg_inactive_large_warning.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 15 | -------------------------------------------------------------------------------- /common/src/main/res/drawable/btn_bg_large.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /common/src/main/res/drawable/btn_bg_large_secondary.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /common/src/main/res/drawable/btn_bg_large_warning.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /common/src/main/res/drawable/checkbox_false.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 10 | -------------------------------------------------------------------------------- /common/src/main/res/drawable/checkbox_style.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /common/src/main/res/drawable/checkbox_true.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | -------------------------------------------------------------------------------- /common/src/main/res/drawable/confirm_dialog_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /common/src/main/res/drawable/dialog_search_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 10 | 11 | -------------------------------------------------------------------------------- /common/src/main/res/drawable/dialog_search_clear.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/helloklf/ScreenFilter/780ffb7b9fd626c150aa625ead6b1d1b5b04676b/common/src/main/res/drawable/dialog_search_clear.png -------------------------------------------------------------------------------- /common/src/main/res/drawable/in_card_item_inactive.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /common/src/main/res/drawable/radio_false.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 10 | -------------------------------------------------------------------------------- /common/src/main/res/drawable/radio_style.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /common/src/main/res/drawable/radio_true.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | -------------------------------------------------------------------------------- /common/src/main/res/drawable/seekbar_big_thumb.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 8 | -------------------------------------------------------------------------------- /common/src/main/res/drawable/seekbar_progress_big_drawable.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /common/src/main/res/drawable/seekbar_progress_drawable.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /common/src/main/res/drawable/seekbar_progress_icon.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /common/src/main/res/drawable/seekbar_thumb.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 8 | -------------------------------------------------------------------------------- /common/src/main/res/drawable/switch_thumb.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /common/src/main/res/drawable/switch_track.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /common/src/main/res/drawable/switch_track_close.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /common/src/main/res/drawable/switch_track_disabled.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /common/src/main/res/drawable/switch_track_open.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /common/src/main/res/layout/app_multiple_chooser_item.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 16 | 17 | 25 | 31 | 37 | 38 | 39 | 47 | -------------------------------------------------------------------------------- /common/src/main/res/layout/app_single_chooser_item.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 16 | 17 | 25 | 31 | 37 | 38 | 39 | 47 | -------------------------------------------------------------------------------- /common/src/main/res/layout/dialog_alert.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 11 | 12 | 20 | 21 | 30 | 39 | 40 | 44 | 45 | 46 | 51 | 52 | 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /common/src/main/res/layout/dialog_app_chooser.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 15 | 29 | 30 | 41 | 42 | 43 | 51 | 52 | 59 | 60 | 66 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /common/src/main/res/layout/dialog_confirm.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 11 | 12 | 20 | 21 | 25 | 29 | 30 | 34 | 35 | 36 | 41 | 42 | 48 | 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /common/src/main/res/layout/dialog_confirm_custom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 11 | 12 | 20 | 21 | 25 | 29 | 30 | 34 | 35 | 36 | 41 | 42 | 48 | 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /common/src/main/res/layout/dialog_help_info.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 15 | 16 | 22 | 23 | -------------------------------------------------------------------------------- /common/src/main/res/layout/dialog_item_chooser.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 13 | 27 | 28 | 39 | 40 | 41 | 47 | 48 | 56 | 57 | 65 | 66 | 67 | 75 | 76 | 83 | 84 | 90 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /common/src/main/res/layout/dialog_item_chooser_small.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 15 | 29 | 30 | 41 | 42 | 43 | 48 | 49 | 57 | 58 | 66 | 67 | 68 | 77 | 78 | 84 | 85 | 91 | 96 | 97 | 98 | -------------------------------------------------------------------------------- /common/src/main/res/layout/dialog_loading.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 14 | 15 | 23 | 24 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /common/src/main/res/layout/dialog_loading_accurate.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 16 | 17 | 25 | 26 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /common/src/main/res/layout/dialog_warning.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 11 | 12 | 20 | 21 | 25 | 29 | 30 | 34 | 35 | 36 | 37 | 42 | 43 | 49 | 55 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /common/src/main/res/layout/item_multiple_chooser_item.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 16 | 22 | 28 | 29 | 30 | 38 | -------------------------------------------------------------------------------- /common/src/main/res/layout/item_single_chooser_item.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 16 | 22 | 28 | 29 | 30 | 38 | -------------------------------------------------------------------------------- /common/src/main/res/values-v23/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 18 | 19 | 28 | 29 | 38 | -------------------------------------------------------------------------------- /common/src/main/res/values/attrs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /common/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #FFB300 4 | -------------------------------------------------------------------------------- /common/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 执行成功 3 | 执行失败 4 | 正在执行,请稍等… 5 | 确定 6 | 输入应用名/包名进行搜索 7 | 搜索可选择项 8 | 9 | -------------------------------------------------------------------------------- /common/src/test/java/com/omarea/common/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package com.omarea.common; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.assertEquals; 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * @see Testing documentation 11 | */ 12 | public class ExampleUnitTest { 13 | @Test 14 | public void addition_isCorrect() { 15 | assertEquals(4, 2 + 2); 16 | } 17 | } -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | ## For more details on how to configure your build environment visit 2 | # http://www.gradle.org/docs/current/userguide/build_environment.html 3 | # 4 | # Specifies the JVM arguments used for the daemon process. 5 | # The setting is particularly useful for tweaking memory settings. 6 | # Default value: -Xmx1024m -XX:MaxPermSize=256m 7 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 8 | # 9 | # When configured, Gradle will run in incubating parallel mode. 10 | # This option should only be used with decoupled projects. More details, visit 11 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 12 | # org.gradle.parallel=true 13 | #Fri Apr 30 11:58:50 GMT+08:00 2021 14 | android.enableJetifier=true 15 | android.useAndroidX=true 16 | org.gradle.jvmargs=-Xmx1536m 17 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/helloklf/ScreenFilter/780ffb7b9fd626c150aa625ead6b1d1b5b04676b/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Fri Oct 30 09:24:02 GMT+08:00 2020 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-all.zip 7 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | include ':common' 3 | --------------------------------------------------------------------------------