Compare commits

...

16 Commits

Author SHA1 Message Date
302a7dd438 Merge pull request 'master' (#1) from master into dev
Reviewed-on: #1
2024-06-26 17:43:10 +08:00
269cbb6736 适配android 12PendingIntent. 2024-06-25 01:25:27 +08:00
7297b8f1c4 Update MainActivity.java 2024-05-16 01:12:54 +08:00
48be0900e1 Merge branch 'master' of https://gitea.kimgo.cn/wsy182/EchoLink 2024-05-16 00:55:21 +08:00
620235c089 Update DeviceInfoUtils.java 2024-05-16 00:55:14 +08:00
b3752e4716 Update HeartbeatAlarmReceiver.java 2024-05-16 00:55:09 +08:00
ffc88920db Update AndroidManifest.xml 2024-05-16 00:55:01 +08:00
492cafb51a 删除 app/debug/output-metadata.json 2024-05-16 00:52:58 +08:00
bfc5e4905a Update .gitignore 2024-05-16 00:52:19 +08:00
e55cba4b63 Update .gitignore 2024-05-16 00:51:13 +08:00
59eae71d70 change .gitignore 2024-05-15 10:10:18 +08:00
4463c24107 Update .gitignore 2024-05-15 10:05:15 +08:00
c416971d67 Update NotificationListener.java 2024-04-22 15:12:55 +08:00
21dc14ba5f Update DeviceInfoUtils.java 2024-04-22 14:53:20 +08:00
b4b02d0b1c Update FileLoggingTree.java 2024-04-22 14:53:16 +08:00
443b41fde6 Update EchoLink.java 2024-04-22 14:53:13 +08:00
10 changed files with 92 additions and 75 deletions

22
.gitignore vendored
View File

@@ -2,4 +2,24 @@
.idea .idea
.DS_Store .DS_Store
local.properties local.properties
app/debug/app-debug.apk # Built application files
*.apk
*.ap_
# Generated files
bin/
gen/
out/
# Gradle files
build/
# Keystore files
*.jks
*.keystore
app/release
app/release/*
app/debug
app/debug/*
app/debug/output-metadata.json

View File

@@ -1,20 +0,0 @@
{
"version": 3,
"artifactType": {
"type": "APK",
"kind": "Directory"
},
"applicationId": "com.nbee.echolink",
"variantName": "debug",
"elements": [
{
"type": "SINGLE",
"filters": [],
"attributes": [],
"versionCode": 1,
"versionName": "1.0.1",
"outputFile": "app-debug.apk"
}
],
"elementType": "File"
}

View File

@@ -2,6 +2,7 @@
<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">
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" /> <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACTION_NOTIFICATION_LISTENER_SETTINGS" /> <uses-permission android:name="android.permission.ACTION_NOTIFICATION_LISTENER_SETTINGS" />
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"/> <uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"/>
<uses-permission android:name="android.permission.ANSWER_PHONE_CALLS" /> <uses-permission android:name="android.permission.ANSWER_PHONE_CALLS" />

View File

@@ -1,9 +1,9 @@
package com.nbee.echolink; package com.nbee.echolink;
import android.app.Application; import android.app.Application;
import timber.log.Timber; import timber.log.Timber;
public class EchoLink extends Application { public class EchoLink extends Application {
@Override @Override
public void onCreate() { public void onCreate() {

View File

@@ -3,7 +3,6 @@ package com.nbee.echolink;
import android.content.Context; import android.content.Context;
import android.util.Log; import android.util.Log;
import timber.log.Timber; import timber.log.Timber;
import java.io.File; import java.io.File;
import java.io.FileWriter; import java.io.FileWriter;
import java.io.IOException; import java.io.IOException;

View File

@@ -15,6 +15,7 @@ import com.nbee.echolink.async.BatteryOptimizationTask;
import com.nbee.echolink.service.MonitorService; import com.nbee.echolink.service.MonitorService;
import com.nbee.echolink.service.NotificationListener; import com.nbee.echolink.service.NotificationListener;
import com.nbee.echolink.utils.BatteryOptimizationUtil; import com.nbee.echolink.utils.BatteryOptimizationUtil;
import com.nbee.echolink.utils.DeviceInfoUtils;
import com.nbee.echolink.utils.PermissionUtils; import com.nbee.echolink.utils.PermissionUtils;
import com.nbee.echolink.utils.SharedPreferencesManager; import com.nbee.echolink.utils.SharedPreferencesManager;
import com.nbee.echolink.utils.ShellUtils; import com.nbee.echolink.utils.ShellUtils;
@@ -60,6 +61,8 @@ public class MainActivity extends AppCompatActivity {
if (isFirstRun()) { if (isFirstRun()) {
setupInitialDataAsync(); // 异步设置初始数据 setupInitialDataAsync(); // 异步设置初始数据
spManager.putBoolean("isFirstRun", false); // 标记不再首次运行 spManager.putBoolean("isFirstRun", false); // 标记不再首次运行
Timber.i("首次运行,设置初始数据...");
Timber.d("android_ID: " + DeviceInfoUtils.getAndroidID(this));
} }
// 请求忽略电池优化设置 // 请求忽略电池优化设置

View File

@@ -105,9 +105,8 @@ public class HeartbeatAlarmReceiver extends BroadcastReceiver {
*/ */
private <T> Request buildRequest(String apiUrl) { private <T> Request buildRequest(String apiUrl) {
// 从资源文件中读取序列号和访问令牌 // 从资源文件中读取序列号和访问令牌
// SN = context.getResources().getString(R.string.SN); //SN = thisContext.getResources().getString(R.string.SN);
SN = DeviceInfoUtils.getDeviceSerial(); SN = DeviceInfoUtils.getAndroidID(thisContext);
Timber.i("SN: " + SN);
accessToken = thisContext.getResources().getString(R.string.access_token); accessToken = thisContext.getResources().getString(R.string.access_token);
// 创建设备信息对象并设置设备相关属性 // 创建设备信息对象并设置设备相关属性
DeviceInfo deviceInfo = new DeviceInfo(); DeviceInfo deviceInfo = new DeviceInfo();

View File

@@ -216,8 +216,16 @@ public class MonitorService extends Service {
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
// 创建一个意图,指定当闹钟触发时要执行的广播接收器 // 创建一个意图,指定当闹钟触发时要执行的广播接收器
Intent intent = new Intent(context, HeartbeatAlarmReceiver.class); Intent intent = new Intent(context, HeartbeatAlarmReceiver.class);
// 根据意图和标志位创建一个唯一的PendingIntent系统通过这个PendingIntent触发广播
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0); // 根据Android版本选择合适的标志位创建一个唯一的PendingIntent
PendingIntent pendingIntent = null;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
// Android 12及以上版本需要指定FLAG_IMMUTABLE或FLAG_MUTABLE
pendingIntent = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_IMMUTABLE);
} else {
// 早期版本不需要指定这些标志
pendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
}
// 计算心跳事件的触发间隔,单位为毫秒 // 计算心跳事件的触发间隔,单位为毫秒
long intervalMillis = HEARTBEAT_INTERVAL_MINUTES * 60 * 1000; // 10分钟的毫秒数 long intervalMillis = HEARTBEAT_INTERVAL_MINUTES * 60 * 1000; // 10分钟的毫秒数
@@ -235,4 +243,5 @@ public class MonitorService extends Service {
} }
} }
} }

View File

@@ -12,6 +12,7 @@ import com.nbee.echolink.model.WeChatMsg;
import com.nbee.echolink.utils.HandleNoticeUtils; import com.nbee.echolink.utils.HandleNoticeUtils;
import com.nbee.echolink.utils.NetworkUtils; import com.nbee.echolink.utils.NetworkUtils;
import java.text.DateFormat;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.Arrays; import java.util.Arrays;
import java.util.Date; import java.util.Date;
@@ -27,6 +28,7 @@ public class NotificationListener extends NotificationListenerService {
private static final List<String> notAllowList = Arrays.asList("com.github.kr328.clash","com.google.android.dialer", private static final List<String> notAllowList = Arrays.asList("com.github.kr328.clash","com.google.android.dialer",
"com.google.android.apps.messaging"); "com.google.android.apps.messaging");
private HandleNoticeUtils handleNoticeUtils; private HandleNoticeUtils handleNoticeUtils;
private static final DateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault());
private NetworkUtils networkUtil; private NetworkUtils networkUtil;
private final HashMap<String, Long> recentLogs = new HashMap<>(); private final HashMap<String, Long> recentLogs = new HashMap<>();
private final Handler logCleanerHandler = new Handler(Looper.getMainLooper()); private final Handler logCleanerHandler = new Handler(Looper.getMainLooper());
@@ -46,39 +48,52 @@ public class NotificationListener extends NotificationListenerService {
} }
Bundle extras = sbn.getNotification().extras; Bundle extras = sbn.getNotification().extras;
String title = extras.getString(Notification.EXTRA_TITLE); String title = getNotificationText(extras, Notification.EXTRA_TITLE);
String content = extras.getString(Notification.EXTRA_TEXT); String content = getNotificationText(extras, Notification.EXTRA_TEXT);
String tickerText = sbn.getNotification().tickerText != null ? sbn.getNotification().tickerText.toString() : ""; String tickerText = sbn.getNotification().tickerText != null ? sbn.getNotification().tickerText.toString() : "";
String logMessage = String.format("packageName: %s, title: %s, content: %s, tickerText: %s", packageName, title, content, tickerText); String logMessage = String.format("packageName: %s, title: %s, content: %s, tickerText: %s", packageName, title, content, tickerText);
String appName = handleNoticeUtils.messageHandle(packageName);
if ("微信".equals(appName) && tickerText.contains(":")) { if (!shouldPrintLog(logMessage)) {
return; // 如果在30秒内已打印过则跳过
}
String appName = handleNoticeUtils.messageHandle(packageName);
if ("微信".equals(appName)) {
handleWeChatNotification(packageName, title, tickerText);
}
Timber.d(logMessage);
}
private String getNotificationText(Bundle extras, String key) {
CharSequence charSequence = extras.getCharSequence(key);
return charSequence != null ? charSequence.toString() : "";
}
private void handleWeChatNotification(String packageName, String title, String tickerText) {
if (tickerText.contains(":")) {
String[] parts = tickerText.split(":", 2); String[] parts = tickerText.split(":", 2);
String sender = parts[0].trim(); // 去除两端的空格 if (parts.length < 2) return; // 安全检查,确保不会因数组越界而崩溃
String message = parts.length > 1 ? parts[1].trim() : ""; // 同样去除两端的空格
String sender = parts[0].trim();
String message = parts[1].trim();
WeChatMsg weChatMsg = new WeChatMsg(); WeChatMsg weChatMsg = new WeChatMsg();
weChatMsg.setPackageName(packageName); weChatMsg.setPackageName(packageName);
weChatMsg.setSender(sender); weChatMsg.setSender(sender);
weChatMsg.setMessage(message); weChatMsg.setMessage(message);
weChatMsg.setTitle(title); weChatMsg.setTitle(title);
weChatMsg.setAppName(appName); weChatMsg.setAppName("微信");
weChatMsg.setCurrentTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault()).format(new Date())); weChatMsg.setCurrentTime(DATE_FORMAT.format(new Date()));
Timber.d("准备发送微信消息: %s", weChatMsg); try {
// 异步执行网络请求 Timber.d("准备将接受的微信通知转发: %s", weChatMsg);
networkUtil.postRequest(weChatMsg); networkUtil.postRequest(weChatMsg);
return; } catch (Exception e) {
Timber.e(e, "转发送微信通知失败");
} }
// 检查是否在30秒内已打印过相同内容
if (!shouldPrintLog(logMessage)) {
return; // 如果在30秒内已打印过则跳过
} }
// Timber.d(logMessage);
} }
@Override @Override
public void onNotificationRemoved(StatusBarNotification sbn) { public void onNotificationRemoved(StatusBarNotification sbn) {
// 当通知被移除时调用 // 当通知被移除时调用

View File

@@ -1,14 +1,16 @@
package com.nbee.echolink.utils; package com.nbee.echolink.utils;
import java.util.Locale; import java.util.Locale;
import android.content.Context; import android.content.Context;
import android.os.Build;
import android.provider.Settings;
import android.telephony.TelephonyManager; import android.telephony.TelephonyManager;
import android.util.Log; import android.util.Log;
public class DeviceInfoUtils { public class DeviceInfoUtils {
/** /**
* 获取设备宽度px * 获取设备宽度px
*
*/ */
public static int getDeviceWidth(Context context) { public static int getDeviceWidth(Context context) {
return context.getResources().getDisplayMetrics().widthPixels; return context.getResources().getDisplayMetrics().widthPixels;
@@ -20,6 +22,7 @@ public class DeviceInfoUtils {
public static int getDeviceHeight(Context context) { public static int getDeviceHeight(Context context) {
return context.getResources().getDisplayMetrics().heightPixels; return context.getResources().getDisplayMetrics().heightPixels;
} }
/** /**
* 获取厂商名 * 获取厂商名
**/ **/
@@ -63,8 +66,6 @@ public class DeviceInfoUtils {
} }
/** /**
*
*
* fingerprit 信息 * fingerprit 信息
**/ **/
public static String getDeviceFubgerprint() { public static String getDeviceFubgerprint() {
@@ -73,7 +74,6 @@ public class DeviceInfoUtils {
/** /**
* 硬件名 * 硬件名
*
**/ **/
public static String getDeviceHardware() { public static String getDeviceHardware() {
return android.os.Build.HARDWARE; return android.os.Build.HARDWARE;
@@ -81,14 +81,12 @@ public class DeviceInfoUtils {
/** /**
* 主机 * 主机
*
**/ **/
public static String getDeviceHost() { public static String getDeviceHost() {
return android.os.Build.HOST; return android.os.Build.HOST;
} }
/** /**
*
* 显示ID * 显示ID
**/ **/
public static String getDeviceDisplay() { public static String getDeviceDisplay() {
@@ -97,15 +95,24 @@ public class DeviceInfoUtils {
/** /**
* ID * ID
*
**/ **/
public static String getDeviceId() { public static String getDeviceId() {
return android.os.Build.ID; return android.os.Build.ID;
} }
/** /**
* 获取手机用户名 * 获取设备的Android ID。
* *
* @param context 上下文对象,用于访问应用特定的资源和类。
* @return 设备唯一的Android ID是一个64位的十进制字符串。
*/
public static String getAndroidID(Context context) {
// 通过Settings.Secure.getString获取设备的Android ID
return Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID);
}
/**
* 获取手机用户名
**/ **/
public static String getDeviceUser() { public static String getDeviceUser() {
return android.os.Build.USER; return android.os.Build.USER;
@@ -115,9 +122,10 @@ public class DeviceInfoUtils {
* 获取手机 硬件序列号 * 获取手机 硬件序列号
**/ **/
public static String getDeviceSerial() { public static String getDeviceSerial() {
return android.os.Build.SERIAL; return "89KX0ARVK";
} }
/** /**
* 获取手机Android 系统SDK * 获取手机Android 系统SDK
* *
@@ -143,21 +151,4 @@ public class DeviceInfoUtils {
return Locale.getDefault().getLanguage(); return Locale.getDefault().getLanguage();
} }
/**
* 获取当前系统上的语言列表(Locale列表)
*/
public static String getDeviceSupportLanguage() {
Log.e("wangjie", "Local:" + Locale.GERMAN);
Log.e("wangjie", "Local:" + Locale.ENGLISH);
Log.e("wangjie", "Local:" + Locale.US);
Log.e("wangjie", "Local:" + Locale.CHINESE);
Log.e("wangjie", "Local:" + Locale.TAIWAN);
Log.e("wangjie", "Local:" + Locale.FRANCE);
Log.e("wangjie", "Local:" + Locale.FRENCH);
Log.e("wangjie", "Local:" + Locale.GERMANY);
Log.e("wangjie", "Local:" + Locale.ITALIAN);
Log.e("wangjie", "Local:" + Locale.JAPAN);
Log.e("wangjie", "Local:" + Locale.JAPANESE);
return Locale.getAvailableLocales().toString();
}
} }