├── .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 |
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 |
--------------------------------------------------------------------------------