Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Sign in / Register
Toggle navigation
L
location share white
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wanglei
location share white
Commits
895d920d
Commit
895d920d
authored
Oct 29, 2024
by
wanglei
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
...
parent
5d198b5b
Hide whitespace changes
Inline
Side-by-side
Showing
18 changed files
with
857 additions
and
8 deletions
+857
-8
AndroidManifest.xml
app/src/main/AndroidManifest.xml
+14
-2
ConstObject.kt
...main/java/com/base/locationsharewhite/bean/ConstObject.kt
+2
-0
Viewing.kt
...src/main/java/com/base/locationsharewhite/bean/Viewing.kt
+3
-2
NotificationHoverUtils.kt
...com/base/locationsharewhite/fcm/NotificationHoverUtils.kt
+66
-0
NotificationUiUtil.kt
...ava/com/base/locationsharewhite/fcm/NotificationUiUtil.kt
+233
-0
PopupConstObject.kt
.../java/com/base/locationsharewhite/fcm/PopupConstObject.kt
+28
-0
EventUtils.kt
...ain/java/com/base/locationsharewhite/helper/EventUtils.kt
+81
-0
LocationPositionUtils.kt
...base/locationsharewhite/location/LocationPositionUtils.kt
+63
-0
StayNotificationService.kt
...ase/locationsharewhite/service/StayNotificationService.kt
+201
-0
LocationMapActivity.kt
.../locationsharewhite/ui/locationmap/LocationMapActivity.kt
+24
-0
LocationPresenter.kt
...se/locationsharewhite/ui/locationmap/LocationPresenter.kt
+0
-2
SplashActivity.kt
...a/com/base/locationsharewhite/ui/splash/SplashActivity.kt
+15
-2
stay_notification_big.xml
app/src/main/res/layout/stay_notification_big.xml
+124
-0
home_notification.png
app/src/main/res/mipmap-xxhdpi/home_notification.png
+0
-0
mycode_notification.png
app/src/main/res/mipmap-xxhdpi/mycode_notification.png
+0
-0
settings_notification.png
app/src/main/res/mipmap-xxhdpi/settings_notification.png
+0
-0
share_notification.png
app/src/main/res/mipmap-xxhdpi/share_notification.png
+0
-0
strings.xml
app/src/main/res/values/strings.xml
+3
-0
No files found.
app/src/main/AndroidManifest.xml
View file @
895d920d
...
...
@@ -10,8 +10,15 @@
<!-- android:foregroundServiceType="location" -->
<!-- android:name="MyNavigationService" /> -->
<!-- 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.ACTIVITY_RECOGNITION"
/>
<!-- <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />-->
<!-- 身体活动数据 -->
<!-- <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
android:name=
".helper.MyApplication"
...
...
@@ -106,6 +113,11 @@
android:screenOrientation=
"portrait"
tools:ignore=
"DiscouragedApi,LockedOrientationActivity"
/>
<service
android:name=
".service.StayNotificationService"
android:foregroundServiceType=
"dataSync"
/>
<meta-data
android:name=
"com.google.android.gms.ads.APPLICATION_ID"
android:value=
"ca-app-pub-3940256099942544~3347511713"
/>
...
...
app/src/main/java/com/base/locationsharewhite/bean/ConstObject.kt
View file @
895d920d
...
...
@@ -5,6 +5,8 @@ import java.util.Locale
object
ConstObject
{
var
isFirstLauncher
=
true
get
()
{
return
AppPreferences
.
getInstance
().
getBoolean
(
"isFirstLauncher"
,
field
)
...
...
app/src/main/java/com/base/locationsharewhite/bean/Viewing.kt
View file @
895d920d
...
...
@@ -4,12 +4,13 @@ package com.base.locationsharewhite.bean
* 我可以看谁,自身无法切换状态
*/
data class
ViewingBean
(
val
device
:
String
,
val
nickname
:
String
,
val
status
:
Int
=
-
1
,
val
locatDate
:
LocationDat
e
?
=
null
,
val
locatDate
:
LocationDat
a
?
=
null
,
)
data class
LocationDat
e
(
data class
LocationDat
a
(
val
longitude
:
Double
,
val
latitude
:
Double
,
val
power
:
Int
,
...
...
app/src/main/java/com/base/locationsharewhite/fcm/NotificationHoverUtils.kt
0 → 100644
View file @
895d920d
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
app/src/main/java/com/base/locationsharewhite/fcm/NotificationUiUtil.kt
0 → 100644
View file @
895d920d
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
app/src/main/java/com/base/locationsharewhite/fcm/PopupConstObject.kt
0 → 100644
View file @
895d920d
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
app/src/main/java/com/base/locationsharewhite/helper/EventUtils.kt
0 → 100644
View file @
895d920d
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
app/src/main/java/com/base/locationsharewhite/location/LocationPositionUtils.kt
View file @
895d920d
...
...
@@ -2,12 +2,14 @@ package com.base.locationsharewhite.location
import
android.os.Build
import
com.base.locationsharewhite.BuildConfig
import
com.base.locationsharewhite.bean.LocationData
import
com.base.locationsharewhite.helper.AESHelper
import
com.base.locationsharewhite.helper.ConfigHelper
import
com.base.locationsharewhite.helper.ReportUtils
import
com.base.locationsharewhite.utils.AppPreferences
import
com.base.locationsharewhite.utils.LogEx
import
com.google.android.gms.maps.model.LatLng
import
com.google.gson.Gson
import
org.json.JSONObject
/**
...
...
@@ -66,4 +68,65 @@ object LocationPositionUtils {
}
}.
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
app/src/main/java/com/base/locationsharewhite/service/StayNotificationService.kt
0 → 100644
View file @
895d920d
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
app/src/main/java/com/base/locationsharewhite/ui/locationmap/LocationMapActivity.kt
View file @
895d920d
...
...
@@ -14,6 +14,7 @@ import com.base.locationsharewhite.bean.ViewingBean
import
com.base.locationsharewhite.databinding.ActivityLocationMapBinding
import
com.base.locationsharewhite.helper.BaseActivity
import
com.base.locationsharewhite.helper.MyApplication
import
com.base.locationsharewhite.location.LocationPositionUtils
import
com.base.locationsharewhite.location.LocationShareListUtils
import
com.base.locationsharewhite.map.MapUtils.addLocationMarker
import
com.base.locationsharewhite.map.MapUtils.getLatLngByLocationManager
...
...
@@ -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.Marker
import
kotlinx.coroutines.Dispatchers
import
kotlinx.coroutines.Job
import
kotlinx.coroutines.delay
import
kotlinx.coroutines.isActive
import
kotlinx.coroutines.launch
...
...
@@ -40,6 +43,7 @@ class LocationMapActivity : BaseActivity<ActivityLocationMapBinding>(), OnMapRea
private
var
map
:
GoogleMap
?
=
null
private
lateinit
var
locationPresenter
:
LocationPresenter
private
lateinit
var
adapter
:
ViewingAdapter
private
var
getLocationJob
:
Job
?
=
null
override
val
binding
:
ActivityLocationMapBinding
by
lazy
{
ActivityLocationMapBinding
.
inflate
(
layoutInflater
)
...
...
@@ -73,8 +77,10 @@ class LocationMapActivity : BaseActivity<ActivityLocationMapBinding>(), OnMapRea
adapter
=
ViewingAdapter
(
itemClick
=
{
if
(
currentViewingBean
!=
it
)
{
currentViewingBean
=
it
startGetLocationJob
()
initFriendLocationMarker
(
it
)
}
},
...
...
@@ -86,6 +92,24 @@ class LocationMapActivity : BaseActivity<ActivityLocationMapBinding>(), OnMapRea
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
()
{
if
(
ConstObject
.
noShowFriendsShareGuide
)
{
binding
.
llFriendsGuide
.
visibility
=
View
.
GONE
...
...
app/src/main/java/com/base/locationsharewhite/ui/locationmap/LocationPresenter.kt
View file @
895d920d
...
...
@@ -2,10 +2,8 @@ package com.base.locationsharewhite.ui.locationmap
import
android.annotation.SuppressLint
import
android.app.Activity
import
android.content.Context
import
android.location.Location
import
androidx.lifecycle.LifecycleCoroutineScope
import
com.base.locationsharewhite.helper.BaseActivity
import
com.base.locationsharewhite.location.LocationPositionUtils.uploadMyLocation
import
com.base.locationsharewhite.map.MapUtils.getLatLngByLocationManager
import
com.base.locationsharewhite.utils.BatteryUtils.getBatteryLevel
...
...
app/src/main/java/com/base/locationsharewhite/ui/splash/SplashActivity.kt
View file @
895d920d
...
...
@@ -8,11 +8,13 @@ import com.base.locationsharewhite.R
import
com.base.locationsharewhite.bean.ConstObject.ifAgreePrivacy
import
com.base.locationsharewhite.bean.ConstObject.isFirstLauncher
import
com.base.locationsharewhite.databinding.ActivitySplashBinding
import
com.base.locationsharewhite.fcm.NotificationHoverUtils
import
com.base.locationsharewhite.helper.BaseActivity
import
com.base.locationsharewhite.ui.howuse.HowUseActivity
import
com.base.locationsharewhite.ui.main.MainActivity
import
com.base.locationsharewhite.ui.set.LanguageActivity
import
com.base.locationsharewhite.utils.BarUtils
import
com.base.locationsharewhite.utils.LogEx
import
kotlinx.coroutines.Dispatchers
import
kotlinx.coroutines.Job
import
kotlinx.coroutines.delay
...
...
@@ -24,20 +26,29 @@ import java.util.concurrent.atomic.AtomicBoolean
@SuppressLint
(
"CustomSplashScreen"
)
class
SplashActivity
:
BaseActivity
<
ActivitySplashBinding
>(),
SplashView
{
private
val
TAG
=
"SplashActivity"
private
lateinit
var
splashPresenter
:
SplashPresenter
private
var
progressJob
:
Job
?
=
null
override
val
binding
:
ActivitySplashBinding
by
lazy
{
ActivitySplashBinding
.
inflate
(
layoutInflater
)
}
private
var
actionId
=
""
override
fun
initView
()
{
BarUtils
.
setStatusBarLightMode
(
this
,
true
)
BarUtils
.
setStatusBarColor
(
this
,
Color
.
TRANSPARENT
)
// binding.root.updatePadding(top = BarUtils.getStatusBarHeight())
splashPresenter
=
SplashPresenter
(
this
)
actionId
=
intent
.
extras
?.
getString
(
"actionId"
)
?:
""
LogEx
.
logDebug
(
TAG
,
"actionId=$actionId"
)
if
(
actionId
.
isNotEmpty
())
{
NotificationHoverUtils
.
stopNotificationHandler
()
}
if
(
ifAgreePrivacy
)
{
agreePrivacy
()
}
...
...
@@ -69,7 +80,9 @@ class SplashActivity : BaseActivity<ActivitySplashBinding>(), SplashView {
isFirstLauncher
=
false
firstLauncherJump
()
}
else
{
startActivity
(
Intent
(
this
,
MainActivity
::
class
.
java
))
startActivity
(
Intent
(
this
,
MainActivity
::
class
.
java
).
apply
{
putExtra
(
"actionId"
,
actionId
)
})
finish
()
}
...
...
app/src/main/res/layout/stay_notification_big.xml
0 → 100644
View file @
895d920d
<?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
app/src/main/res/mipmap-xxhdpi/home_notification.png
0 → 100644
View file @
895d920d
11.1 KB
app/src/main/res/mipmap-xxhdpi/mycode_notification.png
0 → 100644
View file @
895d920d
9.65 KB
app/src/main/res/mipmap-xxhdpi/settings_notification.png
0 → 100644
View file @
895d920d
11.7 KB
app/src/main/res/mipmap-xxhdpi/share_notification.png
0 → 100644
View file @
895d920d
9.87 KB
app/src/main/res/values/strings.xml
View file @
895d920d
...
...
@@ -55,4 +55,7 @@
<string
name=
"name_is_empty"
>
Name is empty
</string>
<string
name=
"me"
>
me
</string>
<string
name=
"delete"
>
Delete
</string>
<string
name=
"home"
>
Home
</string>
<string
name=
"my_code"
>
My Code
</string>
<string
name=
"share"
>
Share
</string>
</resources>
\ No newline at end of file
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment