fun setupPolling() {
val constraints = Constraints.Builder()
.setRequiredNetworkType(NetworkType.CONNECTED)
.setRequiresDeviceIdle(false)
.setRequiresCharging(false)
.build()
val daysOfWeek = listOf(
DayOfWeek.MONDAY,
DayOfWeek.TUESDAY,
DayOfWeek.WEDNESDAY,
DayOfWeek.THURSDAY,
DayOfWeek.FRIDAY
)
val timeWindowStart = TimeOfDay(9, 10)
val timeWindowEndMorning = TimeOfDay(11, 20)
val timeWindowStartAfternoon = TimeOfDay(13, 10)
val timeWindowEnd = TimeOfDay(17, 20)
val periodStartTime = PeriodicWorkRequest.calculateNextRunTime(
FlexTimeInterval.Builder()
.setDaysOfWeek(daysOfWeek)
.setStartTime(timeWindowStart)
.setEndTime(timeWindowEnd)
.addInterval(TimeInterval=timeWindowStartAfternoon.timeIntervalSince(timeWindowEndMorning))
.build(),
System.currentTimeMillis(),
TimeUnit.MINUTES.toMillis(1)
)
val pollingRequest = PeriodicWorkRequestBuilder<PollingWorker>(1, TimeUnit.MINUTES)
.setConstraints(constraints)
.setInitialDelay(periodStartTime - System.currentTimeMillis(), TimeUnit.MILLISECONDS)
.build()
WorkManager.getInstance().enqueueUniquePeriodicWork("polling_work", ExistingPeriodicWorkPolicy.REPLACE, pollingRequest)
}
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.2" // 或者其他版本
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.5.2" // 如果你在Android上
implementation "androidx.work:work-runtime-ktx:2.7.0" // WorkManager
implementation "com.squareup.retrofit2:retrofit:2.9.0" // Retrofit
implementation "com.squareup.retrofit2:converter-gson:2.9.0" // 如果使用Gson作为转换器
class PollingWork(appContext: Context, params: WorkerParameters) :
Worker(appContext, params) {
private val api: MyApi by lazy {
retrofit.create(MyApi::class.java)
}
override fun doWork(): Result {
return try {
val currentTime = System.currentTimeMillis()
if (isWeekdayMorning(currentTime) || isWeekdayAfternoon(currentTime)) {
val data = api.fetchData()
// 处理获取到的数据
Result.success()
} else {
// 如果不是工作时间,则提前结束WorkRequest
Result.retry()
}
} catch (e: Exception) {
// 处理异常
Result.retry()
}
}
private fun isWeekdayMorning(time: Long): Boolean {
val calendar = Calendar.getInstance()
calendar.timeInMillis = time
return calendar.get(Calendar.DAY_OF_WEEK) in 1..5 &&
time >= 9 * 60 * 1000 && time < 11 * 60 * 1000 + 20 * 60 * 1000
}
private fun isWeekdayAfternoon(time: Long): Boolean {
val calendar = Calendar.getInstance()
calendar.timeInMillis = time
return calendar.get(Calendar.DAY_OF_WEEK) in 1..5 &&
time >= 13 * 60 * 1000 && time < 17 * 60 * 1000 + 20 * 60 * 1000
}
}
val workRequest = OneTimeWorkRequest.Builder(PollingWork::class.java)
.build()
WorkManager.getInstance(context).enqueue(workRequest)
class PollingJobService : JobService() {
private val apiService: ApiService by lazy {
val retrofit = Retrofit.Builder()
.baseUrl("https://your-api-url.com/")
.addConverterFactory(GsonConverterFactory.create())
.build()
retrofit.create(ApiService::class.java)
}
override fun onStartJob(params: JobParameters?): Boolean {
doPollingTask(params!!)
return true
}
private fun doPollingTask(jobParameters: JobParameters) {
val jobScheduler = getSystemService(Context.JOB_SCHEDULER_SERVICE) as JobScheduler
val jobId = jobParameters.jobId
val workTimeIntervals = listOf(
Pair(Calendar.MONDAY, Pair(9, 10)), // 9:10 AM
Pair(Calendar.MONDAY, Pair(13, 10)), // 1:10 PM
Pair(Calendar.FRIDAY, Pair(17, 20)) // 5:20 PM for Friday (you need to add other weekdays too)
)
if (isWithinWorkTimeInterval(workTimeIntervals)) {
apiService.getData().enqueue(object : Callback<YourDataType> {
override fun onResponse(call: Call<YourDataType>, response: Response<YourDataType>) {
// Handle the response here
}
override fun onFailure(call: Call<YourDataType>, t: Throwable) {
// Handle error here
}
})
}
jobFinished(jobParameters, false)
scheduleNextJob(jobScheduler, jobId)
}
private fun isWithinWorkTimeInterval(intervals: List<Pair<Int, Pair<Int, Int>>>): Boolean {
val calendar = Calendar.getInstance()
val hour = calendar.get(Calendar.HOUR_OF_DAY)
val minute = calendar.get(Calendar.MINUTE)
val dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK)
for ((day, time) in intervals) {
if (day == dayOfWeek && time.first <= hour && hour < time.second) {
return true
}
}
return false
}
private fun scheduleNextJob(jobScheduler: JobScheduler, jobId: Int) {
// Schedule your next job based on your requirement
// For example, every minute within the specified time interval.
// Here we are not scheduling the exact minute-based poll but just a sample.
val jobInfo = JobInfo.Builder(jobId, ComponentName(this, PollingJobService::class.java))
.setPeriodic(60 * 1000) // Every minute
.build()
jobScheduler.schedule(jobInfo)
}
override fun onStopJob(params: JobParameters?): Boolean {
// You may want to reschedule the job if it was stopped before completion
return false
}
}
<service
android:name=".MyJobService"
android:permission="android.permission.BIND_JOB_SERVICE"/>
import android.app.job.JobInfo
import android.app.job.JobParameters
import android.app.job.JobScheduler
import android.app.job.JobService
import android.content.ComponentName
import android.content.Context
import android.util.Log
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOn
import java.lang.Exception
import java.util.concurrent.TimeUnit
class PeriodicJobService: JobService() {
private suspend fun Count(): Flow<Int> {
return flow {
for(i in 200..210){
delay(100)
emit(i)
}
}
}
override fun onStartJob(p0: JobParameters?): Boolean {
val resScope = CoroutineScope(Job())
resScope.launch {
try {
Count().flowOn(Dispatchers.IO).collect {
Log.i(TAG, "collect $it")
}
Log.i(TAG, "jobFinished")
}catch (e: Exception){
e.printStackTrace()
Log.e(TAG, e.message.toString())
}
}
startScheduler(this)
return false
}
override fun onStopJob(p0: JobParameters?): Boolean = false
companion object {
var TAG: String = "taskjob"
var JOBID : Int = 100
var InterValTime :Long = 10000
private var jobScheduler: JobScheduler? = null
private var jobInfo: JobInfo? = null
fun startScheduler(context: Context) {
jobScheduler = context.getSystemService(Context.JOB_SCHEDULER_SERVICE) as JobScheduler
cancelScheduler()
if (jobInfo == null) {
jobInfo = JobInfo.Builder(JOBID, ComponentName(context, PeriodicJobService::class.java))
.setMinimumLatency(InterValTime) // 最小为10秒
.build()
}
val result = jobScheduler?.schedule(jobInfo!!)
}
fun cancelScheduler() {
jobScheduler?.cancel(JOBID)
}
}
}
import android.app.job.JobInfo
import android.app.job.JobParameters
import android.app.job.JobScheduler
import android.app.job.JobService
import android.content.ComponentName
import android.content.Context
import android.util.Log
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
class PollingJobService : JobService() {
private lateinit var retrofit: Retrofit
private lateinit var apiService: MyApiService
override fun onStartJob(params: JobParameters): Boolean {
// 初始化Retrofit
retrofit = Retrofit.Builder()
.baseUrl("https://your-api-base-url.com")
.addConverterFactory(GsonConverterFactory.create())
.build()
apiService = retrofit.create(MyApiService::class.java)
// 发起网络请求
apiService.fetchData().enqueue(object : Callback<YourDataType> {
override fun onResponse(call: Call<YourDataType>, response: Response<YourDataType>) {
// 处理你的数据
Log.d("PollingJobService", "Received data: ${response.body()}")
// 检查是否还需要继续轮询
if (shouldContinuePolling()) {
scheduleNextJob()
}
}
override fun onFailure(call: Call<YourDataType>, t: Throwable) {
// 处理网络请求失败的情况
Log.e("PollingJobService", "Failed to fetch data", t)
// 检查是否还需要继续轮询
if (shouldContinuePolling()) {
scheduleNextJob()
}
}
})
return true // 表示任务已完成,不需要重新调度
}
override fun onStopJob(params: JobParameters): Boolean {
// 停止轮询
return true
}
private fun shouldContinuePolling(): Boolean {
// 实现你的逻辑来判断是否应该继续轮询
// 例如,检查当前时间是否在上午9:10到11:20或下午13:10到17:20之间
// 并且是周一到周五
val currentTime = // 获取当前时间
// 实现你的时间判断逻辑
return // 返回true如果应该继续轮询,否则返回false
}
private fun scheduleNextJob() {
// 安排下一个轮询任务
val jobScheduler = getSystemService(Context.JOB_SCHEDULER_SERVICE) as JobScheduler
val jobInfo = JobInfo.Builder(
JOB_ID, // 唯一标识符
ComponentName(this, PollingJobService::class.java)
).setMinimumLatency(1, TimeUnit.MINUTES) // 设置最小延迟
// 添加其他调度参数,比如只在工作日特定时间运行等
jobScheduler.schedule(jobInfo.build())
}
companion object {
const val JOB_ID = 1000 // 自定义的任务ID
}
}