码桶
发现社区成员的开源项目
ForumSyncWorker.kt4.3 KB
package com.dalao.forum
import android.content.Context
import android.webkit.CookieManager
import androidx.work.Worker
import androidx.work.WorkerParameters
import org.json.JSONObject
import java.net.HttpURLConnection
import java.net.URL
/**
* 后台轮询:复用 WebView 登录 Cookie 请求论坛接口,比对新帖/评论/私信数量,增加则弹通知。
*
* ============ 需要你填的地方 ============
* STATUS_ENDPOINT:填 dalao.net 返回未读计数的接口地址(需登录后可访问)。
* 期望返回 JSON,形如:{"new_posts":3,"new_comments":1,"new_messages":2}
* 若字段名不同,改 parseCounts() 里的取值键名即可。
* 未配置(留空)时 Worker 安全空转,不会崩溃。
* =======================================
*/
class ForumSyncWorker(
context: Context,
params: WorkerParameters
) : Worker(context, params) {
companion object {
private const val STATUS_ENDPOINT = "" // 例如 "https://www.dalao.net/api/notifications"
private const val PREFS = "forum_sync_prefs"
private const val KEY_POSTS = "last_posts"
private const val KEY_COMMENTS = "last_comments"
private const val KEY_MESSAGES = "last_messages"
private const val NOTIF_POSTS = 2001
private const val NOTIF_COMMENTS = 2002
private const val NOTIF_MESSAGES = 2003
}
override fun doWork(): Result {
if (STATUS_ENDPOINT.isBlank()) return Result.success() // 未配置接口:空转
val body = fetch(STATUS_ENDPOINT) ?: return Result.retry()
val counts = parseCounts(body) ?: return Result.success()
val prefs = applicationContext.getSharedPreferences(PREFS, Context.MODE_PRIVATE)
val ctx = applicationContext
checkAndNotify(
ctx, NotificationHelper.CHANNEL_POSTS, NOTIF_POSTS,
prefs, KEY_POSTS, counts.posts,
ctx.getString(R.string.channel_posts_name),
ctx.getString(R.string.notif_new_posts, counts.posts)
)
checkAndNotify(
ctx, NotificationHelper.CHANNEL_COMMENTS, NOTIF_COMMENTS,
prefs, KEY_COMMENTS, counts.comments,
ctx.getString(R.string.channel_comments_name),
ctx.getString(R.string.notif_new_comments, counts.comments)
)
checkAndNotify(
ctx, NotificationHelper.CHANNEL_MESSAGES, NOTIF_MESSAGES,
prefs, KEY_MESSAGES, counts.messages,
ctx.getString(R.string.channel_messages_name),
ctx.getString(R.string.notif_new_messages, counts.messages)
)
return Result.success()
}
private data class Counts(val posts: Int, val comments: Int, val messages: Int)
private fun parseCounts(body: String): Counts? = try {
val json = JSONObject(body)
Counts(
posts = json.optInt("new_posts", 0),
comments = json.optInt("new_comments", 0),
messages = json.optInt("new_messages", 0)
)
} catch (e: Exception) {
null
}
private fun checkAndNotify(
ctx: Context, channel: String, notifId: Int,
prefs: android.content.SharedPreferences, key: String,
current: Int, title: String, content: String
) {
val last = prefs.getInt(key, 0)
if (current > last && current > 0) {
NotificationHelper.notify(ctx, channel, notifId, title, content)
}
prefs.edit().putInt(key, current).apply()
}
private fun fetch(endpoint: String): String? {
var conn: HttpURLConnection? = null
return try {
conn = (URL(endpoint).openConnection() as HttpURLConnection).apply {
requestMethod = "GET"
connectTimeout = 15000
readTimeout = 15000
// 复用 WebView 登录态:带上该域名的 Cookie
val cookie = CookieManager.getInstance().getCookie(endpoint)
if (!cookie.isNullOrBlank()) setRequestProperty("Cookie", cookie)
setRequestProperty("User-Agent", "DomainForumApp")
}
if (conn.responseCode == 200) {
conn.inputStream.bufferedReader().use { it.readText() }
} else {
null
}
} catch (e: Exception) {
null
} finally {
conn?.disconnect()
}
}
}