diff --git a/app/build.gradle b/app/build.gradle index cad6c524..84e7b0cb 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -170,4 +170,4 @@ dependencies { //jetty implementation "org.eclipse.jetty:jetty-server:$jetty_version" implementation "org.eclipse.jetty:jetty-servlet:$jetty_version" -} +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro index c88393ae..41a6b773 100644 --- a/app/proguard-rules.pro +++ b/app/proguard-rules.pro @@ -21,6 +21,10 @@ #-renamesourcefileattribute SourceFile -keep class com.idormy.sms.forwarder.model.**{*;} +-keep public class com.idormy.sms.forwarder.R$*{ +public static final int *; +} + -keep class com.umeng.** {*;} -keepclassmembers class * { public (org.json.JSONObject); diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index b81ab50a..d428ad3c 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -52,7 +52,12 @@ android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme" - android:usesCleartextTraffic="true"> + android:usesCleartextTraffic="true" + tools:targetApi="m"> + + @@ -74,6 +80,7 @@ @@ -89,22 +96,28 @@ @@ -114,6 +127,7 @@ @@ -123,6 +137,7 @@ @@ -139,7 +154,8 @@ android:name=".service.NotifyService" android:enabled="true" android:label="@string/app_name" - android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE"> + android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE" + android:exported="false"> diff --git a/app/src/main/java/com/idormy/sms/forwarder/MainActivity.java b/app/src/main/java/com/idormy/sms/forwarder/MainActivity.java index 65dae229..708047e7 100644 --- a/app/src/main/java/com/idormy/sms/forwarder/MainActivity.java +++ b/app/src/main/java/com/idormy/sms/forwarder/MainActivity.java @@ -1,11 +1,14 @@ package com.idormy.sms.forwarder; import android.annotation.SuppressLint; +import android.app.Dialog; import android.content.Intent; import android.content.pm.PackageManager; import android.net.Uri; import android.os.*; import android.util.Log; +import android.view.Gravity; +import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; import android.view.View; @@ -27,6 +30,7 @@ import com.idormy.sms.forwarder.service.BatteryService; import com.idormy.sms.forwarder.service.FrontService; import com.idormy.sms.forwarder.utils.*; import com.umeng.analytics.MobclickAgent; +import com.umeng.commonsdk.UMConfigure; import java.lang.reflect.Method; import java.util.*; @@ -41,6 +45,10 @@ public class MainActivity extends AppCompatActivity implements RefreshListView.I private Intent serviceIntent; private String currentType = "sms"; + View inflate; + Dialog dialog; + SharedPreferencesHelper sharedPreferencesHelper; + @Override protected void onCreate(Bundle savedInstanceState) { @@ -95,6 +103,14 @@ public class MainActivity extends AppCompatActivity implements RefreshListView.I super.onStart(); Log.d(TAG, "onStart"); + /* sp中uminit为1已经同意隐私协议*/ + sharedPreferencesHelper = new SharedPreferencesHelper(this, "umeng"); + String isAllowed = String.valueOf(sharedPreferencesHelper.getSharedPreference("uminit", "")); + if (isAllowed.equals("") || isAllowed.equals("0")) { + dialog(); + return; + } + //是否关闭页面提示 TextView help_tip = findViewById(R.id.help_tip); help_tip.setVisibility(MyApplication.showHelpTip ? View.VISIBLE : View.GONE); @@ -165,6 +181,7 @@ public class MainActivity extends AppCompatActivity implements RefreshListView.I @Override protected void onResume() { super.onResume(); + MobclickAgent.onPageStart(TAG); MobclickAgent.onResume(this); //第一次打开,未授权无法获取SIM信息,尝试在此重新获取 @@ -208,6 +225,7 @@ public class MainActivity extends AppCompatActivity implements RefreshListView.I @Override protected void onPause() { super.onPause(); + MobclickAgent.onPageEnd(TAG); MobclickAgent.onPause(this); try { if (serviceIntent != null) startService(serviceIntent); @@ -398,4 +416,49 @@ public class MainActivity extends AppCompatActivity implements RefreshListView.I return super.onMenuOpened(featureId, menu); } + /*** 隐私协议授权弹窗*/ + @SuppressLint({"ResourceType", "InflateParams"}) + public void dialog() { + dialog = new Dialog(this, R.style.dialog); + inflate = LayoutInflater.from(MainActivity.this).inflate(R.layout.diaologlayout, null); + TextView succsebtn = (TextView) inflate.findViewById(R.id.succsebtn); + TextView canclebtn = (TextView) inflate.findViewById(R.id.caclebtn); + + succsebtn.setOnClickListener(v -> { + /* uminit为1时代表已经同意隐私协议,sp记录当前状态*/ + sharedPreferencesHelper.put("uminit", "1"); + UMConfigure.submitPolicyGrantResult(getApplicationContext(), true); + /* 友盟sdk正式初始化*/ + UmInitConfig umInitConfig = new UmInitConfig(); + umInitConfig.UMinit(getApplicationContext()); + //关闭弹窗 + dialog.dismiss(); + + //跳转到HomeActivity + final Intent intent = getPackageManager().getLaunchIntentForPackage(getPackageName()); + intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); + startActivity(intent); + + //杀掉以前进程 + android.os.Process.killProcess(android.os.Process.myPid()); + + finish(); + }); + + canclebtn.setOnClickListener(v -> { + dialog.dismiss(); + + UMConfigure.submitPolicyGrantResult(getApplicationContext(), false); + //不同意隐私协议,退出app + android.os.Process.killProcess(android.os.Process.myPid()); + + }); + + dialog.setContentView(inflate); + Window dialogWindow = dialog.getWindow(); + dialogWindow.setGravity(Gravity.CENTER); + + dialog.setCancelable(false); + dialog.show(); + } } diff --git a/app/src/main/java/com/idormy/sms/forwarder/MyApplication.java b/app/src/main/java/com/idormy/sms/forwarder/MyApplication.java index b13bc7b4..42b0f834 100644 --- a/app/src/main/java/com/idormy/sms/forwarder/MyApplication.java +++ b/app/src/main/java/com/idormy/sms/forwarder/MyApplication.java @@ -11,12 +11,11 @@ import android.util.Log; import com.idormy.sms.forwarder.sender.SendHistory; import com.idormy.sms.forwarder.service.BatteryService; import com.idormy.sms.forwarder.service.FrontService; -import com.idormy.sms.forwarder.utils.CommonUtil; import com.idormy.sms.forwarder.utils.Define; import com.idormy.sms.forwarder.utils.PhoneUtils; import com.idormy.sms.forwarder.utils.SettingUtil; +import com.idormy.sms.forwarder.utils.SharedPreferencesHelper; import com.smailnet.emailkit.EmailKit; -import com.umeng.analytics.MobclickAgent; import com.umeng.commonsdk.UMConfigure; import java.util.ArrayList; @@ -28,6 +27,7 @@ public class MyApplication extends Application { public static List SimInfoList = new ArrayList<>(); //是否关闭页面提示 public static boolean showHelpTip = true; + SharedPreferencesHelper sharedPreferencesHelper; @Override protected void attachBaseContext(Context base) { @@ -40,14 +40,6 @@ public class MyApplication extends Application { super.onCreate(); try { - //初始化组件化基础库, 所有友盟业务SDK都必须调用此初始化接口。 - //建议在宿主App的Application.onCreate函数中调用基础组件库初始化函数。 - UMConfigure.init(this, "60254fc7425ec25f10f4293e", CommonUtil.getChannelName(this), UMConfigure.DEVICE_TYPE_PHONE, ""); - // 选用LEGACY_AUTO页面采集模式 - MobclickAgent.setPageCollectionMode(MobclickAgent.PageMode.LEGACY_MANUAL); - //pro close log - UMConfigure.setLogEnabled(true); - //前台服务 Intent intent = new Intent(this, FrontService.class); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { @@ -77,6 +69,20 @@ public class MyApplication extends Application { //电池状态监听 Intent batteryServiceIntent = new Intent(this, BatteryService.class); startService(batteryServiceIntent); + + //友盟统计 + sharedPreferencesHelper = new SharedPreferencesHelper(this, "umeng"); + //设置LOG开关,默认为false + //UMConfigure.setLogEnabled(true); + //友盟预初始化 + UMConfigure.preInit(getApplicationContext(), "60254fc7425ec25f10f4293e", "Umeng"); + + //判断是否同意隐私协议,uminit为1时为已经同意,直接初始化umsdk + if (sharedPreferencesHelper.getSharedPreference("uminit", "").equals("1")) { + //友盟正式初始化 + UmInitConfig umInitConfig = new UmInitConfig(); + umInitConfig.UMinit(getApplicationContext()); + } } catch (Exception e) { Log.e(TAG, "onCreate:", e); } diff --git a/app/src/main/java/com/idormy/sms/forwarder/RuleActivity.java b/app/src/main/java/com/idormy/sms/forwarder/RuleActivity.java index fe550a69..0048efcd 100644 --- a/app/src/main/java/com/idormy/sms/forwarder/RuleActivity.java +++ b/app/src/main/java/com/idormy/sms/forwarder/RuleActivity.java @@ -374,49 +374,49 @@ public class RuleActivity extends AppCompatActivity { buttonInsertSender.setOnClickListener(view -> { textSmsTemplate.setFocusable(true); textSmsTemplate.requestFocus(); - textSmsTemplate.append("{{来源号码}}"); + insertOrReplaceText2Cursor(textSmsTemplate, "{{来源号码}}"); }); Button buttonInsertContent = view1.findViewById(R.id.bt_insert_content); buttonInsertContent.setOnClickListener(view -> { textSmsTemplate.setFocusable(true); textSmsTemplate.requestFocus(); - textSmsTemplate.append("{{短信内容}}"); + insertOrReplaceText2Cursor(textSmsTemplate, "{{短信内容}}"); }); Button buttonInsertSenderApp = view1.findViewById(R.id.bt_insert_sender_app); buttonInsertSenderApp.setOnClickListener(view -> { textSmsTemplate.setFocusable(true); textSmsTemplate.requestFocus(); - textSmsTemplate.append("{{APP包名}}"); + insertOrReplaceText2Cursor(textSmsTemplate, "{{APP包名}}"); }); Button buttonInsertContentApp = view1.findViewById(R.id.bt_insert_content_app); buttonInsertContentApp.setOnClickListener(view -> { textSmsTemplate.setFocusable(true); textSmsTemplate.requestFocus(); - textSmsTemplate.append("{{通知内容}}"); + insertOrReplaceText2Cursor(textSmsTemplate, "{{通知内容}}"); }); Button buttonInsertExtra = view1.findViewById(R.id.bt_insert_extra); buttonInsertExtra.setOnClickListener(view -> { textSmsTemplate.setFocusable(true); textSmsTemplate.requestFocus(); - textSmsTemplate.append("{{卡槽信息}}"); + insertOrReplaceText2Cursor(textSmsTemplate, "{{卡槽信息}}"); }); Button buttonInsertTime = view1.findViewById(R.id.bt_insert_time); buttonInsertTime.setOnClickListener(view -> { textSmsTemplate.setFocusable(true); textSmsTemplate.requestFocus(); - textSmsTemplate.append("{{接收时间}}"); + insertOrReplaceText2Cursor(textSmsTemplate, "{{接收时间}}"); }); Button buttonInsertDeviceName = view1.findViewById(R.id.bt_insert_device_name); buttonInsertDeviceName.setOnClickListener(view -> { textSmsTemplate.setFocusable(true); textSmsTemplate.requestFocus(); - textSmsTemplate.append("{{设备名称}}"); + insertOrReplaceText2Cursor(textSmsTemplate, "{{设备名称}}"); }); //正则替换 @@ -433,6 +433,12 @@ public class RuleActivity extends AppCompatActivity { } + private void insertOrReplaceText2Cursor(EditText editText, String str) { + int start = Math.max(editText.getSelectionStart(), 0); + int end = Math.max(editText.getSelectionEnd(), 0); + editText.getText().replace(Math.min(start, end), Math.max(start, end), str, 0, str.length()); + } + //当更新选择的字段的时候,更新之下各个选项的状态 // 如果设置了转发全部,禁用选择模式和匹配值输入 // 如果设置了多重规则,选择模式置为是 @@ -592,12 +598,14 @@ public class RuleActivity extends AppCompatActivity { @Override protected void onResume() { super.onResume(); + MobclickAgent.onPageStart(TAG); MobclickAgent.onResume(this); } @Override protected void onPause() { super.onPause(); + MobclickAgent.onPageEnd(TAG); MobclickAgent.onPause(this); } diff --git a/app/src/main/java/com/idormy/sms/forwarder/SenderActivity.java b/app/src/main/java/com/idormy/sms/forwarder/SenderActivity.java index b931db1d..9a0103a3 100644 --- a/app/src/main/java/com/idormy/sms/forwarder/SenderActivity.java +++ b/app/src/main/java/com/idormy/sms/forwarder/SenderActivity.java @@ -1022,6 +1022,7 @@ public class SenderActivity extends AppCompatActivity { final EditText editTextTelegramApiToken = view1.findViewById(R.id.editTextTelegramApiToken); final EditText editTextTelegramChatId = view1.findViewById(R.id.editTextTelegramChatId); + final RadioGroup radioGroupTelegramMethod = view1.findViewById(R.id.radioGroupTelegramMethod); final RadioGroup radioGroupProxyType = view1.findViewById(R.id.radioGroupProxyType); final EditText editTextProxyHost = view1.findViewById(R.id.editTextProxyHost); @@ -1058,6 +1059,7 @@ public class SenderActivity extends AppCompatActivity { if (telegramSettingVo != null) { editTextTelegramApiToken.setText(telegramSettingVo.getApiToken()); editTextTelegramChatId.setText(telegramSettingVo.getChatId()); + radioGroupTelegramMethod.check(telegramSettingVo.getMethodCheckId()); radioGroupProxyType.check(telegramSettingVo.getProxyTypeCheckId()); layoutProxyAuthenticator.setVisibility(telegramSettingVo.getProxyAuthenticator() ? View.VISIBLE : View.GONE); @@ -1102,7 +1104,8 @@ public class SenderActivity extends AppCompatActivity { editTextProxyPort.getText().toString().trim(), switchProxyAuthenticator.isChecked(), editTextProxyUsername.getText().toString().trim(), - editTextProxyPassword.getText().toString().trim() + editTextProxyPassword.getText().toString().trim(), + (radioGroupTelegramMethod.getCheckedRadioButtonId() == R.id.radioTelegramMethodGet ? "GET" : "POST") ); newSenderModel.setJsonSetting(JSON.toJSONString(telegramSettingVoNew)); @@ -1121,7 +1124,8 @@ public class SenderActivity extends AppCompatActivity { editTextProxyPort.getText().toString().trim(), switchProxyAuthenticator.isChecked(), editTextProxyUsername.getText().toString().trim(), - editTextProxyPassword.getText().toString().trim() + editTextProxyPassword.getText().toString().trim(), + (radioGroupTelegramMethod.getCheckedRadioButtonId() == R.id.radioTelegramMethodGet ? "GET" : "POST") ); senderModel.setJsonSetting(JSON.toJSONString(telegramSettingVoNew)); SenderUtil.updateSender(senderModel); @@ -1153,9 +1157,10 @@ public class SenderActivity extends AppCompatActivity { editTextProxyPort.getText().toString().trim(), switchProxyAuthenticator.isChecked(), editTextProxyUsername.getText().toString().trim(), - editTextProxyPassword.getText().toString().trim() + editTextProxyPassword.getText().toString().trim(), + (radioGroupTelegramMethod.getCheckedRadioButtonId() == R.id.radioTelegramMethodGet ? "GET" : "POST") ); - SenderTelegramMsg.sendMsg(0, handler, telegramSettingVoNew, getString(R.string.test_phone_num), getString(R.string.test_sms)); + SenderTelegramMsg.sendMsg(0, handler, telegramSettingVoNew, getString(R.string.test_phone_num), getString(R.string.test_sms), telegramSettingVoNew.getMethod()); } catch (Exception e) { Toast.makeText(SenderActivity.this, getString(R.string.failed_to_fwd) + e.getMessage(), Toast.LENGTH_LONG).show(); e.printStackTrace(); @@ -1476,12 +1481,14 @@ public class SenderActivity extends AppCompatActivity { @Override protected void onResume() { super.onResume(); + MobclickAgent.onPageStart(TAG); MobclickAgent.onResume(this); } @Override protected void onPause() { super.onPause(); + MobclickAgent.onPageEnd(TAG); MobclickAgent.onPause(this); } diff --git a/app/src/main/java/com/idormy/sms/forwarder/SettingActivity.java b/app/src/main/java/com/idormy/sms/forwarder/SettingActivity.java index f923cc99..9bb8c0fe 100644 --- a/app/src/main/java/com/idormy/sms/forwarder/SettingActivity.java +++ b/app/src/main/java/com/idormy/sms/forwarder/SettingActivity.java @@ -73,7 +73,8 @@ public class SettingActivity extends AppCompatActivity { switchEnablePhone(switch_enable_phone); @SuppressLint("UseSwitchCompatOrMaterialCode") Switch switch_enable_app_notify = findViewById(R.id.switch_enable_app_notify); - switchEnableAppNotify(switch_enable_app_notify); + @SuppressLint("UseSwitchCompatOrMaterialCode") Switch switch_cancel_app_notify = findViewById(R.id.switch_cancel_app_notify); + switchEnableAppNotify(switch_enable_app_notify, switch_cancel_app_notify); @SuppressLint("UseSwitchCompatOrMaterialCode") Switch switch_exclude_from_recents = findViewById(R.id.switch_exclude_from_recents); switchExcludeFromRecents(switch_exclude_from_recents); @@ -151,10 +152,14 @@ public class SettingActivity extends AppCompatActivity { } //设置转发APP通知 - private void switchEnableAppNotify(@SuppressLint("UseSwitchCompatOrMaterialCode") Switch switch_enable_app_notify) { - switch_enable_app_notify.setChecked(SettingUtil.getSwitchEnableAppNotify()); + private void switchEnableAppNotify(@SuppressLint("UseSwitchCompatOrMaterialCode") Switch switch_enable_app_notify, @SuppressLint("UseSwitchCompatOrMaterialCode") Switch switch_cancel_app_notify) { + final LinearLayout layout_cancel_app_notify = findViewById(R.id.layout_cancel_app_notify); + boolean isEnable = SettingUtil.getSwitchEnableAppNotify(); + switch_enable_app_notify.setChecked(isEnable); + layout_cancel_app_notify.setVisibility(isEnable ? View.VISIBLE : View.GONE); switch_enable_app_notify.setOnCheckedChangeListener((buttonView, isChecked) -> { + layout_cancel_app_notify.setVisibility(isChecked ? View.VISIBLE : View.GONE); //TODO:校验使用APP通知转发必备的权限 if (isChecked) { if (!CommonUtil.isNotificationListenerServiceEnabled(this)) { @@ -169,6 +174,12 @@ public class SettingActivity extends AppCompatActivity { SettingUtil.switchEnableAppNotify(isChecked); Log.d(TAG, "switchEnableAppNotify:" + isChecked); }); + + switch_cancel_app_notify.setChecked(SettingUtil.getSwitchCancelAppNotify()); + switch_cancel_app_notify.setOnCheckedChangeListener((buttonView, isChecked) -> { + SettingUtil.switchCancelAppNotify(isChecked); + Log.d(TAG, "switchCancelAppNotify:" + isChecked); + }); } //不在最近任务列表中显示 @@ -375,24 +386,30 @@ public class SettingActivity extends AppCompatActivity { textSmsTemplate.requestFocus(); switch (v.getId()) { case R.id.bt_insert_sender: - textSmsTemplate.append("{{来源号码}}"); + insertOrReplaceText2Cursor(textSmsTemplate, "{{来源号码}}"); return; case R.id.bt_insert_content: - textSmsTemplate.append("{{短信内容}}"); + insertOrReplaceText2Cursor(textSmsTemplate, "{{短信内容}}"); return; case R.id.bt_insert_extra: - textSmsTemplate.append("{{卡槽信息}}"); + insertOrReplaceText2Cursor(textSmsTemplate, "{{卡槽信息}}"); return; case R.id.bt_insert_time: - textSmsTemplate.append("{{接收时间}}"); + insertOrReplaceText2Cursor(textSmsTemplate, "{{接收时间}}"); return; case R.id.bt_insert_device_name: - textSmsTemplate.append("{{设备名称}}"); + insertOrReplaceText2Cursor(textSmsTemplate, "{{设备名称}}"); return; default: } } + private void insertOrReplaceText2Cursor(EditText editText, String str) { + int start = Math.max(editText.getSelectionStart(), 0); + int end = Math.max(editText.getSelectionEnd(), 0); + editText.getText().replace(Math.min(start, end), Math.max(start, end), str, 0, str.length()); + } + //恢复初始化配置 public void initSetting(View view) { diff --git a/app/src/main/java/com/idormy/sms/forwarder/UmInitConfig.java b/app/src/main/java/com/idormy/sms/forwarder/UmInitConfig.java new file mode 100644 index 00000000..855b82bb --- /dev/null +++ b/app/src/main/java/com/idormy/sms/forwarder/UmInitConfig.java @@ -0,0 +1,59 @@ +package com.idormy.sms.forwarder; + +import android.content.Context; + +import com.umeng.analytics.MobclickAgent; +import com.umeng.commonsdk.UMConfigure; + + +public class UmInitConfig { + + private static final String TAG = "MyApplication"; + + public void UMinit(Context context) { + + //初始化组件化基础库, 统计SDK/推送SDK/分享SDK都必须调用此初始化接口 + UMConfigure.init(context, "60254fc7425ec25f10f4293e", "Umeng", UMConfigure.DEVICE_TYPE_PHONE, ""); + + //集成umeng-crash-vx.x.x.aar,则需要关闭原有统计SDK异常捕获功能 + MobclickAgent.setCatchUncaughtExceptions(false); + + //统计SDK是否支持采集在子进程中打点的自定义事件,默认不支持 + UMConfigure.setProcessEvent(true);//支持多进程打点 + + // 页面数据采集模式 + // setPageCollectionMode接口参数说明: + // 1. MobclickAgent.PageMode.AUTO: 建议大多数用户使用本采集模式,SDK在此模式下自动采集Activity + // 页面访问路径,开发者不需要针对每一个Activity在onResume/onPause函数中进行手动埋点。在此模式下, + // 开发者如需针对Fragment、CustomView等自定义页面进行页面统计,直接调用MobclickAgent.onPageStart/ + // MobclickAgent.onPageEnd手动埋点即可。此采集模式简化埋点工作,唯一缺点是在Android 4.0以下设备中 + // 统计不到Activity页面数据和各类基础指标(提示:目前Android 4.0以下设备市场占比已经极小)。 + + // 2. MobclickAgent.PageMode.MANUAL:对于要求在Android 4.0以下设备中也能正常采集数据的App,可以使用 + // 本模式,开发者需要在每一个Activity的onResume函数中手动调用MobclickAgent.onResume接口,在Activity的 + // onPause函数中手动调用MobclickAgent.onPause接口。在此模式下,开发者如需针对Fragment、CustomView等 + // 自定义页面进行页面统计,直接调用MobclickAgent.onPageStart/MobclickAgent.onPageEnd手动埋点即可。 + + // 如下两种LEGACY模式不建议首次集成友盟统计SDK的新用户选用。 + // 如果您是友盟统计SDK的老用户,App需要从老版本统计SDK升级到8.0.0版本统计SDK, + // 并且:您的App之前MobclickAgent.onResume/onPause接口埋点分散在所有Activity + // 中,逐个删除修改工作量很大且易出错。 + // 若您的App符合以上特征,可以选用如下两种LEGACY模式,否则不建议继续使用LEGACY模式。 + // 简单来说,升级SDK的老用户,如果不需要手动统计页面路径,选用LEGACY_AUTO模式。 + // 如果需要手动统计页面路径,选用LEGACY_MANUAL模式。 + // 3. MobclickAgent.PageMode.LEGACY_AUTO: 本模式适合不需要对Fragment、CustomView + // 等自定义页面进行页面访问统计的开发者,SDK仅对App中所有Activity进行页面统计,开发者需要在 + // 每一个Activity的onResume函数中手动调用MobclickAgent.onResume接口,在Activity的 + // onPause函数中手动调用MobclickAgent.onPause接口。此模式下MobclickAgent.onPageStart + // ,MobclickAgent.onPageEnd这两个接口无效。 + + // 4. MobclickAgent.PageMode.LEGACY_MANUAL: 本模式适合需要对Fragment、CustomView + // 等自定义页面进行手动页面统计的开发者,开发者如需针对Fragment、CustomView等 + // 自定义页面进行页面统计,直接调用MobclickAgent.onPageStart/MobclickAgent.onPageEnd + // 手动埋点即可。开发者还需要在每一个Activity的onResume函数中手动调用MobclickAgent.onResume接口, + // 在Activity的onPause函数中手动调用MobclickAgent.onPause接口。 + MobclickAgent.setPageCollectionMode(MobclickAgent.PageMode.AUTO); + + } + +} diff --git a/app/src/main/java/com/idormy/sms/forwarder/model/vo/TelegramSettingVo.java b/app/src/main/java/com/idormy/sms/forwarder/model/vo/TelegramSettingVo.java index b4cf4c69..fd163d8f 100644 --- a/app/src/main/java/com/idormy/sms/forwarder/model/vo/TelegramSettingVo.java +++ b/app/src/main/java/com/idormy/sms/forwarder/model/vo/TelegramSettingVo.java @@ -17,6 +17,7 @@ public class TelegramSettingVo implements Serializable { private Boolean proxyAuthenticator = false; private String proxyUsername; private String proxyPassword; + private String method; public TelegramSettingVo() { } @@ -25,9 +26,10 @@ public class TelegramSettingVo implements Serializable { this.apiToken = apiToken; this.chatId = chatId; this.proxyType = Proxy.Type.DIRECT; + this.method = "POST"; } - public TelegramSettingVo(String apiToken, String chatId, int proxyTypeId, String proxyHost, String proxyPort, boolean proxyAuthenticator, String proxyUsername, String proxyPassword) { + public TelegramSettingVo(String apiToken, String chatId, int proxyTypeId, String proxyHost, String proxyPort, boolean proxyAuthenticator, String proxyUsername, String proxyPassword, String method) { this.apiToken = apiToken; this.chatId = chatId; if (proxyTypeId == R.id.btnProxyHttp) { @@ -42,6 +44,7 @@ public class TelegramSettingVo implements Serializable { this.proxyAuthenticator = proxyAuthenticator; this.proxyUsername = proxyUsername; this.proxyPassword = proxyPassword; + this.method = method; } public int getProxyTypeCheckId() { @@ -53,4 +56,12 @@ public class TelegramSettingVo implements Serializable { return R.id.btnProxyNone; } } + + public int getMethodCheckId() { + if (method == null || method.equals("POST")) { + return R.id.radioTelegramMethodPost; + } else { + return R.id.radioTelegramMethodGet; + } + } } diff --git a/app/src/main/java/com/idormy/sms/forwarder/receiver/SmsBroadcastReceiver.java b/app/src/main/java/com/idormy/sms/forwarder/receiver/SmsBroadcastReceiver.java index db2fe61c..0cf2e0ec 100644 --- a/app/src/main/java/com/idormy/sms/forwarder/receiver/SmsBroadcastReceiver.java +++ b/app/src/main/java/com/idormy/sms/forwarder/receiver/SmsBroadcastReceiver.java @@ -3,11 +3,13 @@ package com.idormy.sms.forwarder.receiver; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; +import android.os.Build; import android.os.Bundle; import android.telephony.SmsMessage; import android.util.Log; import com.idormy.sms.forwarder.model.vo.SmsHubVo; +import androidx.annotation.RequiresApi; import com.idormy.sms.forwarder.model.vo.SmsVo; import com.idormy.sms.forwarder.sender.SendUtil; import com.idormy.sms.forwarder.utils.*; @@ -21,6 +23,7 @@ import java.util.Objects; public class SmsBroadcastReceiver extends BroadcastReceiver { + @RequiresApi(api = Build.VERSION_CODES.M) @Override public void onReceive(Context context, Intent intent) { diff --git a/app/src/main/java/com/idormy/sms/forwarder/sender/SendUtil.java b/app/src/main/java/com/idormy/sms/forwarder/sender/SendUtil.java index babeb8c0..db4658c8 100644 --- a/app/src/main/java/com/idormy/sms/forwarder/sender/SendUtil.java +++ b/app/src/main/java/com/idormy/sms/forwarder/sender/SendUtil.java @@ -225,7 +225,7 @@ public class SendUtil { TelegramSettingVo telegramSettingVo = JSON.parseObject(senderModel.getJsonSetting(), TelegramSettingVo.class); if (telegramSettingVo != null) { try { - SenderTelegramMsg.sendMsg(logId, handError, telegramSettingVo, smsVo.getMobile(), smsVo.getSmsVoForSend(smsTemplate, regexReplace)); + SenderTelegramMsg.sendMsg(logId, handError, telegramSettingVo, smsVo.getMobile(), smsVo.getSmsVoForSend(smsTemplate, regexReplace), telegramSettingVo.getMethod()); } catch (Exception e) { LogUtil.updateLog(logId, 0, e.getMessage()); Log.e(TAG, "senderSendMsg: SenderTelegramMsg error " + e.getMessage()); diff --git a/app/src/main/java/com/idormy/sms/forwarder/sender/SenderMailMsg.java b/app/src/main/java/com/idormy/sms/forwarder/sender/SenderMailMsg.java index f58f6086..e3614e78 100644 --- a/app/src/main/java/com/idormy/sms/forwarder/sender/SenderMailMsg.java +++ b/app/src/main/java/com/idormy/sms/forwarder/sender/SenderMailMsg.java @@ -8,6 +8,9 @@ import com.idormy.sms.forwarder.utils.SettingUtil; import com.smailnet.emailkit.Draft; import com.smailnet.emailkit.EmailKit; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; import java.util.concurrent.TimeUnit; import io.reactivex.rxjava3.core.Observable; @@ -35,12 +38,15 @@ public class SenderMailMsg extends SenderBaseMsg { .setAccount(fromEmail) //发件人邮箱 .setPassword(pwd); //密码或授权码 + //多个收件人邮箱 + Set toSet = new HashSet<>(Arrays.asList(toAdd.replace(",", ",").split(","))); + //设置一封草稿邮件 Draft draft = new Draft() .setNickname(nickname) //发件人昵称 - .setTo(toAdd) //收件人邮箱 - .setSubject(title) //邮件主题 - .setText(content); //邮件正文 + .setTo(toSet) //收件人邮箱 + .setSubject(title) //邮件主题 + .setText(content); //邮件正文 //使用SMTP服务发送邮件 EmailKit.useSMTPService(config) diff --git a/app/src/main/java/com/idormy/sms/forwarder/sender/SenderSmsMsg.java b/app/src/main/java/com/idormy/sms/forwarder/sender/SenderSmsMsg.java index a9e32678..f4e4ea9f 100644 --- a/app/src/main/java/com/idormy/sms/forwarder/sender/SenderSmsMsg.java +++ b/app/src/main/java/com/idormy/sms/forwarder/sender/SenderSmsMsg.java @@ -1,5 +1,6 @@ package com.idormy.sms.forwarder.sender; +import android.annotation.SuppressLint; import android.os.Handler; import android.util.Log; @@ -11,6 +12,7 @@ public class SenderSmsMsg extends SenderBaseMsg { static final String TAG = "SenderSmsMsg"; + @SuppressLint("NewApi") public static void sendMsg(final long logId, final Handler handError, int simSlot, String mobiles, Boolean onlyNoNetwork, String from, String text) throws Exception { Log.i(TAG, "sendMsg simSlot:" + simSlot + " mobiles:" + mobiles + " onlyNoNetwork:" + onlyNoNetwork + " from:" + from + " text:" + text); diff --git a/app/src/main/java/com/idormy/sms/forwarder/sender/SenderTelegramMsg.java b/app/src/main/java/com/idormy/sms/forwarder/sender/SenderTelegramMsg.java index f3a141e2..6753f49b 100644 --- a/app/src/main/java/com/idormy/sms/forwarder/sender/SenderTelegramMsg.java +++ b/app/src/main/java/com/idormy/sms/forwarder/sender/SenderTelegramMsg.java @@ -37,7 +37,7 @@ public class SenderTelegramMsg extends SenderBaseMsg { static final String TAG = "SenderTelegramMsg"; - public static void sendMsg(final long logId, final Handler handError, TelegramSettingVo telegramSettingVo, String from, String text) throws Exception { + public static void sendMsg(final long logId, final Handler handError, TelegramSettingVo telegramSettingVo, final String from, final String text, final String method) throws Exception { Log.i(TAG, "sendMsg telegramSettingVo:" + telegramSettingVo.toString() + " text:" + text); String apiToken = telegramSettingVo.getApiToken(); @@ -47,22 +47,15 @@ public class SenderTelegramMsg extends SenderBaseMsg { } //特殊处理避免标题重复 - text = text.replaceAll("#", "井").trim(); + final String finalText = text.replaceAll("#", "井").trim(); if (!apiToken.startsWith("http")) { apiToken = "https://api.telegram.org/bot" + apiToken + "/sendMessage"; } + final String requestUrl = apiToken; Log.i(TAG, "requestUrl:" + requestUrl); - Map bodyMap = new HashMap(); - bodyMap.put("chat_id", chatId); - bodyMap.put("text", text); - bodyMap.put("parse_mode", "HTML"); - - final String requestMsg = JSON.toJSONString(bodyMap); - Log.i(TAG, "requestMsg:" + requestMsg); - //代理相关 final Proxy.Type proxyType = telegramSettingVo.getProxyType(); final String proxyHost = telegramSettingVo.getProxyHost(); @@ -107,13 +100,27 @@ public class SenderTelegramMsg extends SenderBaseMsg { .connectionPool(new ConnectionPool(5, 1, TimeUnit.SECONDS)).build(); } - RequestBody requestBody = RequestBody.create(MediaType.parse("application/json;charset=utf-8"), requestMsg); + final Request request; + if (method.equals("GET")) { + request = new Request.Builder() + .url(requestUrl + "?chat_id=" + chatId + "&text=" + finalText) + .build(); + } else { + Map bodyMap = new HashMap(); + bodyMap.put("chat_id", chatId); + bodyMap.put("text", finalText); + bodyMap.put("parse_mode", "HTML"); - final Request request = new Request.Builder() - .url(requestUrl) - .addHeader("Content-Type", "application/json; charset=utf-8") - .post(requestBody) - .build(); + String requestMsg = JSON.toJSONString(bodyMap); + Log.i(TAG, "requestMsg:" + requestMsg); + + RequestBody requestBody = RequestBody.create(MediaType.parse("application/json;charset=utf-8"), requestMsg); + request = new Request.Builder() + .url(requestUrl) + .addHeader("Content-Type", "application/json; charset=utf-8") + .post(requestBody) + .build(); + } client.newCall(request).enqueue(new Callback() { @Override @@ -137,7 +144,7 @@ public class SenderTelegramMsg extends SenderBaseMsg { } } }); - + } catch (Exception e) { LogUtil.updateLog(logId, 0, e.getMessage()); Log.e(TAG, e.getMessage(), e); diff --git a/app/src/main/java/com/idormy/sms/forwarder/service/NotifyService.java b/app/src/main/java/com/idormy/sms/forwarder/service/NotifyService.java index 14e6af64..13a8ab19 100644 --- a/app/src/main/java/com/idormy/sms/forwarder/service/NotifyService.java +++ b/app/src/main/java/com/idormy/sms/forwarder/service/NotifyService.java @@ -66,6 +66,12 @@ public class NotifyService extends NotificationListenerService { packageName, title, text, time) ); + //自动关闭通知 + if (SettingUtil.getSwitchCancelAppNotify()) { + String key = sbn.getKey(); + cancelNotification(key); + } + //重复通知不再处理 String prevHash = SettingUtil.getPrevNoticeHash(packageName); String currHash = CommonUtil.MD5(packageName + title + text + time); @@ -83,7 +89,7 @@ public class NotifyService extends NotificationListenerService { } catch (Exception e) { Log.e(TAG, "onNotificationPosted:", e); } - //NotifyHelper.getInstance().onReceive(sbn); + } /** @@ -99,8 +105,6 @@ public class NotifyService extends NotificationListenerService { if (sbn.getNotification() == null) return; Log.d(TAG, sbn.getPackageName()); - - //NotifyHelper.getInstance().onRemoved(sbn); } /** diff --git a/app/src/main/java/com/idormy/sms/forwarder/utils/CommonUtil.java b/app/src/main/java/com/idormy/sms/forwarder/utils/CommonUtil.java index 3de12192..9f4ef297 100644 --- a/app/src/main/java/com/idormy/sms/forwarder/utils/CommonUtil.java +++ b/app/src/main/java/com/idormy/sms/forwarder/utils/CommonUtil.java @@ -6,10 +6,8 @@ import android.app.Activity; import android.content.ComponentName; import android.content.Context; import android.content.Intent; -import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; -import android.text.TextUtils; import androidx.core.app.ActivityCompat; import androidx.core.app.NotificationManagerCompat; @@ -27,40 +25,6 @@ public class CommonUtil { public static final int NOTIFICATION_REQUEST_CODE = 9527; private static final String ACTION_NOTIFICATION_LISTENER_SETTINGS = "android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS"; - /** - * - * - * - * @param ctx 上下文 - * @return 渠道名称 - */ - // 获取渠道工具函数 - public static String getChannelName(Context ctx) { - if (ctx == null) { - return null; - } - String channelName = null; - try { - PackageManager packageManager = ctx.getPackageManager(); - if (packageManager != null) { - //注意此处为ApplicationInfo 而不是 ActivityInfo,因为友盟设置的meta-data是在application标签中,而不是activity标签中,所以用ApplicationInfo - ApplicationInfo applicationInfo = packageManager.getApplicationInfo(ctx.getPackageName(), PackageManager.GET_META_DATA); - if (applicationInfo.metaData != null) { - channelName = applicationInfo.metaData.get("UMENG_CHANNEL") + ""; - } - } - } catch (PackageManager.NameNotFoundException e) { - e.printStackTrace(); - } - if (TextUtils.isEmpty(channelName)) { - channelName = "Unknown"; - } - - return channelName; - } - //是否启用通知监听服务 public static boolean isNotificationListenerServiceEnabled(Context context) { Set packageNames = NotificationManagerCompat.getEnabledListenerPackages(context); diff --git a/app/src/main/java/com/idormy/sms/forwarder/utils/Define.java b/app/src/main/java/com/idormy/sms/forwarder/utils/Define.java index ec4ceed8..339385e3 100644 --- a/app/src/main/java/com/idormy/sms/forwarder/utils/Define.java +++ b/app/src/main/java/com/idormy/sms/forwarder/utils/Define.java @@ -9,6 +9,7 @@ public class Define { public static final String SP_MSG_KEY_STRING_ENABLE_SMS = "tsms_msg_key_switch_enable_sms"; public static final String SP_MSG_KEY_STRING_ENABLE_PHONE = "tsms_msg_key_switch_enable_phone"; public static final String SP_MSG_KEY_STRING_ENABLE_APP_NOTIFY = "tsms_msg_key_switch_enable_app_notify"; + public static final String SP_MSG_KEY_STRING_CANCEL_APP_NOTIFY = "tsms_msg_key_switch_cancel_app_notify"; public static final String SP_MSG_KEY_STRING_ENABLE_EXCLUDE_FROM_RECENTS = "tsms_msg_key_switch_enable_exclude_from_recents"; public static final String SP_MSG_KEY_STRING_ADD_EXTRA_DEVICE_MARK = "tsms_msg_key_string_add_extra_device_mark"; public static final String SP_MSG_KEY_STRING_ADD_EXTRA_SIM1 = "tsms_msg_key_string_add_extra_sim1"; diff --git a/app/src/main/java/com/idormy/sms/forwarder/utils/PhoneUtils.java b/app/src/main/java/com/idormy/sms/forwarder/utils/PhoneUtils.java index 93140862..71bdefb3 100644 --- a/app/src/main/java/com/idormy/sms/forwarder/utils/PhoneUtils.java +++ b/app/src/main/java/com/idormy/sms/forwarder/utils/PhoneUtils.java @@ -329,7 +329,7 @@ public class PhoneUtils { * * @return 多Sim卡的具体信息 */ - @SuppressLint("ObsoleteSdkInt") + @SuppressLint({"ObsoleteSdkInt", "Range"}) public static List getSimMultiInfo() { List infos = new ArrayList<>(); Log.d(TAG, "Build.VERSION.SDK_INT = " + Build.VERSION.SDK_INT); @@ -533,6 +533,7 @@ public class PhoneUtils { /** * 获取后一条通话记录 */ + @SuppressLint("Range") public static CallInfo getLastCallInfo(String phoneNumber) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP_MR1) { return null; diff --git a/app/src/main/java/com/idormy/sms/forwarder/utils/SettingUtil.java b/app/src/main/java/com/idormy/sms/forwarder/utils/SettingUtil.java index 0cdd855b..5458198a 100644 --- a/app/src/main/java/com/idormy/sms/forwarder/utils/SettingUtil.java +++ b/app/src/main/java/com/idormy/sms/forwarder/utils/SettingUtil.java @@ -78,6 +78,16 @@ public class SettingUtil { return sp_setting.getBoolean(Define.SP_MSG_KEY_STRING_ENABLE_APP_NOTIFY, false); } + public static void switchCancelAppNotify(Boolean enable) { + sp_setting.edit() + .putBoolean(Define.SP_MSG_KEY_STRING_CANCEL_APP_NOTIFY, enable) + .apply(); + } + + public static boolean getSwitchCancelAppNotify() { + return sp_setting.getBoolean(Define.SP_MSG_KEY_STRING_CANCEL_APP_NOTIFY, true); + } + public static void switchEnableBatteryReceiver(Boolean enable) { sp_setting.edit() .putBoolean(Define.SP_MSG_KEY_STRING_BATTERY_RECEIVER, enable) diff --git a/app/src/main/java/com/idormy/sms/forwarder/utils/SharedPreferencesHelper.java b/app/src/main/java/com/idormy/sms/forwarder/utils/SharedPreferencesHelper.java new file mode 100644 index 00000000..c1c98722 --- /dev/null +++ b/app/src/main/java/com/idormy/sms/forwarder/utils/SharedPreferencesHelper.java @@ -0,0 +1,87 @@ +package com.idormy.sms.forwarder.utils; + +import android.content.Context; +import android.content.SharedPreferences; + +import java.util.Map; + +public class SharedPreferencesHelper { + + private final SharedPreferences sharedPreferences; + private final SharedPreferences.Editor editor; + + public SharedPreferencesHelper(Context context, String FILE_NAME) { + sharedPreferences = context.getSharedPreferences(FILE_NAME, + Context.MODE_PRIVATE); + editor = sharedPreferences.edit(); + } + + /** + * 存储 + */ + public void put(String key, Object object) { + if (object instanceof String) { + editor.putString(key, (String) object); + } else if (object instanceof Integer) { + editor.putInt(key, (Integer) object); + } else if (object instanceof Boolean) { + editor.putBoolean(key, (Boolean) object); + } else if (object instanceof Float) { + editor.putFloat(key, (Float) object); + } else if (object instanceof Long) { + editor.putLong(key, (Long) object); + } else { + editor.putString(key, object.toString()); + } + editor.commit(); + } + + /** + * 获取保存的数据 + */ + public Object getSharedPreference(String key, Object defaultObject) { + if (defaultObject instanceof String) { + return sharedPreferences.getString(key, (String) defaultObject); + } else if (defaultObject instanceof Integer) { + return sharedPreferences.getInt(key, (Integer) defaultObject); + } else if (defaultObject instanceof Boolean) { + return sharedPreferences.getBoolean(key, (Boolean) defaultObject); + } else if (defaultObject instanceof Float) { + return sharedPreferences.getFloat(key, (Float) defaultObject); + } else if (defaultObject instanceof Long) { + return sharedPreferences.getLong(key, (Long) defaultObject); + } else { + return sharedPreferences.getString(key, null); + } + } + + /** + * 移除某个key值已经对应的值 + */ + public void remove(String key) { + editor.remove(key); + editor.commit(); + } + + /** + * 清除所有数据 + */ + public void clear() { + editor.clear(); + editor.commit(); + } + + /** + * 查询某个key是否存在 + */ + public Boolean contain(String key) { + return sharedPreferences.contains(key); + } + + /** + * 返回所有的键值对 + */ + public Map getAll() { + return sharedPreferences.getAll(); + } +} diff --git a/app/src/main/res/layout/activity_setting.xml b/app/src/main/res/layout/activity_setting.xml index 7d403675..f2b17c31 100644 --- a/app/src/main/res/layout/activity_setting.xml +++ b/app/src/main/res/layout/activity_setting.xml @@ -300,7 +300,6 @@ android:gravity="end" android:textSize="18sp" tools:ignore="UseSwitchCompatOrMaterialXml" /> - + tools:ignore="SmallSp,TooManyViews" /> + android:layout_height="wrap_content" + android:layout_marginStart="10dp" + android:layout_marginEnd="10dp" + android:layout_marginTop="5dp" + android:background="@android:color/white" + android:gravity="center_vertical" + android:orientation="vertical"> - + android:orientation="horizontal"> + + + + + + tools:ignore="LabelFor,TextFields" /> + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -