This commit is contained in:
JerryXiao 2023-08-18 12:24:07 +08:00
parent f0cd85370f
commit 183f98ac47
Signed by: Jerry
GPG key ID: 22618F758B5BE2E5
11 changed files with 252 additions and 26 deletions

View file

@ -36,6 +36,7 @@ dependencies {
implementation 'androidx.appcompat:appcompat:1.4.1'
implementation 'com.google.android.material:material:1.5.0'
implementation 'androidx.core:core-ktx:1.10.1'
implementation 'androidx.preference:preference:1.2.0'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'

View file

@ -3,6 +3,7 @@
xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
@ -13,18 +14,27 @@
android:supportsRtl="true"
android:theme="@style/Theme.EasterScrSaver"
tools:targetApi="32">
<activity
android:name=".SettingsActivity"
android:exported="false"
android:label="@string/title_activity_settings" />
<service
android:name=".EasterDream"
android:exported="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:permission="android.permission.BIND_DREAM_SERVICE">
<service
android:name=".EasterDream"
android:exported="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:permission="android.permission.BIND_DREAM_SERVICE">
<intent-filter>
<action android:name="android.service.dreams.DreamService" />
<intent-filter>
<action android:name="android.service.dreams.DreamService" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</service>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<meta-data
android:name="android.service.dream"
android:resource="@xml/easterdream" />
</service>
</application>
</manifest>

View file

@ -4,12 +4,13 @@ import static android.graphics.PixelFormat.TRANSLUCENT;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.annotation.SuppressLint;
import android.app.WallpaperManager;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
@ -27,12 +28,17 @@ import android.widget.ImageView;
import androidx.annotation.ChecksSdkIntAtLeast;
import androidx.core.app.ActivityCompat;
import androidx.preference.PreferenceManager;
import java.util.ArrayList;
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;
public class EasterDream extends DreamService {
private static String TAG = "easter_daydream";
private static String TAG = "EasterDream";
private SharedPreferences prefs;
private Drawable wallPaperDrawable = null;
private FrameLayout last = null;
private boolean enabled = false;
@ -101,7 +107,9 @@ public class EasterDream extends DreamService {
@Override
public void onAttachedToWindow() {
super.onAttachedToWindow();
this.prefs = PreferenceManager.getDefaultSharedPreferences(this);
setScreenBright(!this.prefs.getBoolean("dim_screen", false));
// Exit dream upon user touch
setInteractive(false);
// Hide system UI
@ -119,7 +127,7 @@ public class EasterDream extends DreamService {
refresh();
}
private static final String[][] EMOJI_SETS = {
protected static final String[][] EMOJI_SETS = {
{"🍇", "🍈", "🍉", "🍊", "🍋", "🍌", "🍍", "🥭", "🍎", "🍏", "🍐", "🍑",
"🍒", "🍓", "🫐", "🥝"},
{"😺", "😸", "😹", "😻", "😼", "😽", "🙀", "😿", "😾"},
@ -245,20 +253,37 @@ class BubblesDrawable extends Drawable {
//randomize();
//chooseEmojiSet();
}
}, 10000L);
}, Integer.parseInt(EasterDream.this.prefs.getString("switch_time", "10")) * 1000L);
}
public void chooseEmojiSet() {
if (Math.random() < 0.8) {
if (Math.random() < 0.4) {
mEmojiSet = 0;
}
else {
mEmojiSet = 13;
}
ArrayList<Integer> probList = new ArrayList<>();
int probSum = 0;
for (int i = 0; i < EMOJI_SETS.length; i++) {
@SuppressLint("DefaultLocale")
int p = Integer.parseInt(EasterDream.this.prefs.getString(String.format("prob_%d", i), "5"));
probSum += p;
probList.add(probSum);
//Log.d(TAG, String.format("probList %d %d", i, probSum));
}
//Log.d(TAG, String.format("probSum %d", probSum));
if (probSum <= 0) {
mEmojiSet = (int) (Math.random() * EMOJI_SETS.length);
}
else {
mEmojiSet = (int) (Math.random() * EMOJI_SETS.length);
mEmojiSet = -1;
int r = (new Random()).nextInt(probSum);
for (int i = 0; i < EMOJI_SETS.length; i++) {
if (r < probList.get(i)) {
mEmojiSet = i;
break;
}
}
//Log.d(TAG, String.format("probRand %d", r));
if (mEmojiSet < 0) {
Log.e(TAG, String.format("unexpected mEmojiSet %d", mEmojiSet));
mEmojiSet = (int) (Math.random() * EMOJI_SETS.length);
}
}
final String[] emojiSet = EMOJI_SETS[mEmojiSet];
Log.i(TAG, "chooseEmojiSet: " + mEmojiSet);

View file

@ -0,0 +1,102 @@
package cc.jerryxiao.easterscrsaver;
import android.annotation.SuppressLint;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.preference.ListPreference;
import androidx.preference.PreferenceCategory;
import androidx.preference.PreferenceFragmentCompat;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
public class SettingsActivity extends AppCompatActivity {
private static String TAG = "EasterDream";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.settings_activity);
if (savedInstanceState == null) {
getSupportFragmentManager()
.beginTransaction()
.replace(R.id.settings, new SettingsFragment())
.commit();
}
ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
actionBar.setDisplayHomeAsUpEnabled(true);
}
Map<String, String> permissionsToRequest = new HashMap<>();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
permissionsToRequest.putAll(Map.of("android.permission.READ_EXTERNAL_STORAGE",
getString(R.string.permission_denied_read_external_storage)));
Iterator<Map.Entry<String, String>> it = permissionsToRequest.entrySet().iterator();
if (it.hasNext()) {
if (checkSelfPermission(it.next().getKey()) == PackageManager.PERMISSION_GRANTED) {
it.remove();
}
}
}
if (!permissionsToRequest.isEmpty()) {
Log.d(TAG, String.format("requesting permissions %s", String.join(" + ", permissionsToRequest.keySet().toArray(new String[0]))));
ActivityResultLauncher<String[]> permissionReq = registerForActivityResult(new ActivityResultContracts.RequestMultiplePermissions(), (result) -> {
for (var res : result.entrySet()) {
var perm = res.getKey();
var granted = res.getValue();
if (!granted) {
Log.d(TAG, String.format("permission denied: %s", perm));
(new AlertDialog.Builder(this))
.setTitle(getText(R.string.error_title))
.setMessage(permissionsToRequest.get(perm))
.setCancelable(false)
.setPositiveButton(getString(R.string.button_ok), (dialog, id) -> {
})
.create()
.show();
}
}
});
permissionReq.launch(permissionsToRequest.keySet().toArray(new String[0]));
}
}
@Override
public boolean onSupportNavigateUp() {
onBackPressed();
return true;
}
public static class SettingsFragment extends PreferenceFragmentCompat {
@Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
setPreferencesFromResource(R.xml.preferences, rootKey);
PreferenceCategory category = (PreferenceCategory)getPreferenceScreen().getPreference(0);
int index = 0;
for (String[] emojis : EasterDream.EMOJI_SETS) {
var listPreference = new ListPreference(getPreferenceScreen().getContext());
@SuppressLint("DefaultLocale")
String k = String.format("prob_%d", index);
listPreference.setKey(k);
listPreference.setDefaultValue("1");
listPreference.setEntries(R.array.probability_entries_values);
listPreference.setEntryValues(R.array.probability_entries_values);
listPreference.setSummaryProvider(ListPreference.SimpleSummaryProvider.getInstance());
listPreference.setTitle(getString(R.string.prob_fmt, String.join("", Arrays.copyOfRange(emojis, 0, Math.min(emojis.length, 5)))));
category.addPreference(listPreference);
index++;
}
}
}
}

View file

@ -0,0 +1,9 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:id="@+id/settings"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>

View file

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">EasterScrSaver</string>
<string name="title_activity_settings">设置</string>
<string name="daydream_header">屏保</string>
<string name="dim_screen_title">允许降低亮度</string>
<string name="switch_time_title">换页时间</string>
<string name="prob_fmt">%1$s 的出现频率</string>
<string name="permission_denied_read_external_storage">读取存储空间权限被拒绝,壁纸将不会显示</string>
<string name="error_title">错误</string>
<string name="button_ok"></string>
</resources>

View file

@ -0,0 +1,35 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="switch_time_entries">
<item>3600</item>
<item>300</item>
<item>60</item>
<item>30</item>
<item>10</item>
<item>5</item>
</string-array>
<string-array name="switch_time_values">
<item>3600</item>
<item>300</item>
<item>60</item>
<item>30</item>
<item>10</item>
<item>5</item>
</string-array>
<string-array name="probability_entries_values">
<item>100</item>
<item>50</item>
<item>20</item>
<item>10</item>
<item>9</item>
<item>8</item>
<item>7</item>
<item>6</item>
<item>5</item>
<item>4</item>
<item>3</item>
<item>2</item>
<item>1</item>
<item>0</item>
</string-array>
</resources>

View file

@ -1,3 +1,11 @@
<resources>
<string name="app_name">EasterScrSaver</string>
</resources>
<string name="title_activity_settings">Settings</string>
<string name="daydream_header">Daydream</string>
<string name="dim_screen_title">Screen Dimming</string>
<string name="switch_time_title">Switching time</string>
<string name="prob_fmt">Occur freq of %1$s</string>
<string name="permission_denied_read_external_storage">Storage read permission denied, wallpaper can\'t be shown</string>
<string name="error_title">Error occurred</string>
<string name="button_ok">OK</string>
</resources>

View file

@ -0,0 +1,2 @@
<dream xmlns:android="http://schemas.android.com/apk/res/android"
android:settingsActivity="cc.jerryxiao.easterscrsaver/.SettingsActivity" />

View file

@ -0,0 +1,22 @@
<PreferenceScreen xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceCategory app:title="@string/daydream_header">
<SwitchPreferenceCompat
app:key="dim_screen"
app:title="@string/dim_screen_title"
app:defaultValue="false" />
<ListPreference
app:defaultValue="10"
app:entries="@array/switch_time_entries"
app:entryValues="@array/switch_time_values"
app:key="switch_time"
app:title="@string/switch_time_title"
app:useSimpleSummaryProvider="true" />
</PreferenceCategory>
</PreferenceScreen>

View file

@ -1,6 +1,6 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins {
id 'com.android.application' version '8.0.2' apply false
id 'com.android.library' version '8.0.2' apply false
id 'com.android.application' version '8.1.0' apply false
id 'com.android.library' version '8.1.0' apply false
id 'org.jetbrains.kotlin.android' version '1.9.0' apply false
}