feat: 联系人增加头像选择

This commit is contained in:
2026-05-30 04:07:18 +08:00
parent 87903b7216
commit 1c89943459
52 changed files with 1892 additions and 226 deletions

View File

@@ -0,0 +1,90 @@
package com.ttstd.dialer.receiver;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Build;
import androidx.core.app.NotificationCompat;
import com.ttstd.dialer.activity.alarm.AlarmAlertActivity;
import com.ttstd.dialer.alarmclock.AlarmManagerHelper;
import com.ttstd.dialer.alarmclock.AlarmRepeatConfig;
import com.ttstd.dialer.alarmclock.AlarmTimeCalculator;
public class AlarmReceiver extends BroadcastReceiver {
private static final String CHANNEL_ID = "alarm_channel";
@Override
public void onReceive(Context context, Intent intent) {
// 1. 执行原有的响铃和弹出通知/界面的逻辑
// (调用上一次回答中创建的通知栏或全屏拉起逻辑)
showAlarmNotification(context);
// 2. 核心:动态轮转,实现重复闹钟
scheduleNextRepeatAlarm(context);
}
private void scheduleNextRepeatAlarm(Context context) {
// 从 SharedPreferences 中取出用户之前保存的闹钟时间和重复设置
// 实际开发中此处可以替换为 SQLite 数据库
SharedPreferences sp = context.getSharedPreferences("AlarmPrefs", Context.MODE_PRIVATE);
int hour = sp.getInt("alarm_hour", 8);
int minute = sp.getInt("alarm_minute", 0);
int repeatType = sp.getInt("repeat_type", AlarmRepeatConfig.REPEAT_ONCE);
// 如果是“只响一次”,响完就结束了,不需要再设置
if (repeatType == AlarmRepeatConfig.REPEAT_ONCE) {
return;
}
// 如果是 每天 或 周一至周五
AlarmRepeatConfig config = new AlarmRepeatConfig(repeatType);
// 重新计算下一次的时间(由于此时已经过了当前闹钟点,计算出的必定是未来的时间)
long nextTriggerTime = AlarmTimeCalculator.calculateNextAlarmTime(hour, minute, config);
// 再次调用第一步写好的精准闹钟设置工具,埋下新的定时炸弹
AlarmManagerHelper.setExactAlarm(context, nextTriggerTime);
}
private void showAlarmNotification(Context context) {
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
if (notificationManager == null) return;
// 1. 创建通知渠道 (Android 8.0+)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(
CHANNEL_ID, "闹钟响铃", NotificationManager.IMPORTANCE_HIGH);
channel.setDescription("用于展示闹钟响铃界面");
channel.enableLights(true);
channel.setBypassDnd(true); // 绕过免打扰
notificationManager.createNotificationChannel(channel);
}
// 2. 构建点击通知或全屏弹出的 Intent
Intent alertIntent = new Intent(context, AlarmAlertActivity.class);
alertIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
int flags = Build.VERSION.SDK_INT >= Build.VERSION_CODES.M ?
PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE :
PendingIntent.FLAG_UPDATE_CURRENT;
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, alertIntent, flags);
// 3. 构建高优先级通知(兼容 Android 10+ 后台全屏拉起)
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, CHANNEL_ID)
.setSmallIcon(android.R.drawable.ic_lock_idle_alarm)
.setContentTitle("闹钟响了")
.setContentText("时间到了,快起床!")
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setCategory(NotificationCompat.CATEGORY_ALARM)
.setAutoCancel(true)
.setFullScreenIntent(pendingIntent, true); // 核心:锁屏时直接拉起 Activity
notificationManager.notify(1, builder.build());
}
}

View File

@@ -4,16 +4,24 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.text.TextUtils;
import android.util.Log;
import com.tencent.mmkv.MMKV;
import com.ttstd.dialer.config.CommonConfig;
import com.ttstd.dialer.manager.AppManager;
import com.ttstd.dialer.utils.Logger;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class AppChangedReceiver extends BroadcastReceiver {
private static final String TAG = "ApkInstallReceiver";
private static final String TAG = "AppChangedReceiver";
private MMKV mMMKV = MMKV.mmkvWithID(CommonConfig.MMKV_ID, MMKV.MULTI_PROCESS_MODE);
// 创建一个单线程池用于处理应用变更事件
private static final ExecutorService sExecutor = Executors.newSingleThreadExecutor();
@Override
public void onReceive(final Context context, Intent intent) {
String action = intent.getAction();
@@ -35,6 +43,13 @@ public class AppChangedReceiver extends BroadcastReceiver {
default:
break;
}
sExecutor.execute(() -> {
try {
AppManager.getInstance().updateApp(packageName);
} catch (Exception e) {
Log.e(TAG, "onReceive: updateApp " + e.getMessage());
}
});
}
}