From b6a895202791b69fc1db40c9ca73780f8b28dc5c Mon Sep 17 00:00:00 2001 From: pppscn <35696959@qq.com> Date: Sat, 20 Nov 2021 22:48:10 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=EF=BC=9A=E5=BC=80=E5=90=AF?= =?UTF-8?q?=E9=80=9A=E7=9F=A5=E6=9C=8D=E5=8A=A1=E6=9D=83=E9=99=90=E5=88=A4?= =?UTF-8?q?=E6=96=AD=20=E4=BC=98=E5=8C=96=EF=BC=9A=E9=BB=98=E8=AE=A4?= =?UTF-8?q?=E5=85=B3=E9=97=AD=E7=9F=AD=E4=BF=A1=E3=80=81=E6=9D=A5=E7=94=B5?= =?UTF-8?q?=E3=80=81APP=E8=BD=AC=E5=8F=91=EF=BC=88=E8=AE=BE=E7=BD=AE?= =?UTF-8?q?=E4=B8=AD=E6=80=BB=E5=BC=80=E5=85=B3=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../idormy/sms/forwarder/AppListActivity.java | 6 +- .../idormy/sms/forwarder/MainActivity.java | 137 ++---------------- .../idormy/sms/forwarder/RuleActivity.java | 14 ++ .../idormy/sms/forwarder/SettingActivity.java | 87 ++++------- .../idormy/sms/forwarder/model/RuleModel.java | 4 +- .../sms/forwarder/notify/NotifyHelper.java | 76 ---------- .../sms/forwarder/notify/NotifyListener.java | 34 ----- .../sms/forwarder/service/NotifyService.java | 68 +++++++-- .../sms/forwarder/utils/CommonUtil.java | 54 +++++++ .../sms/forwarder/utils/SettingUtil.java | 11 +- app/src/main/res/layout/activity_setting.xml | 2 +- .../layout/alert_dialog_setview_rule_test.xml | 5 +- app/src/main/res/layout/item_rule.xml | 1 + app/src/main/res/values-en/strings.xml | 2 + app/src/main/res/values/strings.xml | 6 +- 15 files changed, 200 insertions(+), 307 deletions(-) delete mode 100644 app/src/main/java/com/idormy/sms/forwarder/notify/NotifyHelper.java delete mode 100644 app/src/main/java/com/idormy/sms/forwarder/notify/NotifyListener.java diff --git a/app/src/main/java/com/idormy/sms/forwarder/AppListActivity.java b/app/src/main/java/com/idormy/sms/forwarder/AppListActivity.java index aa00362b..0e8f03cd 100644 --- a/app/src/main/java/com/idormy/sms/forwarder/AppListActivity.java +++ b/app/src/main/java/com/idormy/sms/forwarder/AppListActivity.java @@ -114,10 +114,12 @@ public class AppListActivity extends AppCompatActivity { PackageManager pm = getApplication().getPackageManager(); @SuppressLint("QueryPermissionsNeeded") List packages = pm.getInstalledPackages(PackageManager.GET_UNINSTALLED_PACKAGES); for (PackageInfo packageInfo : packages) { - if ("user".equals(currentType) && (packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 1) { //用户应用 + //只取用户应用 + if ("user".equals(currentType) && (packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 1) { continue; } - if ("sys".equals(currentType) && (packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) { //系统应用 + //只取系统应用 + if ("sys".equals(currentType) && (packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 1) { continue; } String appName = packageInfo.applicationInfo.loadLabel(pm).toString(); diff --git a/app/src/main/java/com/idormy/sms/forwarder/MainActivity.java b/app/src/main/java/com/idormy/sms/forwarder/MainActivity.java index 14f70bf0..4f75f2ca 100644 --- a/app/src/main/java/com/idormy/sms/forwarder/MainActivity.java +++ b/app/src/main/java/com/idormy/sms/forwarder/MainActivity.java @@ -1,7 +1,6 @@ package com.idormy.sms.forwarder; import android.annotation.SuppressLint; -import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; @@ -9,7 +8,6 @@ import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.os.PowerManager; -import android.service.notification.StatusBarNotification; import android.util.Log; import android.view.Menu; import android.view.MenuItem; @@ -24,41 +22,31 @@ import androidx.annotation.NonNull; import androidx.annotation.RequiresApi; import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AppCompatActivity; -import androidx.core.app.NotificationManagerCompat; import com.idormy.sms.forwarder.adapter.LogAdapter; import com.idormy.sms.forwarder.model.vo.LogVo; -import com.idormy.sms.forwarder.model.vo.SmsVo; -import com.idormy.sms.forwarder.notify.NotifyHelper; -import com.idormy.sms.forwarder.notify.NotifyListener; -import com.idormy.sms.forwarder.sender.SendUtil; import com.idormy.sms.forwarder.service.FrontService; -import com.idormy.sms.forwarder.service.NotifyService; import com.idormy.sms.forwarder.utils.CommonUtil; +import com.idormy.sms.forwarder.utils.KeepAliveUtils; import com.idormy.sms.forwarder.utils.LogUtil; import com.idormy.sms.forwarder.utils.NetUtil; import com.idormy.sms.forwarder.utils.PhoneUtils; +import com.idormy.sms.forwarder.utils.SettingUtil; import com.idormy.sms.forwarder.utils.SmsUtil; import com.idormy.sms.forwarder.utils.TimeUtil; import java.lang.reflect.Method; -import java.text.SimpleDateFormat; import java.util.ArrayList; -import java.util.Date; import java.util.List; -import java.util.Locale; -import java.util.Set; -public class MainActivity extends AppCompatActivity implements NotifyListener, RefreshListView.IRefreshListener { +public class MainActivity extends AppCompatActivity implements RefreshListView.IRefreshListener { private final String TAG = "MainActivity"; - private static final String ACTION_NOTIFICATION_LISTENER_SETTINGS = "android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS"; // logVoList用于存储数据 private List logVos = new ArrayList<>(); private LogAdapter adapter; private RefreshListView listView; private Intent serviceIntent; - private static final int REQUEST_CODE = 9999; private String currentType = "sms"; @Override @@ -81,9 +69,6 @@ public class MainActivity extends AppCompatActivity implements NotifyListener, R SmsUtil.init(this); NetUtil.init(this); - //应用通知 - NotifyHelper.getInstance().setNotifyListener(this); - //前台服务 serviceIntent = new Intent(MainActivity.this, FrontService.class); serviceIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); @@ -171,20 +156,20 @@ public class MainActivity extends AppCompatActivity implements NotifyListener, R } Log.d(TAG, "SimInfoList = " + MyApplication.SimInfoList.size()); - //开启读取通知栏权限 - if (!isNotificationListenerServiceEnabled(this)) { - openNotificationAccess(); - toggleNotificationListenerService(); - Toast.makeText(this, "请先勾选《短信转发器》的读取通知栏权限!", Toast.LENGTH_LONG).show(); - return; - } - //省电优化设置为无限制 if (Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) { - if (!isIgnoringBatteryOptimizations()) { - Toast.makeText(this, "请将省电优化设置为无限制,有利于防止《短信转发器》被杀!!", Toast.LENGTH_LONG).show(); + if (!KeepAliveUtils.isIgnoreBatteryOptimization(this)) { + Toast.makeText(this, "请将省电优化设置为无限制(不优化),有利于《短信转发器》保活!", Toast.LENGTH_LONG).show(); } } + + //开启读取通知栏权限 + if (SettingUtil.getSwitchEnableAppNotify() && !CommonUtil.isNotificationListenerServiceEnabled(this)) { + CommonUtil.toggleNotificationListenerService(this); + SettingUtil.switchEnableAppNotify(false); + Toast.makeText(this, "请先授予《短信转发器》通知使用权,否则无法转发APP通知,已经自动关闭转发!", Toast.LENGTH_LONG).show(); + return; + } startService(serviceIntent); } @@ -196,11 +181,6 @@ public class MainActivity extends AppCompatActivity implements NotifyListener, R @Override protected void onPause() { - //当界面返回到桌面之后.清除通知设置当中的数据.减少内存占有 - //if (applicationList != null) { - // applicationList.setAdapter(null); - // adapter = null; - //} super.onPause(); startService(serviceIntent); } @@ -208,10 +188,10 @@ public class MainActivity extends AppCompatActivity implements NotifyListener, R @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); - if (requestCode == REQUEST_CODE) { - if (isNotificationListenerServiceEnabled(this)) { + if (requestCode == CommonUtil.NOTIFICATION_REQUEST_CODE) { + if (CommonUtil.isNotificationListenerServiceEnabled(this)) { Toast.makeText(this, "通知服务已开启", Toast.LENGTH_SHORT).show(); - toggleNotificationListenerService(); + CommonUtil.toggleNotificationListenerService(this); } else { Toast.makeText(this, "通知服务未开启", Toast.LENGTH_SHORT).show(); } @@ -224,19 +204,6 @@ public class MainActivity extends AppCompatActivity implements NotifyListener, R super.onRequestPermissionsResult(requestCode, permissions, grantResults); } - public void toggleNotificationListenerService() { - PackageManager pm = getPackageManager(); - pm.setComponentEnabledSetting(new ComponentName(getApplicationContext(), NotifyService.class), - PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP); - - pm.setComponentEnabledSetting(new ComponentName(getApplicationContext(), NotifyService.class), - PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP); - } - - private static boolean isNotificationListenerServiceEnabled(Context context) { - Set packageNames = NotificationManagerCompat.getEnabledListenerPackages(context); - return packageNames.contains(context.getPackageName()); - } /** * 判断系统是否已经关闭省电优化 @@ -257,11 +224,6 @@ public class MainActivity extends AppCompatActivity implements NotifyListener, R return isIgnoring; } - private void openNotificationAccess() { - startActivity(new Intent(ACTION_NOTIFICATION_LISTENER_SETTINGS)); - } - - // 初始化数据 private void initTLogs() { logVos = LogUtil.getLog(null, null, currentType); @@ -416,71 +378,4 @@ public class MainActivity extends AppCompatActivity implements NotifyListener, R return super.onMenuOpened(featureId, menu); } - - /** - * 收到通知 - * - * @param type 通知类型 - */ - @Override - public void onReceiveMessage(int type) { - Log.d(TAG, "收到通知=" + type); - } - - /** - * 移除通知 - * - * @param type 通知类型 - */ - @Override - public void onRemovedMessage(int type) { - Log.d(TAG, "移除通知=" + type); - } - - /** - * 收到通知 - * - * @param sbn 状态栏通知 - */ - @Override - public void onReceiveMessage(StatusBarNotification sbn) { - if (sbn.getNotification() == null) return; - if (sbn.getNotification().extras == null) return; - - //推送通知的应用包名 - String packageName = sbn.getPackageName(); - //通知标题 - String title = sbn.getNotification().extras.get("android.title").toString(); - //通知内容 - String text = sbn.getNotification().extras.get("android.text").toString(); - if (text.isEmpty() && sbn.getNotification().tickerText != null) { - text = sbn.getNotification().tickerText.toString(); - } - //通知时间 - String time = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINESE).format(new Date(sbn.getPostTime())); - - Log.d(TAG, String.format( - Locale.getDefault(), - "onNotificationPosted:\n应用包名:%s\n消息标题:%s\n消息内容:%s\n消息时间:%s\n", - packageName, title, text, time) - ); - - //不处理空消息 - if (title.isEmpty() && text.isEmpty()) return; - - SmsVo smsVo = new SmsVo(packageName, text, new Date(), title); - Log.d(TAG, "send_msg" + smsVo.toString()); - SendUtil.send_msg(this, smsVo, 1, "app"); - } - - /** - * 移除掉通知栏消息 - * - * @param sbn 状态栏通知 - */ - @Override - public void onRemovedMessage(StatusBarNotification sbn) { - Log.d(TAG, "移除掉通知栏消息"); - } - } diff --git a/app/src/main/java/com/idormy/sms/forwarder/RuleActivity.java b/app/src/main/java/com/idormy/sms/forwarder/RuleActivity.java index 669fdac7..0d06bc15 100644 --- a/app/src/main/java/com/idormy/sms/forwarder/RuleActivity.java +++ b/app/src/main/java/com/idormy/sms/forwarder/RuleActivity.java @@ -472,9 +472,23 @@ public class RuleActivity extends AppCompatActivity { public void testRule(final RuleModel ruleModel, final Long senderId) { final View view = View.inflate(RuleActivity.this, R.layout.alert_dialog_setview_rule_test, null); + final TextView textTestSimSlot = view.findViewById(R.id.textTestSimSlot); + final TextView textTestPhone = view.findViewById(R.id.textTestPhone); + final TextView textTestContent = view.findViewById(R.id.textTestContent); final RadioGroup radioGroupTestSimSlot = view.findViewById(R.id.radioGroupTestSimSlot); final EditText editTextTestPhone = view.findViewById(R.id.editTextTestPhone); final EditText editTextTestMsgContent = view.findViewById(R.id.editTextTestMsgContent); + + if ("app".equals(currentType)) { + textTestSimSlot.setVisibility(View.GONE); + radioGroupTestSimSlot.setVisibility(View.GONE); + textTestPhone.setText(R.string.test_package_name); + textTestContent.setText(R.string.test_inform_content); + } else if ("call".equals(currentType)) { + textTestContent.setVisibility(View.GONE); + editTextTestMsgContent.setVisibility(View.GONE); + } + Button buttonRuleTest = view.findViewById(R.id.buttonRuleTest); AlertDialog.Builder ad1 = new AlertDialog.Builder(RuleActivity.this); ad1.setTitle(R.string.rule_tester); diff --git a/app/src/main/java/com/idormy/sms/forwarder/SettingActivity.java b/app/src/main/java/com/idormy/sms/forwarder/SettingActivity.java index 66c91d7b..8bf22e96 100644 --- a/app/src/main/java/com/idormy/sms/forwarder/SettingActivity.java +++ b/app/src/main/java/com/idormy/sms/forwarder/SettingActivity.java @@ -2,10 +2,8 @@ package com.idormy.sms.forwarder; import android.annotation.SuppressLint; import android.app.ActivityManager; -import android.content.ComponentName; import android.content.Context; import android.content.Intent; -import android.content.pm.PackageManager; import android.os.Build; import android.os.Bundle; import android.text.Editable; @@ -18,20 +16,17 @@ import android.widget.Switch; import android.widget.TextView; import android.widget.Toast; +import androidx.annotation.RequiresApi; import androidx.appcompat.app.AppCompatActivity; -import androidx.core.app.NotificationManagerCompat; -import com.idormy.sms.forwarder.service.NotifyService; +import com.idormy.sms.forwarder.utils.CommonUtil; import com.idormy.sms.forwarder.utils.KeepAliveUtils; import com.idormy.sms.forwarder.utils.SettingUtil; import java.util.List; -import java.util.Set; public class SettingActivity extends AppCompatActivity { private final String TAG = "SettingActivity"; - - private static final int REQUEST_CODE = 9527; private TextView textView; @Override @@ -87,8 +82,9 @@ public class SettingActivity extends AppCompatActivity { switch_enable_sms.setChecked(SettingUtil.getSwitchEnableSms()); switch_enable_sms.setOnCheckedChangeListener((buttonView, isChecked) -> { + //TODO:校验使用短信转发必备的权限 SettingUtil.switchEnableSms(isChecked); - Log.d(TAG, "onCheckedChanged:" + isChecked); + Log.d(TAG, "switchEnableSms:" + isChecked); }); } @@ -97,8 +93,9 @@ public class SettingActivity extends AppCompatActivity { switch_enable_phone.setChecked(SettingUtil.getSwitchEnablePhone()); switch_enable_phone.setOnCheckedChangeListener((buttonView, isChecked) -> { + //TODO:校验使用来电转发必备的权限 SettingUtil.switchEnablePhone(isChecked); - Log.d(TAG, "onCheckedChanged:" + isChecked); + Log.d(TAG, "switchEnablePhone:" + isChecked); }); } @@ -107,14 +104,25 @@ public class SettingActivity extends AppCompatActivity { switch_enable_app_notify.setChecked(SettingUtil.getSwitchEnableAppNotify()); switch_enable_app_notify.setOnCheckedChangeListener((buttonView, isChecked) -> { + //TODO:校验使用APP通知转发必备的权限 + if (isChecked) { + if (!CommonUtil.isNotificationListenerServiceEnabled(this)) { + CommonUtil.openNotificationAccess(this); + Toast.makeText(this, "请先授予《短信转发器》通知使用权,否则无法转发APP通知,开启失败!", Toast.LENGTH_LONG).show(); + return; + } else { + Toast.makeText(this, "通知服务已开启", Toast.LENGTH_LONG).show(); + CommonUtil.toggleNotificationListenerService(this); + } + } SettingUtil.switchEnableAppNotify(isChecked); - Log.d(TAG, "onCheckedChanged:" + isChecked); + Log.d(TAG, "switchEnableAppNotify:" + isChecked); }); } //不在最近任务列表中显示 @SuppressLint("ObsoleteSdkInt") - private void switchExcludeFromRecents(Switch switch_exclude_from_recents) { + private void switchExcludeFromRecents(@SuppressLint("UseSwitchCompatOrMaterialCode") Switch switch_exclude_from_recents) { switch_exclude_from_recents.setChecked(SettingUtil.getExcludeFromRecents()); switch_exclude_from_recents.setOnCheckedChangeListener((buttonView, isChecked) -> { @@ -139,12 +147,10 @@ public class SettingActivity extends AppCompatActivity { et_add_extra_device_mark.addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { - } @Override public void onTextChanged(CharSequence s, int start, int before, int count) { - } @Override @@ -161,12 +167,10 @@ public class SettingActivity extends AppCompatActivity { et_add_extra_sim1.addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { - } @Override public void onTextChanged(CharSequence s, int start, int before, int count) { - } @Override @@ -183,12 +187,10 @@ public class SettingActivity extends AppCompatActivity { et_add_extra_sim2.addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { - } @Override public void onTextChanged(CharSequence s, int start, int before, int count) { - } @Override @@ -341,6 +343,7 @@ public class SettingActivity extends AppCompatActivity { } //电池优化设置 + @RequiresApi(api = Build.VERSION_CODES.M) public void batterySetting(View view) { if (KeepAliveUtils.isIgnoreBatteryOptimization(this)) { Toast.makeText(this, R.string.isIgnored, Toast.LENGTH_SHORT).show(); @@ -350,58 +353,30 @@ public class SettingActivity extends AppCompatActivity { } /** - * 请求权限 + * 请求通知使用权限 * * @param view 控件 */ - @SuppressWarnings("deprecation") - public void requestPermission(View view) { - if (!isNLServiceEnabled()) { - Intent intent = new Intent("android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS"); - startActivityForResult(intent, REQUEST_CODE); + public void requestNotificationPermission(View view) { + if (!CommonUtil.isNotificationListenerServiceEnabled(this)) { + CommonUtil.openNotificationAccess(this); } else { - showMsg("通知服务已开启"); - toggleNotificationListenerService(); + Toast.makeText(this, "通知服务已开启", Toast.LENGTH_SHORT).show(); + CommonUtil.toggleNotificationListenerService(this); } } - /** - * 是否启用通知监听服务 - * - * @return boolean - */ - public boolean isNLServiceEnabled() { - Set packageNames = NotificationManagerCompat.getEnabledListenerPackages(this); - return packageNames.contains(getPackageName()); - } - - /** - * 切换通知监听器服务 - */ - public void toggleNotificationListenerService() { - PackageManager pm = getPackageManager(); - pm.setComponentEnabledSetting(new ComponentName(getApplicationContext(), NotifyService.class), - PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP); - - pm.setComponentEnabledSetting(new ComponentName(getApplicationContext(), NotifyService.class), - PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP); - } - @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); - if (requestCode == REQUEST_CODE) { - if (isNLServiceEnabled()) { - showMsg("通知服务已开启"); - toggleNotificationListenerService(); + if (requestCode == CommonUtil.NOTIFICATION_REQUEST_CODE) { + if (CommonUtil.isNotificationListenerServiceEnabled(this)) { + Toast.makeText(this, "通知服务已开启", Toast.LENGTH_SHORT).show(); + CommonUtil.toggleNotificationListenerService(this); } else { - showMsg("通知服务未开启"); + Toast.makeText(this, "通知服务未开启", Toast.LENGTH_SHORT).show(); } } } - private void showMsg(String msg) { - Toast.makeText(this, msg, Toast.LENGTH_SHORT).show(); - } - } diff --git a/app/src/main/java/com/idormy/sms/forwarder/model/RuleModel.java b/app/src/main/java/com/idormy/sms/forwarder/model/RuleModel.java index a868bec5..0fba6cfa 100644 --- a/app/src/main/java/com/idormy/sms/forwarder/model/RuleModel.java +++ b/app/src/main/java/com/idormy/sms/forwarder/model/RuleModel.java @@ -153,9 +153,11 @@ public class RuleModel { mixChecked = true; break; case FILED_PHONE_NUM: + case FILED_PACKAGE_NAME: mixChecked = checkValue(msg.getMobile()); break; case FILED_MSG_CONTENT: + case FILED_INFORM_CONTENT: mixChecked = checkValue(msg.getContent()); break; case FILED_MULTI_MATCH: @@ -163,11 +165,9 @@ public class RuleModel { break; default: break; - } } - Log.i(TAG, "rule:" + this + " checkMsg:" + msg + " checked:" + mixChecked); return mixChecked; diff --git a/app/src/main/java/com/idormy/sms/forwarder/notify/NotifyHelper.java b/app/src/main/java/com/idormy/sms/forwarder/notify/NotifyHelper.java deleted file mode 100644 index 019bced3..00000000 --- a/app/src/main/java/com/idormy/sms/forwarder/notify/NotifyHelper.java +++ /dev/null @@ -1,76 +0,0 @@ -package com.idormy.sms.forwarder.notify; - -import android.service.notification.StatusBarNotification; - -public class NotifyHelper { - - private static NotifyHelper instance; - - public static final int N_MESSAGE = 0; - public static final int N_CALL = 1; - public static final int N_QQ = 2; - public static final int N_WX = 3; - - private NotifyListener notifyListener; - - public static NotifyHelper getInstance() { - if (instance == null) { - instance = new NotifyHelper(); - } - return instance; - } - - /** - * 收到消息 - * - * @param type 消息类型 - */ - public void onReceive(int type) { - if (notifyListener != null) { - notifyListener.onReceiveMessage(type); - } - - } - - /** - * 收到消息 - * - * @param sbn 状态栏通知 - */ - public void onReceive(StatusBarNotification sbn) { - if (notifyListener != null) { - notifyListener.onReceiveMessage(sbn); - } - } - - /** - * 移除消息 - * - * @param type 消息类型 - */ - public void onRemoved(int type) { - if (notifyListener != null) { - notifyListener.onRemovedMessage(type); - } - } - - /** - * 移除消息 - * - * @param sbn 状态栏通知 - */ - public void onRemoved(StatusBarNotification sbn) { - if (notifyListener != null) { - notifyListener.onRemovedMessage(sbn); - } - } - - /** - * 设置回调方法 - * - * @param notifyListener 通知监听 - */ - public void setNotifyListener(NotifyListener notifyListener) { - this.notifyListener = notifyListener; - } -} diff --git a/app/src/main/java/com/idormy/sms/forwarder/notify/NotifyListener.java b/app/src/main/java/com/idormy/sms/forwarder/notify/NotifyListener.java deleted file mode 100644 index c35f862d..00000000 --- a/app/src/main/java/com/idormy/sms/forwarder/notify/NotifyListener.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.idormy.sms.forwarder.notify; - -import android.service.notification.StatusBarNotification; - -public interface NotifyListener { - - /** - * 接收到通知栏消息 - * - * @param type - */ - void onReceiveMessage(int type); - - /** - * 移除掉通知栏消息 - * - * @param type - */ - void onRemovedMessage(int type); - - /** - * 接收到通知栏消息 - * - * @param sbn - */ - void onReceiveMessage(StatusBarNotification sbn); - - /** - * 移除掉通知栏消息 - * - * @param sbn - */ - void onRemovedMessage(StatusBarNotification sbn); -} diff --git a/app/src/main/java/com/idormy/sms/forwarder/service/NotifyService.java b/app/src/main/java/com/idormy/sms/forwarder/service/NotifyService.java index da96cdef..9bd65e23 100644 --- a/app/src/main/java/com/idormy/sms/forwarder/service/NotifyService.java +++ b/app/src/main/java/com/idormy/sms/forwarder/service/NotifyService.java @@ -8,9 +8,15 @@ import android.util.Log; import androidx.annotation.RequiresApi; -import com.idormy.sms.forwarder.notify.NotifyHelper; +import com.idormy.sms.forwarder.model.vo.SmsVo; +import com.idormy.sms.forwarder.sender.SendUtil; +import com.idormy.sms.forwarder.utils.CommonUtil; import com.idormy.sms.forwarder.utils.SettingUtil; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Locale; + @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2) public class NotifyService extends NotificationListenerService { @@ -24,12 +30,50 @@ public class NotifyService extends NotificationListenerService { @RequiresApi(api = Build.VERSION_CODES.KITKAT) @Override public void onNotificationPosted(StatusBarNotification sbn) { - if (!SettingUtil.getSwitchEnableAppNotify()) { + //未开启转发 + if (!SettingUtil.getSwitchEnableAppNotify()) return; + //异常通知跳过 + if (sbn.getNotification() == null) return; + if (sbn.getNotification().extras == null) return; + + //推送通知的应用包名 + String packageName = sbn.getPackageName(); + //自身通知跳过 + if ("com.idormy.sms.forwarder".equals(packageName)) return; + + //通知标题 + String title = sbn.getNotification().extras.get("android.title").toString(); + //通知内容 + String text = sbn.getNotification().extras.get("android.text").toString(); + if (text.isEmpty() && sbn.getNotification().tickerText != null) { + text = sbn.getNotification().tickerText.toString(); + } + //不处理空消息(标题跟内容都为空) + if (title.isEmpty() && text.isEmpty()) return; + + //通知时间 + String time = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINESE).format(new Date(sbn.getPostTime())); + Log.d(TAG, String.format( + Locale.getDefault(), + "onNotificationPosted:\n应用包名:%s\n消息标题:%s\n消息内容:%s\n消息时间:%s\n", + packageName, title, text, time) + ); + + //重复通知不再处理 + String prevHash = SettingUtil.getPrevNoticeHash(packageName); + String currHash = CommonUtil.MD5(packageName + title + text + time); + Log.d(TAG, "prevHash=" + prevHash + " currHash=" + currHash); + if (prevHash != null && prevHash.equals(currHash)) { + Log.w(TAG, "重复通知不再处理"); return; } - if (sbn.getNotification() == null) return; - Log.d(TAG, sbn.getPackageName()); - NotifyHelper.getInstance().onReceive(sbn); + SettingUtil.setPrevNoticeHash(packageName, currHash); + + SmsVo smsVo = new SmsVo(packageName, text, new Date(), title); + Log.d(TAG, "send_msg" + smsVo.toString()); + SendUtil.send_msg(this, smsVo, 1, "app"); + + //NotifyHelper.getInstance().onReceive(sbn); } /** @@ -39,11 +83,14 @@ public class NotifyService extends NotificationListenerService { */ @Override public void onNotificationRemoved(StatusBarNotification sbn) { + //未开启转发 + if (!SettingUtil.getSwitchEnableAppNotify()) return; + //异常通知跳过 + if (sbn.getNotification() == null) return; + Log.d(TAG, sbn.getPackageName()); - if (!SettingUtil.getSwitchEnableAppNotify()) { - return; - } - NotifyHelper.getInstance().onRemoved(sbn); + + //NotifyHelper.getInstance().onRemoved(sbn); } /** @@ -51,6 +98,9 @@ public class NotifyService extends NotificationListenerService { */ @Override public void onListenerDisconnected() { + //未开启转发 + if (!SettingUtil.getSwitchEnableAppNotify()) return; + Log.d(TAG, "通知侦听器断开连接 - 请求重新绑定"); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { requestRebind(new ComponentName(this, NotificationListenerService.class)); diff --git a/app/src/main/java/com/idormy/sms/forwarder/utils/CommonUtil.java b/app/src/main/java/com/idormy/sms/forwarder/utils/CommonUtil.java index 65c70af3..0d3f07ff 100644 --- a/app/src/main/java/com/idormy/sms/forwarder/utils/CommonUtil.java +++ b/app/src/main/java/com/idormy/sms/forwarder/utils/CommonUtil.java @@ -3,16 +3,49 @@ package com.idormy.sms.forwarder.utils; import android.Manifest; import android.annotation.SuppressLint; import android.app.Activity; +import android.content.ComponentName; import android.content.Context; +import android.content.Intent; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import androidx.core.app.ActivityCompat; +import androidx.core.app.NotificationManagerCompat; + +import com.idormy.sms.forwarder.service.NotifyService; + +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.Set; /** * 权限相关工具类 */ public class CommonUtil { + public static final int NOTIFICATION_REQUEST_CODE = 9527; + private static final String ACTION_NOTIFICATION_LISTENER_SETTINGS = "android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS"; + + //是否启用通知监听服务 + public static boolean isNotificationListenerServiceEnabled(Context context) { + Set packageNames = NotificationManagerCompat.getEnabledListenerPackages(context); + return packageNames.contains(context.getPackageName()); + } + + //开关通知监听服务 + public static void toggleNotificationListenerService(Context context) { + PackageManager pm = context.getPackageManager(); + pm.setComponentEnabledSetting(new ComponentName(context.getApplicationContext(), NotifyService.class), + PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP); + + pm.setComponentEnabledSetting(new ComponentName(context.getApplicationContext(), NotifyService.class), + PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP); + } + + //跳转通知使用权设置界面 + public static void openNotificationAccess(Activity activity) { + Intent intent = new Intent(ACTION_NOTIFICATION_LISTENER_SETTINGS); + activity.startActivityForResult(intent, NOTIFICATION_REQUEST_CODE); + } //获取当前版本名称 public static String getVersionName(Context context) throws Exception { @@ -74,4 +107,25 @@ public class CommonUtil { }, 0x01); } } + + //计算MD5 + public static String MD5(String input) { + if (input == null || input.length() == 0) return null; + + try { + MessageDigest md5 = MessageDigest.getInstance("MD5"); + md5.update(input.getBytes()); + byte[] byteArray = md5.digest(); + StringBuilder sb = new StringBuilder(); + for (byte b : byteArray) { + // 一个byte格式化成两位的16进制,不足两位高位补零 + sb.append(String.format("%02x", b)); + } + return sb.toString().toUpperCase(); + } catch (NoSuchAlgorithmException e) { + e.printStackTrace(); + } + + return null; + } } diff --git a/app/src/main/java/com/idormy/sms/forwarder/utils/SettingUtil.java b/app/src/main/java/com/idormy/sms/forwarder/utils/SettingUtil.java index 9e68b449..bd0b850b 100644 --- a/app/src/main/java/com/idormy/sms/forwarder/utils/SettingUtil.java +++ b/app/src/main/java/com/idormy/sms/forwarder/utils/SettingUtil.java @@ -53,7 +53,7 @@ public class SettingUtil { } public static boolean getSwitchEnableSms() { - return sp_setting.getBoolean(Define.SP_MSG_KEY_STRING_ENABLE_SMS, true); + return sp_setting.getBoolean(Define.SP_MSG_KEY_STRING_ENABLE_SMS, false); } public static void switchEnablePhone(Boolean enable) { @@ -63,7 +63,7 @@ public class SettingUtil { } public static boolean getSwitchEnablePhone() { - return sp_setting.getBoolean(Define.SP_MSG_KEY_STRING_ENABLE_PHONE, true); + return sp_setting.getBoolean(Define.SP_MSG_KEY_STRING_ENABLE_PHONE, false); } public static void switchEnableAppNotify(Boolean enable) { @@ -196,4 +196,11 @@ public class SettingUtil { sp_setting.edit().putInt(key, retry_delay_time).apply(); } + public static String getPrevNoticeHash(String key) { + return sp_setting.getString(key, ""); + } + + public static void setPrevNoticeHash(String key, String value) { + sp_setting.edit().putString(key, value).apply(); + } } diff --git a/app/src/main/res/layout/activity_setting.xml b/app/src/main/res/layout/activity_setting.xml index 26b87b90..f7b283d0 100644 --- a/app/src/main/res/layout/activity_setting.xml +++ b/app/src/main/res/layout/activity_setting.xml @@ -541,7 +541,7 @@ android:layout_marginStart="10dp" android:layout_weight="1" android:background="@color/colorPrimary" - android:onClick="requestPermission" + android:onClick="requestNotificationPermission" android:text="@string/request_permission" tools:ignore="ButtonStyle,NestedWeights,UsingOnClickInXml" /> diff --git a/app/src/main/res/layout/alert_dialog_setview_rule_test.xml b/app/src/main/res/layout/alert_dialog_setview_rule_test.xml index 3b48f931..2f9de9e0 100644 --- a/app/src/main/res/layout/alert_dialog_setview_rule_test.xml +++ b/app/src/main/res/layout/alert_dialog_setview_rule_test.xml @@ -16,6 +16,7 @@ android:orientation="vertical"> - - Test Sim Slot Test Phone Number Test Msg Content + Test PackageName + Test Inform content Sim Slot Field Phone No. diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 22b18ffc..70135fd8 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -62,6 +62,8 @@ 测试模拟的接收卡槽 测试模拟的来源号码 测试模拟的短信内容 + 测试模拟的APP包名 + 测试模拟的通知内容 设置匹配的卡槽 设置匹配的字段 手机号 @@ -133,7 +135,7 @@ Tip:指定接收消息的成员,成员ID列表(多个接收者用‘|’分隔,最多支持1000个) 设置WebHook地址:示例:https://qyapi.weixin.qq.com/cgixx?key=xxx 设置Server酱·Turbo版的SendKey - 设置Telegram机器人的ApiToken 或 自定义地址 + 设置Telegram机器人的ApiToken 或 自定义地址(http开头) 设置被通知人(或群组)的ChatId 请求方式 设置WebServer:例如:https://a.b.com/msg?token=xyz @@ -174,7 +176,7 @@ 未知号码 来电 您的手机不支持此设置 - 已设置成功! + 已将省电优化设置为无限制(不优化)! v1.0 https://github.com/pppscn/SmsForwarder