适配小米15,修改通知模块。

This commit is contained in:
ZhanGSKen 2025-03-22 05:53:58 +08:00
parent 0d21994291
commit 508c8b0b97
10 changed files with 308 additions and 41 deletions

View File

@ -1,8 +1,8 @@
#Created by .winboll/winboll_app_build.gradle #Created by .winboll/winboll_app_build.gradle
#Thu Jan 02 11:13:45 HKT 2025 #Fri Mar 21 21:51:15 GMT 2025
stageCount=6 stageCount=6
libraryProject= libraryProject=
baseVersion=4.0 baseVersion=4.0
publishVersion=4.0.5 publishVersion=4.0.5
buildCount=0 buildCount=13
baseBetaVersion=4.0.6 baseBetaVersion=4.0.6

View File

@ -2,10 +2,9 @@
<manifest <manifest
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
package="cc.winboll.studio.powerbell"> package="cc.winboll.studio.powerbell">
<uses-permission android:name="android.permission.CAMERA" /> <!-- 拍摄照片和视频 -->
<uses-feature android:name="android.hardware.camera" /> <uses-permission android:name="android.permission.CAMERA"/>
<uses-feature android:name="android.hardware.camera.autofocus" />
<!-- 运行前台服务 --> <!-- 运行前台服务 -->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/> <uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
@ -22,6 +21,23 @@
<!-- MANAGE_EXTERNAL_STORAGE --> <!-- MANAGE_EXTERNAL_STORAGE -->
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"/>
<!-- 显示通知 -->
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
<uses-feature android:name="android.hardware.camera"/>
<uses-feature android:name="android.hardware.camera.autofocus"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"/>
<application <application
android:name=".GlobalApplication" android:name=".GlobalApplication"
android:allowBackup="true" android:allowBackup="true"
@ -34,7 +50,8 @@
<activity <activity
android:name=".MainActivity" android:name=".MainActivity"
android:launchMode="singleTask"> android:launchMode="singleTask"
android:exported="true">
<intent-filter> <intent-filter>

View File

@ -17,7 +17,7 @@ import cc.winboll.studio.powerbell.activities.AboutActivity;
import cc.winboll.studio.powerbell.activities.BackgroundPictureActivity; import cc.winboll.studio.powerbell.activities.BackgroundPictureActivity;
import cc.winboll.studio.powerbell.activities.ClearRecordActivity; import cc.winboll.studio.powerbell.activities.ClearRecordActivity;
import cc.winboll.studio.powerbell.fragments.MainViewFragment; import cc.winboll.studio.powerbell.fragments.MainViewFragment;
import cc.winboll.studio.powerbell.utils.NotificationUtils; import cc.winboll.studio.powerbell.utils.NotificationHelper;
import cc.winboll.studio.shared.log.LogUtils; import cc.winboll.studio.shared.log.LogUtils;
import cc.winboll.studio.shared.log.LogView; import cc.winboll.studio.shared.log.LogView;
@ -64,8 +64,10 @@ public class MainActivity extends Activity {
} }
showFragment(mMainViewFragment); showFragment(mMainViewFragment);
NotificationUtils notificationUtils = new NotificationUtils(this); // NotificationHelper notificationUtils = new NotificationHelper(this);
notificationUtils.createNotificationChannel(); // notificationUtils.createNotificationChannels();
} }
void showFragment(Fragment fragment) { void showFragment(Fragment fragment) {
@ -113,7 +115,7 @@ public class MainActivity extends Activity {
protected void onResume() { protected void onResume() {
super.onResume(); super.onResume();
// 回到窗口自动取消提醒消息 // 回到窗口自动取消提醒消息
NotificationUtils.cancelRemindNotification(this); //NotificationHelper.cancelRemindNotification(this);
reloadBackground(); reloadBackground();
} }

View File

@ -8,7 +8,7 @@ import cc.winboll.studio.powerbell.GlobalApplication;
import cc.winboll.studio.powerbell.fragments.MainViewFragment; import cc.winboll.studio.powerbell.fragments.MainViewFragment;
import cc.winboll.studio.powerbell.utils.AppConfigUtils; import cc.winboll.studio.powerbell.utils.AppConfigUtils;
import cc.winboll.studio.powerbell.utils.BatteryUtils; import cc.winboll.studio.powerbell.utils.BatteryUtils;
import cc.winboll.studio.powerbell.utils.NotificationUtils; import cc.winboll.studio.powerbell.utils.NotificationHelper;
public class GlobalApplicationReceiver extends BroadcastReceiver { public class GlobalApplicationReceiver extends BroadcastReceiver {
@ -45,7 +45,7 @@ public class GlobalApplicationReceiver extends BroadcastReceiver {
// 新电池状态标志某一个有变化就更新显示信息 // 新电池状态标志某一个有变化就更新显示信息
if (_mIsCharging != isCharging || _mnTheQuantityOfElectricityOld != nTheQuantityOfElectricity) { if (_mIsCharging != isCharging || _mnTheQuantityOfElectricityOld != nTheQuantityOfElectricity) {
// 电池状态改变先取消旧的提醒消息 // 电池状态改变先取消旧的提醒消息
NotificationUtils.cancelRemindNotification(context); //NotificationHelper.cancelRemindNotification(context);
GlobalApplication.getAppCacheUtils(context).addChangingTime(nTheQuantityOfElectricity); GlobalApplication.getAppCacheUtils(context).addChangingTime(nTheQuantityOfElectricity);
MainViewFragment.sendMsgCurrentValueBattery(nTheQuantityOfElectricity); MainViewFragment.sendMsgCurrentValueBattery(nTheQuantityOfElectricity);

View File

@ -8,14 +8,17 @@ package cc.winboll.studio.powerbell.services;
* Android Service之onStartCommand方法研究 * Android Service之onStartCommand方法研究
* https://blog.csdn.net/cyp331203/article/details/38920491 * https://blog.csdn.net/cyp331203/article/details/38920491
*/ */
import cc.winboll.studio.powerbell.R; import android.app.Notification;
import android.app.Service; import android.app.Service;
import android.content.ComponentName; import android.content.ComponentName;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.ServiceConnection; import android.content.ServiceConnection;
import android.os.IBinder; import android.os.IBinder;
import android.widget.RemoteViews;
import cc.winboll.studio.powerbell.GlobalApplication; import cc.winboll.studio.powerbell.GlobalApplication;
import cc.winboll.studio.powerbell.MainActivity;
import cc.winboll.studio.powerbell.R;
import cc.winboll.studio.powerbell.beans.AppConfigBean; import cc.winboll.studio.powerbell.beans.AppConfigBean;
import cc.winboll.studio.powerbell.beans.NotificationMessage; import cc.winboll.studio.powerbell.beans.NotificationMessage;
import cc.winboll.studio.powerbell.handlers.ControlCenterServiceHandler; import cc.winboll.studio.powerbell.handlers.ControlCenterServiceHandler;
@ -24,11 +27,12 @@ import cc.winboll.studio.powerbell.services.AssistantService;
import cc.winboll.studio.powerbell.threads.RemindThread; import cc.winboll.studio.powerbell.threads.RemindThread;
import cc.winboll.studio.powerbell.utils.AppCacheUtils; import cc.winboll.studio.powerbell.utils.AppCacheUtils;
import cc.winboll.studio.powerbell.utils.AppConfigUtils; import cc.winboll.studio.powerbell.utils.AppConfigUtils;
import cc.winboll.studio.powerbell.utils.NotificationUtils; import cc.winboll.studio.powerbell.utils.NotificationHelper;
import cc.winboll.studio.powerbell.utils.ServiceUtils; import cc.winboll.studio.powerbell.utils.ServiceUtils;
import cc.winboll.studio.powerbell.utils.StringUtils; import cc.winboll.studio.powerbell.utils.StringUtils;
import cc.winboll.studio.shared.log.LogUtils; import cc.winboll.studio.shared.log.LogUtils;
import com.hjq.toast.ToastUtils; import com.hjq.toast.ToastUtils;
import android.graphics.Color;
public class ControlCenterService extends Service { public class ControlCenterService extends Service {
@ -43,7 +47,8 @@ public class ControlCenterService extends Service {
AppConfigUtils mAppConfigUtils; AppConfigUtils mAppConfigUtils;
AppCacheUtils mAppCacheUtils; AppCacheUtils mAppCacheUtils;
// 前台服务通知工具 // 前台服务通知工具
NotificationUtils mNotificationUtils; NotificationHelper mNotificationHelper;
Notification notification;
RemindThread mRemindThread; RemindThread mRemindThread;
ControlCenterServiceHandler mControlCenterServiceHandler; ControlCenterServiceHandler mControlCenterServiceHandler;
MyServiceConnection mMyServiceConnection; MyServiceConnection mMyServiceConnection;
@ -66,7 +71,9 @@ public class ControlCenterService extends Service {
isServiceRunning = false; isServiceRunning = false;
mAppConfigUtils = GlobalApplication.getAppConfigUtils(this); mAppConfigUtils = GlobalApplication.getAppConfigUtils(this);
mAppCacheUtils = GlobalApplication.getAppCacheUtils(this); mAppCacheUtils = GlobalApplication.getAppCacheUtils(this);
mNotificationUtils = new NotificationUtils(ControlCenterService.this); mNotificationHelper = new NotificationHelper(ControlCenterService.this);
if (mMyServiceConnection == null) { if (mMyServiceConnection == null) {
mMyServiceConnection = new MyServiceConnection(); mMyServiceConnection = new MyServiceConnection();
} }
@ -92,10 +99,16 @@ public class ControlCenterService extends Service {
// 唤醒守护进程 // 唤醒守护进程
wakeupAndBindAssistant(); wakeupAndBindAssistant();
// 显示前台通知栏 // 显示前台通知栏
NotificationMessage notificationMessage=createNotificationMessage(); // 在Service中
//Toast.makeText(getApplication(), "", Toast.LENGTH_SHORT).show(); NotificationHelper helper = new NotificationHelper(this);
mNotificationUtils.createForegroundNotification(this, notificationMessage); Intent intent = new Intent(this, MainActivity.class);
mNotificationUtils.createRemindNotification(this, notificationMessage); notification = helper.showForegroundNotification(intent, getString(R.string.app_name), "Service Running, Click to open app");
startForeground(NotificationHelper.FOREGROUND_NOTIFICATION_ID, notification);
// NotificationMessage notificationMessage=createNotificationMessage();
// //Toast.makeText(getApplication(), "", Toast.LENGTH_SHORT).show();
// mNotificationUtils.createForegroundNotification(this, notificationMessage);
// mNotificationUtils.createRemindNotification(this, notificationMessage);
if (mControlCenterServiceReceiver == null) { if (mControlCenterServiceReceiver == null) {
// 注册广播接收器 // 注册广播接收器
@ -126,19 +139,19 @@ public class ControlCenterService extends Service {
// 更新前台通知 // 更新前台通知
// //
public void updateServiceNotification() { public void updateServiceNotification() {
mNotificationUtils.updateForegroundNotification(ControlCenterService.this, createNotificationMessage()); //mNotificationUtils.updateForegroundNotification(ControlCenterService.this, createNotificationMessage());
} }
// 更新前台通知 // 更新前台通知
// //
public void updateServiceNotification(NotificationMessage notificationMessage) { public void updateServiceNotification(NotificationMessage notificationMessage) {
mNotificationUtils.updateForegroundNotification(ControlCenterService.this, notificationMessage); //mNotificationUtils.updateForegroundNotification(ControlCenterService.this, notificationMessage);
} }
// 更新前台通知 // 更新前台通知
// //
public void updateRemindNotification(NotificationMessage notificationMessage) { public void updateRemindNotification(NotificationMessage notificationMessage) {
mNotificationUtils.updateRemindNotification(ControlCenterService.this, notificationMessage); //mNotificationUtils.updateRemindNotification(ControlCenterService.this, notificationMessage);
} }
// 唤醒和绑定守护进程 // 唤醒和绑定守护进程
@ -234,10 +247,32 @@ public class ControlCenterService extends Service {
} }
public void appenRemindMSG(String szRemindMSG) { public void appenRemindMSG(String szRemindMSG) {
NotificationMessage notificationMessage = createNotificationMessage(); String msg = "";
notificationMessage.setRemindMSG(szRemindMSG); for (int i = 0; i < 20; i++) {
//LogUtils.d(TAG, "notificationMessage : " + notificationMessage.getRemindMSG()); msg += szRemindMSG;
updateRemindNotification(notificationMessage); }
NotificationHelper helper = new NotificationHelper(ControlCenterService.this);
Intent intent = new Intent(ControlCenterService.this, MainActivity.class);
helper.showTemporaryNotification(intent, getString(R.string.app_name), msg);
// NotificationMessage notificationMessage = createNotificationMessage();
// notificationMessage.setRemindMSG(szRemindMSG);
// //LogUtils.d(TAG, "notificationMessage : " + notificationMessage.getRemindMSG());
// updateRemindNotification(notificationMessage);
}
// 设置颜色背景
public static RemoteViews setLinearLayoutColor(RemoteViews remoteViews, int viewId, int color) {
remoteViews.setInt(viewId, "setBackgroundColor", color);
return remoteViews;
}
// 设置Drawable背景
public static RemoteViews setLinearLayoutDrawable(RemoteViews remoteViews, int viewId, int drawableRes) {
remoteViews.setInt(viewId, "setBackgroundResource", drawableRes);
return remoteViews;
} }
// //

View File

@ -193,7 +193,7 @@ public class AppConfigUtils {
// //
void saveConfigData() { void saveConfigData() {
// 更新配置先取消一下旧的的提醒消息 // 更新配置先取消一下旧的的提醒消息
NotificationUtils.cancelRemindNotification(mContext); //NotificationHelper.cancelRemindNotification(mContext);
AppConfigBean.saveBean(mContext, mAppConfigBean); AppConfigBean.saveBean(mContext, mAppConfigBean);
// 通知活动窗口和服务配置已更新 // 通知活动窗口和服务配置已更新

View File

@ -0,0 +1,150 @@
package cc.winboll.studio.powerbell.utils;
/**
* @Author ZhanGSKen@AliYun.Com
* @Date 2025/03/22 04:39:40
* @Describe 通知工具类
*/
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.graphics.BitmapFactory;
import android.os.Build;
import android.widget.RemoteViews;
import androidx.annotation.RequiresApi;
import androidx.core.app.NotificationCompat;
import cc.winboll.studio.powerbell.R;
public class NotificationHelper {
public static final String TAG = "NotificationHelper";
// 渠道ID和名称
private static final String CHANNEL_ID_FOREGROUND = "foreground_channel";
private static final String CHANNEL_NAME_FOREGROUND = "Foreground Service";
private static final String CHANNEL_ID_TEMPORARY = "temporary_channel";
private static final String CHANNEL_NAME_TEMPORARY = "Temporary Notifications";
// 通知ID
public static final int FOREGROUND_NOTIFICATION_ID = 1001;
public static final int TEMPORARY_NOTIFICATION_ID = 2001;
private final Context mContext;
private final NotificationManager mNotificationManager;
public NotificationHelper(Context context) {
mContext = context;
mNotificationManager = context.getSystemService(NotificationManager.class);
createNotificationChannels();
}
@RequiresApi(api = Build.VERSION_CODES.O)
private void createNotificationChannels() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
createForegroundChannel();
createTemporaryChannel();
}
}
@RequiresApi(api = Build.VERSION_CODES.O)
private void createForegroundChannel() {
NotificationChannel channel = new NotificationChannel(
CHANNEL_ID_FOREGROUND,
CHANNEL_NAME_FOREGROUND,
NotificationManager.IMPORTANCE_LOW
);
channel.setDescription("Persistent service notifications");
channel.setSound(null, null);
channel.enableVibration(false);
mNotificationManager.createNotificationChannel(channel);
}
@RequiresApi(api = Build.VERSION_CODES.O)
private void createTemporaryChannel() {
NotificationChannel channel = new NotificationChannel(
CHANNEL_ID_TEMPORARY,
CHANNEL_NAME_TEMPORARY,
NotificationManager.IMPORTANCE_HIGH
);
channel.setDescription("Temporary alert notifications");
channel.setSound(null, null);
channel.enableVibration(true);
channel.setVibrationPattern(new long[]{100, 200, 300, 400});
channel.setBypassDnd(true);
mNotificationManager.createNotificationChannel(channel);
}
// 显示常驻通知通常用于前台服务
public Notification showForegroundNotification(Intent intent, String title, String content) {
PendingIntent pendingIntent = createPendingIntent(intent);
Notification notification = new NotificationCompat.Builder(mContext, CHANNEL_ID_FOREGROUND)
.setSmallIcon(R.drawable.ic_launcher)
.setLargeIcon(BitmapFactory.decodeResource(mContext.getResources(), R.drawable.ic_launcher))
.setContentTitle(title)
.setContentText(content)
.setContentIntent(pendingIntent)
.setPriority(NotificationCompat.PRIORITY_LOW)
.setOngoing(true)
.build();
mNotificationManager.notify(FOREGROUND_NOTIFICATION_ID, notification);
return notification;
}
// 显示临时通知自动消失
public void showTemporaryNotification(Intent intent, String title, String content) {
PendingIntent pendingIntent = createPendingIntent(intent);
Notification notification = new NotificationCompat.Builder(mContext, CHANNEL_ID_TEMPORARY)
.setSmallIcon(R.drawable.ic_launcher)
.setLargeIcon(BitmapFactory.decodeResource(mContext.getResources(), R.drawable.ic_launcher))
.setContentTitle(title)
.setContentText(content)
.setContentIntent(pendingIntent)
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setAutoCancel(true)
.setVibrate(new long[]{100, 200, 300, 400})
.build();
mNotificationManager.notify(TEMPORARY_NOTIFICATION_ID, notification);
}
// 创建自定义布局通知可扩展
public void showCustomNotification(Intent intent, RemoteViews contentView, RemoteViews bigContentView) {
PendingIntent pendingIntent = createPendingIntent(intent);
Notification notification = new NotificationCompat.Builder(mContext, CHANNEL_ID_TEMPORARY)
.setSmallIcon(R.drawable.ic_launcher)
.setContentIntent(pendingIntent)
.setContent(contentView)
.setCustomBigContentView(bigContentView)
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setAutoCancel(true)
.build();
mNotificationManager.notify(TEMPORARY_NOTIFICATION_ID + 1, notification);
}
// 取消所有通知
public void cancelAllNotifications() {
mNotificationManager.cancelAll();
}
// 创建PendingIntent兼容不同API版本
private PendingIntent createPendingIntent(Intent intent) {
int flags = PendingIntent.FLAG_UPDATE_CURRENT;
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
// flags |= PendingIntent.FLAG_IMMUTABLE;
// }
return PendingIntent.getActivity(
mContext,
0,
intent,
flags
);
}
}

View File

@ -18,14 +18,15 @@ import android.media.RingtoneManager;
import android.os.Build; import android.os.Build;
import android.view.View; import android.view.View;
import android.widget.RemoteViews; import android.widget.RemoteViews;
import androidx.annotation.RequiresApi;
import cc.winboll.studio.powerbell.MainActivity; import cc.winboll.studio.powerbell.MainActivity;
import cc.winboll.studio.powerbell.R; import cc.winboll.studio.powerbell.R;
import cc.winboll.studio.powerbell.beans.NotificationMessage; import cc.winboll.studio.powerbell.beans.NotificationMessage;
import cc.winboll.studio.powerbell.services.ControlCenterService; import cc.winboll.studio.powerbell.services.ControlCenterService;
public class NotificationUtils { public class NotificationUtils2 {
public static final String TAG = NotificationUtils.class.getSimpleName(); public static final String TAG = NotificationHelper.class.getSimpleName();
Context mContext; Context mContext;
NotificationManager mNotificationManager; NotificationManager mNotificationManager;
@ -45,19 +46,53 @@ public class NotificationUtils {
private static String _mszChannelIDRemind = "2"; private static String _mszChannelIDRemind = "2";
private static String _mszChannelNameRemind = "Remind"; private static String _mszChannelNameRemind = "Remind";
public NotificationUtils(Context context) { // public NotificationUtils(Context context) {
// mContext = context;
// mNotificationManager = (NotificationManager) context.getSystemService(
// Context.NOTIFICATION_SERVICE);
// }
public NotificationUtils2(Context context) {
mContext = context; mContext = context;
mNotificationManager = (NotificationManager) context.getSystemService( mNotificationManager = context.getSystemService(NotificationManager.class);
Context.NOTIFICATION_SERVICE); //createNotificationChannels();
} }
public void createNotificationChannel() { @RequiresApi(api = Build.VERSION_CODES.O)
NotificationChannel channel1 = new NotificationChannel(_mszChannelIDService, _mszChannelNameService, NotificationManager.IMPORTANCE_DEFAULT); public void createNotificationChannels() {
channel1.setSound(null, null); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
mNotificationManager.createNotificationChannel(channel1); createServiceChannel();
NotificationChannel channel2 = new NotificationChannel(_mszChannelIDRemind, _mszChannelNameRemind, NotificationManager.IMPORTANCE_HIGH); createRemindChannel();
channel2.setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE), Notification.AUDIO_ATTRIBUTES_DEFAULT); }
mNotificationManager.createNotificationChannel(channel2); }
@RequiresApi(api = Build.VERSION_CODES.O)
private void createServiceChannel() {
NotificationChannel channel = new NotificationChannel(
_mszChannelIDService,
_mszChannelNameService,
NotificationManager.IMPORTANCE_LOW
);
channel.setDescription("Background service updates");
channel.setSound(null, null);
channel.enableVibration(false);
mNotificationManager.createNotificationChannel(channel);
}
@RequiresApi(api = Build.VERSION_CODES.O)
private void createRemindChannel() {
NotificationChannel channel = new NotificationChannel(
_mszChannelIDRemind,
_mszChannelNameRemind,
NotificationManager.IMPORTANCE_HIGH
);
channel.setDescription("Critical reminders");
channel.setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALARM), null);
channel.enableVibration(true);
channel.setVibrationPattern(new long[]{100, 200, 300, 400});
channel.setBypassDnd(true);
channel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);
mNotificationManager.createNotificationChannel(channel);
} }
// 创建并发送服务通知 // 创建并发送服务通知

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/ll_notification">
</LinearLayout>

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/ll_notification">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Text"
android:id="@+id/info_tv"/>
</LinearLayout>