新增:监听其他APP通知信息

This commit is contained in:
pppscn 2021-11-13 18:01:50 +08:00
parent 27d35cb276
commit e8ea004bc4
20 changed files with 2104 additions and 1612 deletions

View File

@ -260,6 +260,7 @@
+ https://github.com/xuexiangjys/XUpdateAPI (在线升级) + https://github.com/xuexiangjys/XUpdateAPI (在线升级)
+ https://github.com/mailhu/emailkit (邮件发送) + https://github.com/mailhu/emailkit (邮件发送)
+ https://github.com/alibaba/fastjson (Json解析) + https://github.com/alibaba/fastjson (Json解析)
+ https://github.com/lilongweidev/NotifyListenerDemo (手机通知服务)
## LICENSE ## LICENSE

View File

@ -1,154 +1,154 @@
apply plugin: 'com.android.application' apply plugin: 'com.android.application'
def keyProps = new Properties() def keyProps = new Properties()
def keyPropsFile = rootProject.file('keystore/keystore.properties') def keyPropsFile = rootProject.file('keystore/keystore.properties')
if (keyPropsFile.exists()) { if (keyPropsFile.exists()) {
keyProps.load(new FileInputStream(keyPropsFile)) keyProps.load(new FileInputStream(keyPropsFile))
} }
// version.properties // version.properties
def versionProps = new Properties() def versionProps = new Properties()
def versionPropsFile = rootProject.file('version.properties') def versionPropsFile = rootProject.file('version.properties')
if (versionPropsFile.exists()) { if (versionPropsFile.exists()) {
versionProps.load(new FileInputStream(versionPropsFile)) versionProps.load(new FileInputStream(versionPropsFile))
} }
android { android {
buildToolsVersion '30.0.3' buildToolsVersion '30.0.3'
compileSdkVersion 30 compileSdkVersion 30
compileOptions { compileOptions {
sourceCompatibility 1.8 sourceCompatibility 1.8
targetCompatibility 1.8 targetCompatibility 1.8
} }
defaultConfig { defaultConfig {
applicationId "com.idormy.sms.forwarder" applicationId "com.idormy.sms.forwarder"
minSdkVersion 23 minSdkVersion 21
targetSdkVersion 30 targetSdkVersion 30
versionCode versionProps['versionCode'].toInteger() versionCode versionProps['versionCode'].toInteger()
versionName versionProps['versionName'] versionName versionProps['versionName']
testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner' testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
} }
lintOptions { lintOptions {
checkReleaseBuilds false checkReleaseBuilds false
} }
signingConfigs { signingConfigs {
release { release {
keyAlias keyProps['keyAlias'] keyAlias keyProps['keyAlias']
keyPassword keyProps['keyPassword'] keyPassword keyProps['keyPassword']
storeFile keyProps['storeFile'] ? file(keyProps['storeFile']) : null storeFile keyProps['storeFile'] ? file(keyProps['storeFile']) : null
storePassword keyProps['storePassword'] storePassword keyProps['storePassword']
} }
debug { debug {
keyAlias keyProps['keyAlias'] keyAlias keyProps['keyAlias']
keyPassword keyProps['keyPassword'] keyPassword keyProps['keyPassword']
storeFile keyProps['storeFile'] ? file(keyProps['storeFile']) : null storeFile keyProps['storeFile'] ? file(keyProps['storeFile']) : null
storePassword keyProps['storePassword'] storePassword keyProps['storePassword']
} }
} }
buildTypes { buildTypes {
release { release {
minifyEnabled true minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.release signingConfig signingConfigs.release
} }
debug { debug {
minifyEnabled true minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.debug signingConfig signingConfigs.debug
} }
} }
//apk file name //apk file name
android.applicationVariants.all { variant -> android.applicationVariants.all { variant ->
variant.outputs.all { variant.outputs.all {
//def date = new Date().format("yyyyMMdd" , TimeZone.getTimeZone("Asia/Shanghai")) //def date = new Date().format("yyyyMMdd" , TimeZone.getTimeZone("Asia/Shanghai"))
def date = new Date().format("yyyyMMdd", TimeZone.getTimeZone("GMT+08")) def date = new Date().format("yyyyMMdd", TimeZone.getTimeZone("GMT+08"))
if (variant.buildType.name == 'debug') { if (variant.buildType.name == 'debug') {
outputFileName = "SmsForwarder_debug_${date}_${versionName}.apk" outputFileName = "SmsForwarder_debug_${date}_${versionName}.apk"
} }
if (variant.buildType.name == 'release') { if (variant.buildType.name == 'release') {
outputFileName = "SmsForwarder_release_${date}_${versionName}.apk" outputFileName = "SmsForwarder_release_${date}_${versionName}.apk"
} }
} }
} }
} }
task upgradeVersion { task upgradeVersion {
group 'help' group 'help'
description '构建新版本' description '构建新版本'
doLast { doLast {
println("---自动升级版本号---\n") println("---自动升级版本号---\n")
String oldVersionCode = versionProps['versionCode'] String oldVersionCode = versionProps['versionCode']
String oldVersionName = versionProps['versionName'] String oldVersionName = versionProps['versionName']
if (oldVersionCode == null || oldVersionName == null || if (oldVersionCode == null || oldVersionName == null ||
oldVersionCode.isEmpty() || oldVersionName.isEmpty()) { oldVersionCode.isEmpty() || oldVersionName.isEmpty()) {
println("error:版本号不能为空") println("error:版本号不能为空")
return return
} }
versionProps['versionCode'] = String.valueOf(versionProps['versionCode'].toInteger() + 1) versionProps['versionCode'] = String.valueOf(versionProps['versionCode'].toInteger() + 1)
String str = versionProps['versionName'].toString() String str = versionProps['versionName'].toString()
versionProps['versionName'] = str.substring(0, str.lastIndexOf('.') + 1) + versionProps['versionName'] = str.substring(0, str.lastIndexOf('.') + 1) +
(str.substring(str.lastIndexOf('.') + 1).toInteger() + 1) (str.substring(str.lastIndexOf('.') + 1).toInteger() + 1)
String tip = String tip =
"版本号从$oldVersionName($oldVersionCode)升级到${versionProps['versionName']}(${versionProps['versionCode']})" "版本号从$oldVersionName($oldVersionCode)升级到${versionProps['versionName']}(${versionProps['versionCode']})"
println(tip) println(tip)
def writer = new FileWriter(versionPropsFile) def writer = new FileWriter(versionPropsFile)
versionProps.store(writer, null) versionProps.store(writer, null)
writer.flush() writer.flush()
writer.close() writer.close()
def tag = "v${versionProps['versionName']}" def tag = "v${versionProps['versionName']}"
cmdExecute("git pull") cmdExecute("git pull")
cmdExecute("git add version.properties") cmdExecute("git add version.properties")
cmdExecute("git commit -m \"版本号升级为:$tag\"") cmdExecute("git commit -m \"版本号升级为:$tag\"")
cmdExecute("git push origin") cmdExecute("git push origin")
cmdExecute("git tag $tag") cmdExecute("git tag $tag")
cmdExecute("git push origin $tag") cmdExecute("git push origin $tag")
} }
} }
void cmdExecute(String cmd) { void cmdExecute(String cmd) {
println "\n执行$cmd" println "\n执行$cmd"
println cmd.execute().text println cmd.execute().text
} }
dependencies { dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs') implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation 'androidx.appcompat:appcompat:1.3.1' implementation 'androidx.appcompat:appcompat:1.3.1'
implementation 'androidx.constraintlayout:constraintlayout:2.1.1' implementation 'androidx.constraintlayout:constraintlayout:2.1.1'
testImplementation 'junit:junit:4.13.2' testImplementation 'junit:junit:4.+'
androidTestImplementation 'androidx.test.ext:junit:1.1.3' androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
//okhttp //okhttp
implementation 'com.squareup.okhttp3:okhttp:4.9.1' implementation 'com.squareup.okhttp3:okhttp:4.9.1'
implementation 'com.squareup.okio:okio:2.10.0' implementation 'com.squareup.okio:okio:2.10.0'
//fastjson //fastjson
implementation "com.alibaba:fastjson:1.2.78" implementation "com.alibaba:fastjson:1.2.78"
//SDK //SDK
implementation 'com.umeng.umsdk:common:9.4.4'// implementation 'com.umeng.umsdk:common:9.4.4'//
implementation 'com.umeng.umsdk:asms:1.4.1'// implementation 'com.umeng.umsdk:asms:1.4.1'//
implementation 'com.umeng.umsdk:apm:1.4.2' // SDKcrash数据请一定集成 implementation 'com.umeng.umsdk:apm:1.4.2' // SDKcrash数据请一定集成
//XUpdate //XUpdate
implementation 'com.github.xuexiangjys:XUpdate:2.1.0' implementation 'com.github.xuexiangjys:XUpdate:2.1.0'
implementation 'com.github.xuexiangjys.XUpdateAPI:xupdate-easy:1.0.0' implementation 'com.github.xuexiangjys.XUpdateAPI:xupdate-easy:1.0.0'
implementation 'com.github.xuexiangjys.XUpdateAPI:xupdate-downloader-aria:1.0.0' implementation 'com.github.xuexiangjys.XUpdateAPI:xupdate-downloader-aria:1.0.0'
//EmailKit //EmailKit
implementation 'com.github.mailhu:emailkit:4.2.2' implementation 'com.github.mailhu:emailkit:4.2.2'
//Lombok //Lombok
//noinspection AnnotationProcessorOnCompilePath //noinspection AnnotationProcessorOnCompilePath
compileOnly 'org.projectlombok:lombok:1.18.20' compileOnly 'org.projectlombok:lombok:1.18.20'
annotationProcessor 'org.projectlombok:lombok:1.18.20' annotationProcessor 'org.projectlombok:lombok:1.18.20'
//RxJava //RxJava
implementation 'io.reactivex.rxjava3:rxjava:3.1.1' implementation 'io.reactivex.rxjava3:rxjava:3.1.1'
//AndroidAsync //AndroidAsync
implementation 'com.koushikdutta.async:androidasync:3.1.0' implementation 'com.koushikdutta.async:androidasync:3.1.0'
} }

View File

@ -1,120 +1,143 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
package="com.idormy.sms.forwarder"> package="com.idormy.sms.forwarder">
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.INTERNET" />
<!-- 授予应用程序访问系统开机事件的权限 --> <!-- 授予应用程序访问系统开机事件的权限 -->
<uses-permission <uses-permission
android:name="android.permission.READ_PRIVILEGED_PHONE_STATE" android:name="android.permission.READ_PRIVILEGED_PHONE_STATE"
tools:ignore="ProtectedPermissions" /> tools:ignore="ProtectedPermissions" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission <uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:name="android.permission.WRITE_EXTERNAL_STORAGE"
tools:ignore="ScopedStorage" /> tools:ignore="ScopedStorage" />
<uses-permission android:name="android.permission.RECEIVE_SMS" /> <uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.READ_SMS" /> <uses-permission android:name="android.permission.READ_SMS" />
<uses-permission android:name="android.permission.SEND_SMS" /> <uses-permission android:name="android.permission.SEND_SMS" />
<uses-permission android:name="android.permission.CALL_PHONE" /> <uses-permission android:name="android.permission.CALL_PHONE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" /> <uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.READ_PHONE_NUMBERS" /> <uses-permission android:name="android.permission.READ_PHONE_NUMBERS" />
<uses-permission android:name="android.permission.READ_CALL_LOG" /> <uses-permission android:name="android.permission.READ_CALL_LOG" />
<uses-permission android:name="android.permission.READ_CONTACTS" /> <uses-permission android:name="android.permission.READ_CONTACTS" />
<!--Android 9API 级别 28或更高版本并使用前台服务则其必须请求 FOREGROUND_SERVICE 权限--> <!--Android 9API 级别 28或更高版本并使用前台服务则其必须请求 FOREGROUND_SERVICE 权限-->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" /> <uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
<uses-permission <uses-permission
android:name="android.permission.BATTERY_STATS" android:name="android.permission.BATTERY_STATS"
tools:ignore="ProtectedPermissions" /> tools:ignore="ProtectedPermissions" />
<uses-permission
<application android:name="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE"
android:name=".MyApplication" tools:ignore="ProtectedPermissions" />
android:allowBackup="true" <uses-permission android:name="android.permission.ACTION_NOTIFICATION_LISTENER_SETTINGS" />
android:icon="@mipmap/ic_launcher" <uses-permission
android:label="@string/app_name" android:name="android.permission.INSTALL_PACKAGES"
android:requestLegacyExternalStorage="true" tools:ignore="ProtectedPermissions" />
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme" <application
android:usesCleartextTraffic="true" android:name=".MyApplication"
android:fullBackupContent="@xml/backup_descriptor"> android:allowBackup="true"
android:fullBackupContent="@xml/backup_descriptor"
<meta-data android:icon="@mipmap/ic_launcher"
android:name="UPDATE_APP_KEY" android:label="@string/app_name"
android:value="SVSfseesfsf" /> android:requestLegacyExternalStorage="true"
<meta-data android:roundIcon="@mipmap/ic_launcher_round"
android:name="UMENG_APPKEY" android:supportsRtl="true"
android:value="60254fc7425ec25f10f4293e" /> android:theme="@style/AppTheme"
<meta-data android:usesCleartextTraffic="true">
android:name="UMENG_CHANNEL"
android:value="Umeng" /> <meta-data
android:name="UPDATE_APP_KEY"
<activity android:value="SVSfseesfsf" />
android:name=".MainActivity" <meta-data
tools:ignore="IntentFilterExportedReceiver"> android:name="UMENG_APPKEY"
<intent-filter> android:value="60254fc7425ec25f10f4293e" />
<action android:name="android.intent.action.MAIN" /> <meta-data
<category android:name="android.intent.category.LAUNCHER" /> android:name="UMENG_CHANNEL"
</intent-filter> android:value="Umeng" />
</activity>
<activity <activity
android:name=".AboutActivity" android:name=".MainActivity"
android:label="@string/about" tools:ignore="IntentFilterExportedReceiver">
tools:ignore="IntentFilterExportedReceiver"> <intent-filter>
<intent-filter> <action android:name="android.intent.action.MAIN" />
<!--协议部分,随便设置--> <category android:name="android.intent.category.LAUNCHER" />
<data </intent-filter>
android:scheme="forwarder" </activity>
android:host="main" /> <activity
<!--下面这几行也必须得设置--> android:name=".AboutActivity"
<category android:name="android.intent.category.DEFAULT" /> android:label="@string/about"
<action android:name="android.intent.action.VIEW" /> tools:ignore="IntentFilterExportedReceiver">
<category android:name="android.intent.category.BROWSABLE" /> <intent-filter>
</intent-filter> <!--协议部分,随便设置-->
</activity> <data
<activity android:host="main"
android:name=".SettingActivity" android:scheme="forwarder" />
android:label="@string/setting" /> <!--下面这几行也必须得设置-->
<activity <category android:name="android.intent.category.DEFAULT" />
android:name=".CloneActivity" <action android:name="android.intent.action.VIEW" />
android:label="@string/clone" /> <category android:name="android.intent.category.BROWSABLE" />
<activity </intent-filter>
android:name=".RuleActivity" </activity>
android:label="@string/rule_setting" /> <activity
<activity android:name=".SettingActivity"
android:name=".SenderActivity" android:label="@string/setting" />
android:label="@string/sender_setting" /> <activity
android:name=".CloneActivity"
<receiver android:label="@string/clone" />
android:name=".receiver.RebootBroadcastReceiver" <activity
tools:ignore="IntentFilterExportedReceiver"> android:name=".RuleActivity"
<intent-filter android:priority="2147483647"> android:label="@string/rule_setting" />
<!--重启广播--> <activity
<action android:name="android.intent.action.BOOT_COMPLETED" /> android:name=".SenderActivity"
</intent-filter> android:label="@string/sender_setting" />
</receiver>
<receiver <receiver
android:name=".receiver.SmsForwarderBroadcastReceiver" android:name=".receiver.RebootBroadcastReceiver"
android:permission="android.permission.BROADCAST_SMS" tools:ignore="IntentFilterExportedReceiver">
tools:ignore="IntentFilterExportedReceiver"> <intent-filter android:priority="2147483647">
<intent-filter android:priority="2147483647"> <action android:name="android.intent.action.BOOT_COMPLETED" />
<!--短信广播--> <action android:name="android.intent.action.USER_PRESENT" />
<action android:name="android.provider.Telephony.SMS_RECEIVED" /> <action android:name="android.intent.action.PACKAGE_RESTARTED" />
</intent-filter> </intent-filter>
</receiver> </receiver>
<receiver
<receiver android:name=".receiver.SmsForwarderBroadcastReceiver"
android:name=".receiver.PhoneStateReceiver" android:permission="android.permission.BROADCAST_SMS"
tools:ignore="IntentFilterExportedReceiver"> tools:ignore="IntentFilterExportedReceiver">
<intent-filter> <intent-filter android:priority="2147483647">
<action android:name="android.intent.action.PHONE_STATE" /> <!--短信广播-->
</intent-filter> <action android:name="android.provider.Telephony.SMS_RECEIVED" />
</receiver> </intent-filter>
</receiver>
<service android:name=".service.FrontService" /> <receiver
</application> android:name=".receiver.PhoneStateReceiver"
tools:ignore="IntentFilterExportedReceiver">
<intent-filter>
<action android:name="android.intent.action.PHONE_STATE" />
</intent-filter>
</receiver>
<service
android:name=".service.FrontService"
android:enabled="true" />
<service
android:name=".service.BatteryService"
android:enabled="true" />
<service
android:name=".service.NotifyService"
android:enabled="true"
android:label="@string/app_name"
android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE">
<intent-filter>
<action android:name="android.service.notification.NotificationListenerService" />
</intent-filter>
</service>
</application>
</manifest> </manifest>

View File

@ -1,247 +1,430 @@
package com.idormy.sms.forwarder; package com.idormy.sms.forwarder;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.content.Intent; import android.content.ComponentName;
import android.content.pm.PackageManager; import android.content.Context;
import android.os.Bundle; import android.content.Intent;
import android.os.Handler; import android.content.pm.PackageManager;
import android.util.Log; import android.os.Build;
import android.view.Menu; import android.os.Bundle;
import android.view.MenuInflater; import android.os.Handler;
import android.view.MenuItem; import android.os.PowerManager;
import android.view.View; import android.service.notification.StatusBarNotification;
import android.widget.TextView; import android.util.Log;
import android.widget.Toast; import android.view.Menu;
import android.view.MenuInflater;
import androidx.appcompat.app.AlertDialog; import android.view.MenuItem;
import androidx.appcompat.app.AppCompatActivity; import android.view.View;
import android.widget.TextView;
import com.idormy.sms.forwarder.adapter.LogAdapter; import android.widget.Toast;
import com.idormy.sms.forwarder.model.vo.LogVo;
import com.idormy.sms.forwarder.utils.LogUtil; import androidx.annotation.NonNull;
import com.idormy.sms.forwarder.utils.NetUtil; import androidx.annotation.RequiresApi;
import com.idormy.sms.forwarder.utils.PhoneUtils; import androidx.appcompat.app.AlertDialog;
import com.idormy.sms.forwarder.utils.SmsUtil; import androidx.appcompat.app.AppCompatActivity;
import com.idormy.sms.forwarder.utils.aUtil; import androidx.core.app.NotificationManagerCompat;
import java.util.ArrayList; import com.idormy.sms.forwarder.adapter.LogAdapter;
import java.util.List; import com.idormy.sms.forwarder.model.vo.LogVo;
import com.idormy.sms.forwarder.model.vo.SmsVo;
public class MainActivity extends AppCompatActivity implements RefreshListView.IRefreshListener { import com.idormy.sms.forwarder.notify.NotifyHelper;
import com.idormy.sms.forwarder.notify.NotifyListener;
private final String TAG = "MainActivity"; import com.idormy.sms.forwarder.sender.SendUtil;
// logVoList用于存储数据 import com.idormy.sms.forwarder.service.FrontService;
private List<LogVo> logVos = new ArrayList<>(); import com.idormy.sms.forwarder.service.NotifyService;
private LogAdapter adapter; import com.idormy.sms.forwarder.utils.LogUtil;
private RefreshListView listView; import com.idormy.sms.forwarder.utils.NetUtil;
import com.idormy.sms.forwarder.utils.PhoneUtils;
@Override import com.idormy.sms.forwarder.utils.SmsUtil;
protected void onCreate(Bundle savedInstanceState) { import com.idormy.sms.forwarder.utils.aUtil;
LogUtil.init(this); import java.text.SimpleDateFormat;
Log.d(TAG, "onCreate"); import java.util.ArrayList;
import java.util.Date;
super.onCreate(savedInstanceState); import java.util.List;
setContentView(R.layout.activity_main); import java.util.Locale;
import java.util.Set;
//检查权限是否获取
PackageManager pm = getPackageManager(); public class MainActivity extends AppCompatActivity implements NotifyListener, RefreshListView.IRefreshListener {
PhoneUtils.CheckPermission(pm, this);
private final String TAG = "MainActivity";
//获取SIM信息 private static final String ACTION_NOTIFICATION_LISTENER_SETTINGS = "android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS";
PhoneUtils.init(this); // logVoList用于存储数据
private List<LogVo> logVos = new ArrayList<>();
//短信&网络组件初始化 private LogAdapter adapter;
SmsUtil.init(this); private RefreshListView listView;
NetUtil.init(this); private Intent serviceIntent;
} private static final int REQUEST_CODE = 9999;
@Override @Override
protected void onStart() { protected void onCreate(Bundle savedInstanceState) {
super.onStart();
Log.d(TAG, "onStart"); LogUtil.init(this);
Log.d(TAG, "onCreate");
//是否关闭页面提示
TextView help_tip = findViewById(R.id.help_tip); super.onCreate(savedInstanceState);
help_tip.setVisibility(MyApplication.showHelpTip ? View.VISIBLE : View.GONE); setContentView(R.layout.activity_main);
// 先拿到数据并放在适配器上 //检查权限是否获取
initTLogs(); //初始化数据 PackageManager pm = getPackageManager();
showList(logVos); PhoneUtils.CheckPermission(pm, this);
// 为ListView注册一个监听器当用户点击了ListView中的任何一个子项时就会回调onItemClick()方法 //获取SIM信息
// 在这个方法中可以通过position参数判断出用户点击的是那一个子项 PhoneUtils.init(this);
listView.setOnItemClickListener((parent, view, position, id) -> {
if (position <= 0) return; //短信&网络组件初始化
SmsUtil.init(this);
LogVo logVo = logVos.get(position - 1); NetUtil.init(this);
logDetail(logVo);
}); //应用通知
NotifyHelper.getInstance().setNotifyListener(this);
listView.setOnItemLongClickListener((parent, view, position, id) -> {
if (position <= 0) return false; //前台服务
serviceIntent = new Intent(MainActivity.this, FrontService.class);
//定义AlertDialog.Builder对象当长按列表项的时候弹出确认删除对话框 serviceIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this); startService(serviceIntent);
builder.setTitle(R.string.delete_log_title); }
builder.setMessage(R.string.delete_log_tips);
@Override
//添加AlertDialog.Builder对象的setPositiveButton()方法 protected void onStart() {
builder.setPositiveButton(R.string.confirm, (dialog, which) -> { super.onStart();
Long id1 = logVos.get(position - 1).getId(); Log.d(TAG, "onStart");
Log.d(TAG, "id = " + id1);
LogUtil.delLog(id1, null); //是否关闭页面提示
initTLogs(); //初始化数据 TextView help_tip = findViewById(R.id.help_tip);
showList(logVos); help_tip.setVisibility(MyApplication.showHelpTip ? View.VISIBLE : View.GONE);
Toast.makeText(getBaseContext(), R.string.delete_log_toast, Toast.LENGTH_SHORT).show();
}); // 先拿到数据并放在适配器上
initTLogs(); //初始化数据
//添加AlertDialog.Builder对象的setNegativeButton()方法 showList(logVos);
builder.setNegativeButton(R.string.cancel, (dialog, which) -> {
}); // 为ListView注册一个监听器当用户点击了ListView中的任何一个子项时就会回调onItemClick()方法
// 在这个方法中可以通过position参数判断出用户点击的是那一个子项
builder.create().show(); listView.setOnItemClickListener((parent, view, position, id) -> {
return true; if (position <= 0) return;
});
} LogVo logVo = logVos.get(position - 1);
logDetail(logVo);
@Override });
protected void onResume() {
super.onResume(); listView.setOnItemLongClickListener((parent, view, position, id) -> {
//第一次打开未授权无法获取SIM信息尝试在此重新获取 if (position <= 0) return false;
if (MyApplication.SimInfoList.isEmpty()) {
MyApplication.SimInfoList = PhoneUtils.getSimMultiInfo(); //定义AlertDialog.Builder对象当长按列表项的时候弹出确认删除对话框
} AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
Log.d(TAG, "SimInfoList = " + MyApplication.SimInfoList.size()); builder.setTitle(R.string.delete_log_title);
} builder.setMessage(R.string.delete_log_tips);
// 初始化数据 //添加AlertDialog.Builder对象的setPositiveButton()方法
private void initTLogs() { builder.setPositiveButton(R.string.confirm, (dialog, which) -> {
logVos = LogUtil.getLog(null, null); Long id1 = logVos.get(position - 1).getId();
} Log.d(TAG, "id = " + id1);
LogUtil.delLog(id1, null);
private void showList(List<LogVo> logVosN) { initTLogs(); //初始化数据
Log.d(TAG, "showList: " + logVosN); showList(logVos);
if (adapter == null) { Toast.makeText(getBaseContext(), R.string.delete_log_toast, Toast.LENGTH_SHORT).show();
// 将适配器上的数据传递给listView });
listView = findViewById(R.id.list_view_log);
listView.setInterface(this); //添加AlertDialog.Builder对象的setNegativeButton()方法
adapter = new LogAdapter(MainActivity.this, R.layout.item_log, logVosN); builder.setNegativeButton(R.string.cancel, (dialog, which) -> {
});
listView.setAdapter(adapter);
} else { builder.create().show();
adapter.onDateChange(logVosN); return true;
} });
} }
@Override @SuppressLint("ObsoleteSdkInt")
public void onRefresh() { @Override
Handler handler = new Handler(); protected void onResume() {
handler.postDelayed(() -> { super.onResume();
// TODO Auto-generated method stub //第一次打开未授权无法获取SIM信息尝试在此重新获取
//获取最新数据 if (MyApplication.SimInfoList.isEmpty()) {
initTLogs(); MyApplication.SimInfoList = PhoneUtils.getSimMultiInfo();
//通知界面显示 }
showList(logVos); Log.d(TAG, "SimInfoList = " + MyApplication.SimInfoList.size());
//通知listview 刷新数据完毕
listView.refreshComplete(); //开启读取通知栏权限
}, 2000); if (!isNotificationListenerServiceEnabled(this)) {
} openNotificationAccess();
toggleNotificationListenerService();
Toast.makeText(this, "请先勾选《短信转发器》的读取通知栏权限!", Toast.LENGTH_LONG).show();
public void logDetail(LogVo logVo) { return;
AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this); }
builder.setTitle(R.string.details);
String simInfo = logVo.getSimInfo(); //省电优化设置为无限制
if (simInfo != null) { if (Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
builder.setMessage(logVo.getFrom() + "\n\n" + logVo.getContent() + "\n\n" + logVo.getSimInfo() + "\n\n" + logVo.getRule() + "\n\n" + aUtil.utc2Local(logVo.getTime()) + "\n\nResponse" + logVo.getForwardResponse()); if (!isIgnoringBatteryOptimizations()) {
} else { Toast.makeText(this, "请将省电优化设置为无限制,有利于防止《短信转发器》被杀!!", Toast.LENGTH_LONG).show();
builder.setMessage(logVo.getFrom() + "\n\n" + logVo.getContent() + "\n\n" + logVo.getRule() + "\n\n" + aUtil.utc2Local(logVo.getTime()) + "\n\nResponse" + logVo.getForwardResponse()); }
} }
//删除 startService(serviceIntent);
builder.setNegativeButton(R.string.del, (dialog, which) -> { }
Long id = logVo.getId();
Log.d(TAG, "id = " + id); @Override
LogUtil.delLog(id, null); protected void onDestroy() {
initTLogs(); //初始化数据 super.onDestroy();
showList(logVos); startService(serviceIntent);
Toast.makeText(MainActivity.this, R.string.delete_log_toast, Toast.LENGTH_SHORT).show(); }
dialog.dismiss();
}); @Override
builder.show(); protected void onPause() {
} //当界面返回到桌面之后.清除通知设置当中的数据.减少内存占有
//if (applicationList != null) {
public void toClone() { // applicationList.setAdapter(null);
Intent intent = new Intent(this, CloneActivity.class); // adapter = null;
startActivity(intent); //}
} super.onPause();
startService(serviceIntent);
public void toSetting() { }
Intent intent = new Intent(this, SettingActivity.class);
startActivity(intent); @Override
} protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
public void toAbout() { if (requestCode == REQUEST_CODE) {
Intent intent = new Intent(this, AboutActivity.class); if (isNotificationListenerServiceEnabled(this)) {
startActivity(intent); Toast.makeText(this, "通知服务已开启", Toast.LENGTH_SHORT).show();
} toggleNotificationListenerService();
} else {
public void toRuleSetting(View view) { Toast.makeText(this, "通知服务未开启", Toast.LENGTH_SHORT).show();
Intent intent = new Intent(this, RuleActivity.class); }
startActivity(intent); }
} }
public void toSendSetting(View view) { // 权限判断相关
Intent intent = new Intent(this, SenderActivity.class); @Override
startActivity(intent); public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
} super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
public void cleanLog(View view) {
AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this); public void toggleNotificationListenerService() {
builder.setTitle(R.string.clear_logs_tips) PackageManager pm = getPackageManager();
.setPositiveButton(R.string.confirm, (dialog, which) -> { pm.setComponentEnabledSetting(new ComponentName(getApplicationContext(), NotifyService.class),
// TODO Auto-generated method stub PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);
LogUtil.delLog(null, null);
initTLogs(); pm.setComponentEnabledSetting(new ComponentName(getApplicationContext(), NotifyService.class),
adapter.add(logVos); PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP);
}); }
builder.show();
} private static boolean isNotificationListenerServiceEnabled(Context context) {
Set<String> packageNames = NotificationManagerCompat.getEnabledListenerPackages(context);
//按返回键不退出回到桌面 return packageNames.contains(context.getPackageName());
@Override }
public void onBackPressed() {
Intent intent = new Intent(Intent.ACTION_MAIN); /**
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); * 判断系统是否已经关闭省电优化
intent.addCategory(Intent.CATEGORY_HOME); *
startActivity(intent); * @return boolean
} */
@RequiresApi(api = Build.VERSION_CODES.M)
@SuppressLint("NonConstantResourceId") private boolean isIgnoringBatteryOptimizations() {
@Override boolean isIgnoring = false;
public boolean onOptionsItemSelected(MenuItem item) { PowerManager powerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
// Handle item selection if (powerManager != null) {
switch (item.getItemId()) { isIgnoring = powerManager.isIgnoringBatteryOptimizations(getPackageName());
case R.id.to_clone: }
toClone(); if (!isIgnoring) {
return true; Intent i = new Intent(android.provider.Settings.ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS);
case R.id.to_setting: startActivity(i);
toSetting(); }
return true; return isIgnoring;
case R.id.to_about: }
toAbout();
return true; private void openNotificationAccess() {
default: startActivity(new Intent(ACTION_NOTIFICATION_LISTENER_SETTINGS));
return super.onOptionsItemSelected(item); }
}
}
// 初始化数据
@Override private void initTLogs() {
public boolean onCreateOptionsMenu(Menu menu) { logVos = LogUtil.getLog(null, null);
MenuInflater inflater = getMenuInflater(); }
inflater.inflate(R.menu.menu_main, menu);
return true; private void showList(List<LogVo> logVosN) {
Log.d(TAG, "showList: " + logVosN);
} if (adapter == null) {
// 将适配器上的数据传递给listView
} listView = findViewById(R.id.list_view_log);
listView.setInterface(this);
adapter = new LogAdapter(MainActivity.this, R.layout.item_log, logVosN);
listView.setAdapter(adapter);
} else {
adapter.onDateChange(logVosN);
}
}
@Override
public void onRefresh() {
Handler handler = new Handler();
handler.postDelayed(() -> {
// TODO Auto-generated method stub
//获取最新数据
initTLogs();
//通知界面显示
showList(logVos);
//通知listview 刷新数据完毕
listView.refreshComplete();
}, 2000);
}
public void logDetail(LogVo logVo) {
AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
builder.setTitle(R.string.details);
String simInfo = logVo.getSimInfo();
if (simInfo != null) {
builder.setMessage(logVo.getFrom() + "\n\n" + logVo.getContent() + "\n\n" + logVo.getSimInfo() + "\n\n" + logVo.getRule() + "\n\n" + aUtil.utc2Local(logVo.getTime()) + "\n\nResponse" + logVo.getForwardResponse());
} else {
builder.setMessage(logVo.getFrom() + "\n\n" + logVo.getContent() + "\n\n" + logVo.getRule() + "\n\n" + aUtil.utc2Local(logVo.getTime()) + "\n\nResponse" + logVo.getForwardResponse());
}
//删除
builder.setNegativeButton(R.string.del, (dialog, which) -> {
Long id = logVo.getId();
Log.d(TAG, "id = " + id);
LogUtil.delLog(id, null);
initTLogs(); //初始化数据
showList(logVos);
Toast.makeText(MainActivity.this, R.string.delete_log_toast, Toast.LENGTH_SHORT).show();
dialog.dismiss();
});
builder.show();
}
public void toClone() {
Intent intent = new Intent(this, CloneActivity.class);
startActivity(intent);
}
public void toSetting() {
Intent intent = new Intent(this, SettingActivity.class);
startActivity(intent);
}
public void toAbout() {
Intent intent = new Intent(this, AboutActivity.class);
startActivity(intent);
}
public void toRuleSetting(View view) {
Intent intent = new Intent(this, RuleActivity.class);
startActivity(intent);
}
public void toSendSetting(View view) {
Intent intent = new Intent(this, SenderActivity.class);
startActivity(intent);
}
public void cleanLog(View view) {
AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
builder.setTitle(R.string.clear_logs_tips)
.setPositiveButton(R.string.confirm, (dialog, which) -> {
// TODO Auto-generated method stub
LogUtil.delLog(null, null);
initTLogs();
adapter.add(logVos);
});
builder.show();
}
//按返回键不退出回到桌面
@Override
public void onBackPressed() {
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addCategory(Intent.CATEGORY_HOME);
startActivity(intent);
}
@SuppressLint("NonConstantResourceId")
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle item selection
switch (item.getItemId()) {
case R.id.to_clone:
toClone();
return true;
case R.id.to_setting:
toSetting();
return true;
case R.id.to_about:
toAbout();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu_main, menu);
return true;
}
/**
* 收到通知
*
* @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;
//推送通知的应用包名
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);
}
/**
* 移除掉通知栏消息
*
* @param sbn 状态栏通知
*/
@Override
public void onRemovedMessage(StatusBarNotification sbn) {
Log.d(TAG, "移除掉通知栏消息");
}
}

View File

@ -1,288 +1,356 @@
package com.idormy.sms.forwarder; package com.idormy.sms.forwarder;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.os.Bundle; import android.content.ComponentName;
import android.text.Editable; import android.content.Intent;
import android.text.TextWatcher; import android.content.pm.PackageManager;
import android.util.Log; import android.os.Bundle;
import android.view.View; import android.text.Editable;
import android.widget.EditText; import android.text.TextWatcher;
import android.widget.LinearLayout; import android.util.Log;
import android.widget.Switch; import android.view.View;
import android.widget.Toast; import android.widget.EditText;
import android.widget.LinearLayout;
import androidx.appcompat.app.AppCompatActivity; import android.widget.Switch;
import android.widget.TextView;
import com.idormy.sms.forwarder.utils.KeepAliveUtils; import android.widget.Toast;
import com.idormy.sms.forwarder.utils.SettingUtil;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.NotificationManagerCompat;
public class SettingActivity extends AppCompatActivity {
private final String TAG = "SettingActivity"; import com.idormy.sms.forwarder.service.NotifyService;
import com.idormy.sms.forwarder.utils.KeepAliveUtils;
@Override import com.idormy.sms.forwarder.utils.SettingUtil;
public void onCreate(Bundle savedInstanceState) {
Log.d(TAG, "onCreate"); import java.util.Set;
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_setting); public class SettingActivity extends AppCompatActivity {
private final String TAG = "SettingActivity";
EditText et_add_extra_device_mark = findViewById(R.id.et_add_extra_device_mark);
editAddExtraDeviceMark(et_add_extra_device_mark); private static final int REQUEST_CODE = 9527;
private TextView textView;
EditText et_add_extra_sim1 = findViewById(R.id.et_add_extra_sim1);
editAddExtraSim1(et_add_extra_sim1); @Override
public void onCreate(Bundle savedInstanceState) {
EditText et_add_extra_sim2 = findViewById(R.id.et_add_extra_sim2); Log.d(TAG, "onCreate");
editAddExtraSim2(et_add_extra_sim2); super.onCreate(savedInstanceState);
setContentView(R.layout.activity_setting);
EditText et_battery_level_alarm = findViewById(R.id.et_battery_level_alarm);
editBatteryLevelAlarm(et_battery_level_alarm); EditText et_add_extra_device_mark = findViewById(R.id.et_add_extra_device_mark);
editAddExtraDeviceMark(et_add_extra_device_mark);
EditText et_retry_delay_time1 = findViewById(R.id.et_retry_delay_time1);
editRetryDelayTime(et_retry_delay_time1, 1); EditText et_add_extra_sim1 = findViewById(R.id.et_add_extra_sim1);
EditText et_retry_delay_time2 = findViewById(R.id.et_retry_delay_time2); editAddExtraSim1(et_add_extra_sim1);
editRetryDelayTime(et_retry_delay_time2, 2);
EditText et_retry_delay_time3 = findViewById(R.id.et_retry_delay_time3); EditText et_add_extra_sim2 = findViewById(R.id.et_add_extra_sim2);
editRetryDelayTime(et_retry_delay_time3, 3); editAddExtraSim2(et_add_extra_sim2);
EditText et_retry_delay_time4 = findViewById(R.id.et_retry_delay_time4);
editRetryDelayTime(et_retry_delay_time4, 4); EditText et_battery_level_alarm = findViewById(R.id.et_battery_level_alarm);
EditText et_retry_delay_time5 = findViewById(R.id.et_retry_delay_time5); editBatteryLevelAlarm(et_battery_level_alarm);
editRetryDelayTime(et_retry_delay_time5, 5);
EditText et_retry_delay_time1 = findViewById(R.id.et_retry_delay_time1);
@SuppressLint("UseSwitchCompatOrMaterialCode") Switch switch_sms_template = findViewById(R.id.switch_sms_template); editRetryDelayTime(et_retry_delay_time1, 1);
switchSmsTemplate(switch_sms_template); EditText et_retry_delay_time2 = findViewById(R.id.et_retry_delay_time2);
editRetryDelayTime(et_retry_delay_time2, 2);
@SuppressLint("UseSwitchCompatOrMaterialCode") Switch switch_enable_phone = findViewById(R.id.switch_enable_phone); EditText et_retry_delay_time3 = findViewById(R.id.et_retry_delay_time3);
switchEnablePhone(switch_enable_phone); editRetryDelayTime(et_retry_delay_time3, 3);
EditText et_retry_delay_time4 = findViewById(R.id.et_retry_delay_time4);
EditText textSmsTemplate = findViewById(R.id.text_sms_template); editRetryDelayTime(et_retry_delay_time4, 4);
editSmsTemplate(textSmsTemplate); EditText et_retry_delay_time5 = findViewById(R.id.et_retry_delay_time5);
} editRetryDelayTime(et_retry_delay_time5, 5);
//设置转发来电 @SuppressLint("UseSwitchCompatOrMaterialCode") Switch switch_sms_template = findViewById(R.id.switch_sms_template);
private void switchEnablePhone(@SuppressLint("UseSwitchCompatOrMaterialCode") Switch switch_enable_phone) { switchSmsTemplate(switch_sms_template);
switch_enable_phone.setChecked(SettingUtil.getSwitchEnablePhone());
@SuppressLint("UseSwitchCompatOrMaterialCode") Switch switch_enable_phone = findViewById(R.id.switch_enable_phone);
switch_enable_phone.setOnCheckedChangeListener((buttonView, isChecked) -> { switchEnablePhone(switch_enable_phone);
SettingUtil.switchEnablePhone(isChecked);
Log.d(TAG, "onCheckedChanged:" + isChecked); EditText textSmsTemplate = findViewById(R.id.text_sms_template);
}); editSmsTemplate(textSmsTemplate);
} }
//设置设备名称 //设置转发来电
private void editAddExtraDeviceMark(final EditText et_add_extra_device_mark) { private void switchEnablePhone(@SuppressLint("UseSwitchCompatOrMaterialCode") Switch switch_enable_phone) {
et_add_extra_device_mark.setText(SettingUtil.getAddExtraDeviceMark()); switch_enable_phone.setChecked(SettingUtil.getSwitchEnablePhone());
et_add_extra_device_mark.addTextChangedListener(new TextWatcher() { switch_enable_phone.setOnCheckedChangeListener((buttonView, isChecked) -> {
@Override SettingUtil.switchEnablePhone(isChecked);
public void beforeTextChanged(CharSequence s, int start, int count, int after) { Log.d(TAG, "onCheckedChanged:" + isChecked);
});
} }
@Override //设置设备名称
public void onTextChanged(CharSequence s, int start, int before, int count) { private void editAddExtraDeviceMark(final EditText et_add_extra_device_mark) {
et_add_extra_device_mark.setText(SettingUtil.getAddExtraDeviceMark());
}
et_add_extra_device_mark.addTextChangedListener(new TextWatcher() {
@Override @Override
public void afterTextChanged(Editable s) { public void beforeTextChanged(CharSequence s, int start, int count, int after) {
SettingUtil.setAddExtraDeviceMark(et_add_extra_device_mark.getText().toString());
} }
});
} @Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
//设置SIM1备注
private void editAddExtraSim1(final EditText et_add_extra_sim1) { }
et_add_extra_sim1.setText(SettingUtil.getAddExtraSim1());
@Override
et_add_extra_sim1.addTextChangedListener(new TextWatcher() { public void afterTextChanged(Editable s) {
@Override SettingUtil.setAddExtraDeviceMark(et_add_extra_device_mark.getText().toString());
public void beforeTextChanged(CharSequence s, int start, int count, int after) { }
});
} }
@Override //设置SIM1备注
public void onTextChanged(CharSequence s, int start, int before, int count) { private void editAddExtraSim1(final EditText et_add_extra_sim1) {
et_add_extra_sim1.setText(SettingUtil.getAddExtraSim1());
}
et_add_extra_sim1.addTextChangedListener(new TextWatcher() {
@Override @Override
public void afterTextChanged(Editable s) { public void beforeTextChanged(CharSequence s, int start, int count, int after) {
SettingUtil.setAddExtraSim1(et_add_extra_sim1.getText().toString());
} }
});
} @Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
//设置SIM2备注
private void editAddExtraSim2(final EditText et_add_extra_sim2) { }
et_add_extra_sim2.setText(SettingUtil.getAddExtraSim2());
@Override
et_add_extra_sim2.addTextChangedListener(new TextWatcher() { public void afterTextChanged(Editable s) {
@Override SettingUtil.setAddExtraSim1(et_add_extra_sim1.getText().toString());
public void beforeTextChanged(CharSequence s, int start, int count, int after) { }
});
} }
@Override //设置SIM2备注
public void onTextChanged(CharSequence s, int start, int before, int count) { private void editAddExtraSim2(final EditText et_add_extra_sim2) {
et_add_extra_sim2.setText(SettingUtil.getAddExtraSim2());
}
et_add_extra_sim2.addTextChangedListener(new TextWatcher() {
@Override @Override
public void afterTextChanged(Editable s) { public void beforeTextChanged(CharSequence s, int start, int count, int after) {
SettingUtil.setAddExtraSim2(et_add_extra_sim2.getText().toString());
} }
});
} @Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
//设置低电量报警值
private void editBatteryLevelAlarm(final EditText et_battery_level_alarm) { }
et_battery_level_alarm.setText(String.valueOf(SettingUtil.getBatteryLevelAlarm()));
@Override
et_battery_level_alarm.addTextChangedListener(new TextWatcher() { public void afterTextChanged(Editable s) {
@Override SettingUtil.setAddExtraSim2(et_add_extra_sim2.getText().toString());
public void beforeTextChanged(CharSequence s, int start, int count, int after) { }
} });
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) { //设置低电量报警值
} private void editBatteryLevelAlarm(final EditText et_battery_level_alarm) {
et_battery_level_alarm.setText(String.valueOf(SettingUtil.getBatteryLevelAlarm()));
@Override
public void afterTextChanged(Editable s) { et_battery_level_alarm.addTextChangedListener(new TextWatcher() {
String batteryLevel = et_battery_level_alarm.getText().toString(); @Override
if (!batteryLevel.isEmpty()) { public void beforeTextChanged(CharSequence s, int start, int count, int after) {
SettingUtil.setBatteryLevelAlarm(Integer.parseInt(batteryLevel)); }
} else {
SettingUtil.setBatteryLevelAlarm(0); @Override
} public void onTextChanged(CharSequence s, int start, int before, int count) {
} }
});
} @Override
public void afterTextChanged(Editable s) {
String batteryLevel = et_battery_level_alarm.getText().toString();
//接口请求失败重试 if (!batteryLevel.isEmpty()) {
private void editRetryDelayTime(final EditText et_retry_delay_time, final int index) { SettingUtil.setBatteryLevelAlarm(Integer.parseInt(batteryLevel));
et_retry_delay_time.setText(String.valueOf(SettingUtil.getRetryDelayTime(index))); } else {
SettingUtil.setBatteryLevelAlarm(0);
et_retry_delay_time.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) { //接口请求失败重试
} private void editRetryDelayTime(final EditText et_retry_delay_time, final int index) {
et_retry_delay_time.setText(String.valueOf(SettingUtil.getRetryDelayTime(index)));
@Override
public void afterTextChanged(Editable s) { et_retry_delay_time.addTextChangedListener(new TextWatcher() {
String delayTime = et_retry_delay_time.getText().toString(); @Override
if (!delayTime.isEmpty()) { public void beforeTextChanged(CharSequence s, int start, int count, int after) {
SettingUtil.setRetryDelayTime(index, Integer.parseInt(delayTime)); }
} else {
SettingUtil.setRetryDelayTime(index, 0); @Override
} public void onTextChanged(CharSequence s, int start, int before, int count) {
} }
});
} @Override
public void afterTextChanged(Editable s) {
//设置转发时启用自定义模版 String delayTime = et_retry_delay_time.getText().toString();
private void switchSmsTemplate(@SuppressLint("UseSwitchCompatOrMaterialCode") Switch switch_sms_template) { if (!delayTime.isEmpty()) {
boolean isOn = SettingUtil.getSwitchSmsTemplate(); SettingUtil.setRetryDelayTime(index, Integer.parseInt(delayTime));
switch_sms_template.setChecked(isOn); } else {
SettingUtil.setRetryDelayTime(index, 0);
final LinearLayout layout_sms_template = findViewById(R.id.layout_sms_template); }
layout_sms_template.setVisibility(isOn ? View.VISIBLE : View.GONE); }
final EditText textSmsTemplate = findViewById(R.id.text_sms_template); });
}
switch_sms_template.setOnCheckedChangeListener((buttonView, isChecked) -> {
Log.d(TAG, "onCheckedChanged:" + isChecked); //设置转发时启用自定义模版
layout_sms_template.setVisibility(isChecked ? View.VISIBLE : View.GONE); private void switchSmsTemplate(@SuppressLint("UseSwitchCompatOrMaterialCode") Switch switch_sms_template) {
SettingUtil.switchSmsTemplate(isChecked); boolean isOn = SettingUtil.getSwitchSmsTemplate();
if (!isChecked) { switch_sms_template.setChecked(isOn);
textSmsTemplate.setText("{{来源号码}}\n{{短信内容}}\n{{卡槽信息}}\n{{接收时间}}\n{{设备名称}}");
} final LinearLayout layout_sms_template = findViewById(R.id.layout_sms_template);
}); layout_sms_template.setVisibility(isOn ? View.VISIBLE : View.GONE);
} final EditText textSmsTemplate = findViewById(R.id.text_sms_template);
//设置转发信息模版 switch_sms_template.setOnCheckedChangeListener((buttonView, isChecked) -> {
private void editSmsTemplate(final EditText textSmsTemplate) { Log.d(TAG, "onCheckedChanged:" + isChecked);
textSmsTemplate.setText(SettingUtil.getSmsTemplate()); layout_sms_template.setVisibility(isChecked ? View.VISIBLE : View.GONE);
SettingUtil.switchSmsTemplate(isChecked);
textSmsTemplate.addTextChangedListener(new TextWatcher() { if (!isChecked) {
@Override textSmsTemplate.setText("{{来源号码}}\n{{短信内容}}\n{{卡槽信息}}\n{{接收时间}}\n{{设备名称}}");
public void beforeTextChanged(CharSequence s, int start, int count, int after) { }
});
} }
@Override //设置转发信息模版
public void onTextChanged(CharSequence s, int start, int before, int count) { private void editSmsTemplate(final EditText textSmsTemplate) {
textSmsTemplate.setText(SettingUtil.getSmsTemplate());
}
textSmsTemplate.addTextChangedListener(new TextWatcher() {
@Override @Override
public void afterTextChanged(Editable s) { public void beforeTextChanged(CharSequence s, int start, int count, int after) {
SettingUtil.setSmsTemplate(textSmsTemplate.getText().toString());
} }
});
} @Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
//插入标签
@SuppressLint("NonConstantResourceId") }
public void toInsertLabel(View v) {
EditText textSmsTemplate = findViewById(R.id.text_sms_template); @Override
textSmsTemplate.setFocusable(true); public void afterTextChanged(Editable s) {
textSmsTemplate.requestFocus(); SettingUtil.setSmsTemplate(textSmsTemplate.getText().toString());
switch (v.getId()) { }
case R.id.bt_insert_sender: });
textSmsTemplate.append("{{来源号码}}"); }
return;
case R.id.bt_insert_content: //插入标签
textSmsTemplate.append("{{短信内容}}"); @SuppressLint("NonConstantResourceId")
return; public void toInsertLabel(View v) {
case R.id.bt_insert_extra: EditText textSmsTemplate = findViewById(R.id.text_sms_template);
textSmsTemplate.append("{{卡槽信息}}"); textSmsTemplate.setFocusable(true);
return; textSmsTemplate.requestFocus();
case R.id.bt_insert_time: switch (v.getId()) {
textSmsTemplate.append("{{接收时间}}"); case R.id.bt_insert_sender:
return; textSmsTemplate.append("{{来源号码}}");
case R.id.bt_insert_device_name: return;
textSmsTemplate.append("{{设备名称}}"); case R.id.bt_insert_content:
return; textSmsTemplate.append("{{短信内容}}");
default: return;
} case R.id.bt_insert_extra:
} textSmsTemplate.append("{{卡槽信息}}");
return;
//恢复初始化配置 case R.id.bt_insert_time:
public void initSetting(View view) { textSmsTemplate.append("{{接收时间}}");
return;
EditText et_add_extra_device_mark = findViewById(R.id.et_add_extra_device_mark); case R.id.bt_insert_device_name:
et_add_extra_device_mark.setText(""); textSmsTemplate.append("{{设备名称}}");
editAddExtraDeviceMark(et_add_extra_device_mark); return;
default:
EditText et_add_extra_sim1 = findViewById(R.id.et_add_extra_sim1); }
et_add_extra_sim1.setText(""); }
editAddExtraSim1(et_add_extra_sim1);
//恢复初始化配置
EditText et_add_extra_sim2 = findViewById(R.id.et_add_extra_sim2); public void initSetting(View view) {
et_add_extra_sim2.setText("");
editAddExtraSim2(et_add_extra_sim2); EditText et_add_extra_device_mark = findViewById(R.id.et_add_extra_device_mark);
et_add_extra_device_mark.setText("");
@SuppressLint("UseSwitchCompatOrMaterialCode") Switch switch_sms_template = findViewById(R.id.switch_sms_template); editAddExtraDeviceMark(et_add_extra_device_mark);
switch_sms_template.setChecked(false);
switchSmsTemplate(switch_sms_template); EditText et_add_extra_sim1 = findViewById(R.id.et_add_extra_sim1);
et_add_extra_sim1.setText("");
EditText textSmsTemplate = findViewById(R.id.text_sms_template); editAddExtraSim1(et_add_extra_sim1);
textSmsTemplate.setText("{{来源号码}}\n{{短信内容}}\n{{卡槽信息}}\n{{接收时间}}\n{{设备名称}}");
editSmsTemplate(textSmsTemplate); EditText et_add_extra_sim2 = findViewById(R.id.et_add_extra_sim2);
et_add_extra_sim2.setText("");
} editAddExtraSim2(et_add_extra_sim2);
public void batterySetting(View view) { @SuppressLint("UseSwitchCompatOrMaterialCode") Switch switch_sms_template = findViewById(R.id.switch_sms_template);
if (KeepAliveUtils.isIgnoreBatteryOptimization(this)) { switch_sms_template.setChecked(false);
Toast.makeText(this, R.string.isIgnored, Toast.LENGTH_SHORT).show(); switchSmsTemplate(switch_sms_template);
} else {
KeepAliveUtils.ignoreBatteryOptimization(this); EditText textSmsTemplate = findViewById(R.id.text_sms_template);
} textSmsTemplate.setText("{{来源号码}}\n{{短信内容}}\n{{卡槽信息}}\n{{接收时间}}\n{{设备名称}}");
} editSmsTemplate(textSmsTemplate);
}
}
public void batterySetting(View view) {
if (KeepAliveUtils.isIgnoreBatteryOptimization(this)) {
Toast.makeText(this, R.string.isIgnored, Toast.LENGTH_SHORT).show();
} else {
KeepAliveUtils.ignoreBatteryOptimization(this);
}
}
/**
* 请求权限
*
* @param view 控件
*/
public void requestPermission(View view) {
if (!isNLServiceEnabled()) {
Intent intent = new Intent("android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS");
startActivityForResult(intent, REQUEST_CODE);
} else {
showMsg("通知服务已开启");
toggleNotificationListenerService();
}
}
/**
* 是否启用通知监听服务
*
* @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();
} else {
showMsg("通知服务未开启");
}
}
}
private void showMsg(String msg) {
Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
}
}

View File

@ -0,0 +1,76 @@
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;
}
}

View File

@ -0,0 +1,34 @@
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);
}

View File

@ -76,7 +76,7 @@ public class SendUtil {
public static void sendMsgByRuleModelSenderId(final Handler handError, RuleModel ruleModel, SmsVo smsVo, Long senderId) throws Exception { public static void sendMsgByRuleModelSenderId(final Handler handError, RuleModel ruleModel, SmsVo smsVo, Long senderId) throws Exception {
if (senderId == null) { if (senderId == null) {
throw new Exception("先新建并选择发送"); throw new Exception("先新建并选择发送通道");
} }
String testSim = smsVo.getSimInfo().substring(0, 4); String testSim = smsVo.getSimInfo().substring(0, 4);
@ -92,7 +92,7 @@ public class SendUtil {
List<SenderModel> senderModels = SenderUtil.getSender(senderId, null); List<SenderModel> senderModels = SenderUtil.getSender(senderId, null);
if (senderModels.isEmpty()) { if (senderModels.isEmpty()) {
throw new Exception("未找到发送"); throw new Exception("未找到发送通道");
} }
for (SenderModel senderModel : senderModels for (SenderModel senderModel : senderModels

View File

@ -1,111 +1,109 @@
package com.idormy.sms.forwarder.service; package com.idormy.sms.forwarder.service;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.app.Service; import android.app.Service;
import android.content.BroadcastReceiver; import android.content.BroadcastReceiver;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.IntentFilter; import android.content.IntentFilter;
import android.os.BatteryManager; import android.os.BatteryManager;
import android.os.IBinder; import android.os.IBinder;
import android.util.Log; import android.util.Log;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
public class BatteryService extends Service { public class BatteryService extends Service {
private static final String TAG = "BatteryReceiver"; private static final String TAG = "BatteryReceiver";
@Override @Override
public IBinder onBind(Intent intent) { public IBinder onBind(Intent intent) {
return null; return null;
} }
@Override @Override
public void onCreate() { public void onCreate() {
super.onCreate(); super.onCreate();
Log.i(TAG, "onCreate--------------"); Log.i(TAG, "onCreate--------------");
IntentFilter batteryFilter = new IntentFilter(); IntentFilter batteryFilter = new IntentFilter();
batteryFilter.addAction(Intent.ACTION_BATTERY_CHANGED); batteryFilter.addAction(Intent.ACTION_BATTERY_CHANGED);
registerReceiver(batteryReceiver, batteryFilter); registerReceiver(batteryReceiver, batteryFilter);
} }
@Override @Override
public void onStart(Intent intent, int startId) { public void onStart(Intent intent, int startId) {
super.onStart(intent, startId); super.onStart(intent, startId);
} }
@Override @Override
public int onStartCommand(Intent intent, int flags, int startId) { public int onStartCommand(Intent intent, int flags, int startId) {
Log.i(TAG, "onStartCommand--------------"); Log.i(TAG, "onStartCommand--------------");
return Service.START_STICKY; //保证service不被杀死 return Service.START_STICKY; //保证service不被杀死
} }
@Override @Override
public void onDestroy() { public void onDestroy() {
Log.i(TAG, "onDestroy--------------"); Log.i(TAG, "onDestroy--------------");
super.onDestroy(); super.onDestroy();
this.unregisterReceiver(batteryReceiver); this.unregisterReceiver(batteryReceiver);
}
}
// 接收电池信息更新的广播
// 接收电池信息更新的广播 private final BroadcastReceiver batteryReceiver = new BroadcastReceiver() {
private final BroadcastReceiver batteryReceiver = new BroadcastReceiver() { @SuppressWarnings("unused")
@SuppressWarnings("unused") @Override
@Override public void onReceive(Context context, Intent intent) {
public void onReceive(Context context, Intent intent) { Log.i(TAG, "BatteryReceiver--------------");
Log.i(TAG, "BatteryReceiver--------------"); String action = intent.getAction();
String action = intent.getAction(); Log.i(TAG, " 0 action:" + action);
Log.i(TAG, " 0 action:" + action); Log.i(TAG, "ACTION_BATTERY_CHANGED");
Log.i(TAG, "ACTION_BATTERY_CHANGED"); int status = intent.getIntExtra("status", 0);
int status = intent.getIntExtra("status", 0); int health = intent.getIntExtra("health", 0);
int health = intent.getIntExtra("health", 0); boolean present = intent.getBooleanExtra("present", false);
boolean present = intent.getBooleanExtra("present", false); int level = intent.getIntExtra("level", 0);
int level = intent.getIntExtra("level", 0); int scale = intent.getIntExtra("scale", 0);
int scale = intent.getIntExtra("scale", 0); int icon_small = intent.getIntExtra("icon-small", 0);
int icon_small = intent.getIntExtra("icon-small", 0); int plugged = intent.getIntExtra("plugged", 0);
int plugged = intent.getIntExtra("plugged", 0); int voltage = intent.getIntExtra("voltage", 0);
int voltage = intent.getIntExtra("voltage", 0); int temperature = intent.getIntExtra("temperature", 0);
int temperature = intent.getIntExtra("temperature", 0); String technology = intent.getStringExtra("technology");
String technology = intent.getStringExtra("technology");
String statusString = "";
String statusString = ""; switch (status) {
switch (status) { case BatteryManager.BATTERY_STATUS_UNKNOWN:
case BatteryManager.BATTERY_STATUS_UNKNOWN: statusString = "unknown";
statusString = "unknown"; break;
break; case BatteryManager.BATTERY_STATUS_CHARGING:
case BatteryManager.BATTERY_STATUS_CHARGING: statusString = "charging";
statusString = "charging"; break;
break; case BatteryManager.BATTERY_STATUS_DISCHARGING:
case BatteryManager.BATTERY_STATUS_DISCHARGING: statusString = "discharging";
statusString = "discharging"; break;
break; case BatteryManager.BATTERY_STATUS_NOT_CHARGING:
case BatteryManager.BATTERY_STATUS_NOT_CHARGING: statusString = "not charging";
statusString = "not charging"; break;
break; case BatteryManager.BATTERY_STATUS_FULL:
case BatteryManager.BATTERY_STATUS_FULL: statusString = "full";
statusString = "full"; break;
break; }
} String acString = "";
String acString = "";
switch (plugged) {
switch (plugged) { case BatteryManager.BATTERY_PLUGGED_AC:
case BatteryManager.BATTERY_PLUGGED_AC: acString = "plugged ac";
acString = "plugged ac"; break;
break; case BatteryManager.BATTERY_PLUGGED_USB:
case BatteryManager.BATTERY_PLUGGED_USB: acString = "plugged usb";
acString = "plugged usb"; break;
break; }
}
@SuppressLint("SimpleDateFormat") SimpleDateFormat sDateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss:SSS ");
@SuppressLint("SimpleDateFormat") SimpleDateFormat sDateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss:SSS "); String date = sDateFormat.format(new java.util.Date());
String date = sDateFormat.format(new java.util.Date());
Log.i(TAG, "battery: date=" + date + ",status " + statusString
Log.i(TAG, "battery: date=" + date + ",status " + statusString + ",level=" + level + ",scale=" + scale
+ ",level=" + level + ",scale=" + scale + ",voltage=" + voltage + ",acString=" + acString);
+ ",voltage=" + voltage + ",acString=" + acString); }
};
} }
};
}

View File

@ -1,142 +1,174 @@
package com.idormy.sms.forwarder.service; package com.idormy.sms.forwarder.service;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.app.Notification; import android.app.Notification;
import android.app.NotificationChannel; import android.app.NotificationChannel;
import android.app.NotificationManager; import android.app.NotificationManager;
import android.app.PendingIntent; import android.app.PendingIntent;
import android.app.Service; import android.app.Service;
import android.content.Context; import android.content.ComponentName;
import android.content.ContextWrapper; import android.content.Context;
import android.content.Intent; import android.content.ContextWrapper;
import android.content.IntentFilter; import android.content.Intent;
import android.os.BatteryManager; import android.content.IntentFilter;
import android.os.Build; import android.content.pm.PackageManager;
import android.os.IBinder; import android.os.BatteryManager;
import android.util.Log; import android.os.Build;
import android.os.IBinder;
import androidx.annotation.Nullable; import android.util.Log;
import com.idormy.sms.forwarder.MainActivity; import androidx.annotation.Nullable;
import com.idormy.sms.forwarder.MyApplication; import androidx.core.app.NotificationManagerCompat;
import com.idormy.sms.forwarder.R;
import com.idormy.sms.forwarder.model.vo.SmsVo; import com.idormy.sms.forwarder.MainActivity;
import com.idormy.sms.forwarder.sender.SendUtil; import com.idormy.sms.forwarder.MyApplication;
import com.idormy.sms.forwarder.sender.SenderUtil; import com.idormy.sms.forwarder.R;
import com.idormy.sms.forwarder.utils.PhoneUtils; import com.idormy.sms.forwarder.model.vo.SmsVo;
import com.idormy.sms.forwarder.utils.SettingUtil; import com.idormy.sms.forwarder.sender.SendUtil;
import com.idormy.sms.forwarder.sender.SenderUtil;
import java.util.Date; import com.idormy.sms.forwarder.utils.PhoneUtils;
import java.util.Timer; import com.idormy.sms.forwarder.utils.SettingUtil;
import java.util.TimerTask;
import java.util.Date;
import java.util.Set;
public class FrontService extends Service { import java.util.Timer;
private static final String TAG = "FrontService"; import java.util.TimerTask;
private static final String CHANNEL_ONE_ID = "com.idormy.sms.forwarder";
private static final String CHANNEL_ONE_NAME = "com.idormy.sms.forwarderName"; public class FrontService extends Service {
private static final String TAG = "FrontService";
@SuppressLint("IconColors") private static final String CHANNEL_ONE_ID = "com.idormy.sms.forwarder";
@Override private static final String CHANNEL_ONE_NAME = "com.idormy.sms.forwarderName";
public void onCreate() { private static final String ACTION_NOTIFICATION_LISTENER_SETTINGS = "android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS";
super.onCreate();
Log.i(TAG, "onCreate"); @SuppressLint("IconColors")
Notification.Builder builder = new Notification.Builder(this); @Override
builder.setSmallIcon(R.drawable.ic_forwarder); public void onCreate() {
//OSUtils.ROM_TYPE romType = OSUtils.getRomType(); super.onCreate();
//Log.d(TAG, "onCreate: " + romType); Log.i(TAG, "onCreate");
//if (romType == OSUtils.ROM_TYPE.MIUI_ROM) { Notification.Builder builder = new Notification.Builder(this);
builder.setContentTitle(getString(R.string.app_name)); builder.setSmallIcon(R.drawable.ic_forwarder);
//} builder.setContentTitle(getString(R.string.app_name));
builder.setContentText(getString(R.string.notification_content)); builder.setContentText(getString(R.string.notification_content));
Intent intent = new Intent(this, MainActivity.class); Intent intent = new Intent(this, MainActivity.class);
@SuppressLint("UnspecifiedImmutableFlag") PendingIntent pendingIntent = PendingIntent.getActivity @SuppressLint("UnspecifiedImmutableFlag") PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); builder.setContentIntent(pendingIntent);
builder.setContentIntent(pendingIntent);
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) { //修改安卓8.1以上系统报错
//修改安卓8.1以上系统报错 NotificationChannel notificationChannel = new NotificationChannel(CHANNEL_ONE_ID, CHANNEL_ONE_NAME, NotificationManager.IMPORTANCE_MIN);
NotificationChannel notificationChannel = new NotificationChannel(CHANNEL_ONE_ID, CHANNEL_ONE_NAME, NotificationManager.IMPORTANCE_MIN); notificationChannel.enableLights(false);//如果使用中的设备支持通知灯则说明此通知通道是否应显示灯
notificationChannel.enableLights(false);//如果使用中的设备支持通知灯则说明此通知通道是否应显示灯 notificationChannel.setShowBadge(false);//是否显示角标
notificationChannel.setShowBadge(false);//是否显示角标 notificationChannel.setLockscreenVisibility(Notification.VISIBILITY_SECRET);
notificationChannel.setLockscreenVisibility(Notification.VISIBILITY_SECRET); NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); manager.createNotificationChannel(notificationChannel);
manager.createNotificationChannel(notificationChannel); builder.setChannelId(CHANNEL_ONE_ID);
builder.setChannelId(CHANNEL_ONE_ID); }
}
Notification notification = builder.build();
Notification notification = builder.build(); startForeground(1, notification);
startForeground(1, notification);
//检查权限是否获取
//检查权限是否获取 //PackageManager pm = getPackageManager();
//PackageManager pm = getPackageManager(); //PhoneUtils.CheckPermission(pm, this);
//PhoneUtils.CheckPermission(pm, this);
//Android8.1以下尝试启动主界面以便动态获取权限
//Android8.1以下尝试启动主界面以便动态获取权限 if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.O_MR1) {
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.O_MR1) { intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(intent);
startActivity(intent); }
} // 手机重启未打开app时主动获取SIM卡信息
// 手机重启未打开app时主动获取SIM卡信息 if (MyApplication.SimInfoList.isEmpty()) {
if (MyApplication.SimInfoList.isEmpty()) { PhoneUtils.init(this);
PhoneUtils.init(this); MyApplication.SimInfoList = PhoneUtils.getSimMultiInfo();
MyApplication.SimInfoList = PhoneUtils.getSimMultiInfo(); }
}
// 低电量预警
// 低电量预警 final int[] alarmTimes = {0}; //通知次数只通知2次
final int[] alarmTimes = {0}; //通知次数只通知2次 Context context1 = this;
Context context1 = this; SenderUtil.init(context1);
SenderUtil.init(context1); new Timer().schedule(new TimerTask() {
new Timer().schedule(new TimerTask() { @Override
@Override public void run() {
public void run() { int batteryLevel = getBatteryLevel();
int batteryLevel = getBatteryLevel(); System.out.println("当前剩余电量:" + batteryLevel + "%");
System.out.println("当前剩余电量:" + batteryLevel + "%"); int batteryLevelAlarm = SettingUtil.getBatteryLevelAlarm();
int batteryLevelAlarm = SettingUtil.getBatteryLevelAlarm(); if (alarmTimes[0] <= 1 && batteryLevelAlarm > 0 && batteryLevelAlarm <= 100 && (batteryLevel == batteryLevelAlarm || batteryLevel == batteryLevelAlarm - 1)) {
if (alarmTimes[0] <= 1 && batteryLevelAlarm > 0 && batteryLevelAlarm <= 100 && (batteryLevel == batteryLevelAlarm || batteryLevel == batteryLevelAlarm - 1)) { try {
try { alarmTimes[0] = alarmTimes[0] + 1;
alarmTimes[0] = alarmTimes[0] + 1; SmsVo smsVo = new SmsVo("88888888",
SmsVo smsVo = new SmsVo("88888888", "当前剩余电量:" + batteryLevel + "%,已经到达低电量预警阈值,请及时充电!",
"当前剩余电量:" + batteryLevel + "%,已经到达低电量预警阈值,请及时充电!", new Date(),
new Date(), "低电量预警");
"低电量预警"); Log.d(TAG, "send_msg" + smsVo.toString());
Log.d(TAG, "send_msg" + smsVo.toString()); SendUtil.send_msg(context1, smsVo, 1);
SendUtil.send_msg(context1, smsVo, 1); } catch (Exception e) {
} catch (Exception e) { Log.e(TAG, "getLog e:" + e.getMessage());
Log.e(TAG, "getLog e:" + e.getMessage()); }
} }
}
if (batteryLevelAlarm > 0 && batteryLevelAlarm <= 100 && batteryLevel > batteryLevelAlarm) {
if (batteryLevelAlarm > 0 && batteryLevelAlarm <= 100 && batteryLevel > batteryLevelAlarm) { alarmTimes[0] = 0;
alarmTimes[0] = 0; }
} }
} }, 0, 10000);
}, 0, 10000);
} if (!isNotificationListenerServiceEnabled(this)) {
openNotificationAccess();
@Nullable }
@Override toggleNotificationListenerService();
public IBinder onBind(Intent intent) { }
return null;
} @Override
public void onDestroy() {
@Override //进行自动重启
public int onStartCommand(Intent intent, int flags, int startId) { Intent intent = new Intent(FrontService.this, FrontService.class);
Log.i(TAG, "flags: " + flags + " startId: " + startId); //重新开启服务
return START_STICKY; //保证service不被杀死 startService(intent);
} stopForeground(true);
super.onDestroy();
//获取当前电量 }
@SuppressLint("ObsoleteSdkInt")
private int getBatteryLevel() { @Override
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { public int onStartCommand(Intent intent, int flags, int startId) {
BatteryManager batteryManager = (BatteryManager) getSystemService(BATTERY_SERVICE); //return super.onStartCommand(intent, flags, startId);
return batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY); return START_STICKY; //保证service不被杀死
} else { }
Intent intent = new ContextWrapper(getApplicationContext()).
registerReceiver(null, new IntentFilter(Intent.ACTION_BATTERY_CHANGED)); @Nullable
return (intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1) * 100) / @Override
intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1); public IBinder onBind(Intent intent) {
} return null;
} }
}
//获取当前电量
@SuppressLint("ObsoleteSdkInt")
private int getBatteryLevel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
BatteryManager batteryManager = (BatteryManager) getSystemService(BATTERY_SERVICE);
return batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY);
} else {
Intent intent = new ContextWrapper(getApplicationContext()).
registerReceiver(null, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
return (intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1) * 100) /
intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1);
}
}
private void toggleNotificationListenerService() {
PackageManager pm = getPackageManager();
pm.setComponentEnabledSetting(new ComponentName(this, NotifyService.class),
PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);
pm.setComponentEnabledSetting(new ComponentName(this, 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());
}
private void openNotificationAccess() {
startActivity(new Intent(ACTION_NOTIFICATION_LISTENER_SETTINGS));
}
}

View File

@ -0,0 +1,52 @@
package com.idormy.sms.forwarder.service;
import android.content.ComponentName;
import android.os.Build;
import android.service.notification.NotificationListenerService;
import android.service.notification.StatusBarNotification;
import android.util.Log;
import androidx.annotation.RequiresApi;
import com.idormy.sms.forwarder.notify.NotifyHelper;
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
public class NotifyService extends NotificationListenerService {
public static final String TAG = "NotifyService";
/**
* 发布通知
*
* @param sbn 状态栏通知
*/
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
@Override
public void onNotificationPosted(StatusBarNotification sbn) {
if (sbn.getNotification() == null) return;
Log.d(TAG, sbn.getPackageName());
NotifyHelper.getInstance().onReceive(sbn);
}
/**
* 通知已删除
*
* @param sbn 状态栏通知
*/
@Override
public void onNotificationRemoved(StatusBarNotification sbn) {
Log.d(TAG, sbn.getPackageName());
NotifyHelper.getInstance().onRemoved(sbn);
}
/**
* 监听断开
*/
@Override
public void onListenerDisconnected() {
Log.d(TAG, "通知侦听器断开连接 - 请求重新绑定");
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
requestRebind(new ComponentName(this, NotificationListenerService.class));
}
}
}

View File

@ -545,12 +545,13 @@ public class PhoneUtils {
boolean permission_read_call_log = (PackageManager.PERMISSION_GRANTED == pm.checkPermission("android.permission.READ_CALL_LOG", that.getPackageName())); boolean permission_read_call_log = (PackageManager.PERMISSION_GRANTED == pm.checkPermission("android.permission.READ_CALL_LOG", that.getPackageName()));
boolean permission_read_contacts = (PackageManager.PERMISSION_GRANTED == pm.checkPermission("android.permission.READ_CONTACTS", that.getPackageName())); boolean permission_read_contacts = (PackageManager.PERMISSION_GRANTED == pm.checkPermission("android.permission.READ_CONTACTS", that.getPackageName()));
boolean permission_battery_stats = (PackageManager.PERMISSION_GRANTED == pm.checkPermission("android.permission.BATTERY_STATS", that.getPackageName())); boolean permission_battery_stats = (PackageManager.PERMISSION_GRANTED == pm.checkPermission("android.permission.BATTERY_STATS", that.getPackageName()));
boolean permission_bind_notification_listener_service = (PackageManager.PERMISSION_GRANTED == pm.checkPermission("android.permission.BIND_NOTIFICATION_LISTENER_SERVICE", that.getPackageName()));
if (!(permission_internet && permission_receive_boot && permission_foreground_service && if (!(permission_internet && permission_receive_boot && permission_foreground_service &&
permission_read_external_storage && permission_write_external_storage && permission_read_external_storage && permission_write_external_storage &&
permission_receive_sms && permission_read_sms && permission_send_sms && permission_receive_sms && permission_read_sms && permission_send_sms &&
permission_read_call_log && permission_read_contacts && permission_read_call_log && permission_read_contacts &&
permission_read_phone_state && permission_read_phone_numbers && permission_battery_stats)) { permission_read_phone_state && permission_read_phone_numbers && permission_battery_stats && permission_bind_notification_listener_service)) {
ActivityCompat.requestPermissions((Activity) that, new String[]{ ActivityCompat.requestPermissions((Activity) that, new String[]{
Manifest.permission.INTERNET, Manifest.permission.INTERNET,
Manifest.permission.RECEIVE_BOOT_COMPLETED, Manifest.permission.RECEIVE_BOOT_COMPLETED,
@ -565,6 +566,7 @@ public class PhoneUtils {
Manifest.permission.READ_PHONE_NUMBERS, Manifest.permission.READ_PHONE_NUMBERS,
Manifest.permission.FOREGROUND_SERVICE, Manifest.permission.FOREGROUND_SERVICE,
Manifest.permission.BATTERY_STATS, Manifest.permission.BATTERY_STATS,
Manifest.permission.BIND_NOTIFICATION_LISTENER_SERVICE,
}, 0x01); }, 0x01);
} }
} }

View File

@ -17,7 +17,6 @@ public class SmsUtil {
@SuppressLint("StaticFieldLeak") @SuppressLint("StaticFieldLeak")
static Context context; static Context context;
public static void init(Context context1) { public static void init(Context context1) {
synchronized (hasInit) { synchronized (hasInit) {
if (hasInit) return; if (hasInit) return;

View File

@ -1,72 +1,72 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:orientation="vertical"> android:orientation="vertical">
<com.idormy.sms.forwarder.RefreshListView <com.idormy.sms.forwarder.RefreshListView
android:id="@+id/list_view_log" android:id="@+id/list_view_log"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="0dp" android:layout_height="0dp"
android:layout_margin="5dp" android:layout_margin="5dp"
android:layout_weight="1" /> android:layout_weight="1" />
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical"> android:orientation="vertical">
<TextView <TextView
android:id="@+id/help_tip" android:id="@+id/help_tip"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:gravity="center" android:gravity="center"
android:text="@string/log_tips" android:text="@string/log_tips"
android:textColor="@color/colorPrimary" /> android:textColor="@color/colorPrimary" />
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="horizontal"> android:orientation="horizontal">
<Button <Button
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="35dp" android:layout_height="35dp"
android:layout_marginStart="10dp" android:layout_marginStart="10dp"
android:layout_marginTop="5dp" android:layout_marginTop="5dp"
android:layout_marginBottom="10dp" android:layout_marginBottom="10dp"
android:layout_weight="1" android:layout_weight="1"
android:background="@color/colorPrimary" android:background="@color/colorPrimary"
android:onClick="cleanLog" android:onClick="cleanLog"
android:text="@string/bt_refresh_log" android:text="@string/bt_refresh_log"
tools:ignore="ButtonStyle,NestedWeights" /> tools:ignore="ButtonStyle,NestedWeights" />
<Button <Button
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="35dp" android:layout_height="35dp"
android:layout_marginStart="10dp" android:layout_marginStart="10dp"
android:layout_marginTop="5dp" android:layout_marginTop="5dp"
android:layout_marginBottom="10dp" android:layout_marginBottom="10dp"
android:layout_weight="1" android:layout_weight="1"
android:background="@color/colorPrimary" android:background="@color/colorPrimary"
android:onClick="toRuleSetting" android:onClick="toRuleSetting"
android:text="@string/rule_setting" android:text="@string/rule_setting"
tools:ignore="ButtonStyle,NestedWeights" /> tools:ignore="ButtonStyle,NestedWeights" />
<Button <Button
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="35dp" android:layout_height="35dp"
android:layout_marginLeft="10dp" android:layout_marginLeft="10dp"
android:layout_marginTop="5dp" android:layout_marginTop="5dp"
android:layout_marginRight="10dp" android:layout_marginRight="10dp"
android:layout_marginBottom="10dp" android:layout_marginBottom="10dp"
android:layout_weight="1" android:layout_weight="1"
android:background="@color/colorPrimary" android:background="@color/colorPrimary"
android:onClick="toSendSetting" android:onClick="toSendSetting"
android:text="@string/sender_setting" android:text="@string/sender_setting"
tools:ignore="ButtonStyle" /> tools:ignore="ButtonStyle" />
</LinearLayout> </LinearLayout>
</LinearLayout> </LinearLayout>
</LinearLayout> </LinearLayout>

View File

@ -1,459 +1,480 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android" <ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent">
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical"> android:orientation="vertical">
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="2dp" android:layout_marginTop="2dp"
android:background="@android:color/white" android:background="@android:color/white"
android:gravity="center_vertical" android:gravity="center_vertical"
android:orientation="horizontal" android:orientation="horizontal"
android:padding="15dp"> android:padding="15dp">
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@string/device_name" android:text="@string/device_name"
android:textStyle="bold" /> android:textStyle="bold" />
<EditText <EditText
android:id="@+id/et_add_extra_device_mark" android:id="@+id/et_add_extra_device_mark"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="5dp" android:layout_marginStart="5dp"
android:autofillHints="" android:autofillHints=""
android:ems="16" android:ems="16"
android:inputType="text" android:inputType="text"
android:maxLines="1" android:maxLines="1"
android:text="" android:text=""
tools:ignore="LabelFor" /> tools:ignore="LabelFor" />
</LinearLayout> </LinearLayout>
<LinearLayout <LinearLayout
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="2dp" android:layout_marginTop="2dp"
android:background="@android:color/white" android:background="@android:color/white"
android:gravity="center_vertical" android:gravity="center_vertical"
android:orientation="horizontal" android:orientation="horizontal"
android:padding="15dp"> android:padding="15dp">
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical"> android:orientation="vertical">
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@string/sim1_remark" android:text="@string/sim1_remark"
android:textStyle="bold" /> android:textStyle="bold" />
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:gravity="end" android:gravity="end"
android:text="@string/carrier_mobile" android:text="@string/carrier_mobile"
android:textSize="9sp" android:textSize="9sp"
tools:ignore="SmallSp" /> tools:ignore="SmallSp" />
</LinearLayout> </LinearLayout>
<EditText <EditText
android:id="@+id/et_add_extra_sim1" android:id="@+id/et_add_extra_sim1"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="5dp" android:layout_marginStart="5dp"
android:autofillHints="" android:autofillHints=""
android:ems="16" android:ems="16"
android:inputType="text" android:inputType="text"
android:maxLines="1" android:maxLines="1"
android:text="" android:text=""
tools:ignore="LabelFor" /> tools:ignore="LabelFor" />
</LinearLayout> </LinearLayout>
<LinearLayout <LinearLayout
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="2dp" android:layout_marginTop="2dp"
android:background="@android:color/white" android:background="@android:color/white"
android:gravity="center_vertical" android:gravity="center_vertical"
android:orientation="horizontal" android:orientation="horizontal"
android:padding="15dp"> android:padding="15dp">
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical"> android:orientation="vertical">
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@string/sim2_remark" android:text="@string/sim2_remark"
android:textStyle="bold" /> android:textStyle="bold" />
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:gravity="end" android:gravity="end"
android:text="@string/carrier_mobile" android:text="@string/carrier_mobile"
android:textSize="9sp" android:textSize="9sp"
tools:ignore="SmallSp" /> tools:ignore="SmallSp" />
</LinearLayout> </LinearLayout>
<EditText <EditText
android:id="@+id/et_add_extra_sim2" android:id="@+id/et_add_extra_sim2"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="5dp" android:layout_marginStart="5dp"
android:autofillHints="" android:autofillHints=""
android:ems="16" android:ems="16"
android:inputType="text" android:inputType="text"
android:maxLines="1" android:maxLines="1"
android:text="" android:text=""
tools:ignore="LabelFor" /> tools:ignore="LabelFor" />
</LinearLayout> </LinearLayout>
<LinearLayout <LinearLayout
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="2dp" android:layout_marginTop="2dp"
android:background="@android:color/white" android:background="@android:color/white"
android:gravity="center_vertical" android:gravity="center_vertical"
android:orientation="horizontal" android:orientation="horizontal"
android:padding="15dp"> android:padding="15dp">
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical"> android:orientation="vertical">
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@string/low_power_alarm_threshold" android:text="@string/low_power_alarm_threshold"
android:textStyle="bold" /> android:textStyle="bold" />
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:gravity="end" android:gravity="end"
android:text="@string/low_power_alarm_threshold_tips" android:text="@string/low_power_alarm_threshold_tips"
android:textSize="9sp" android:textSize="9sp"
tools:ignore="SmallSp" /> tools:ignore="SmallSp" />
</LinearLayout> </LinearLayout>
<EditText <EditText
android:id="@+id/et_battery_level_alarm" android:id="@+id/et_battery_level_alarm"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="5dp" android:layout_marginStart="5dp"
android:autofillHints="" android:autofillHints=""
android:ems="16" android:ems="16"
android:inputType="number" android:inputType="number"
android:maxLines="1" android:maxLines="1"
android:text="" android:text=""
tools:ignore="LabelFor" /> tools:ignore="LabelFor" />
</LinearLayout> </LinearLayout>
<LinearLayout <LinearLayout
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="2dp" android:layout_marginTop="2dp"
android:background="@android:color/white" android:background="@android:color/white"
android:gravity="center_vertical" android:gravity="center_vertical"
android:orientation="horizontal" android:orientation="horizontal"
android:padding="15dp"> android:padding="15dp">
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical"> android:orientation="vertical">
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@string/retry_interval" android:text="@string/retry_interval"
android:textStyle="bold" /> android:textStyle="bold" />
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:gravity="end" android:gravity="end"
android:text="@string/retry_interval_tips" android:text="@string/retry_interval_tips"
android:textSize="9sp" android:textSize="9sp"
tools:ignore="SmallSp" /> tools:ignore="SmallSp" />
</LinearLayout> </LinearLayout>
<LinearLayout <LinearLayout
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="horizontal"> android:orientation="horizontal">
<EditText <EditText
android:id="@+id/et_retry_delay_time1" android:id="@+id/et_retry_delay_time1"
android:layout_width="42dp" android:layout_width="42dp"
android:layout_height="48dp" android:layout_height="48dp"
android:layout_marginStart="5dp" android:layout_marginStart="5dp"
android:autofillHints="" android:autofillHints=""
android:ems="16" android:ems="16"
android:inputType="number" android:inputType="number"
android:maxLines="1" android:maxLines="1"
android:text="" android:text=""
android:textAlignment="center" android:textAlignment="center"
tools:ignore="LabelFor" /> tools:ignore="LabelFor" />
<EditText <EditText
android:id="@+id/et_retry_delay_time2" android:id="@+id/et_retry_delay_time2"
android:layout_width="42dp" android:layout_width="42dp"
android:layout_height="48dp" android:layout_height="48dp"
android:layout_marginStart="5dp" android:layout_marginStart="5dp"
android:autofillHints="" android:autofillHints=""
android:ems="16" android:ems="16"
android:inputType="number" android:inputType="number"
android:maxLines="1" android:maxLines="1"
android:text="" android:text=""
android:textAlignment="center" android:textAlignment="center"
tools:ignore="LabelFor" /> tools:ignore="LabelFor" />
<EditText <EditText
android:id="@+id/et_retry_delay_time3" android:id="@+id/et_retry_delay_time3"
android:layout_width="42dp" android:layout_width="42dp"
android:layout_height="48dp" android:layout_height="48dp"
android:layout_marginStart="5dp" android:layout_marginStart="5dp"
android:autofillHints="" android:autofillHints=""
android:ems="16" android:ems="16"
android:inputType="number" android:inputType="number"
android:maxLines="1" android:maxLines="1"
android:text="" android:text=""
android:textAlignment="center" android:textAlignment="center"
tools:ignore="LabelFor" /> tools:ignore="LabelFor" />
<EditText <EditText
android:id="@+id/et_retry_delay_time4" android:id="@+id/et_retry_delay_time4"
android:layout_width="42dp" android:layout_width="42dp"
android:layout_height="48dp" android:layout_height="48dp"
android:layout_marginStart="5dp" android:layout_marginStart="5dp"
android:autofillHints="" android:autofillHints=""
android:ems="16" android:ems="16"
android:inputType="number" android:inputType="number"
android:maxLines="1" android:maxLines="1"
android:text="" android:text=""
android:textAlignment="center" android:textAlignment="center"
tools:ignore="LabelFor" /> tools:ignore="LabelFor" />
<EditText <EditText
android:id="@+id/et_retry_delay_time5" android:id="@+id/et_retry_delay_time5"
android:layout_width="42dp" android:layout_width="42dp"
android:layout_height="48dp" android:layout_height="48dp"
android:layout_marginStart="5dp" android:layout_marginStart="5dp"
android:autofillHints="" android:autofillHints=""
android:ems="16" android:ems="16"
android:inputType="number" android:inputType="number"
android:maxLines="1" android:maxLines="1"
android:text="" android:text=""
android:textAlignment="center" android:textAlignment="center"
tools:ignore="LabelFor" /> tools:ignore="LabelFor" />
</LinearLayout> </LinearLayout>
</LinearLayout> </LinearLayout>
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="2dp" android:layout_marginTop="2dp"
android:background="@android:color/white" android:background="@android:color/white"
android:gravity="center_vertical" android:gravity="center_vertical"
android:orientation="horizontal" android:orientation="horizontal"
android:padding="15dp"> android:padding="15dp">
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@string/forward_missed_calls" android:text="@string/forward_missed_calls"
android:textStyle="bold" android:textStyle="bold"
tools:ignore="RelativeOverlap" /> tools:ignore="RelativeOverlap" />
<Switch <Switch
android:id="@+id/switch_enable_phone" android:id="@+id/switch_enable_phone"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="3" android:layout_weight="3"
android:gravity="end" android:gravity="end"
android:textSize="18sp" android:textSize="18sp"
tools:ignore="UseSwitchCompatOrMaterialXml" /> tools:ignore="UseSwitchCompatOrMaterialXml" />
</LinearLayout> </LinearLayout>
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="2dp" android:layout_marginTop="2dp"
android:background="@android:color/white" android:background="@android:color/white"
android:gravity="center_vertical" android:gravity="center_vertical"
android:orientation="horizontal" android:orientation="horizontal"
android:padding="15dp"> android:padding="15dp">
<TextView <TextView
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="3" android:layout_weight="3"
android:text="@string/enable_custom_templates" android:text="@string/enable_custom_templates"
android:textStyle="bold" /> android:textStyle="bold" />
<Switch <Switch
android:id="@+id/switch_sms_template" android:id="@+id/switch_sms_template"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="3" android:layout_weight="3"
android:gravity="end" android:gravity="end"
android:textSize="18sp" android:textSize="18sp"
tools:ignore="UseSwitchCompatOrMaterialXml" /> tools:ignore="UseSwitchCompatOrMaterialXml" />
</LinearLayout> </LinearLayout>
<LinearLayout <LinearLayout
android:id="@+id/layout_sms_template" android:id="@+id/layout_sms_template"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="2dp" android:layout_marginTop="2dp"
android:background="@android:color/white" android:background="@android:color/white"
android:gravity="center_vertical" android:gravity="center_vertical"
android:orientation="vertical" android:orientation="vertical"
android:padding="15dp" android:padding="15dp"
android:visibility="gone"> android:visibility="gone">
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="horizontal"> android:orientation="horizontal">
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@string/custom_templates" android:text="@string/custom_templates"
android:textStyle="bold" /> android:textStyle="bold" />
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="5dp" android:layout_marginStart="5dp"
android:text="@string/custom_templates_tips" android:text="@string/custom_templates_tips"
android:textSize="11sp" /> android:textSize="11sp" />
</LinearLayout> </LinearLayout>
<EditText <EditText
android:id="@+id/text_sms_template" android:id="@+id/text_sms_template"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:autofillHints="" android:autofillHints=""
android:inputType="textMultiLine" android:inputType="textMultiLine"
android:gravity="left|top" android:gravity="left|top"
android:minLines="1" android:minLines="1"
android:text="" android:text=""
tools:ignore="LabelFor" /> tools:ignore="LabelFor" />
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="horizontal"> android:orientation="horizontal">
<Button <Button
android:id="@+id/bt_insert_sender" android:id="@+id/bt_insert_sender"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="25dp" android:layout_height="25dp"
android:layout_marginTop="5dp" android:layout_marginTop="5dp"
android:layout_marginBottom="5dp" android:layout_marginBottom="5dp"
android:layout_weight="1" android:layout_weight="1"
android:background="@color/colorPrimary" android:background="@color/colorPrimary"
android:onClick="toInsertLabel" android:onClick="toInsertLabel"
android:text="@string/insert_sender" android:text="@string/insert_sender"
tools:ignore="ButtonStyle,NestedWeights" /> tools:ignore="ButtonStyle,NestedWeights" />
<Button <Button
android:id="@+id/bt_insert_content" android:id="@+id/bt_insert_content"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="25dp" android:layout_height="25dp"
android:layout_marginStart="5dp" android:layout_marginStart="5dp"
android:layout_marginTop="5dp" android:layout_marginTop="5dp"
android:layout_marginBottom="5dp" android:layout_marginBottom="5dp"
android:layout_weight="1" android:layout_weight="1"
android:background="@color/colorPrimary" android:background="@color/colorPrimary"
android:onClick="toInsertLabel" android:onClick="toInsertLabel"
android:text="@string/insert_content" android:text="@string/insert_content"
tools:ignore="ButtonStyle,NestedWeights" /> tools:ignore="ButtonStyle,NestedWeights" />
<Button <Button
android:id="@+id/bt_insert_extra" android:id="@+id/bt_insert_extra"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="25dp" android:layout_height="25dp"
android:layout_marginStart="5dp" android:layout_marginStart="5dp"
android:layout_marginTop="5dp" android:layout_marginTop="5dp"
android:layout_marginBottom="5dp" android:layout_marginBottom="5dp"
android:layout_weight="1" android:layout_weight="1"
android:background="@color/colorPrimary" android:background="@color/colorPrimary"
android:onClick="toInsertLabel" android:onClick="toInsertLabel"
android:text="@string/insert_extra" android:text="@string/insert_extra"
tools:ignore="ButtonStyle,NestedWeights" /> tools:ignore="ButtonStyle,NestedWeights" />
<Button <Button
android:id="@+id/bt_insert_time" android:id="@+id/bt_insert_time"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="25dp" android:layout_height="25dp"
android:layout_marginStart="5dp" android:layout_marginStart="5dp"
android:layout_marginTop="5dp" android:layout_marginTop="5dp"
android:layout_marginBottom="5dp" android:layout_marginBottom="5dp"
android:layout_weight="1" android:layout_weight="1"
android:background="@color/colorPrimary" android:background="@color/colorPrimary"
android:onClick="toInsertLabel" android:onClick="toInsertLabel"
android:text="@string/insert_time" android:text="@string/insert_time"
tools:ignore="ButtonStyle,NestedWeights" /> tools:ignore="ButtonStyle,NestedWeights" />
<Button <Button
android:id="@+id/bt_insert_device_name" android:id="@+id/bt_insert_device_name"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="25dp" android:layout_height="25dp"
android:layout_marginStart="5dp" android:layout_marginStart="5dp"
android:layout_marginTop="5dp" android:layout_marginTop="5dp"
android:layout_marginBottom="5dp" android:layout_marginBottom="5dp"
android:layout_weight="1" android:layout_weight="1"
android:background="@color/colorPrimary" android:background="@color/colorPrimary"
android:onClick="toInsertLabel" android:onClick="toInsertLabel"
android:text="@string/insert_device_name" android:text="@string/insert_device_name"
tools:ignore="ButtonStyle,NestedWeights" /> tools:ignore="ButtonStyle,NestedWeights" />
</LinearLayout> </LinearLayout>
</LinearLayout> </LinearLayout>
<Button <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="35dp" android:layout_height="wrap_content"
android:layout_margin="10dp" android:layout_marginTop="2dp"
android:background="@color/colorPrimary" android:background="@android:color/white"
android:onClick="initSetting" android:gravity="center_vertical"
android:padding="0dp" android:orientation="horizontal"
android:text="@string/init_setting" /> android:padding="15dp">
<Button <Button
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="35dp" android:layout_height="35dp"
android:layout_margin="10dp" android:layout_weight="1"
android:background="@color/colorPrimary" android:background="@color/colorPrimary"
android:onClick="batterySetting" android:onClick="batterySetting"
android:padding="0dp" android:text="@string/battery_setting"
android:text="@string/battery_setting" /> tools:ignore="ButtonStyle,NestedWeights" />
</LinearLayout> <Button
android:layout_width="match_parent"
android:layout_height="35dp"
android:layout_marginStart="10dp"
android:layout_weight="1"
android:background="@color/colorPrimary"
android:onClick="requestPermission"
android:text="@string/request_permission"
tools:ignore="ButtonStyle,NestedWeights" />
<Button
android:layout_width="match_parent"
android:layout_height="35dp"
android:layout_marginStart="10dp"
android:layout_weight="1"
android:background="@color/colorBlueGreyDark"
android:onClick="initSetting"
android:text="@string/init_setting"
tools:ignore="ButtonStyle,NestedWeights" />
</LinearLayout>
</LinearLayout>
</ScrollView> </ScrollView>

View File

@ -159,6 +159,7 @@
<string name="insert_device_name">Device</string> <string name="insert_device_name">Device</string>
<string name="init_setting">Restore initial Setting</string> <string name="init_setting">Restore initial Setting</string>
<string name="battery_setting">Battery Optimization</string> <string name="battery_setting">Battery Optimization</string>
<string name="request_permission">Request Notify Permission</string>
<string name="unknown_number">Unknown Number</string> <string name="unknown_number">Unknown Number</string>
<string name="calling">Incoming telegram</string> <string name="calling">Incoming telegram</string>
<string name="unsupport">Your phone does not support this setting</string> <string name="unsupport">Your phone does not support this setting</string>

View File

@ -12,11 +12,11 @@
<string name="clone">一键克隆</string> <string name="clone">一键克隆</string>
<string name="setting">设置</string> <string name="setting">设置</string>
<string name="about">关于</string> <string name="about">关于</string>
<string name="rule_setting">设置转发规则</string> <string name="rule_setting">转发规则</string>
<string name="sender_setting">设置发送方</string> <string name="sender_setting">发送通道</string>
<string name="log_tips">提示:置顶下拉刷新,长按删除单条记录</string> <string name="log_tips">提示:置顶下拉刷新,长按删除单条记录</string>
<string name="rule_tips">提示:新建规则点击“添加”,长按删除/点击编辑已有</string> <string name="rule_tips">提示:新建规则点击“添加”,长按删除/点击编辑已有</string>
<string name="sender_tips">提示:新建发送点击“添加”,长按删除/点击编辑已有</string> <string name="sender_tips">提示:新建发送通道点击“添加”,长按删除/点击编辑已有</string>
<!--AboutActivity--> <!--AboutActivity-->
<string name="version">当前版本</string> <string name="version">当前版本</string>
<string name="check_for_updates">检查新版本</string> <string name="check_for_updates">检查新版本</string>
@ -50,9 +50,9 @@
<string name="delete_rule_title">规则删除确认</string> <string name="delete_rule_title">规则删除确认</string>
<string name="delete_rule_tips">确定删除该条规则?</string> <string name="delete_rule_tips">确定删除该条规则?</string>
<string name="delete_rule_toast">该条规则已经删除!</string> <string name="delete_rule_toast">该条规则已经删除!</string>
<string name="new_sender_first">请先创建发送再选择</string> <string name="new_sender_first">请先创建发送通道再选择</string>
<string name="add_sender_first">请先去设置发送页面添加</string> <string name="add_sender_first">请先去设置发送通道页面添加</string>
<string name="select_sender">选择发送</string> <string name="select_sender">选择发送通道</string>
<string name="rule_tester">规则测试</string> <string name="rule_tester">规则测试</string>
<string name="new_forwarding_rule">添加转发规则</string> <string name="new_forwarding_rule">添加转发规则</string>
<string name="test_sim_slot">测试模拟的接收卡槽</string> <string name="test_sim_slot">测试模拟的接收卡槽</string>
@ -72,11 +72,11 @@
<string name="btn_regex">正则匹配</string> <string name="btn_regex">正则匹配</string>
<string name="match_value">设置匹配的值</string> <string name="match_value">设置匹配的值</string>
<!--SenderActivity--> <!--SenderActivity-->
<string name="invalid_sender">异常的发送类型,自动删除!</string> <string name="invalid_sender">异常的发送通道类型,自动删除!</string>
<string name="delete_sender_title">发送删除确认</string> <string name="delete_sender_title">发送通道删除确认</string>
<string name="delete_sender_tips">确定删除该条发送?</string> <string name="delete_sender_tips">确定删除该条发送通道?</string>
<string name="delete_sender_toast">该条发送已经删除!</string> <string name="delete_sender_toast">该条发送通道已经删除!</string>
<string name="add_sender_title">选择发送类型</string> <string name="add_sender_title">选择发送通道类型</string>
<string name="not_supported">暂不支持这种转发</string> <string name="not_supported">暂不支持这种转发</string>
<string name="setdingdingtitle">设置钉钉机器人</string> <string name="setdingdingtitle">设置钉钉机器人</string>
<string name="setemailtitle">设置邮箱</string> <string name="setemailtitle">设置邮箱</string>
@ -102,7 +102,7 @@
<string name="invalid_webhook">webHook 不能为空</string> <string name="invalid_webhook">webHook 不能为空</string>
<string name="invalid_at_mobiles">指定成员 不能为空 或者 选择@all</string> <string name="invalid_at_mobiles">指定成员 不能为空 或者 选择@all</string>
<string name="invalid_phone_num">接收手机号不能为空</string> <string name="invalid_phone_num">接收手机号不能为空</string>
<string name="new_sender">添加发送</string> <string name="new_sender">添加发送通道</string>
<string name="set_bark_name">设置分组名称</string> <string name="set_bark_name">设置分组名称</string>
<string name="set_bark_server">设置Bark-Server地址示例https://bark.bms.ink/XXXXXXXX/</string> <string name="set_bark_server">设置Bark-Server地址示例https://bark.bms.ink/XXXXXXXX/</string>
<string name="set_bark_icon">设置推送消息图标(可选)示例http://day.app/assets/images/avatar.jpg</string> <string name="set_bark_icon">设置推送消息图标(可选)示例http://day.app/assets/images/avatar.jpg</string>
@ -157,8 +157,9 @@
<string name="insert_extra">卡槽信息</string> <string name="insert_extra">卡槽信息</string>
<string name="insert_time">接收时间</string> <string name="insert_time">接收时间</string>
<string name="insert_device_name">设备名称</string> <string name="insert_device_name">设备名称</string>
<string name="init_setting">恢复初始化配置</string> <string name="init_setting">恢复默认配置</string>
<string name="battery_setting">设置电池优化</string> <string name="battery_setting">设置电池优化</string>
<string name="request_permission">请求通知权限</string>
<string name="unknown_number">未知号码</string> <string name="unknown_number">未知号码</string>
<string name="calling">来电</string> <string name="calling">来电</string>
<string name="unsupport">您的手机不支持此设置</string> <string name="unsupport">您的手机不支持此设置</string>
@ -174,7 +175,7 @@
<string name="post">POST</string> <string name="post">POST</string>
<string name="get">GET</string> <string name="get">GET</string>
<string name="local_ip">本机IP</string> <string name="local_ip">本机IP</string>
<string name="operating_instruction">操作说明:\n1.请保持新旧手机在同一个WiFi网络下且没有开启隔离\n2.旧手机直接点【发送】按钮获取到【服务端IP】\n3.新手机填写【服务端IP】后点【接收】按钮\n【注意】新手机接收后发送、转发规则将完全被覆盖,清空历史记录!</string> <string name="operating_instruction">操作说明:\n1.新旧手机连接同一个WiFi网络(禁用AP隔离)\n2.旧手机直接点【发送】按钮获取到【服务端IP】\n3.新手机填写【服务端IP】后点【接收】按钮\n【注意】新手机接收后发送通道、转发规则将完全被覆盖,清空历史记录!</string>
<string name="send">发送</string> <string name="send">发送</string>
<string name="stop">停止</string> <string name="stop">停止</string>
<string name="old_mobile_phone">我是旧手机</string> <string name="old_mobile_phone">我是旧手机</string>

View File

@ -8,7 +8,7 @@
# The setting is particularly useful for tweaking memory settings. # The setting is particularly useful for tweaking memory settings.
android.enableJetifier=true android.enableJetifier=true
android.useAndroidX=true android.useAndroidX=true
org.gradle.jvmargs=-Xmx1536m org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
# When configured, Gradle will run in incubating parallel mode. # When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit # This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects

View File

@ -1 +1,2 @@
rootProject.name = "SmsForwarder"
include ':app' include ':app'

View File

@ -1,3 +1,3 @@
#Fri Jul 16 10:33:23 CST 2021 #Fri Jul 16 10:33:23 CST 2021
versionName=2.1.1 versionName=2.2.0
versionCode=29 versionCode=30