运单轨迹上传

This commit is contained in:
lijia 2024-04-01 10:36:29 +08:00
parent bd050080c5
commit 23b8714d2f
9 changed files with 470 additions and 43 deletions

View File

@ -140,6 +140,7 @@ dependencies {
implementation 'me.zhanghai.android.materialratingbar:library:1.4.0'
implementation project(path: ':mylibrary')
implementation project(path: ':keeplibrary')
//
// implementation 'com.amap.api:3dmap:9.8.3'

View File

@ -46,7 +46,7 @@
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
<!-- 安卓11使用相机 -->
<queries package="${applicationId}">
<intent>
@ -94,7 +94,13 @@
<service android:name="com.amap.api.location.APSService"
android:foregroundServiceType="location"/>
<meta-data
android:name="com.google.firebase.messaging.default_notification_icon"
android:resource="@mipmap/app_icon" />
<service android:name=".service.UpLocationService"/>
<service android:name=".service.UpLocationService2"/>
<activity
android:name=".ui.LauncherActivity"

View File

@ -11,9 +11,11 @@ import com.dahe.gldriver.R
import com.dahe.gldriver.net.Api
import com.dahe.gldriver.oss.OssServiceUtil
import com.dahe.gldriver.push.PushHelper
import com.dahe.gldriver.service.MyNotification
import com.dahe.gldriver.ui.HomeActivity
import com.dahe.gldriver.utils.OrderUtils
import com.dahe.mylibrary.CommonBaseLibrary
import com.dahe.mylibrary.utils.ActivityUtils
import com.dahe.mylibrary.utils.AppUtils
import com.esign.esignsdk.EsignSdk
import com.github.gzuliyujiang.dialog.DialogConfig
@ -60,35 +62,64 @@ class App : Application() {
Intent(applicationContext, HomeActivity::class.java),
FLAG_UPDATE_CURRENT
)
Cactus.instance
.isDebug(true)
.setChannelId(AppUtils.getAppPackageName())
.setChannelName(AppUtils.getAppPackageName())
//可选,设置通知栏点击事件
.setPendingIntent(pendingIntent)
.setBackgroundMusicEnabled(true)//可选,退到后台是否可以播放音乐
// .setMusicInterval(20000)//设置音乐间隔时间时间间隔越长越省电默认间隔时间是0
.setMusicId(R.raw.main) //可选,设置音乐
// .addCallback(new CactusCallback())//可选,运行时回调
// .setCrashRestartUIEnabled(true) //可选设置奔溃可以重启google原生rom android 10以下可以正常重启
.setTitle("大河好运")
.setContent("大河好运司机端为您提供服务")
.hideNotificationAfterO(true)
.setSmallIcon(R.mipmap.app_icon)
.addCallback {
OrderUtils.getInstance().upLocation(applicationContext)
println("22222222222")
Log.i("lijia","11111111")
}
.addBackgroundCallback(object : CactusBackgroundCallback {
// Cactus.instance
// .isDebug(true)
// //.setTitle("大河好运")
//// .setContent("大河好运司机端为您提供服务")
//// .setSmallIcon(R.mipmap.app_icon)
//// .setChannelId(AppUtils.getAppPackageName())
//// .setChannelName(AppUtils.getAppPackageName())
// //可选,设置通知栏点击事件
// .setPendingIntent(pendingIntent)
// .setBackgroundMusicEnabled(true)//可选,退到后台是否可以播放音乐
//// .setMusicInterval(20000)//设置音乐间隔时间时间间隔越长越省电默认间隔时间是0
// .setMusicId(R.raw.main) //可选,设置音乐
//// .addCallback(new CactusCallback())//可选,运行时回调
//// .setCrashRestartUIEnabled(true) //可选设置奔溃可以重启google原生rom android 10以下可以正常重启
//// .setNotification(MyNotification.getInstance().getNotification(this))
// .hideNotificationAfterO(true)
// .addCallback {
// OrderUtils.getInstance().upLocation(applicationContext)
// }
// .addBackgroundCallback(object : CactusBackgroundCallback {
//
// override fun onBackground(background: Boolean) {
// if (background) {
//// getBillLocation();
// }
// }
// })
// .register(this)
override fun onBackground(background: Boolean) {
if (background) {
// getBillLocation();
}
}
})
.register(this)
// 定义前台通知的默认样式
// val foregroundNotification = ForegroundNotification(
// "大河好运2", "大河好运司机端为您提供服务", R.mipmap.app_icon
// ) { context, intent ->
// // 定义前台服务的通知点击事件
//// ActivityUtils.startActivity(applicationContext,HomeActivity::class.java)
// }
//// 启动保活服务
// KeepLive.startWork(this,
// KeepLive.RunMode.ENERGY,
// foregroundNotification, //你需要保活的服务如socket连接、定时任务等建议不用匿名内部类的方式在这里写
// object : UpLocationService23() {
// /**
// * 运行中
// * 由于服务可能会多次自动启动,该方法可能重复调用
// */
// override fun onWorking() {
// // do something
// }
//
// /**
// * 服务终止
// * 由于服务可能会被多次终止该方法可能重复调用需同onWorking配套使用如注册和注销broadcast
// */
// override fun onStop() {
// // do something
// }
// }
// )
}
override fun attachBaseContext(base: Context) {

View File

@ -0,0 +1,137 @@
package com.dahe.gldriver.service
import android.annotation.SuppressLint
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.Context.NOTIFICATION_SERVICE
import android.content.Intent
import android.graphics.Color
import android.os.Build
import androidx.core.app.NotificationCompat
import com.dahe.gldriver.R
import com.dahe.gldriver.ui.HomeActivity
import com.dahe.gldriver.utils.OcrUtils
import com.dahe.mylibrary.base.SingletonNoPHolder
/**
* @ClassName MyNotification
* @Author john
* @Date 2024/4/1 08:37
* @Description TODO
*/
class MyNotification private constructor() {
companion object : SingletonNoPHolder<MyNotification>(::MyNotification)
fun getNotification(context: Context): Notification {
// return buildNotification(context)
return sendNotify(context)
}
/**
* 实现包装方法参数按自己需求来
* @param title 标题
* @param content 内容
* @param priorityType 通知级别0为重要通知有提示音非0为普通通知无提示音
*/
}
private var notificationManager: NotificationManager? = null
var isCreateChannel = false
fun buildNotification(ctx: Context): Notification {
var builder: Notification.Builder? = null
var notification: Notification? = null
if (Build.VERSION.SDK_INT >= 26) {
//Android O上对Notification进行了修改如果设置的targetSDKVersion>=26建议使用此种方式创建通知栏
if (null == notificationManager) {
notificationManager =
ctx.getSystemService(Service.NOTIFICATION_SERVICE) as NotificationManager
}
val channelId = ctx.packageName
if (!isCreateChannel) {
val notificationChannel = NotificationChannel(
channelId,
"BackgroundLocation", NotificationManager.IMPORTANCE_DEFAULT
)
notificationChannel.enableLights(true) //是否在桌面icon右上角展示小圆点
notificationChannel.lightColor = Color.BLUE //小圆点颜色
notificationChannel.setShowBadge(true) //是否在久按桌面图标时显示此渠道的通知
notificationManager?.createNotificationChannel(notificationChannel)
isCreateChannel = true
}
builder = Notification.Builder(ctx, channelId)
} else {
builder = Notification.Builder(ctx)
}
builder.setSmallIcon(R.mipmap.app_icon)
.setContentTitle("大河好运司机端")
.setContentText("大河好运司机端为您提供服务")
.setWhen(System.currentTimeMillis())
notification = if (Build.VERSION.SDK_INT >= 16) {
builder.build()
} else {
return builder.notification
}
return notification
}
fun sendNotify( context: Context) : Notification{
var manager = context.getSystemService (NOTIFICATION_SERVICE) as NotificationManager
var wsschannel:NotificationChannel;// channel安卓8.0及以上才用到)
var channel_id = "my_notification_important"; // channelId用于绑定builder配置
var priority = NotificationCompat.PRIORITY_LOW; // 通知级别
// 判断是否8.0及以上版本,并选择发送消息的级别
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
// if (priorityType == 0) {
wsschannel =
NotificationChannel ("my_notification_important", "重要通知", NotificationManager.IMPORTANCE_HIGH);
channel_id = "my_notification_important";
// } else {
// wsschannel =
// NotificationChannel (NORMAL_CHANNEL_ID, "一般通知", NotificationManager.IMPORTANCE_LOW);
// channel_id = NORMAL_CHANNEL_ID;
// }
manager.createNotificationChannel(wsschannel);
}
// 通知级别
// if (priorityType == 0) {
// priority = NotificationCompat.PRIORITY_HIGH;
// } else {
// priority = NotificationCompat.PRIORITY_LOW;
// }
// 点击意图
var intent = Intent(context, HomeActivity::class.java);
var pendingIntent = PendingIntent.getActivity (context, 0, intent, PendingIntent.FLAG_IMMUTABLE);
// 通知配置
var notification = NotificationCompat.Builder (context, channel_id)
.setContentTitle("大河好运司机端") // 标题
.setContentText("大河好运司机端为您提供服务") // 内容
.setSmallIcon(R.mipmap.app_icon) // 小图标
.setPriority(NotificationCompat.PRIORITY_HIGH) // 7.0 设置优先级
.setContentIntent(pendingIntent) // 跳转意图
// .setAutoCancel(true) // 点击后自动销毁
.build();
// 给每个通知随机id
// int id =(int)((Math.random() * 9 + 1) * (6));
// 生成通知
manager.notify(1, notification);
return notification
}

View File

@ -0,0 +1,185 @@
package com.dahe.gldriver.service
import android.annotation.SuppressLint
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.graphics.Color
import android.os.Build
import android.os.Environment
import android.os.Handler
import android.os.IBinder
import android.os.Message
import android.util.Log
import com.amap.api.location.AMapLocation
import com.dahe.gldriver.R
import com.dahe.gldriver.base.AppConfig
import com.dahe.gldriver.bean.OrderDetailBean
import com.dahe.gldriver.bean.UpLocation
import com.dahe.gldriver.net.BaseObserver
import com.dahe.gldriver.net.DataManager
import com.dahe.gldriver.net.RxHttpCallBack
import com.dahe.gldriver.ui.HomeActivity
import com.dahe.gldriver.utils.GDLocationUtils
import com.dahe.mylibrary.net.CommonResponseBean
import com.dahe.mylibrary.utils.BaseSPUtils
import com.dahe.mylibrary.utils.FileIOUtils
import com.google.gson.Gson
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
import io.reactivex.rxjava3.schedulers.Schedulers
import java.text.DateFormat
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Timer
import java.util.TimerTask
/**
* @ClassName UpLocationService
* @Author john
* @Date 2024/3/28 09:08
* @Description TODO
*/
class UpLocationService2 : Service() {
private val hd = Handler { msg: Message ->
when (msg.what) {
123 -> {
var orderString =
BaseSPUtils.get(application, AppConfig.NEED_UP_ORDER, "") as String
if (!orderString.isNullOrEmpty()) {
var order = Gson().fromJson(orderString, OrderDetailBean::class.java)
GDLocationUtils.instance.getLocation2(application) {
if (it.errorCode == 0 && it.latitude != 0.0) {
loadLocation(it, order)
}
}
} else {
GDLocationUtils.instance.stopLocation()
}
//获取文件输出路径
// val path = Environment.getExternalStorageDirectory()
// .toString() + "/crashinfo/"
// val time: String = formatter.format(Date())
// val time2: String = formatter2.format(Date())
// val fileName = "crash-$time.txt"
//
// GDLocationUtils.instance.getLocation2(application) {
// if (it.errorCode == 0 && it.latitude != 0.0) {
// FileIOUtils.writeFileFromString(
// path + fileName,
// """当前时间:${time2},经纬度:${it.latitude}:${it.longitude}""",
// true
// )
//
// } else {
// FileIOUtils.writeFileFromString(
// path + fileName,
// """当前时间:${time2},经纬度:${it.latitude}${it.errorInfo}""",
// true
// )
// }
// }
}
}
false
}
private val formatter: DateFormat = SimpleDateFormat("yyyy-MM-dd")
private val formatter2: DateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
override fun onBind(intent: Intent?): IBinder? {
return null
}
override fun onRebind(intent: Intent?) {
super.onRebind(intent)
}
private val timeSum = 1000 * 60 * 3
// private val timeSum = 3000
private var timer: Timer? = null
override fun onCreate() {
super.onCreate()
Log.e("开始循环上传等待100ms", "-----")
timer = Timer()
timer?.schedule(object : TimerTask() {
override fun run() {
val msg = Message.obtain()
msg.what = 123
hd.sendMessage(msg)
}
}, 1000, timeSum.toLong())
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
// Log.d(TAG, "onStartCommand flags:$flags, startId:$startId [$this] ${Thread.currentThread()}")
val pendingIntent: PendingIntent =
Intent(this, HomeActivity::class.java).let { notificationIntent ->
PendingIntent.getActivity(this, 0, notificationIntent, 0)
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val chanId = "f-channel"
val chan = NotificationChannel(
chanId, "前台服务channel",
NotificationManager.IMPORTANCE_NONE
)
chan.lightColor = Color.BLUE
chan.lockscreenVisibility = Notification.VISIBILITY_PRIVATE
val service = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
service.createNotificationChannel(chan)
// Log.d(TAG, "服务调用startForeground")
val notification: Notification =
Notification.Builder(applicationContext, chanId)
.setContentTitle("大河好运司机端")
.setContentText("大河好运司机端为您提供服务")
.setSmallIcon(R.mipmap.app_icon)
.setContentIntent(pendingIntent)
.build()
startForeground(1, notification)
} else {
// Log.d(TAG, "${Build.VERSION.SDK_INT} < O(API 26) ")
}
return START_STICKY
}
private fun loadLocation(loc: AMapLocation, order: OrderDetailBean) {
DataManager.getInstance().driverUploadLocus(
UpLocation(
loc.latitude,
loc.longitude,
order.orderId,
order.waybillId
)
)
.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
.subscribe(BaseObserver(application, object : RxHttpCallBack<Any>() {
override fun onSuccess(t: CommonResponseBean<Any>) {
super.onSuccess(t)
}
}))
}
override fun onDestroy() {
super.onDestroy()
if (timer != null) {
timer?.cancel()
timer = null
}
GDLocationUtils.instance.stopLocation()
}
}

View File

@ -14,6 +14,7 @@ import com.dahe.gldriver.net.DataManager
import com.dahe.gldriver.net.RxHttpCallBack
import com.dahe.gldriver.oss.OssServiceUtil
import com.dahe.gldriver.utils.GDLocationUtils
import com.dahe.gldriver.utils.OrderUtils
import com.dahe.mylibrary.adapter.GridImageAdapter
import com.dahe.mylibrary.adapter.GridImageAdapter.OnItemClickListener
import com.dahe.mylibrary.base.BaseActivity
@ -256,7 +257,10 @@ class WaybillUpPicActivity : BaseActivity<ActivityWaybillUppicBinding>() {
mContext,
WaybillSuccActivity::class.java,
intent.extras)
//装货成功-开启轨迹上传
OrderUtils.getInstance().upLocation(mContext)
} else {
OrderUtils.getInstance().stopUpLocation(mContext)
ActivityUtils.startActivity(
mContext,
WaybillSuccActivity::class.java,

View File

@ -1,10 +1,18 @@
package com.dahe.gldriver.utils
import android.annotation.SuppressLint
import android.app.Notification
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.Service
import android.content.Context
import android.graphics.Color
import android.os.Build
import com.amap.api.location.AMapLocationClient
import com.amap.api.location.AMapLocationClientOption
import com.amap.api.location.AMapLocationListener
import com.dahe.gldriver.R
import com.dahe.gldriver.service.MyNotification
class GDLocationUtils private constructor(){
@ -52,7 +60,8 @@ class GDLocationUtils private constructor(){
//设置是否允许模拟位置,默认为true允许模拟位置
mLocationOption?.setMockEnable(true)
//启动后台定位第一个参数为通知栏ID建议整个APP使用一个
// mLocationClient?.enableBackgroundLocation(1,buildNotification(ctx))
//给定位客户端对象设置定位参数
mLocationClient?.setLocationOption(mLocationOption);
if(null != mLocationClient){
@ -62,8 +71,57 @@ class GDLocationUtils private constructor(){
mLocationClient?.startLocation()
}
}
/**
* 上传轨迹专用
* @param ctx Context
* @param mLocationListener AMapLocationListener
*/
fun getLocation2(ctx : Context,mLocationListener : AMapLocationListener){
//初始化定位
mLocationClient = AMapLocationClient(ctx)
//设置定位回调监听
mLocationClient?.setLocationListener(mLocationListener)
//初始化AMapLocationClientOption对象
mLocationOption = AMapLocationClientOption()
/**
* 设置定位场景目前支持三种场景签到出行运动默认无场景
*/
mLocationOption?.setLocationPurpose(AMapLocationClientOption.AMapLocationPurpose.SignIn)
//设置定位模式为AMapLocationMode.Hight_Accuracy高精度模式。
mLocationOption?.setLocationMode(AMapLocationClientOption.AMapLocationMode.Battery_Saving)
// mLocationOption?.setLocationMode(AMapLocationClientOption.AMapLocationMode.Battery_Saving)
//获取一次定位结果:
//该方法默认为false。
mLocationOption?.setOnceLocation(true)
//获取最近3s内精度最高的一次定位结果
//设置setOnceLocationLatest(boolean b)接口为true启动定位时SDK会返回最近3s内精度最高的一次定位结果。如果设置其为truesetOnceLocation(boolean b)接口也会被设置为true反之不会默认为false。
mLocationOption?.setOnceLocationLatest(true)
//设置是否允许模拟位置,默认为true允许模拟位置
mLocationOption?.setMockEnable(true)
//启动后台定位第一个参数为通知栏ID建议整个APP使用一个
mLocationClient?.enableBackgroundLocation(1,MyNotification.getInstance().getNotification(ctx))
//给定位客户端对象设置定位参数
mLocationClient?.setLocationOption(mLocationOption);
if(null != mLocationClient){
mLocationClient?.setLocationOption(mLocationOption);
//设置场景模式后最好调用一次stop再调用start以保证场景模式生效
mLocationClient?.stopLocation()
mLocationClient?.startLocation()
}
}
fun stopLocation(){
if(null != mLocationClient){
mLocationClient?.disableBackgroundLocation(true)
mLocationClient?.stopLocation()
}
}

View File

@ -2,6 +2,7 @@ package com.dahe.gldriver.utils
import android.content.Context
import android.content.Intent
import android.os.Build
import android.os.Bundle
import com.dahe.gldriver.base.App
import com.dahe.gldriver.base.AppConfig
@ -14,6 +15,7 @@ import com.dahe.gldriver.net.BaseObserver
import com.dahe.gldriver.net.DataManager
import com.dahe.gldriver.net.RxHttpCallBack
import com.dahe.gldriver.service.UpLocationService
import com.dahe.gldriver.service.UpLocationService2
import com.dahe.gldriver.ui.waybill.activity.WaybillLoadActivity
import com.dahe.mylibrary.base.SingletonNoPHolder
import com.dahe.mylibrary.net.CommonResponseBean
@ -164,23 +166,25 @@ class OrderUtils private constructor() {
super.onSuccess(t)
if (t.data != null) {
BaseSPUtils.put(context, NEED_UP_ORDER, Gson().toJson(t.data))
context.startService(Intent(context, UpLocationService::class.java))
// if (!Cactus.instance.isRunning(context)) {
// Cactus.instance.addCallback {
// context.startService(Intent(context, UpLocationService::class.java))
// }.restart(context)
// }else{
// Cactus.instance.addCallback {
// context.startService(Intent(context, UpLocationService::class.java))
// }.restart(context)
// }
// OrderUtils.getInstance().upLocation("","",t.data.orderId,t.data.waybillId)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
context.startForegroundService(Intent(context, UpLocationService2::class.java))
}else{
context.startService(Intent(context, UpLocationService2::class.java))
}
} else {
context.stopService(Intent(context, UpLocationService::class.java))
context.stopService(Intent(context, UpLocationService2::class.java))
BaseSPUtils.remove(context, NEED_UP_ORDER)
}
}
}))
}
/**
* 关闭上传运行中运单轨迹
* @param context Context
*/
fun stopUpLocation(context: Context){
context.stopService(Intent(context, UpLocationService2::class.java))
}
}

View File

@ -22,3 +22,4 @@ dependencyResolutionManagement {
rootProject.name = "GLDriver"
include ':app'
include ':mylibrary'
include ':keeplibrary'