Compare commits

...

7 Commits

Author SHA1 Message Date
ZhanGSKen
fa43d43110 <mymessagemanager>APK 15.2.4 release Publish. 2025-04-01 19:55:49 +08:00
ZhanGSKen
8f8e7d98c7 通知调试完成,添加旧通知设置清理按钮。 2025-04-01 19:54:30 +08:00
ZhanGSKen
af39f98a51 通知模块调试ing... 2025-04-01 15:20:02 +08:00
ZhanGSKen
5a1d557683 <mymessagemanager>APK 15.2.3 release Publish. 2025-03-31 20:04:51 +08:00
ZhanGSKen
39116f0912 更新类库,修复调试模式保存问题。 2025-03-31 20:03:40 +08:00
ZhanGSKen
a6b711b38b <mymessagemanager>APK 15.2.2 release Publish. 2025-03-31 02:36:56 +08:00
ZhanGSKen
d1703551f5 更新应用调试模式设置方法 2025-03-31 02:36:15 +08:00
11 changed files with 252 additions and 42 deletions

View File

@@ -65,7 +65,7 @@ dependencies {
//api 'androidx.fragment:fragment:1.1.0'
api 'com.google.android.material:material:1.0.0'
api 'cc.winboll.studio:libaes:15.2.3'
api 'cc.winboll.studio:libaes:15.2.4'
api 'cc.winboll.studio:libapputils:15.2.1'
api 'cc.winboll.studio:libappbase:15.2.2'
}

View File

@@ -1,8 +1,8 @@
#Created by .winboll/winboll_app_build.gradle
#Mon Mar 31 02:29:38 HKT 2025
stageCount=2
#Tue Apr 01 19:55:49 HKT 2025
stageCount=5
libraryProject=
baseVersion=15.2
publishVersion=15.2.1
publishVersion=15.2.4
buildCount=0
baseBetaVersion=15.2.2
baseBetaVersion=15.2.5

View File

@@ -29,7 +29,6 @@ public class App extends GlobalApplication {
@Override
public void onCreate() {
super.onCreate();
setIsDebuging(BuildConfig.DEBUG);
// 初始化 Toast 框架
ToastUtils.init(this);

View File

@@ -17,6 +17,8 @@ import cc.winboll.studio.libaes.views.AToolbar;
import cc.winboll.studio.mymessagemanager.R;
import cc.winboll.studio.mymessagemanager.utils.AppConfigUtil;
import cc.winboll.studio.mymessagemanager.utils.PermissionUtil;
import cc.winboll.studio.mymessagemanager.utils.NotificationHelper;
import cc.winboll.studio.libappbase.dialogs.YesNoAlertDialog;
public class AppSettingsActivity extends BaseActivity {
@@ -96,4 +98,18 @@ public class AppSettingsActivity extends BaseActivity {
Toast.makeText(getApplication(), "应用已获得所需权限。", Toast.LENGTH_SHORT).show();
}
}
public void onCleanOldChannels(View view) {
YesNoAlertDialog.show(this, "通知设置清理", "是否清理旧的通知设置?", new YesNoAlertDialog.OnDialogResultListener(){
@Override
public void onNo() {
}
@Override
public void onYes() {
NotificationHelper notificationHelper = new NotificationHelper(AppSettingsActivity.this);
notificationHelper.cleanOldChannels();
}
});
}
}

View File

@@ -22,7 +22,6 @@ import cc.winboll.studio.mymessagemanager.services.MainService;
import cc.winboll.studio.mymessagemanager.unittest.UnitTestActivity;
import cc.winboll.studio.mymessagemanager.utils.AppConfigUtil;
import cc.winboll.studio.mymessagemanager.utils.AppGoToSettingsUtil;
import cc.winboll.studio.mymessagemanager.utils.NotificationUtil;
import cc.winboll.studio.mymessagemanager.utils.PermissionUtil;
import cc.winboll.studio.mymessagemanager.utils.SMSUtil;
import cc.winboll.studio.mymessagemanager.utils.ViewUtil;
@@ -129,12 +128,7 @@ public class MainActivity extends BaseActivity {
mToolbar = findViewById(R.id.activitymainASupportToolbar1);
mToolbar.setSubtitle(getString(R.string.activity_name_main));
setSupportActionBar(mToolbar);
// 创建通知频道
NotificationUtil nu = new NotificationUtil();
nu.createServiceNotificationChannel(MainActivity.this);
nu.createSMSNotificationChannel(MainActivity.this);
boolean isEnableService = mAppConfigUtil.mAppConfigBean.isEnableService();
msvEnableService = findViewById(R.id.activitymainSwitchView1);
msvEnableService.setChecked(isEnableService);

View File

@@ -18,7 +18,6 @@ import cc.winboll.studio.mymessagemanager.R;
import cc.winboll.studio.mymessagemanager.activitys.TTSPlayRuleActivity;
import cc.winboll.studio.mymessagemanager.beans.SMSBean;
import cc.winboll.studio.mymessagemanager.dialogs.YesNoAlertDialog;
import cc.winboll.studio.mymessagemanager.utils.NotificationUtil;
import cc.winboll.studio.mymessagemanager.utils.SMSReceiveRuleUtil;
import cc.winboll.studio.mymessagemanager.utils.SMSRecycleUtil;
import cc.winboll.studio.mymessagemanager.utils.SMSUtil;
@@ -28,6 +27,7 @@ import cc.winboll.studio.mymessagemanager.views.SMSView;
import com.hjq.toast.ToastUtils;
import java.util.ArrayList;
import cc.winboll.studio.mymessagemanager.beans.SMSAcceptRuleBean;
import cc.winboll.studio.mymessagemanager.utils.NotificationHelper;
public class SMSArrayAdapter extends BaseAdapter {
@@ -54,7 +54,8 @@ public class SMSArrayAdapter extends BaseAdapter {
public void cancelMessageNotification() {
for (SMSBean bean : mData) {
NotificationUtil.cancelNotification(mContext, bean.getId());
NotificationHelper notificationHelper = new NotificationHelper(mContext);
notificationHelper.cancelNotification(bean.getId());
}
}

View File

@@ -9,12 +9,12 @@ import cc.winboll.studio.mymessagemanager.App;
import cc.winboll.studio.mymessagemanager.activitys.SMSActivity;
import cc.winboll.studio.mymessagemanager.beans.SMSBean;
import cc.winboll.studio.mymessagemanager.utils.AppConfigUtil;
import cc.winboll.studio.mymessagemanager.utils.NotificationUtil;
import cc.winboll.studio.mymessagemanager.utils.PhoneUtil;
import cc.winboll.studio.mymessagemanager.utils.SMSReceiveRuleUtil;
import cc.winboll.studio.mymessagemanager.utils.SMSRecycleUtil;
import cc.winboll.studio.mymessagemanager.utils.SMSUtil;
import cc.winboll.studio.mymessagemanager.utils.TTSPlayRuleUtil;
import cc.winboll.studio.mymessagemanager.utils.NotificationHelper;
public class SMSRecevier extends BroadcastReceiver {
@@ -46,8 +46,8 @@ public class SMSRecevier extends BroadcastReceiver {
if (checkIsSMSOK(context, szSmsBody, szSmsAddress)) {
int nResultId = SMSUtil.saveReceiveSms(context, szSmsAddress, szSmsBody, "0", System.currentTimeMillis(), "inbox");
if (nResultId >= 0) {
NotificationUtil nu = new NotificationUtil();
nu.sendSMSReceivedMessage(context, nResultId, szSmsAddress, szSmsBody);
NotificationHelper notificationHelper = new NotificationHelper(context);
notificationHelper.sendSMSReceivedMessage(nResultId, szSmsAddress, szSmsBody);
LocalBroadcastManager.getInstance(context).sendBroadcast(new Intent(SMSActivity.ACTION_NOTIFY_SMS_CHANGED));
LogUtils.d(TAG, "<" + szSmsAddress + "> : ( " + szSmsBody + " ) [SAVED]");
if (isEnableTTS) {

View File

@@ -5,6 +5,7 @@ package cc.winboll.studio.mymessagemanager.services;
* @Date 2024/07/19 14:30:57
* @Describe 应用主要服务组件类
*/
import android.app.Notification;
import android.app.Service;
import android.content.ComponentName;
import android.content.Context;
@@ -14,11 +15,12 @@ import android.content.ServiceConnection;
import android.os.IBinder;
import cc.winboll.studio.libappbase.LogUtils;
import cc.winboll.studio.mymessagemanager.R;
import cc.winboll.studio.mymessagemanager.activitys.MainActivity;
import cc.winboll.studio.mymessagemanager.beans.MessageNotificationBean;
import cc.winboll.studio.mymessagemanager.receivers.SMSRecevier;
import cc.winboll.studio.mymessagemanager.services.MainService;
import cc.winboll.studio.mymessagemanager.utils.AppConfigUtil;
import cc.winboll.studio.mymessagemanager.utils.NotificationUtil;
import cc.winboll.studio.mymessagemanager.utils.NotificationHelper;
import cc.winboll.studio.mymessagemanager.utils.ServiceUtil;
import com.hjq.toast.ToastUtils;
@@ -26,6 +28,9 @@ public class MainService extends Service {
public static String TAG = "ManagerService";
// 前台服务通知工具
NotificationHelper mNotificationHelper;
Notification notification;
AppConfigUtil mConfigUtil;
//MyBinder mMyBinder;
MyServiceConnection mMyServiceConnection;
@@ -73,17 +78,12 @@ public class MainService extends Service {
mSMSRecevier = new SMSRecevier();
registerReceiver(mSMSRecevier, localIntentFilter);
// 显示前台通知栏
MessageNotificationBean notificationMessage = createNotificationMessage();
NotificationUtil nu = new NotificationUtil();
nu.sendForegroundNotification(MainService.this, notificationMessage);
NotificationHelper helper = new NotificationHelper(this);
Intent intent = new Intent(this, MainActivity.class);
notification = helper.showForegroundNotification(intent, getString(R.string.app_name), getString(R.string.text_aboutservernotification));
startForeground(NotificationHelper.FOREGROUND_NOTIFICATION_ID, notification);
/*if (mConfigUtil.isEnableTTS()) {
TTSPlayRuleUtil.speakText(ManagerService.this, getString(R.string.text_iamhere), 0);
GlobalApplication.showApplicationMessage(getString(R.string.text_iamhere));
}*/
ToastUtils.show("Service is start.");
LogUtils.i(TAG, "Service is start.");
}
@@ -101,13 +101,6 @@ public class MainService extends Service {
}
private MessageNotificationBean createNotificationMessage() {
String szTitle = getApplicationContext().getString(R.string.app_name);
String szContent = getString(R.string.text_aboutservernotification);
return new MessageNotificationBean(NotificationUtil.ID_MSG_SERVICE, "", szTitle, szContent);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
//return super.onStartCommand(intent, flags, startId);
@@ -116,12 +109,12 @@ public class MainService extends Service {
return mConfigUtil.mAppConfigBean.isEnableService() ? Service.START_STICKY: super.onStartCommand(intent, flags, startId);
}
/*private class MyBinder extends IMyAidlInterface.Stub {
@Override
public String getServiceName() {
return MainService.class.getSimpleName();
}
}*/
/*private class MyBinder extends IMyAidlInterface.Stub {
@Override
public String getServiceName() {
return MainService.class.getSimpleName();
}
}*/
// 主进程与守护进程连接时需要用到此类
//

View File

@@ -0,0 +1,201 @@
package cc.winboll.studio.mymessagemanager.utils;
/**
* @Author ZhanGSKen@AliYun.Com
* @Date 2025/04/01 14:10:35
* @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.libappbase.LogUtils;
import cc.winboll.studio.mymessagemanager.R;
import cc.winboll.studio.mymessagemanager.activitys.SMSActivity;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
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;
// 示例维护当前使用的渠道ID列表
// 键渠道ID渠道重要性级别
Map<String, Integer> activeChannelConfigs = new HashMap<>();
public NotificationHelper(Context context) {
mContext = context;
mNotificationManager = context.getSystemService(NotificationManager.class);
// 初始化配置
activeChannelConfigs.put(
CHANNEL_ID_FOREGROUND,
NotificationManager.IMPORTANCE_HIGH
);
activeChannelConfigs.put(
CHANNEL_ID_TEMPORARY,
NotificationManager.IMPORTANCE_DEFAULT
);
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) {
showTemporaryNotification(intent, TEMPORARY_NOTIFICATION_ID, title, content);
}
// 显示临时通知(自动消失)
public void showTemporaryNotification(Intent intent, int notificationID, 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(notificationID, 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();
}
// 取消指定通知
public void cancelNotification(int notificationID) {
mNotificationManager.cancel(notificationID);
}
// 创建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
);
}
public void sendSMSReceivedMessage(int notificationID, String szPhone, String szBody) {
Intent intent = new Intent(mContext, SMSActivity.class);
intent.putExtra(SMSActivity.EXTRA_PHONE, szPhone);
String szTitle = mContext.getString(R.string.text_smsfrom) + "<" + szPhone + ">";
String szContent = "[ " + szBody + " ]";
showTemporaryNotification(intent, notificationID, szTitle, szContent);
}
public void cleanOldChannels() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
List<NotificationChannel> allChannels = mNotificationManager.getNotificationChannels();
for (NotificationChannel channel : allChannels) {
LogUtils.d(TAG, "Clean channel : " + channel.getId());
if (!activeChannelConfigs.containsKey(channel.getId())) {
// 安全删除渠道
mNotificationManager.deleteNotificationChannel(channel.getId());
LogUtils.d(TAG, String.format("Deleted Channel %s", channel.getId()));
}
}
}
}
}

View File

@@ -22,7 +22,7 @@ import cc.winboll.studio.mymessagemanager.activitys.SMSActivity;
import cc.winboll.studio.mymessagemanager.beans.MessageNotificationBean;
import cc.winboll.studio.mymessagemanager.services.MainService;
public class NotificationUtil {
public class NotificationUtil_Bck {
public static final String TAG = "NotificationUtil";
public static final int ID_MSG_SERVICE = 10000;

View File

@@ -213,6 +213,12 @@
android:text="检查应用权限"
android:onClick="onCheckAndGetAppPermission"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="清理通知设置"
android:onClick="onCleanOldChannels"/>
</LinearLayout>
</LinearLayout>