Compare commits

...

7 Commits

Author SHA1 Message Date
ZhanGSKen
58af5ba074 <powerbell>APK 4.0.7 release Publish. 2025-03-22 16:06:33 +08:00
ZhanGSKen
19743d30ef 修复编译参数 2025-03-22 16:05:10 +08:00
ZhanGSKen
3c2b720e20 调整背景图片设置窗口按钮布局 2025-03-22 16:03:08 +08:00
ZhanGSKen
5a052e4b22 添加电池报告窗口雏形 2025-03-22 15:54:18 +08:00
ZhanGSKen
4ccf6824a6 <powerbell>APK 4.0.6 release Publish. 2025-03-22 06:01:46 +08:00
ZhanGSKen
508c8b0b97 适配小米15,修改通知模块。 2025-03-22 05:53:58 +08:00
ZhanGSKen
0d21994291 编译配置精简 2025-03-22 03:06:40 +08:00
21 changed files with 546 additions and 63 deletions

View File

@@ -41,11 +41,6 @@ android {
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
} }
} }
compileOptions {
sourceCompatibility JavaVersion.VERSION_11
targetCompatibility JavaVersion.VERSION_11
}
} }
dependencies { dependencies {

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 #Sat Mar 22 16:06:33 HKT 2025
stageCount=6 stageCount=8
libraryProject= libraryProject=
baseVersion=4.0 baseVersion=4.0
publishVersion=4.0.5 publishVersion=4.0.7
buildCount=0 buildCount=0
baseBetaVersion=4.0.6 baseBetaVersion=4.0.8

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>
@@ -112,6 +129,8 @@
<activity android:name="cc.winboll.studio.powerbell.activities.AboutActivity"/> <activity android:name="cc.winboll.studio.powerbell.activities.AboutActivity"/>
<activity android:name="cc.winboll.studio.powerbell.activities.BatteryReporterActivity"/>
</application> </application>
</manifest> </manifest>

View File

@@ -15,9 +15,9 @@ import cc.winboll.studio.libaes.views.AToolbar;
import cc.winboll.studio.powerbell.MainActivity; import cc.winboll.studio.powerbell.MainActivity;
import cc.winboll.studio.powerbell.activities.AboutActivity; 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.BatteryReporterActivity;
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.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();
} }
@@ -143,6 +145,10 @@ public class MainActivity extends Activity {
Intent intent = new Intent(); Intent intent = new Intent();
intent.setClass(this, AboutActivity.class); intent.setClass(this, AboutActivity.class);
startActivity(intent); startActivity(intent);
} else if (menuItemId == R.id.action_battery_reporter) {
Intent intent = new Intent();
intent.setClass(this, BatteryReporterActivity.class);
startActivity(intent);
} else if (menuItemId == R.id.action_clearrecord) { } else if (menuItemId == R.id.action_clearrecord) {
Intent intent = new Intent(); Intent intent = new Intent();
intent.setClass(this, ClearRecordActivity.class); intent.setClass(this, ClearRecordActivity.class);

View File

@@ -0,0 +1,51 @@
package cc.winboll.studio.powerbell.activities;
/**
* @Author ZhanGSKen@AliYun.Com
* @Date 2025/03/22 14:20:15
*/
import android.app.Activity;
import android.os.Bundle;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import cc.winboll.studio.powerbell.R;
import cc.winboll.studio.powerbell.adapters.BatteryAdapter;
import cc.winboll.studio.powerbell.beans.BatteryData;
import java.util.Arrays;
import java.util.List;
public class BatteryReporterActivity extends Activity {
public static final String TAG = "BatteryReporterActivity";
private RecyclerView rvBatteryReport;
private BatteryAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_battery_reporter);
rvBatteryReport = findViewById(R.id.rvBatteryReport);
setupRecyclerView();
loadSampleData();
}
private void setupRecyclerView() {
adapter = new BatteryAdapter();
rvBatteryReport.setLayoutManager(new LinearLayoutManager(this));
rvBatteryReport.setAdapter(adapter);
rvBatteryReport.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL));
}
private void loadSampleData() {
List<BatteryData> dataList = Arrays.asList(
new BatteryData(95, "01:23:45", "00:05:12"),
new BatteryData(80, "02:15:30", "00:10:00"),
new BatteryData(65, "03:45:15", "00:15:30"),
new BatteryData(50, "05:00:00", "00:20:45")
);
adapter.updateData(dataList);
}
}

View File

@@ -0,0 +1,61 @@
package cc.winboll.studio.powerbell.adapters;
/**
* @Author ZhanGSKen@AliYun.Com
* @Date 2025/03/22 14:38:55
* @Describe 电池报告数据适配器
*/
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.recyclerview.widget.RecyclerView;
import cc.winboll.studio.powerbell.R;
import cc.winboll.studio.powerbell.adapters.BatteryAdapter;
import cc.winboll.studio.powerbell.beans.BatteryData;
import java.util.ArrayList;
import java.util.List;
public class BatteryAdapter extends RecyclerView.Adapter<BatteryAdapter.ViewHolder> {
public static final String TAG = "BatteryAdapter";
private List<BatteryData> dataList = new ArrayList<>();
public void updateData(List<BatteryData> newData) {
dataList = newData;
notifyDataSetChanged();
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_battery_report, parent, false);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
BatteryData item = dataList.get(position);
holder.tvLevel.setText(String.format("%d%%", item.getCurrentLevel()));
holder.tvDischargeTime.setText("使用时间: " + item.getDischargeTime());
holder.tvChargeTime.setText("充电时间: " + item.getChargeTime());
}
@Override
public int getItemCount() {
return dataList.size();
}
static class ViewHolder extends RecyclerView.ViewHolder {
TextView tvLevel;
TextView tvDischargeTime;
TextView tvChargeTime;
ViewHolder(View itemView) {
super(itemView);
tvLevel = itemView.findViewById(R.id.tvLevel);
tvDischargeTime = itemView.findViewById(R.id.tvDischargeTime);
tvChargeTime = itemView.findViewById(R.id.tvChargeTime);
}
}
}

View File

@@ -0,0 +1,26 @@
package cc.winboll.studio.powerbell.beans;
/**
* @Author ZhanGSKen@AliYun.Com
* @Date 2025/03/22 14:30:51
* @Describe 电池报告数据模型
*/
public class BatteryData {
public static final String TAG = "BatteryData";
private int currentLevel;
private String dischargeTime;
private String chargeTime;
public BatteryData(int currentLevel, String dischargeTime, String chargeTime) {
this.currentLevel = currentLevel;
this.dischargeTime = dischargeTime;
this.chargeTime = chargeTime;
}
public int getCurrentLevel() { return currentLevel; }
public String getDischargeTime() { return dischargeTime; }
public String getChargeTime() { return chargeTime; }
}

View File

@@ -5,11 +5,14 @@ import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.IntentFilter; import android.content.IntentFilter;
import cc.winboll.studio.powerbell.beans.AppConfigBean; import cc.winboll.studio.powerbell.beans.AppConfigBean;
import cc.winboll.studio.powerbell.beans.BatteryData;
import cc.winboll.studio.powerbell.services.ControlCenterService; import cc.winboll.studio.powerbell.services.ControlCenterService;
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.shared.log.LogUtils; import cc.winboll.studio.shared.log.LogUtils;
import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
public class ControlCenterServiceReceiver extends BroadcastReceiver { public class ControlCenterServiceReceiver extends BroadcastReceiver {
public static final String TAG = ControlCenterServiceReceiver.class.getSimpleName(); public static final String TAG = ControlCenterServiceReceiver.class.getSimpleName();
@@ -52,6 +55,13 @@ public class ControlCenterServiceReceiver extends BroadcastReceiver {
appConfigBean.setCurrentValue(nTheQuantityOfElectricity); appConfigBean.setCurrentValue(nTheQuantityOfElectricity);
appConfigBean.setIsCharging(isCharging); appConfigBean.setIsCharging(isCharging);
mwrService.get().startRemindThread(appConfigBean); mwrService.get().startRemindThread(appConfigBean);
// 保存电池报告
// 示例数据更新逻辑
// List<BatteryData> newData = new ArrayList<>(adapter.getDataList());
// newData.add(0, new BatteryData(percentage, "00:00:00", "00:00:00"));
// adapter.updateData(newData);
// 保存好新的电池状态标志 // 保存好新的电池状态标志
_mIsCharging = isCharging; _mIsCharging = isCharging;
_mnTheQuantityOfElectricityOld = nTheQuantityOfElectricity; _mnTheQuantityOfElectricityOld = nTheQuantityOfElectricity;

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,7 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="line">
<stroke
android:width="1dp"
android:color="#E0E0E0"/>
</shape>

View File

@@ -26,29 +26,27 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_below="@id/toolbar"> android:layout_below="@id/toolbar">
<LinearLayout <RelativeLayout
android:orientation="horizontal" android:layout_width="wrap_content"
android:layout_width="match_parent" android:layout_height="wrap_content">
android:layout_height="wrap_content"
android:gravity="right">
<cc.winboll.studio.libaes.views.AButton <cc.winboll.studio.libaes.views.AButton
android:layout_width="180dp" android:layout_width="160dp"
android:layout_height="36dp" android:layout_height="36dp"
android:text="Origin BG" android:text="Origin BG"
android:layout_gravity="center_vertical" android:id="@+id/activitybackgroundpictureAButton5"
android:layout_margin="10dp" android:layout_alignParentLeft="true"
android:id="@+id/activitybackgroundpictureAButton5"/> android:layout_margin="5dp"/>
<cc.winboll.studio.libaes.views.AButton <cc.winboll.studio.libaes.views.AButton
android:layout_width="180dp" android:layout_width="160dp"
android:layout_height="36dp" android:layout_height="36dp"
android:text="Received BG" android:text="Received BG"
android:layout_gravity="center_vertical" android:id="@+id/activitybackgroundpictureAButton4"
android:layout_margin="10dp" android:layout_alignParentRight="true"
android:id="@+id/activitybackgroundpictureAButton4"/> android:layout_margin="5dp"/>
</LinearLayout> </RelativeLayout>
<LinearLayout <LinearLayout
android:orientation="horizontal" android:orientation="horizontal"

View File

@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="16dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="电池使用报告"
android:textSize="24sp"
android:fontFamily="sans-serif-medium"
android:layout_marginBottom="16dp"/>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rvBatteryReport"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:divider="@drawable/divider_line"
android:dividerHeight="1dp"/>
</LinearLayout>

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>

View File

@@ -0,0 +1,34 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="12dp"
android:gravity="center_vertical"
android:background="@android:color/white">
<TextView
android:id="@+id/tvLevel"
android:layout_width="80dp"
android:layout_height="wrap_content"
android:textSize="18sp"
android:fontFamily="sans-serif-medium"/>
<TextView
android:id="@+id/tvDischargeTime"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:textSize="16sp"
android:paddingStart="16dp"/>
<TextView
android:id="@+id/tvChargeTime"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:textSize="16sp"
android:paddingStart="16dp"/>
</LinearLayout>

View File

@@ -1,5 +1,8 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"> <menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/action_battery_reporter"
android:title="@string/item_battery_reporter"/>
<item <item
android:id="@+id/action_clearrecord" android:id="@+id/action_clearrecord"
android:title="@string/item_clearrecord"/> android:title="@string/item_clearrecord"/>

View File

@@ -6,6 +6,7 @@
<string name="about_crashed">This application has crashed, the author level is limited, please understand!</string> <string name="about_crashed">This application has crashed, the author level is limited, please understand!</string>
<string name="item_mainview">Main View</string> <string name="item_mainview">Main View</string>
<string name="item_aboutview">About</string> <string name="item_aboutview">About</string>
<string name="item_battery_reporter">Battery Reporter</string>
<string name="item_clearrecord">Clear Record</string> <string name="item_clearrecord">Clear Record</string>
<string name="item_changepicture">Change Picture</string> <string name="item_changepicture">Change Picture</string>
<string name="item_devoloperoptionsview">Developer View</string> <string name="item_devoloperoptionsview">Developer View</string>