Commit 895d920d authored by wanglei's avatar wanglei

...

parent 5d198b5b
...@@ -10,8 +10,15 @@ ...@@ -10,8 +10,15 @@
<!-- android:foregroundServiceType="location" --> <!-- android:foregroundServiceType="location" -->
<!-- android:name="MyNavigationService" /> --> <!-- android:name="MyNavigationService" /> -->
<!-- Required only when requesting background location access on Android 10 (API level 29) and higher. --> <!-- Required only when requesting background location access on Android 10 (API level 29) and higher. -->
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" /> <!-- 身体活动数据 --> <!-- <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />-->
<uses-permission android:name="android.permission.ACTIVITY_RECOGNITION" /> <!-- 身体活动数据 -->
<!-- <uses-permission android:name="android.permission.ACTIVITY_RECOGNITION" />-->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<application <application
android:name=".helper.MyApplication" android:name=".helper.MyApplication"
...@@ -106,6 +113,11 @@ ...@@ -106,6 +113,11 @@
android:screenOrientation="portrait" android:screenOrientation="portrait"
tools:ignore="DiscouragedApi,LockedOrientationActivity" /> tools:ignore="DiscouragedApi,LockedOrientationActivity" />
<service
android:name=".service.StayNotificationService"
android:foregroundServiceType="dataSync" />
<meta-data <meta-data
android:name="com.google.android.gms.ads.APPLICATION_ID" android:name="com.google.android.gms.ads.APPLICATION_ID"
android:value="ca-app-pub-3940256099942544~3347511713" /> android:value="ca-app-pub-3940256099942544~3347511713" />
......
...@@ -5,6 +5,8 @@ import java.util.Locale ...@@ -5,6 +5,8 @@ import java.util.Locale
object ConstObject { object ConstObject {
var isFirstLauncher = true var isFirstLauncher = true
get() { get() {
return AppPreferences.getInstance().getBoolean("isFirstLauncher", field) return AppPreferences.getInstance().getBoolean("isFirstLauncher", field)
......
...@@ -4,12 +4,13 @@ package com.base.locationsharewhite.bean ...@@ -4,12 +4,13 @@ package com.base.locationsharewhite.bean
* 我可以看谁,自身无法切换状态 * 我可以看谁,自身无法切换状态
*/ */
data class ViewingBean( data class ViewingBean(
val device: String,
val nickname: String, val nickname: String,
val status: Int = -1, val status: Int = -1,
val locatDate: LocationDate? = null, val locatDate: LocationData? = null,
) )
data class LocationDate( data class LocationData(
val longitude: Double, val longitude: Double,
val latitude: Double, val latitude: Double,
val power: Int, val power: Int,
......
package com.base.locationsharewhite.fcm
import android.content.Context
import android.os.Handler
import android.os.HandlerThread
import com.base.locationsharewhite.helper.MyApplication
import com.base.locationsharewhite.utils.AppPreferences
import com.base.locationsharewhite.utils.LogEx
object NotificationHoverUtils {
private val TAG = "NotificationHoverUtils"
private var handlerThread: HandlerThread? = null
private var handler: Handler? = null
/**
* 发送悬停通知
*/
fun sendHoverNotification(context: Context) {
val hoverCount = AppPreferences.getInstance().getString("popup_hover_count", "0").toInt()
val hoverDelay = AppPreferences.getInstance().getString("popup_hover_delay", "0").toLong()
val hoverStatus = AppPreferences.getInstance().getString("popup_hover_status", "0").toInt()
if (hoverStatus == 0) return
if (handlerThread == null) {
handlerThread = HandlerThread("NotificationHandlerThread")
handlerThread?.start()
}
// 创建 Handler
if (handler == null) {
handlerThread?.let {
handler = Handler(it.getLooper())
}
}
for (i in 1..hoverCount) {
val time = i * hoverDelay
handler?.postDelayed(Runnable {
LogEx.logDebug(TAG, "handler ${MyApplication.PAUSED_VALUE}")
if (MyApplication.PAUSED_VALUE == 1) {
handler?.removeCallbacksAndMessages(null)
return@Runnable
}
if (MyApplication.PAUSED_VALUE != 1) {
LogEx.logDebug(TAG, "handler send notification")
NotificationUiUtil.setActionNotification(context, NotificationUiUtil.hoverActionId)
}
}, time)
}
}
fun stopNotificationHandler() {
// 停止 HandlerThread
if (handler != null) {
handler?.removeCallbacksAndMessages(null)
}
if (handlerThread != null) {
handlerThread?.quit()
handlerThread = null
}
handler = null
}
}
\ No newline at end of file
package com.base.locationsharewhite.fcm
import android.annotation.SuppressLint
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.graphics.drawable.Icon
import android.os.Build
import android.widget.RemoteViews
import androidx.core.app.NotificationCompat
import androidx.core.graphics.drawable.IconCompat
import com.base.locationsharewhite.BuildConfig
import com.base.locationsharewhite.R
import com.base.locationsharewhite.fcm.PopupConstObject.NOTIFICATION_ACTION_MY_CODE
import com.base.locationsharewhite.fcm.PopupConstObject.POPUP_WHERE_FCM
import com.base.locationsharewhite.fcm.PopupConstObject.POPUP_WHERE_LOCK
import com.base.locationsharewhite.fcm.PopupConstObject.POPUP_WHERE_TIMBER
import com.base.locationsharewhite.fcm.PopupConstObject.popup_count
import com.base.locationsharewhite.fcm.PopupConstObject.popup_end
import com.base.locationsharewhite.fcm.PopupConstObject.popup_fcm_interval
import com.base.locationsharewhite.fcm.PopupConstObject.popup_interval
import com.base.locationsharewhite.fcm.PopupConstObject.popup_lock_interval
import com.base.locationsharewhite.fcm.PopupConstObject.popup_start
import com.base.locationsharewhite.fcm.PopupConstObject.popup_status
import com.base.locationsharewhite.fcm.PopupConstObject.popup_timer_interval
import com.base.locationsharewhite.helper.EventUtils
import com.base.locationsharewhite.helper.MyApplication
import com.base.locationsharewhite.ui.splash.SplashActivity
import com.base.locationsharewhite.utils.AppPreferences
import com.base.locationsharewhite.utils.LogEx
import java.text.SimpleDateFormat
import java.util.Calendar
import java.util.Locale
import kotlin.random.Random
/**
* 构建发送通知 UI
* 用的actionId代替notificationId使用
*/
object NotificationUiUtil {
private val TAG = "NotificationUiUtil"
var NOTIFICATION_ID = Random.nextInt(1000, 1800)
private fun currentDate(): String {
val dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.getDefault())
val currentDate = Calendar.getInstance().time
return dateFormat.format(currentDate)
}
//当天推送次数
private var dayPopupCount = 0
get() {
return AppPreferences.getInstance().getInt("dayPopupCount_${currentDate()}", field)
}
set(value) {
field = value
AppPreferences.getInstance().put("dayPopupCount_${currentDate()}", value, true)
}
private var lastPopupTime = 0L
get() {
return AppPreferences.getInstance().getLong("lastPopupTime", field)
}
set(value) {
field = value
AppPreferences.getInstance().put("lastPopupTime", value, true)
}
private fun canSendNotification(where: String, actionId: String): Boolean {
//是否开启推送
val status = AppPreferences.getInstance().getString(popup_status, "1").toInt()
if (status == 0) {
EventUtils.event("Notification_Error", "status=$status")
LogEx.logDebug("canSendNotification", "status")
return false
}
//当天推送次数
val count = AppPreferences.getInstance().getString(popup_count, "20").toInt()
if (dayPopupCount > count) {
LogEx.logDebug("canSendNotification", "count")
EventUtils.event("Notification_Error", "dayPopupCount=$dayPopupCount count=$count where=$where actionId=$actionId")
return false
}
//判断是否在时间区域
val start = AppPreferences.getInstance().getString(popup_start, "0").toInt()
val end = AppPreferences.getInstance().getString(popup_end, "24").toInt()
val calendar = Calendar.getInstance()
val currentHour = calendar.get(Calendar.HOUR_OF_DAY)
if (currentHour !in start until end) {
LogEx.logDebug("canSendNotification", "start-end currentHour=$currentHour start=$start end=$end")
EventUtils.event("Notification_Error", "start=$start end=$end currentHour=$currentHour where=$where actionId=$actionId")
return false
}
//单位分钟
var interval = AppPreferences.getInstance().getString(popup_interval, "1").toInt()
if (where == POPUP_WHERE_TIMBER) {
interval = AppPreferences.getInstance().getString(popup_timer_interval, "7").toInt()
}
if (where == POPUP_WHERE_LOCK) {
interval = AppPreferences.getInstance().getString(popup_lock_interval, "1").toInt()
}
if (where == POPUP_WHERE_FCM) {
interval = AppPreferences.getInstance().getString(popup_fcm_interval, "1").toInt()
}
val passedTime = System.currentTimeMillis() - lastPopupTime
if (passedTime < interval * 60 * 1000L) {
EventUtils.event("Notification_Error", "where=$where actionId=$actionId interval=$interval passedTime=$passedTime")
LogEx.logDebug("canSendNotification", "interval where=$where passedTime=$passedTime interval=$interval")
return false
}
return true
}
var hoverActionId = ""
@SuppressLint("RemoteViewLayout")
fun sendNotificationIfCan(context: Context, actionId: String, where: String = "") {
if (!canSendNotification(where, actionId)) return
//发送通知
setActionNotification(context, actionId)
//上报通知
EventUtils.event("Notification_Popup", "where=$where actionId=$actionId")
//当天次数加一
dayPopupCount += 1
//推送时间
lastPopupTime = System.currentTimeMillis()
//悬停通知
hoverActionId = actionId
NotificationHoverUtils.sendHoverNotification(context)
}
fun setActionNotification(context: Context, actionId: String) {
// val bigRemoteViews = RemoteViews(MyApplication.context.packageName, R.layout.notification_message)
// val smallRemoteViews = RemoteViews(MyApplication.context.packageName, R.layout.notification_message)
val intent = Intent(context, SplashActivity::class.java)
intent.putExtra("actionId", actionId)
when (actionId) {
else -> {
EventUtils.event("Notification_Error", "unKnow actionId actionId=$actionId")
}
}
}
private fun sendCustomNotification(
context: Context,
intent: Intent,
bigRemoteViews: RemoteViews,
smallRemoteViews: RemoteViews,
) {
val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
val channelId = context.resources.getString(R.string.app_name).replace(" ", "_") + "_channel_id"
val channelName = context.resources.getString(R.string.app_name).replace(" ", "_") + "_channel"
//创建channel
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val channel = NotificationChannel(
channelId, channelName, NotificationManager.IMPORTANCE_HIGH
)
channel.lockscreenVisibility = NotificationCompat.VISIBILITY_PUBLIC
notificationManager.createNotificationChannel(channel)
}
// Create the notification
val builder: NotificationCompat.Builder = NotificationCompat.Builder(context, channelId)
//设置状态栏内的小图标
val smallIcon = IconCompat.createFromIcon(
context, Icon.createWithResource(
context, R.mipmap.logo
)
)
smallIcon?.let {
builder.setSmallIcon(smallIcon)
}
builder.setContentTitle(context.resources.getString(R.string.app_name))
.setContentText("notification")
val requestCode = Random.nextInt(1000)
val pendingIntent = PendingIntent.getActivity(context, requestCode, intent, PendingIntent.FLAG_IMMUTABLE)
builder.setContentIntent(pendingIntent)
.setPriority(NotificationCompat.PRIORITY_MAX)
.setAutoCancel(true)
var small: RemoteViews? = bigRemoteViews
//Android 12以下需要适配小RemoteViews
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
small = smallRemoteViews
}
// 设置小视图
builder.setCustomContentView(smallRemoteViews)
// 设置悬浮通知视图(Android 12 及以上)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
builder.setCustomHeadsUpContentView(bigRemoteViews)
}
// 设置大视图
builder.setCustomBigContentView(bigRemoteViews)
notificationManager.notify(NOTIFICATION_ID, builder.build())
}
val looper_actionId = listOf(
NOTIFICATION_ACTION_MY_CODE
)
var actionIdList = arrayListOf<String>()
fun getNextActionId(): String {
if (actionIdList.isEmpty()) {
actionIdList.addAll(looper_actionId)
}
val next = actionIdList[0]
actionIdList.removeAt(0)
if (BuildConfig.DEBUG) {
// return NOTIFICATION_ACTION_WEATHER
}
return next
}
}
\ No newline at end of file
package com.base.locationsharewhite.fcm
object PopupConstObject {
const val NOTIFICATION_ACTION_HOME = "notification_action_home"
const val NOTIFICATION_ACTION_MY_CODE = "notification_action_my_code"
const val NOTIFICATION_ACTION_SHARE = "notification_action_share"
const val NOTIFICATION_ACTION_SETTINGS = "notification_action_settings"
const val POPUP_WHERE_TIMBER = "Timer"
const val POPUP_WHERE_LOCK = "Lock"
const val POPUP_WHERE_FCM = "fcm"
//推送总开关 0 关 1开
val popup_status = "popup_status"
//推送总数量现在
val popup_count = "popup_count"//所有常规推送的当日推送次数限制,0 为不限制
val popup_start = "popup_start"
val popup_end = "popup_end"
val popup_interval = "popup_interval"
val popup_timer_interval = "popup_timber_interval"
val popup_lock_interval = "popup_lock_interval"
val popup_fcm_interval = "popup_fcm_interval"
}
\ No newline at end of file
package com.base.locationsharewhite.helper
import android.os.Build
import com.base.locationsharewhite.BuildConfig
import com.base.locationsharewhite.bean.ConstObject.ifAgreePrivacy
import com.base.locationsharewhite.helper.ReportUtils.doPost
import com.base.locationsharewhite.utils.AppPreferences
import com.base.locationsharewhite.utils.LogEx
import org.json.JSONException
import org.json.JSONObject
object EventUtils {
private val TAG = "EventUtils"
fun event(
key: String,
value: String? = null,
ext: JSONObject? = null,
isSingleEvent: Boolean = false
) {
if (!ifAgreePrivacy) {
return
}
if (isSingleEvent) {
val stringSet = AppPreferences.getInstance().getStringSet("singleEvent", setOf())
if (stringSet.contains(key)) {
return
}
}
Thread {
var paramJson: String? = ""
try {
val pkg = ConfigHelper.packageName
val s = JSONObject()
.put("action", key)
.put("value", value)
.put("ext", ext)
val s2 = JSONObject()
.put("${pkg}_3", AppPreferences.getInstance().getString("Equipment", ""))
.put("${pkg}_4", AppPreferences.getInstance().getString("Manufacturer", ""))
.put("${pkg}_5", Build.VERSION.SDK_INT)
.put("${pkg}_9", AppPreferences.getInstance().getString("uuid", ""))
.put("${pkg}_10", AppPreferences.getInstance().getString("gid", ""))
.put("${pkg}_13", "android")
.put("${pkg}_15", "google")
.put("${pkg}_14", BuildConfig.VERSION_CODE)
.put("${pkg}_8", BuildConfig.VERSION_NAME)
.put("${pkg}_24", BuildConfig.BUILD_TYPE)
val data = JSONObject()
.put("data", s)
.put("bp", s2)
.toString()
LogEx.logDebug(TAG, "uuid=${AppPreferences.getInstance().getString("uuid", "")}")
LogEx.logDebug(TAG, "gid=${AppPreferences.getInstance().getString("gid", "")}")
paramJson = AESHelper.encrypt(data)
} catch (e: JSONException) {
paramJson = ""
}
LogEx.logDebug(TAG, "url=$url")
doPost(
url,
HashMap(),
paramJson
)
}.start()
}
private val url by lazy {
val pkg = ConfigHelper.packageName
val url = StringBuilder(
"${ConfigHelper.eventUrl}/${
pkg.filter { it.isLowerCase() }.substring(4, 9)
}sp"
)
url.append("?pkg=$pkg")
url.toString()
}
}
\ No newline at end of file
...@@ -2,12 +2,14 @@ package com.base.locationsharewhite.location ...@@ -2,12 +2,14 @@ package com.base.locationsharewhite.location
import android.os.Build import android.os.Build
import com.base.locationsharewhite.BuildConfig import com.base.locationsharewhite.BuildConfig
import com.base.locationsharewhite.bean.LocationData
import com.base.locationsharewhite.helper.AESHelper import com.base.locationsharewhite.helper.AESHelper
import com.base.locationsharewhite.helper.ConfigHelper import com.base.locationsharewhite.helper.ConfigHelper
import com.base.locationsharewhite.helper.ReportUtils import com.base.locationsharewhite.helper.ReportUtils
import com.base.locationsharewhite.utils.AppPreferences import com.base.locationsharewhite.utils.AppPreferences
import com.base.locationsharewhite.utils.LogEx import com.base.locationsharewhite.utils.LogEx
import com.google.android.gms.maps.model.LatLng import com.google.android.gms.maps.model.LatLng
import com.google.gson.Gson
import org.json.JSONObject import org.json.JSONObject
/** /**
...@@ -66,4 +68,65 @@ object LocationPositionUtils { ...@@ -66,4 +68,65 @@ object LocationPositionUtils {
} }
}.start() }.start()
} }
/**
* 获取定位接口
*/
private val getLatLngUrl by lazy {
val pkg = ConfigHelper.packageName
val url = StringBuilder(
"${ConfigHelper.apiUrl}/dingwei/${pkg.filter { it.isLowerCase() }.substring(4, 9)}u"
)
url.append("?pkg=$pkg")
url.toString()
}
fun getLocation(
device: String,
callBack: ((locationData: LocationData) -> Unit)? = null
) {
Thread {
val pkg = ConfigHelper.packageName
val data = JSONObject()
data.put("device", device)
val bp = JSONObject()
// .put("${pkg}_1", "")
.put("${pkg}_5", Build.VERSION.SDK_INT)
.put("${pkg}_8", BuildConfig.VERSION_NAME)
.put("${pkg}_9", AppPreferences.getInstance().getString("uuid", ""))
.put("${pkg}_10", AppPreferences.getInstance().getString("uuid", ""))//gid
.put("${pkg}_13", "android")
.put("${pkg}_14", BuildConfig.VERSION_CODE)
.put("${pkg}_15", "google")
.put("${pkg}_24", BuildConfig.BUILD_TYPE)
LogEx.logDebug(TAG, "uuid=${AppPreferences.getInstance().getString("uuid", "")}")
val body = JSONObject()
.put("data", data)
.put("bp", bp)
.toString()
val paramJson = AESHelper.encrypt(body)
runCatching {
val result = ReportUtils.doPost(getLatLngUrl, HashMap(), paramJson)
LogEx.logDebug(TAG, "result=$result")
val responseData = LocationLoginUtils.extractData(result)
if (responseData != null) {
val decryptedData = AESHelper.decrypt(responseData)
LogEx.logDebug(TAG, "decryptedData=$decryptedData")
val locationData: LocationData? = parseLoginData(decryptedData)
locationData?.let { callBack?.invoke(it) }
}
}
}
}
private fun parseLoginData(decryptedData: String): LocationData? {
val gson = Gson()
val locationData = gson.fromJson(decryptedData, LocationData::class.java)
LogEx.logDebug(TAG, "locationData=$locationData")
return locationData
}
} }
\ No newline at end of file
package com.base.locationsharewhite.service
import android.app.Notification
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.app.Service
import android.content.Context
import android.content.Intent
import android.content.pm.ServiceInfo
import android.graphics.BitmapFactory
import android.graphics.drawable.Icon
import android.os.Build
import android.os.IBinder
import android.widget.RemoteViews
import androidx.core.app.NotificationCompat
import androidx.core.graphics.drawable.IconCompat
import com.base.locationsharewhite.R
import com.base.locationsharewhite.bean.ConstObject
import com.base.locationsharewhite.helper.EventUtils
import com.base.locationsharewhite.helper.MyApplication
import com.base.locationsharewhite.ui.main.MainActivity
import com.base.locationsharewhite.ui.splash.SplashActivity
import com.base.locationsharewhite.utils.LogEx
import kotlin.random.Random
/**
* 常驻通知栏
*/
class StayNotificationService : Service() {
private val TAG = "StayNotificationService"
companion object {
var isRunning = false
fun Context.startStayNotification() {
if (isRunning) return
val intent = Intent(this, StayNotificationService::class.java)
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.TIRAMISU) {
return
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
startForegroundService(intent)
} else {
startService(intent)
}
}
fun Context.restartStartStayNotification() {
val intent = Intent(this, StayNotificationService::class.java)
stopService(intent)
startStayNotification()
}
fun createPermanentNotification(context: Context): Notification {
val channelName = "PDF Reader Foreground Service Channel"
val channelId = "PDF_Reader_Service_Id"
val contentView = RemoteViews(context.packageName, R.layout.stay_notification_big)
val expendView = RemoteViews(context.packageName, R.layout.stay_notification_big)
val requestCode1 = Random.nextInt(1800)
val intent1 = Intent(context, SplashActivity::class.java).apply {
putExtra("actionId", ConstObject.NOTIFICATION_ACTION_HOME)
}
val pendingIntent1 =
PendingIntent.getActivity(
context,
requestCode1,
intent1,
PendingIntent.FLAG_IMMUTABLE
)
contentView.setOnClickPendingIntent(R.id.ll_1, pendingIntent1)
expendView.setOnClickPendingIntent(R.id.ll_1, pendingIntent1)
val requestCode2 = Random.nextInt(1800)
val intent2 = Intent(context, SplashActivity::class.java).apply {
putExtra("actionId", ConstObject.NOTIFICATION_ACTION_MY_CODE)
}
val pendingIntent2 =
PendingIntent.getActivity(
context,
requestCode2,
intent2,
PendingIntent.FLAG_IMMUTABLE
)
contentView.setOnClickPendingIntent(R.id.ll_2, pendingIntent2)
expendView.setOnClickPendingIntent(R.id.ll_2, pendingIntent2)
val requestCode3 = Random.nextInt(1800)
val intent3 = Intent(context, SplashActivity::class.java).apply {
putExtra("actionId", ConstObject.NOTIFICATION_ACTION_SHARE)
}
val pendingIntent3 =
PendingIntent.getActivity(
context,
requestCode3,
intent3,
PendingIntent.FLAG_IMMUTABLE
)
contentView.setOnClickPendingIntent(R.id.ll_3, pendingIntent3)
expendView.setOnClickPendingIntent(R.id.ll_3, pendingIntent3)
val requestCode4 = Random.nextInt(1800)
val intent4 = Intent(context, SplashActivity::class.java).apply {
putExtra("actionId", ConstObject.NOTIFICATION_ACTION_SETTINGS)
}
val pendingIntent4 =
PendingIntent.getActivity(
context,
requestCode4,
intent4,
PendingIntent.FLAG_IMMUTABLE
)
contentView.setOnClickPendingIntent(R.id.ll_4, pendingIntent4)
expendView.setOnClickPendingIntent(R.id.ll_4, pendingIntent4)
val builder = NotificationCompat.Builder(context, channelId)
val smallIcon = IconCompat.createFromIcon(
context, Icon.createWithResource(
MyApplication.context, R.mipmap.logo
)
)
smallIcon?.let {
builder.setSmallIcon(smallIcon) //设置状态栏内的小图标
}
val nfIntent = Intent(context, MainActivity::class.java)
val pendingIntent =
PendingIntent.getActivity(context, 0, nfIntent, PendingIntent.FLAG_IMMUTABLE)
builder.setLargeIcon(BitmapFactory.decodeResource(context.resources, R.mipmap.logo))
builder.setContentTitle(context.resources.getString(R.string.app_name))
builder.setContentIntent(pendingIntent) //设置PendingIntent
builder.setVisibility(NotificationCompat.VISIBILITY_PRIVATE) //设置通知公开可见
builder.setAutoCancel(false)
builder.setPriority(NotificationCompat.PRIORITY_MAX) //优先级为:重要通知
builder.setWhen(System.currentTimeMillis())
builder.setCustomContentView(contentView)
builder.setCustomBigContentView(expendView)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val channel =
NotificationChannel(channelId, channelName, NotificationManager.IMPORTANCE_LOW)
channel.lockscreenVisibility = 1
val notificationManager =
context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
notificationManager.createNotificationChannel(channel)
builder.setChannelId(channelId)
}
return builder.build()
}
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
LogEx.logDebug(TAG, "onStartCommand intent=$intent")
if (intent == null) {
EventUtils.event("onStartCommand", "Foreground System auto launch intent=null isRunning=$isRunning")
return START_NOT_STICKY
}
if (!isRunning) {
LogEx.logDebug(TAG, "onStartCommand startForeground")
startForeground()
isRunning = true
}
return START_STICKY
}
private fun startForeground() {
val notification = createPermanentNotification(MyApplication.context)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
startForeground(100, notification, ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC)
} else {
startForeground(100, notification)
}
isRunning = true
}
override fun onBind(intent: Intent?): IBinder? {
return null
}
override fun onDestroy() {
isRunning = false
super.onDestroy()
}
}
\ No newline at end of file
...@@ -14,6 +14,7 @@ import com.base.locationsharewhite.bean.ViewingBean ...@@ -14,6 +14,7 @@ import com.base.locationsharewhite.bean.ViewingBean
import com.base.locationsharewhite.databinding.ActivityLocationMapBinding import com.base.locationsharewhite.databinding.ActivityLocationMapBinding
import com.base.locationsharewhite.helper.BaseActivity import com.base.locationsharewhite.helper.BaseActivity
import com.base.locationsharewhite.helper.MyApplication import com.base.locationsharewhite.helper.MyApplication
import com.base.locationsharewhite.location.LocationPositionUtils
import com.base.locationsharewhite.location.LocationShareListUtils import com.base.locationsharewhite.location.LocationShareListUtils
import com.base.locationsharewhite.map.MapUtils.addLocationMarker import com.base.locationsharewhite.map.MapUtils.addLocationMarker
import com.base.locationsharewhite.map.MapUtils.getLatLngByLocationManager import com.base.locationsharewhite.map.MapUtils.getLatLngByLocationManager
...@@ -30,7 +31,9 @@ import com.google.android.gms.maps.SupportMapFragment ...@@ -30,7 +31,9 @@ import com.google.android.gms.maps.SupportMapFragment
import com.google.android.gms.maps.model.LatLng import com.google.android.gms.maps.model.LatLng
import com.google.android.gms.maps.model.Marker import com.google.android.gms.maps.model.Marker
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
...@@ -40,6 +43,7 @@ class LocationMapActivity : BaseActivity<ActivityLocationMapBinding>(), OnMapRea ...@@ -40,6 +43,7 @@ class LocationMapActivity : BaseActivity<ActivityLocationMapBinding>(), OnMapRea
private var map: GoogleMap? = null private var map: GoogleMap? = null
private lateinit var locationPresenter: LocationPresenter private lateinit var locationPresenter: LocationPresenter
private lateinit var adapter: ViewingAdapter private lateinit var adapter: ViewingAdapter
private var getLocationJob: Job? = null
override val binding: ActivityLocationMapBinding by lazy { override val binding: ActivityLocationMapBinding by lazy {
ActivityLocationMapBinding.inflate(layoutInflater) ActivityLocationMapBinding.inflate(layoutInflater)
...@@ -73,8 +77,10 @@ class LocationMapActivity : BaseActivity<ActivityLocationMapBinding>(), OnMapRea ...@@ -73,8 +77,10 @@ class LocationMapActivity : BaseActivity<ActivityLocationMapBinding>(), OnMapRea
adapter = ViewingAdapter( adapter = ViewingAdapter(
itemClick = { itemClick = {
if (currentViewingBean != it) { if (currentViewingBean != it) {
currentViewingBean = it currentViewingBean = it
startGetLocationJob()
initFriendLocationMarker(it) initFriendLocationMarker(it)
} }
}, },
...@@ -86,6 +92,24 @@ class LocationMapActivity : BaseActivity<ActivityLocationMapBinding>(), OnMapRea ...@@ -86,6 +92,24 @@ class LocationMapActivity : BaseActivity<ActivityLocationMapBinding>(), OnMapRea
binding.rvViewing.adapter = adapter binding.rvViewing.adapter = adapter
} }
private fun startGetLocationJob() {
getLocationJob?.cancel()
getLocationJob = null
getLocationJob = lifecycleScope.launch(Dispatchers.IO) {
while (isActive) {
currentViewingBean?.let {
LocationPositionUtils.getLocation(it.device) {
lifecycleScope.launch(Dispatchers.Main) {
}
}
}
delay(30 * 1000L)
}
}
}
private fun showFriendGuideOrNoFriend() { private fun showFriendGuideOrNoFriend() {
if (ConstObject.noShowFriendsShareGuide) { if (ConstObject.noShowFriendsShareGuide) {
binding.llFriendsGuide.visibility = View.GONE binding.llFriendsGuide.visibility = View.GONE
......
...@@ -2,10 +2,8 @@ package com.base.locationsharewhite.ui.locationmap ...@@ -2,10 +2,8 @@ package com.base.locationsharewhite.ui.locationmap
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.app.Activity import android.app.Activity
import android.content.Context
import android.location.Location import android.location.Location
import androidx.lifecycle.LifecycleCoroutineScope import androidx.lifecycle.LifecycleCoroutineScope
import com.base.locationsharewhite.helper.BaseActivity
import com.base.locationsharewhite.location.LocationPositionUtils.uploadMyLocation import com.base.locationsharewhite.location.LocationPositionUtils.uploadMyLocation
import com.base.locationsharewhite.map.MapUtils.getLatLngByLocationManager import com.base.locationsharewhite.map.MapUtils.getLatLngByLocationManager
import com.base.locationsharewhite.utils.BatteryUtils.getBatteryLevel import com.base.locationsharewhite.utils.BatteryUtils.getBatteryLevel
......
...@@ -8,11 +8,13 @@ import com.base.locationsharewhite.R ...@@ -8,11 +8,13 @@ import com.base.locationsharewhite.R
import com.base.locationsharewhite.bean.ConstObject.ifAgreePrivacy import com.base.locationsharewhite.bean.ConstObject.ifAgreePrivacy
import com.base.locationsharewhite.bean.ConstObject.isFirstLauncher import com.base.locationsharewhite.bean.ConstObject.isFirstLauncher
import com.base.locationsharewhite.databinding.ActivitySplashBinding import com.base.locationsharewhite.databinding.ActivitySplashBinding
import com.base.locationsharewhite.fcm.NotificationHoverUtils
import com.base.locationsharewhite.helper.BaseActivity import com.base.locationsharewhite.helper.BaseActivity
import com.base.locationsharewhite.ui.howuse.HowUseActivity import com.base.locationsharewhite.ui.howuse.HowUseActivity
import com.base.locationsharewhite.ui.main.MainActivity import com.base.locationsharewhite.ui.main.MainActivity
import com.base.locationsharewhite.ui.set.LanguageActivity import com.base.locationsharewhite.ui.set.LanguageActivity
import com.base.locationsharewhite.utils.BarUtils import com.base.locationsharewhite.utils.BarUtils
import com.base.locationsharewhite.utils.LogEx
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
...@@ -24,20 +26,29 @@ import java.util.concurrent.atomic.AtomicBoolean ...@@ -24,20 +26,29 @@ import java.util.concurrent.atomic.AtomicBoolean
@SuppressLint("CustomSplashScreen") @SuppressLint("CustomSplashScreen")
class SplashActivity : BaseActivity<ActivitySplashBinding>(), SplashView { class SplashActivity : BaseActivity<ActivitySplashBinding>(), SplashView {
private val TAG="SplashActivity"
private lateinit var splashPresenter: SplashPresenter private lateinit var splashPresenter: SplashPresenter
private var progressJob: Job? = null private var progressJob: Job? = null
override val binding: ActivitySplashBinding by lazy { override val binding: ActivitySplashBinding by lazy {
ActivitySplashBinding.inflate(layoutInflater) ActivitySplashBinding.inflate(layoutInflater)
} }
private var actionId = ""
override fun initView() { override fun initView() {
BarUtils.setStatusBarLightMode(this, true) BarUtils.setStatusBarLightMode(this, true)
BarUtils.setStatusBarColor(this, Color.TRANSPARENT) BarUtils.setStatusBarColor(this, Color.TRANSPARENT)
// binding.root.updatePadding(top = BarUtils.getStatusBarHeight()) // binding.root.updatePadding(top = BarUtils.getStatusBarHeight())
splashPresenter = SplashPresenter(this) splashPresenter = SplashPresenter(this)
actionId = intent.extras?.getString("actionId") ?: ""
LogEx.logDebug(TAG, "actionId=$actionId")
if (actionId.isNotEmpty()) {
NotificationHoverUtils.stopNotificationHandler()
}
if (ifAgreePrivacy) { if (ifAgreePrivacy) {
agreePrivacy() agreePrivacy()
} }
...@@ -69,7 +80,9 @@ class SplashActivity : BaseActivity<ActivitySplashBinding>(), SplashView { ...@@ -69,7 +80,9 @@ class SplashActivity : BaseActivity<ActivitySplashBinding>(), SplashView {
isFirstLauncher = false isFirstLauncher = false
firstLauncherJump() firstLauncherJump()
} else { } else {
startActivity(Intent(this, MainActivity::class.java)) startActivity(Intent(this, MainActivity::class.java).apply {
putExtra("actionId", actionId)
})
finish() finish()
} }
......
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingVertical="8dp"
tools:ignore="DisableBaselineAlignment">
<LinearLayout
android:id="@+id/ll_1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_weight="1"
android:orientation="vertical"
tools:ignore="UseCompoundDrawables">
<ImageView
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_gravity="center_horizontal"
android:src="@mipmap/home_notification"
tools:ignore="ContentDescription" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="2dp"
android:includeFontPadding="false"
android:text="@string/home"
android:textColor="@color/black"
android:textSize="14sp"
tools:ignore="HardcodedText" />
</LinearLayout>
<LinearLayout
android:id="@+id/ll_2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_weight="1"
android:orientation="vertical"
tools:ignore="UseCompoundDrawables">
<ImageView
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_gravity="center_horizontal"
android:src="@mipmap/mycode_notification"
tools:ignore="ContentDescription" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="2dp"
android:includeFontPadding="false"
android:text="@string/my_code"
android:textColor="@color/black"
android:textSize="14sp"
tools:ignore="HardcodedText" />
</LinearLayout>
<LinearLayout
android:id="@+id/ll_3"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical"
tools:ignore="UseCompoundDrawables">
<ImageView
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_gravity="center_horizontal"
android:src="@mipmap/share_notification"
tools:ignore="ContentDescription" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="2dp"
android:includeFontPadding="false"
android:text="@string/share"
android:textColor="@color/black"
android:textSize="14sp"
tools:ignore="HardcodedText" />
</LinearLayout>
<LinearLayout
android:id="@+id/ll_4"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical"
tools:ignore="UseCompoundDrawables">
<ImageView
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_gravity="center_horizontal"
android:src="@mipmap/settings_notification"
tools:ignore="ContentDescription" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="2dp"
android:includeFontPadding="false"
android:text="@string/settings"
android:textColor="@color/black"
android:textSize="14sp"
tools:ignore="HardcodedText" />
</LinearLayout>
</LinearLayout>
\ No newline at end of file
...@@ -55,4 +55,7 @@ ...@@ -55,4 +55,7 @@
<string name="name_is_empty">Name is empty</string> <string name="name_is_empty">Name is empty</string>
<string name="me">me</string> <string name="me">me</string>
<string name="delete">Delete</string> <string name="delete">Delete</string>
<string name="home">Home</string>
<string name="my_code">My Code</string>
<string name="share">Share</string>
</resources> </resources>
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment