mirror of
https://github.com/pppscn/SmsForwarder
synced 2025-08-03 01:17:41 +08:00
优化:开启通知服务权限判断
优化:默认关闭短信、来电、APP转发(设置中总开关)
This commit is contained in:
parent
e6cafa521a
commit
b6a8952027
@ -114,10 +114,12 @@ public class AppListActivity extends AppCompatActivity {
|
||||
PackageManager pm = getApplication().getPackageManager();
|
||||
@SuppressLint("QueryPermissionsNeeded") List<PackageInfo> 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();
|
||||
|
@ -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<LogVo> 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<String> 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, "移除掉通知栏消息");
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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<String> 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();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
@ -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));
|
||||
|
@ -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<String> 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;
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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" />
|
||||
|
||||
|
@ -16,6 +16,7 @@
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textTestSimSlot"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="3dp"
|
||||
@ -44,12 +45,12 @@
|
||||
</RadioGroup>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textTestPhone"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="3dp"
|
||||
android:text="@string/test_phone_number" />
|
||||
|
||||
|
||||
<EditText
|
||||
android:id="@+id/editTextTestPhone"
|
||||
android:layout_width="match_parent"
|
||||
@ -62,12 +63,12 @@
|
||||
tools:ignore="LabelFor,TextFields" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textTestContent"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="3dp"
|
||||
android:text="@string/test_msg_content" />
|
||||
|
||||
|
||||
<EditText
|
||||
android:id="@+id/editTextTestMsgContent"
|
||||
android:layout_width="match_parent"
|
||||
|
@ -9,6 +9,7 @@
|
||||
android:layout_width="32dp"
|
||||
android:layout_height="32dp"
|
||||
android:layout_margin="5dp"
|
||||
android:layout_gravity="center_vertical"
|
||||
tools:ignore="ContentDescription" />
|
||||
|
||||
<TextView
|
||||
|
@ -62,6 +62,8 @@
|
||||
<string name="test_sim_slot">Test Sim Slot</string>
|
||||
<string name="test_phone_number">Test Phone Number</string>
|
||||
<string name="test_msg_content">Test Msg Content</string>
|
||||
<string name="test_package_name">Test PackageName</string>
|
||||
<string name="test_inform_content">Test Inform content</string>
|
||||
<string name="match_sim_slot">Sim Slot</string>
|
||||
<string name="match_field">Field</string>
|
||||
<string name="phone_number">Phone No.</string>
|
||||
|
@ -62,6 +62,8 @@
|
||||
<string name="test_sim_slot">测试模拟的接收卡槽</string>
|
||||
<string name="test_phone_number">测试模拟的来源号码</string>
|
||||
<string name="test_msg_content">测试模拟的短信内容</string>
|
||||
<string name="test_package_name">测试模拟的APP包名</string>
|
||||
<string name="test_inform_content">测试模拟的通知内容</string>
|
||||
<string name="match_sim_slot">设置匹配的卡槽</string>
|
||||
<string name="match_field">设置匹配的字段</string>
|
||||
<string name="phone_number">手机号</string>
|
||||
@ -133,7 +135,7 @@
|
||||
<string name="specified_member_tips">Tip:指定接收消息的成员,成员ID列表(多个接收者用‘|’分隔,最多支持1000个)</string>
|
||||
<string name="QYWXGroupRobotWebHook">设置WebHook地址:示例:https://qyapi.weixin.qq.com/cgixx?key=xxx</string>
|
||||
<string name="ServerChanSendKey">设置Server酱·Turbo版的SendKey</string>
|
||||
<string name="TelegramApiToken">设置Telegram机器人的ApiToken 或 自定义地址</string>
|
||||
<string name="TelegramApiToken">设置Telegram机器人的ApiToken 或 自定义地址(http开头)</string>
|
||||
<string name="TelegramChatId">设置被通知人(或群组)的ChatId</string>
|
||||
<string name="WebNotifyMethod" formatted="false">请求方式</string>
|
||||
<string name="WebNotifyWebServer">设置WebServer:例如:https://a.b.com/msg?token=xyz</string>
|
||||
@ -174,7 +176,7 @@
|
||||
<string name="unknown_number">未知号码</string>
|
||||
<string name="calling">来电</string>
|
||||
<string name="unsupport">您的手机不支持此设置</string>
|
||||
<string name="isIgnored">已设置成功!</string>
|
||||
<string name="isIgnored">已将省电优化设置为无限制(不优化)!</string>
|
||||
<!--Other-->
|
||||
<string name="version_now">v1.0</string>
|
||||
<string name="linkweb">https://github.com/pppscn/SmsForwarder</string>
|
||||
|
Loading…
x
Reference in New Issue
Block a user