TokenUtil.kt迁移到lib模块 根build.gradle.kts迁移变量到子模块 增加拉取通知的后台服务 MessageService.kt 增加通知相关接口master
parent
94b057d1cf
commit
e7f07a3415
@ -1,30 +0,0 @@ |
||||
package com.gyf.csams.util |
||||
|
||||
import android.app.Activity |
||||
import android.view.View |
||||
import android.view.inputmethod.InputMethodManager |
||||
import com.orhanobut.logger.Logger |
||||
|
||||
object ContextUtil { |
||||
fun hideKeyBoard(activity: Activity?) { |
||||
Logger.i("隐藏软键盘") |
||||
activity?.apply { |
||||
val imm = getSystemService(Activity.INPUT_METHOD_SERVICE) as InputMethodManager |
||||
window.peekDecorView()?.let { |
||||
imm.hideSoftInputFromWindow(it.windowToken, 0) |
||||
} |
||||
} |
||||
} |
||||
|
||||
fun testHideKeyBoard(activity: Activity) { |
||||
Logger.i("隐藏软键盘") |
||||
val imm = activity.getSystemService(Activity.INPUT_METHOD_SERVICE) as InputMethodManager |
||||
//Find the currently focused view, so we can grab the correct window token from it. |
||||
var view: View? = activity.currentFocus |
||||
//If no view currently has focus, create a new one, just so we can grab a window token from it |
||||
if (view == null) { |
||||
view = View(activity) |
||||
} |
||||
imm.hideSoftInputFromWindow(view.windowToken, 0) |
||||
} |
||||
} |
@ -0,0 +1,73 @@ |
||||
package com.gyf |
||||
|
||||
import android.content.Context |
||||
import androidx.work.Data |
||||
import androidx.work.Worker |
||||
import androidx.work.WorkerParameters |
||||
import com.google.gson.Gson |
||||
import com.google.gson.reflect.TypeToken |
||||
import com.gyf.lib.BuildConfig |
||||
import com.gyf.lib.util.* |
||||
|
||||
import com.orhanobut.logger.Logger |
||||
import java.net.SocketTimeoutException |
||||
|
||||
const val NOTIFICATION_API = "${BuildConfig.SERVER_ADDRESS}/api/notification/pull" |
||||
|
||||
data class NotificationVo(val title: String, val content: String, val id: Int) |
||||
|
||||
data class PageDto(val currentPage: Long, val pageSize: Int = 10) |
||||
|
||||
data class NotificationDto( |
||||
val receiverId: Int, |
||||
val receiverClient: String, |
||||
override val token: Token, |
||||
val page: PageDto? = null |
||||
) : BaseToken() |
||||
|
||||
/** |
||||
* 通知接收客户端 |
||||
* |
||||
*/ |
||||
enum class ReceiverType { |
||||
//前台 |
||||
Foreground, |
||||
|
||||
//后台 |
||||
Background |
||||
} |
||||
|
||||
class NotificationWorker(context: Context, workerParams: WorkerParameters) : |
||||
Worker(context, workerParams) { |
||||
|
||||
override fun doWork(): Result { |
||||
TokenManager.token?.let { |
||||
return try { |
||||
Logger.i("开始拉取通知") |
||||
val data = HttpClient.postAsync<NotificationVo>(url = NOTIFICATION_API, |
||||
jsonParam = NotificationDto( |
||||
receiverId = it.id, |
||||
receiverClient = inputData.getString("receiverClient") |
||||
?: throw IllegalArgumentException("缺少receiverClient参数"), |
||||
token = it |
||||
), |
||||
type = object : TypeToken<ApiResponse<NotificationVo>>() {}.type |
||||
) |
||||
val result = |
||||
Data.Builder().putString(NotificationVo::class.java.name, Gson().toJson(data)) |
||||
.build() |
||||
Logger.i("拉取通知成功:\n${result}") |
||||
Result.success(result) |
||||
} catch (e: SocketTimeoutException) { |
||||
Logger.e(e, "网络异常,拉取通知失败稍后再试") |
||||
Result.retry() |
||||
} catch (e: Exception) { |
||||
Logger.e(e, "发生未知异常,中止任务") |
||||
Result.failure() |
||||
} |
||||
} |
||||
Logger.w("找不到token信息,中止任务") |
||||
return Result.failure() |
||||
} |
||||
|
||||
} |
@ -0,0 +1,61 @@ |
||||
package com.gyf.lib |
||||
|
||||
import android.content.Intent |
||||
import androidx.core.app.JobIntentService |
||||
import androidx.core.app.NotificationCompat |
||||
import androidx.core.app.NotificationManagerCompat |
||||
import com.google.gson.Gson |
||||
import com.google.gson.reflect.TypeToken |
||||
import com.gyf.NOTIFICATION_API |
||||
import com.gyf.NotificationDto |
||||
import com.gyf.NotificationVo |
||||
import com.gyf.ReceiverType |
||||
import com.gyf.lib.util.ApiResponse |
||||
import com.gyf.lib.util.HttpClient |
||||
import com.gyf.lib.util.NotificationUtil |
||||
import com.gyf.lib.util.TokenManager |
||||
import com.orhanobut.logger.Logger |
||||
|
||||
class MessageService : JobIntentService() { |
||||
|
||||
val gson = Gson() |
||||
|
||||
override fun onCreate() { |
||||
super.onCreate() |
||||
Logger.i("服务启动") |
||||
} |
||||
|
||||
override fun onDestroy() { |
||||
super.onDestroy() |
||||
Logger.i("服务销毁") |
||||
} |
||||
|
||||
override fun onHandleWork(intent: Intent) { |
||||
TokenManager.token?.let { it -> |
||||
HttpClient.postAsync<List<NotificationVo>>(url = NOTIFICATION_API, |
||||
jsonParam = NotificationDto( |
||||
receiverId = it.id, |
||||
receiverClient = ReceiverType.Foreground.name, |
||||
token = it |
||||
), |
||||
type = object : TypeToken<ApiResponse<List<NotificationVo>>>() {}.type |
||||
)?.let { it -> |
||||
Logger.i("拉取最新通知") |
||||
it.body?.forEach { |
||||
Logger.i("构造通知【${it.title}】") |
||||
val builder = |
||||
NotificationCompat.Builder(applicationContext, NotificationUtil.CHANNEL_ID) |
||||
.setSmallIcon(R.drawable.ic_notification) |
||||
.setContentTitle(it.title) |
||||
.setContentText(it.content) |
||||
.setPriority(NotificationCompat.PRIORITY_HIGH) |
||||
builder.build() |
||||
with(NotificationManagerCompat.from(applicationContext)) { |
||||
// notificationId is a unique int for each notification that you must define |
||||
notify(it.id, builder.build()) |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,62 @@ |
||||
package com.gyf.lib.util |
||||
|
||||
import android.app.Activity |
||||
import android.content.Context |
||||
import android.view.View |
||||
import android.view.inputmethod.InputMethodManager |
||||
import androidx.lifecycle.LiveData |
||||
import androidx.work.* |
||||
import com.gyf.NotificationWorker |
||||
import com.gyf.ReceiverType |
||||
import com.orhanobut.logger.Logger |
||||
import java.util.* |
||||
|
||||
object ContextUtil { |
||||
private var name = "pullNotification" |
||||
|
||||
private fun getNotification(context: Context): UUID { |
||||
val data = Data.Builder() |
||||
.putString("receiverClient", ReceiverType.Foreground.name) |
||||
.build() |
||||
val uploadWorkRequest: OneTimeWorkRequest = |
||||
OneTimeWorkRequestBuilder<NotificationWorker>() |
||||
.setInputData(data) |
||||
.build() |
||||
Logger.i("构建任务") |
||||
val workManager = WorkManager.getInstance(context) |
||||
workManager.enqueueUniqueWork(name, ExistingWorkPolicy.KEEP, uploadWorkRequest) |
||||
return uploadWorkRequest.id |
||||
} |
||||
|
||||
fun getNotificationLiveData(context: Context): LiveData<WorkInfo> { |
||||
val id = getNotification(context = context) |
||||
return WorkManager.getInstance(context).getWorkInfoByIdLiveData(id) |
||||
} |
||||
|
||||
fun getNotification(context: Context, callback: (wordId: UUID) -> Unit) { |
||||
callback(getNotification(context = context)) |
||||
} |
||||
|
||||
|
||||
fun hideKeyBoard(activity: Activity?) { |
||||
Logger.i("隐藏软键盘") |
||||
activity?.apply { |
||||
val imm = getSystemService(Activity.INPUT_METHOD_SERVICE) as InputMethodManager |
||||
window.peekDecorView()?.let { |
||||
imm.hideSoftInputFromWindow(it.windowToken, 0) |
||||
} |
||||
} |
||||
} |
||||
|
||||
fun testHideKeyBoard(activity: Activity) { |
||||
Logger.i("隐藏软键盘") |
||||
val imm = activity.getSystemService(Activity.INPUT_METHOD_SERVICE) as InputMethodManager |
||||
//Find the currently focused view, so we can grab the correct window token from it. |
||||
var view: View? = activity.currentFocus |
||||
//If no view currently has focus, create a new one, just so we can grab a window token from it |
||||
if (view == null) { |
||||
view = View(activity) |
||||
} |
||||
imm.hideSoftInputFromWindow(view.windowToken, 0) |
||||
} |
||||
} |
@ -0,0 +1,66 @@ |
||||
/* |
||||
* Copyright (C) 2017 Google Inc. All Rights Reserved. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0 |
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
package com.gyf.lib.util |
||||
|
||||
import android.app.NotificationChannel |
||||
import android.app.NotificationManager |
||||
import android.content.Context |
||||
import android.os.Build |
||||
import androidx.core.app.NotificationCompat |
||||
import com.gyf.lib.BuildConfig |
||||
|
||||
|
||||
/** |
||||
* Simplifies common [Notification] tasks. |
||||
*/ |
||||
object NotificationUtil { |
||||
// The id of the channel. |
||||
const val CHANNEL_ID = BuildConfig.LIBRARY_PACKAGE_NAME |
||||
|
||||
fun createNotificationChannel( |
||||
context: Context, |
||||
channelImportance: Int |
||||
): String? { |
||||
// NotificationChannels are required for Notifications on O (API 26) and above. |
||||
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { |
||||
|
||||
// The user-visible name of the channel. |
||||
val channelName: CharSequence = "" |
||||
// The user-visible description of the channel. |
||||
val channelDescription = "" |
||||
val channelEnableVibrate = false |
||||
val channelLockscreenVisibility: Int = NotificationCompat.VISIBILITY_PUBLIC |
||||
|
||||
// Initializes NotificationChannel. |
||||
val notificationChannel = |
||||
NotificationChannel(CHANNEL_ID, channelName, channelImportance) |
||||
notificationChannel.description = channelDescription |
||||
notificationChannel.enableVibration(channelEnableVibrate) |
||||
notificationChannel.lockscreenVisibility = channelLockscreenVisibility |
||||
|
||||
// Adds NotificationChannel to system. Attempting to create an existing notification |
||||
// channel with its original values performs no operation, so it's safe to perform the |
||||
// below sequence. |
||||
val notificationManager: NotificationManager = |
||||
context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager |
||||
notificationManager.createNotificationChannel(notificationChannel) |
||||
CHANNEL_ID |
||||
} else { |
||||
// Returns null for pre-O (26) devices. |
||||
null |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,15 @@ |
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android" |
||||
android:width="64dp" |
||||
android:height="64dp" |
||||
android:viewportWidth="1024" |
||||
android:viewportHeight="1024"> |
||||
<path |
||||
android:pathData="M752.77,955.39H257.92c-112.38,0 -203.39,-91.01 -203.39,-203.39V257.15C54.53,144.77 145.54,53.76 257.92,53.76h494.85C865.15,53.76 956.16,144.77 956.16,257.15v494.85c0,112.38 -91.01,203.39 -203.39,203.39z" |
||||
android:fillColor="#FF4D3C" /> |
||||
<path |
||||
android:pathData="M616.58,765.95H370.56c-67.97,0 -123.01,-55.04 -123.01,-123.01V396.8c0,-67.97 55.04,-123.01 123.01,-123.01h166.27c9.98,0 18.18,8.06 18.18,18.18 0,9.98 -8.06,18.18 -18.18,18.18H370.56c-47.87,0 -86.66,38.78 -86.66,86.66v246.02c0,47.87 38.78,86.66 86.66,86.66h246.02c47.87,0 86.66,-38.78 86.66,-86.66V469.12c0,-9.98 8.06,-18.18 18.18,-18.18 9.98,0 18.18,8.06 18.18,18.18v173.82c0,67.97 -55.04,123.01 -123.01,123.01z" |
||||
android:fillColor="#FFFFFF" /> |
||||
<path |
||||
android:pathData="M694.78,312.7m-113.41,0a113.41,113.41 0,1 0,226.82 0,113.41 113.41,0 1,0 -226.82,0Z" |
||||
android:fillColor="#FFFFFF" /> |
||||
</vector> |
Loading…
Reference in new issue