diff --git a/app/src/main/java/cn/shangyu/gdxzExpert/application/BaseApplication.java b/app/src/main/java/cn/shangyu/gdxzExpert/application/BaseApplication.java index a0aaef2..c74efd4 100644 --- a/app/src/main/java/cn/shangyu/gdxzExpert/application/BaseApplication.java +++ b/app/src/main/java/cn/shangyu/gdxzExpert/application/BaseApplication.java @@ -309,14 +309,17 @@ public class BaseApplication extends Application { // CrashHandler.getInstance().init(getApplicationContext()); // } - // 注册Activity生命周期回调,用于跟踪当前resumed的Activity + // 注册Activity生命周期回调,用于跟踪当前resumed的Activity并在退后台时上报缓存画像埋点 registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() { + private int startedActivityCount = 0; + @Override public void onActivityCreated(Activity activity, Bundle savedInstanceState) { } @Override public void onActivityStarted(Activity activity) { + startedActivityCount++; } @Override @@ -334,6 +337,10 @@ public class BaseApplication extends Application { @Override public void onActivityStopped(Activity activity) { + startedActivityCount = Math.max(0, startedActivityCount - 1); + if (startedActivityCount == 0 && activity != null && !activity.isChangingConfigurations()) { + startReport(null); + } } @Override diff --git a/app/src/main/java/cn/shangyu/gdxzExpert/base/BaseActivity.java b/app/src/main/java/cn/shangyu/gdxzExpert/base/BaseActivity.java index ee5899e..bc69482 100644 --- a/app/src/main/java/cn/shangyu/gdxzExpert/base/BaseActivity.java +++ b/app/src/main/java/cn/shangyu/gdxzExpert/base/BaseActivity.java @@ -1527,10 +1527,15 @@ public abstract class BaseActivity extends AppCompatActivity implements * @param context * @param type 操作类型 整型数据 ---1登入系统 2退出系统 3专家客户端在手机前台运行 4.专家客户端在手机后台运行 void */ - public static void foreBack(Context context, int type) { - if (type==2){ - type =4; - } + public static void foreBack(Context context, int type) { + if (type==2){ + type =4; + } + if (type == 4 && context != null) { + Intent reportIntent = new Intent(context, ReportService.class); + reportIntent.putExtra("report_token", Constant.Repotr_token); + context.startService(reportIntent); + } String uuid = SharePrefUtil.getString(context, Constant.uuid, ""); RequestParams params = new RequestParams();//封装参数 params.addBodyParameter("expertUuid", uuid); diff --git a/app/src/main/java/cn/shangyu/gdxzExpert/report/ReportService.java b/app/src/main/java/cn/shangyu/gdxzExpert/report/ReportService.java index 8bd2359..a6f1a11 100644 --- a/app/src/main/java/cn/shangyu/gdxzExpert/report/ReportService.java +++ b/app/src/main/java/cn/shangyu/gdxzExpert/report/ReportService.java @@ -52,6 +52,8 @@ public class ReportService extends Service { } private static final ExecutorService REPORT_EXECUTOR = Executors.newSingleThreadExecutor(); private static final List PENDING_BEFORE_TOKEN_LIST = new ArrayList<>(); + /** 普通浏览埋点攒批阈值(满 20 条自动打包上传) */ + private static final int BATCH_UPLOAD_THRESHOLD = 20; public String ReportFile; public String ReportUploadingDir; @@ -155,7 +157,7 @@ public class ReportService extends Service { } // Token 已就绪:先把之前暂存的埋点补齐 user_id/app_key 并落盘 - flushPendingBeforeTokenList(); + boolean pendingHasImmediate = flushPendingBeforeTokenList(); if (incomingList == null) { if (checkReport()) { @@ -165,25 +167,63 @@ public class ReportService extends Service { } if (!incomingList.isEmpty()) { - writeReport(incomingList); + writeReport(incomingList, pendingHasImmediate); + } else if (pendingHasImmediate && checkReport()) { + zipFile(); } } - private void flushPendingBeforeTokenList() { + private boolean flushPendingBeforeTokenList() { if (!PENDING_BEFORE_TOKEN_LIST.isEmpty()) { + boolean hasImmediate = shouldFlushImmediately(PENDING_BEFORE_TOKEN_LIST); CommUtil.saveListToFile(PENDING_BEFORE_TOKEN_LIST, ReportFile, "upload", ReportFileZip); CommUtil.totalreport += PENDING_BEFORE_TOKEN_LIST.size(); PENDING_BEFORE_TOKEN_LIST.clear(); + return hasImmediate; } + return false; + } + + /** + * 判断是否包含高优先级关键业务事件(登录、签到、支付/积分兑换、文献下载、修改资料、收藏、分享等), + * 关键事件落盘后立即触发打包上传,保证实时性。 + */ + private boolean shouldFlushImmediately(List beanList) { + if (beanList == null || beanList.isEmpty()) { + return false; + } + for (reportBean item : beanList) { + if (item == null) { + continue; + } + if (!StringUtil.isEmpty(item.getEvent_val())) { + return true; + } + String eventName = item.getEvent_nickname(); + if ("login".equals(eventName) + || "signin".equals(eventName) + || "magazine_donwload".equals(eventName) + || "modify".equals(eventName) + || "collect".equals(eventName) + || "share".equals(eventName)) { + return true; + } + } + return false; } public void writeReport(List currentList) { - // 始终先把当前批次写入本地 upload.txt,避免第 100 条埋点丢失或上传期间新埋点丢失 + writeReport(currentList, false); + } + + public void writeReport(List currentList, boolean forceImmediate) { + // 始终先把当前批次写入本地 upload.txt,避免触发阈值那条埋点丢失或上传期间新埋点丢失 CommUtil.saveListToFile(currentList, ReportFile, "upload", ReportFileZip); CommUtil.totalreport += currentList.size(); Log.d("okhttp", "CommUtil.totalreport " + CommUtil.totalreport); - if (CommUtil.totalreport >= 100 && checkReport()) { + boolean immediate = forceImmediate || shouldFlushImmediately(currentList); + if ((immediate || CommUtil.totalreport >= BATCH_UPLOAD_THRESHOLD) && checkReport()) { zipFile(); } } @@ -252,7 +292,7 @@ public class ReportService extends Service { // 仅清理已上传成功的快照目录 ReportUploadingDir,保留上传期间新写入 ReportFile 的数据 CommUtil.deleteFile(ReportFileZip, "outputandroid.zip", ReportUploadingDir); CommUtil.isReoprtingNow = "false"; - if (CommUtil.totalreport >= 100 && checkReport()) { + if (CommUtil.totalreport >= BATCH_UPLOAD_THRESHOLD && checkReport()) { zipFile(); } } @@ -370,8 +410,8 @@ public class ReportService extends Service { REPORT_EXECUTOR.execute(new Runnable() { @Override public void run() { - flushPendingBeforeTokenList(); - if (!retryUploadAfterToken && CommUtil.totalreport >= 100 && checkReport()) { + boolean hasImmediate = flushPendingBeforeTokenList(); + if (!retryUploadAfterToken && (hasImmediate || CommUtil.totalreport >= BATCH_UPLOAD_THRESHOLD) && checkReport()) { zipFile(); } }