Merge branch 'feat_overview_mode_290' into dev_robotaxi-d-app-module_290_220715_2.9.0

全览模式合并到远端290
This commit is contained in:
liujing
2022-07-20 11:54:05 +08:00
67 changed files with 2555 additions and 488 deletions

View File

@@ -61,12 +61,14 @@ dependencies {
implementation rootProject.ext.dependencies.modulecommon
implementation rootProject.ext.dependencies.mogo_core_data
implementation rootProject.ext.dependencies.mogo_core_function_call
implementation rootProject.ext.dependencies.mogo_core_function_hmi
}else {
implementation project(":core:mogo-core-utils")
implementation project(":foudations:mogo-commons")
implementation project(':modules:mogo-module-common')
implementation project(':core:mogo-core-data')
implementation project(':core:mogo-core-function-call')
implementation project(':core:function-impl:mogo-core-function-hmi')
}
}

View File

@@ -32,6 +32,7 @@ import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotStatusListener
import com.mogo.eagle.core.function.call.autopilot.CallerAutopilotRecordListenerManager;
import com.mogo.eagle.core.function.call.devatools.CallerDevaToolsManager;
import com.mogo.eagle.core.function.call.hmi.CallerHmiManager;
import com.mogo.eagle.core.function.hmi.ui.widget.TrafficDataView;
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger;
import com.mogo.eagle.core.utilcode.util.ToastUtils;
import com.mogo.eagle.core.utilcode.util.UiThreadHandler;
@@ -76,7 +77,8 @@ public abstract class BaseBusTabFragment<V extends IView, P extends Presenter<V>
private FrameLayout flStationPanelContainer;
private Group groupTestPanel;
private FrameLayout flSpeed;
private BusArcView mouduleArc;
// private BusArcView mouduleArc;
private TrafficDataView mTrafficDataView;
private ImageView mUpgradeTipIv;
// private BusTrafficLightView mTrafficLightView;
@@ -122,7 +124,7 @@ public abstract class BaseBusTabFragment<V extends IView, P extends Presenter<V>
tvOperationStatus = findViewById(R.id.module_mogo_och_operation_status);
flSpeed = (FrameLayout) findViewById(R.id.fl_speed);
mouduleArc = (BusArcView) findViewById(R.id.bus_arc);
mTrafficDataView = (TrafficDataView) findViewById(R.id.bus_arc);
panelView = LayoutInflater.from(getContext()).inflate(getStationPanelViewId(), flStationPanelContainer);
slidePanelView.setOnSlidePanelMoveToEndListener(onSlideToEndListener);
@@ -150,8 +152,8 @@ public abstract class BaseBusTabFragment<V extends IView, P extends Presenter<V>
});
if (DebugConfig.isDebug()) {
mouduleArc.setLongClickable(true);
mouduleArc.setOnLongClickListener(v -> {
mTrafficDataView.setLongClickable(true);
mTrafficDataView.setOnLongClickListener(v -> {
CallerLogger.INSTANCE.d(M_BUS + TAG, "长按显示状态工具栏");
Intent intent = new Intent();
intent.putExtra("oper", 52);
@@ -483,9 +485,9 @@ public abstract class BaseBusTabFragment<V extends IView, P extends Presenter<V>
*/
public void updateSpeedView(float newSpeed) {
int speed = (int) (Math.abs(newSpeed) * 3.6F); // 倒车时工控机反馈定位信息中speed为负值
mouduleArc.setArcColor(Color.parseColor(speed > 60 ? "#DB3137" : "#3E77F6"));
mouduleArc.setValues(speed);
flSpeed.setBackgroundResource(speed > 60 ? R.drawable.bus_yi_biao_pan_bg_speeding : R.drawable.bus_yi_biao_pan_bg_nor);
if (mTrafficDataView != null){
mTrafficDataView.updateSpeedWithValue(speed);
}
}
@Override

View File

@@ -5,23 +5,22 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="@dimen/dp_72">
<FrameLayout
android:id="@+id/fl_speed"
android:layout_width="@dimen/bus_ext_speed_width"
android:layout_height="@dimen/bus_ext_speed_height"
android:layout_marginLeft="@dimen/module_mogo_och_margin_left"
android:layout_marginTop="@dimen/module_mogo_och_margin_left"
android:background="@drawable/bus_yi_biao_pan_bg_nor"
android:elevation="@dimen/bus_dp_10"
android:padding="@dimen/bus_dp_20"
android:visibility="visible"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent">
<FrameLayout
android:id="@+id/fl_speed"
android:layout_width="@dimen/dp_616"
android:layout_height="@dimen/dp_320"
android:layout_marginLeft="@dimen/dp_10"
android:layout_marginTop="@dimen/dp_40"
android:elevation="@dimen/bus_dp_10"
android:padding="@dimen/bus_dp_20"
android:visibility="visible"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent">
<com.mogo.och.bus.view.BusArcView
<com.mogo.eagle.core.function.hmi.ui.widget.TrafficDataView
android:id="@+id/bus_arc"
android:layout_width="@dimen/bus_ext_arcView_width"
android:layout_height="@dimen/bus_ext_arcView_height"
android:layout_width="@dimen/dp_616"
android:layout_height="@dimen/dp_320"
android:layout_gravity="center" />
</FrameLayout>

View File

@@ -104,9 +104,9 @@
<dimen name="bus_ext_arcView_stroke_with">20px</dimen>
<dimen name="bus_ext_arcView_top">40px</dimen>
<dimen name="bus_ext_arcView_width">320px</dimen>
<dimen name="bus_ext_speed_height">460px</dimen>
<dimen name="bus_ext_speed_height">320px</dimen>
<dimen name="bus_ext_speed_padding">70px</dimen>
<dimen name="bus_ext_speed_width">460px</dimen>
<dimen name="bus_ext_speed_width">616px</dimen>
<dimen name="bus_ext_speed_width_big_radius">130px</dimen>
<dimen name="bus_ext_speed_width_sm_radius">30px</dimen>
<dimen name="bus_switch_map">279px</dimen>

View File

@@ -0,0 +1,265 @@
package com.mogo.och.taxi.passenger.ui.video
import android.content.Context
import android.graphics.Bitmap
import android.graphics.Color
import android.graphics.drawable.BitmapDrawable
import android.util.AttributeSet
import android.view.LayoutInflater
import android.view.View
import android.widget.RelativeLayout
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.Glide
import com.bumptech.glide.request.RequestOptions
import com.bumptech.glide.request.target.SimpleTarget
import com.bumptech.glide.request.transition.Transition
import com.mogo.eagle.core.utilcode.util.ToastUtils
import com.mogo.och.taxi.passenger.R
import com.mogo.och.taxi.passenger.bean.TaxiPassengerVideoPlay
import com.mogo.och.taxi.passenger.ui.video.layoutmanage.CarouselLayoutManager
import com.mogo.och.taxi.passenger.ui.video.layoutmanage.CarouselZoomPostLayoutListener
import com.mogo.och.taxi.passenger.ui.video.layoutmanage.CenterScrollListener
import com.mogo.och.taxi.passenger.utils.blur.GlideBlurTransform
import com.mogo.och.taxi.passenger.widget.ConsultVideoPlayer
import com.mogo.och.taxi.passenger.widget.indicator.IndicatorView
import com.mogo.och.taxi.passenger.widget.indicator.enums.IndicatorOrientation
import com.mogo.och.taxi.passenger.widget.indicator.enums.IndicatorSlideMode
import com.mogo.och.taxi.passenger.widget.indicator.enums.IndicatorStyle
import com.shuyu.gsyvideoplayer.listener.GSYSampleCallBack
import com.shuyu.gsyvideoplayer.video.base.GSYVideoView
import java.util.*
import kotlin.math.floor
/**
*
* 蘑菇咨询
* Created on 2022/5/16
*/
class TaxiPassengerMogoConsultView :RelativeLayout {
constructor(context: Context?) : super(context)
constructor(context: Context?, attributeSet: AttributeSet) : super(context, attributeSet)
constructor(context: Context?, attributeSet: AttributeSet, defStyleAttr: Int) : super(context, attributeSet, defStyleAttr)
constructor(context: Context?, attributeSet: AttributeSet, defStyleAttr: Int, defStyleRes: Int) : super(context, attributeSet, defStyleAttr, defStyleRes)
private lateinit var rvVideoPlaylist: RecyclerView
private lateinit var indicatorView: IndicatorView
private lateinit var clContain: ConstraintLayout
private fun initView(context: Context) {
LayoutInflater.from(context).inflate(R.layout.taxi_p_arrived_mogo_consult, this, true)
rvVideoPlaylist = findViewById(R.id.rv_video_playlist)
indicatorView = findViewById(R.id.indicatorView)
clContain = findViewById(R.id.cl_contain)
val arrayListOf = ArrayList<TaxiPassengerVideoPlay>()
arrayListOf.add(TaxiPassengerVideoPlay("https://img.zhidaohulian.com/fileServer/online_car_hailing/1655708409810/20210610重新排版3屏.m4v","https://img.zhidaohulian.com/fileServer/online_car_hailing/1655969579713/三屏.png","重新排版"))
arrayListOf.add(TaxiPassengerVideoPlay("https://img.zhidaohulian.com/fileServer/online_car_hailing/1655708499497/大运会合作解说版.m4v","https://img.zhidaohulian.com/fileServer/online_car_hailing/1655969536177/大运会.png","大运会"))
arrayListOf.add(TaxiPassengerVideoPlay("https://img.zhidaohulian.com/fileServer/online_car_hailing/1655708554279/红旗车队.m4v","https://img.zhidaohulian.com/fileServer/online_car_hailing/1655969553174/红旗重新排版.png","红旗车队"))
arrayListOf.add(TaxiPassengerVideoPlay("https://img.zhidaohulian.com/fileServer/online_car_hailing/1655708596763/全车型混剪增加红旗车队.m4v","https://img.zhidaohulian.com/fileServer/online_car_hailing/1655969511280/车队.png","全车型混剪增加红旗车队"))
val recyclerVideoAdapter = RecyclerVideoAdapter(context, arrayListOf)
val carouselLayoutManager = CarouselLayoutManager(CarouselLayoutManager.HORIZONTAL, true)
carouselLayoutManager.setPostLayoutListener(CarouselZoomPostLayoutListener ())
carouselLayoutManager.maxVisibleItems = 1
indicatorView.notifyDataChanged(arrayListOf.size)
indicatorView.setSlideMode(IndicatorSlideMode.SCALE)
indicatorView.setOrientation(IndicatorOrientation.INDICATOR_HORIZONTAL)
indicatorView.setIndicatorStyle(IndicatorStyle.ROUND_RECT)
indicatorView.setSliderColor(Color.parseColor("#80FFFFFF"), Color.parseColor("#2972FF"))
indicatorView.setSliderWidth(16f, 101f)
indicatorView.setSliderHeight(16f)
indicatorView.setSliderGap(30f)
rvVideoPlaylist.addOnScrollListener(object: CenterScrollListener() {
var prePlayerPosition = 0
override fun pageSelect(recyclerView: RecyclerView?, newState: Int) {
//播放视频
val (centerItemPosition: Int, player) = getPlayer(carouselLayoutManager)
indicatorView.onPageSelected(centerItemPosition)
if(player is ConsultVideoPlayer){
if(prePlayerPosition!=centerItemPosition) {
if(player.currentState==GSYVideoView.CURRENT_STATE_PAUSE){
player.onVideoReset()
}else{
}
val playerHolder = carouselLayoutManager.findViewByPosition(prePlayerPosition)
val prePlayer = playerHolder?.findViewById<ConsultVideoPlayer>(R.id.video_item_player)
prePlayer?.let {
if(it is ConsultVideoPlayer){
it.onVideoReset()
}
}
val taxiPassengerVideoPlay = arrayListOf[centerItemPosition]
if (player.getVideoAllCallBack()==null) {
setBackageAndPlayNext(taxiPassengerVideoPlay, player, centerItemPosition)
}
}else{
player.onVideoResume(false)
}
}
prePlayerPosition = centerItemPosition
}
override fun pageStop() {
val (centerItemPosition: Int, player) = getPlayer(carouselLayoutManager)
if(player is ConsultVideoPlayer){
player.onVideoPause()
}
}
})
carouselLayoutManager.addOnDargAutoDiffListener { adapterPosition, currentPosition ->
val fl = adapterPosition - floor(adapterPosition)
var currentIndex = currentPosition
if(fl>0.5){
if(currentPosition==0){
currentIndex = rvVideoPlaylist.adapter!!.itemCount-1
}else {
currentIndex -= 1
}
}
indicatorView.onPageScrolled(currentIndex, fl, 0)
}
recyclerVideoAdapter.setOnThumbImageClilckListener {
val (centerItemPosition: Int, player) = getPlayer(carouselLayoutManager)
if(player is ConsultVideoPlayer) {
player.onVideoReset()
player.thumbImageViewLayout.visibility = View.VISIBLE
}
rvVideoPlaylist.smoothScrollToPosition(it)
}
rvVideoPlaylist.layoutManager = carouselLayoutManager
rvVideoPlaylist.setHasFixedSize(true)
rvVideoPlaylist.adapter = recyclerVideoAdapter
}
private fun setBackageAndPlayNext(
taxiPassengerVideoPlay: TaxiPassengerVideoPlay,
player: ConsultVideoPlayer,
centerItemPosition: Int,
) {
// 设置背景图片
Glide.with(context).asBitmap()
.load(taxiPassengerVideoPlay.imageUrl)
.apply(
RequestOptions().transform(
GlideBlurTransform(context, taxiPassengerVideoPlay.imageUrl, 5)
)
)
.into(object : SimpleTarget<Bitmap?>() {
override fun onResourceReady(
resource: Bitmap,
transition: Transition<in Bitmap?>?
) {
clContain.background = BitmapDrawable(context.resources, resource)
}
})
if(player.getVideoAllCallBack()==null) {
player.setVideoAllCallBack(object : GSYSampleCallBack() {
override fun onAutoComplete(url: String?, vararg objects: Any?) {
player.onVideoReset()
val itemCount = rvVideoPlaylist.adapter?.itemCount
itemCount?.let {
if (centerItemPosition == itemCount - 1) {
rvVideoPlaylist.smoothScrollToPosition(0)
} else {
rvVideoPlaylist.smoothScrollToPosition(centerItemPosition + 1)
}
}
}
override fun onClickBlank(url: String?, vararg objects: Any?) {
super.onClickBlank(url, *objects)
rvVideoPlaylist.smoothScrollToPosition(centerItemPosition)
}
override fun onPlayError(url: String?, vararg objects: Any?) {
super.onPlayError(url, *objects)
ToastUtils.showLong("哎呀,出错了,看看其他视频吧")
}
override fun onClickStartError(url: String?, vararg objects: Any?) {
super.onClickStartError(url, *objects)
ToastUtils.showLong("哎呀,出错了,看看其他视频吧")
}
})
}
}
override fun onWindowFocusChanged(hasWindowFocus: Boolean) {
super.onWindowFocusChanged(hasWindowFocus)
val carouselLayoutManager = rvVideoPlaylist.layoutManager as CarouselLayoutManager
val (centerItemPosition: Int, player) = getPlayer(carouselLayoutManager)
player?.let {
if (player is ConsultVideoPlayer) {
if(hasWindowFocus){// 获取焦点两种情况
// 恢复播放和开始播放
if(player.isIfCurrentIsFullscreen){// 全屏了
}else {
when (player.currentState) {
GSYVideoView.CURRENT_STATE_PAUSE -> {
player.onVideoResume(false)
}
GSYVideoView.CURRENT_STATE_PLAYING -> {
}
else -> {
val recyclerVideoAdapter =
rvVideoPlaylist.adapter as RecyclerVideoAdapter
setBackageAndPlayNext(
recyclerVideoAdapter.getItemByPosition(centerItemPosition),
player, centerItemPosition
)
//player.startPlayLogic()
}
}
}
}else {
// 离开应用 暂停视频
// 关闭 onDetachedFromWindow 会reset
if(player.isIfCurrentIsFullscreen){// 全屏了
}else {
player.onVideoPause()
}
}
}
}
}
private fun getPlayer(carouselLayoutManager: CarouselLayoutManager): Pair<Int, ConsultVideoPlayer?> {
val centerItemPosition: Int = carouselLayoutManager.centerItemPosition
val playerHolder = carouselLayoutManager.findViewByPosition(centerItemPosition)
val player = playerHolder?.findViewById<ConsultVideoPlayer>(R.id.video_item_player)
return Pair(centerItemPosition, player)
}
override fun onDetachedFromWindow() {
val carouselLayoutManager = rvVideoPlaylist.layoutManager as CarouselLayoutManager
val (_: Int, player) = getPlayer(carouselLayoutManager)
player?.let {
if(player is ConsultVideoPlayer){
player.currentPlayer.release()
player.onVideoReset()
}
}
super.onDetachedFromWindow()
}
init {
try {
initView(context)
} catch (e: Exception) {
e.printStackTrace()
}
}
}

View File

@@ -0,0 +1,268 @@
package com.mogo.och.taxi.passenger.ui.video
import android.content.Context
import android.graphics.Bitmap
import android.graphics.Color
import android.graphics.drawable.BitmapDrawable
import android.util.AttributeSet
import android.view.LayoutInflater
import android.view.View
import android.widget.RelativeLayout
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.Glide
import com.bumptech.glide.request.RequestOptions
import com.bumptech.glide.request.target.SimpleTarget
import com.bumptech.glide.request.transition.Transition
import com.mogo.eagle.core.utilcode.util.ToastUtils
import com.mogo.och.taxi.passenger.R
import com.mogo.och.taxi.passenger.bean.TaxiPassengerVideoPlay
import com.mogo.och.taxi.passenger.ui.video.layoutmanage.CarouselLayoutManager
import com.mogo.och.taxi.passenger.ui.video.layoutmanage.CarouselZoomPostLayoutListener
import com.mogo.och.taxi.passenger.ui.video.layoutmanage.CenterScrollListener
import com.mogo.och.taxi.passenger.utils.blur.GlideBlurTransform
import com.mogo.och.taxi.passenger.widget.ConsultVideoPlayer
import com.mogo.och.taxi.passenger.widget.indicator.IndicatorView
import com.mogo.och.taxi.passenger.widget.indicator.enums.IndicatorOrientation
import com.mogo.och.taxi.passenger.widget.indicator.enums.IndicatorSlideMode
import com.mogo.och.taxi.passenger.widget.indicator.enums.IndicatorStyle
import com.shuyu.gsyvideoplayer.listener.GSYSampleCallBack
import com.shuyu.gsyvideoplayer.video.base.GSYVideoView
import java.util.*
import kotlin.math.floor
/**
*
* 蘑菇咨询
* Created on 2022/5/16
*/
class TaxiPassengerMogoMoviesView :RelativeLayout {
constructor(context: Context?) : super(context)
constructor(context: Context?, attributeSet: AttributeSet) : super(context, attributeSet)
constructor(context: Context?, attributeSet: AttributeSet, defStyleAttr: Int) : super(context, attributeSet, defStyleAttr)
constructor(context: Context?, attributeSet: AttributeSet, defStyleAttr: Int, defStyleRes: Int) : super(context, attributeSet, defStyleAttr, defStyleRes)
private lateinit var rvVideoPlaylist: RecyclerView
private lateinit var indicatorView: IndicatorView
private lateinit var clContain: ConstraintLayout
private fun initView(context: Context) {
LayoutInflater.from(context).inflate(R.layout.taxi_p_mogo_movies, this, true)
rvVideoPlaylist = findViewById(R.id.rv_video_playlist)
indicatorView = findViewById(R.id.indicatorView)
clContain = findViewById(R.id.cl_contain)
val arrayListOf = ArrayList<TaxiPassengerVideoPlay>()
arrayListOf.add(TaxiPassengerVideoPlay("https://img.zhidaohulian.com/fileServer/online_car_hailing/1655708409810/20210610重新排版3屏.m4v","https://img.zhidaohulian.com/fileServer/online_car_hailing/1655969579713/三屏.png","重新排版"))
arrayListOf.add(TaxiPassengerVideoPlay("https://img.zhidaohulian.com/fileServer/online_car_hailing/1655708499497/大运会合作解说版.m4v","https://img.zhidaohulian.com/fileServer/online_car_hailing/1655969536177/大运会.png","大运会"))
arrayListOf.add(TaxiPassengerVideoPlay("https://img.zhidaohulian.com/fileServer/online_car_hailing/1655708554279/红旗车队.m4v","https://img.zhidaohulian.com/fileServer/online_car_hailing/1655969553174/红旗重新排版.png","红旗车队"))
arrayListOf.add(TaxiPassengerVideoPlay("https://img.zhidaohulian.com/fileServer/online_car_hailing/1655708596763/全车型混剪增加红旗车队.m4v","https://img.zhidaohulian.com/fileServer/online_car_hailing/1655969511280/车队.png","全车型混剪增加红旗车队"))
val recyclerVideoAdapter = RecyclerVideoAdapter(context, arrayListOf)
val carouselLayoutManager = CarouselLayoutManager(CarouselLayoutManager.HORIZONTAL, true)
carouselLayoutManager.setPostLayoutListener(CarouselZoomPostLayoutListener ())
carouselLayoutManager.maxVisibleItems = 1
indicatorView.notifyDataChanged(arrayListOf.size)
indicatorView.setSlideMode(IndicatorSlideMode.SCALE)
indicatorView.setOrientation(IndicatorOrientation.INDICATOR_HORIZONTAL)
indicatorView.setIndicatorStyle(IndicatorStyle.ROUND_RECT)
indicatorView.setSliderColor(Color.parseColor("#80FFFFFF"), Color.parseColor("#2972FF"))
indicatorView.setSliderWidth(14f, 90f)
indicatorView.setSliderHeight(14f)
rvVideoPlaylist.addOnScrollListener(object: CenterScrollListener() {
var prePlayerPosition = 0
override fun pageSelect(recyclerView: RecyclerView?, newState: Int) {
//播放视频
val (centerItemPosition: Int, player) = getPlayer(carouselLayoutManager)
indicatorView.onPageSelected(centerItemPosition)
if(player is ConsultVideoPlayer){
if(prePlayerPosition!=centerItemPosition) {
if(player.currentState==GSYVideoView.CURRENT_STATE_PAUSE){
player.onVideoReset()
}else{
}
val playerHolder = carouselLayoutManager.findViewByPosition(prePlayerPosition)
val prePlayer = playerHolder?.findViewById<ConsultVideoPlayer>(R.id.video_item_player)
prePlayer?.let {
if(it is ConsultVideoPlayer){
it.onVideoReset()
}
}
val taxiPassengerVideoPlay = arrayListOf[centerItemPosition]
if (player.getVideoAllCallBack()==null) {
setBackageAndPlayNext(taxiPassengerVideoPlay, player, centerItemPosition)
}
}else{
player.onVideoResume(false)
}
}
prePlayerPosition = centerItemPosition
}
override fun pageStop() {
val (centerItemPosition: Int, player) = getPlayer(carouselLayoutManager)
if(player is ConsultVideoPlayer){
player.onVideoPause()
}
}
})
carouselLayoutManager.addOnDargAutoDiffListener { adapterPosition, currentPosition ->
val fl = adapterPosition - floor(adapterPosition)
var currentIndex = currentPosition
if(fl>0.5){
if(currentPosition==0){
currentIndex = rvVideoPlaylist.adapter!!.itemCount-1
}else {
currentIndex -= 1
}
}
indicatorView.onPageScrolled(currentIndex, fl, 0)
}
recyclerVideoAdapter.setOnThumbImageClilckListener {
val (centerItemPosition: Int, player) = getPlayer(carouselLayoutManager)
if(player is ConsultVideoPlayer) {
player.onVideoReset()
player.thumbImageViewLayout.visibility = View.VISIBLE
}
rvVideoPlaylist.smoothScrollToPosition(it)
}
rvVideoPlaylist.layoutManager = carouselLayoutManager
rvVideoPlaylist.setHasFixedSize(true)
rvVideoPlaylist.adapter = recyclerVideoAdapter
}
private fun setBackageAndPlayNext(
taxiPassengerVideoPlay: TaxiPassengerVideoPlay,
player: ConsultVideoPlayer,
centerItemPosition: Int,
) {
// 设置背景图片
Glide.with(context).asBitmap()
.load(taxiPassengerVideoPlay.imageUrl)
.apply(
RequestOptions().transform(
GlideBlurTransform(
context,
taxiPassengerVideoPlay.imageUrl,
5
)
)
)
.into(object : SimpleTarget<Bitmap?>() {
override fun onResourceReady(
resource: Bitmap,
transition: Transition<in Bitmap?>?
) {
clContain.background = BitmapDrawable(context.resources, resource)
}
})
if(player.getVideoAllCallBack()==null) {
player.setVideoAllCallBack(object : GSYSampleCallBack() {
override fun onAutoComplete(url: String?, vararg objects: Any?) {
player.onVideoReset()
val itemCount = rvVideoPlaylist.adapter?.itemCount
itemCount?.let {
if (centerItemPosition == itemCount - 1) {
rvVideoPlaylist.smoothScrollToPosition(0)
} else {
rvVideoPlaylist.smoothScrollToPosition(centerItemPosition + 1)
}
}
}
override fun onClickBlank(url: String?, vararg objects: Any?) {
super.onClickBlank(url, *objects)
rvVideoPlaylist.smoothScrollToPosition(centerItemPosition)
}
override fun onPlayError(url: String?, vararg objects: Any?) {
super.onPlayError(url, *objects)
ToastUtils.showLong("哎呀,出错了,看看其他视频吧")
}
override fun onClickStartError(url: String?, vararg objects: Any?) {
super.onClickStartError(url, *objects)
ToastUtils.showLong("哎呀,出错了,看看其他视频吧")
}
})
}
}
override fun onWindowFocusChanged(hasWindowFocus: Boolean) {
super.onWindowFocusChanged(hasWindowFocus)
val carouselLayoutManager = rvVideoPlaylist.layoutManager as CarouselLayoutManager
val (centerItemPosition: Int, player) = getPlayer(carouselLayoutManager)
player?.let {
if (player is ConsultVideoPlayer) {
if(hasWindowFocus){// 获取焦点两种情况
// 恢复播放和开始播放
if(player.isIfCurrentIsFullscreen){// 全屏了
}else {
when (player.currentState) {
GSYVideoView.CURRENT_STATE_PAUSE -> {
player.onVideoResume(false)
}
GSYVideoView.CURRENT_STATE_PLAYING -> {
}
else -> {
val recyclerVideoAdapter =
rvVideoPlaylist.adapter as RecyclerVideoAdapter
setBackageAndPlayNext(
recyclerVideoAdapter.getItemByPosition(centerItemPosition),
player, centerItemPosition
)
//player.startPlayLogic()
}
}
}
}else {
// 离开应用 暂停视频
// 关闭 onDetachedFromWindow 会reset
if(player.isIfCurrentIsFullscreen){// 全屏了
}else {
player.onVideoPause()
}
}
}
}
}
private fun getPlayer(carouselLayoutManager: CarouselLayoutManager): Pair<Int, ConsultVideoPlayer?> {
val centerItemPosition: Int = carouselLayoutManager.centerItemPosition
val playerHolder = carouselLayoutManager.findViewByPosition(centerItemPosition)
val player = playerHolder?.findViewById<ConsultVideoPlayer>(R.id.video_item_player)
return Pair(centerItemPosition, player)
}
override fun onDetachedFromWindow() {
val carouselLayoutManager = rvVideoPlaylist.layoutManager as CarouselLayoutManager
val (_: Int, player) = getPlayer(carouselLayoutManager)
player?.let {
if(player is ConsultVideoPlayer){
player.currentPlayer.release()
player.onVideoReset()
}
}
super.onDetachedFromWindow()
}
init {
try {
initView(context)
} catch (e: Exception) {
e.printStackTrace()
}
}
}

View File

@@ -0,0 +1,974 @@
/*
* Copyright (C) 2011 The Android Open Source Project
*
* 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.mogo.och.taxi.passenger.utils.blur;
import java.io.BufferedWriter;
import java.io.Closeable;
import java.io.EOFException;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* A cache that uses a bounded amount of space on a filesystem. Each cache
* entry has a string key and a fixed number of values. Each key must match
* the regex <strong>[a-z0-9_-]{1,64}</strong>. Values are byte sequences,
* accessible as streams or files. Each value must be between {@code 0} and
* {@code Integer.MAX_VALUE} bytes in length.
*
* <p>The cache stores its data in a directory on the filesystem. This
* directory must be exclusive to the cache; the cache may delete or overwrite
* files from its directory. It is an error for multiple processes to use the
* same cache directory at the same time.
*
* <p>This cache limits the number of bytes that it will store on the
* filesystem. When the number of stored bytes exceeds the limit, the cache will
* remove entries in the background until the limit is satisfied. The limit is
* not strict: the cache may temporarily exceed it while waiting for files to be
* deleted. The limit does not include filesystem overhead or the cache
* journal so space-sensitive applications should set a conservative limit.
*
* <p>Clients call {@link #edit} to create or update the values of an entry. An
* entry may have only one editor at one time; if a value is not available to be
* edited then {@link #edit} will return null.
* <ul>
* <li>When an entry is being <strong>created</strong> it is necessary to
* supply a full set of values; the empty value should be used as a
* placeholder if necessary.
* <li>When an entry is being <strong>edited</strong>, it is not necessary
* to supply data for every value; values default to their previous
* value.
* </ul>
* Every {@link #edit} call must be matched by a call to {@link Editor#commit}
* or {@link Editor#abort}. Committing is atomic: a read observes the full set
* of values as they were before or after the commit, but never a mix of values.
*
* <p>Clients call {@link #get} to read a snapshot of an entry. The read will
* observe the value at the time that {@link #get} was called. Updates and
* removals after the call do not impact ongoing reads.
*
* <p>This class is tolerant of some I/O errors. If files are missing from the
* filesystem, the corresponding entries will be dropped from the cache. If
* an error occurs while writing a cache value, the edit will fail silently.
* Callers should handle other problems by catching {@code IOException} and
* responding appropriately.
*/
final class DiskLruCache implements Closeable {
static final String JOURNAL_FILE = "journal";
static final String JOURNAL_FILE_TEMP = "journal.tmp";
static final String JOURNAL_FILE_BACKUP = "journal.bkp";
static final String MAGIC = "libcore.io.DiskLruCache";
static final String VERSION_1 = "1";
static final long ANY_SEQUENCE_NUMBER = -1;
static final Pattern LEGAL_KEY_PATTERN = Pattern.compile("[a-z0-9_-]{1,64}");
private static final String CLEAN = "CLEAN";
private static final String DIRTY = "DIRTY";
private static final String REMOVE = "REMOVE";
private static final String READ = "READ";
/*
* This cache uses a journal file named "journal". A typical journal file
* looks like this:
* libcore.io.DiskLruCache
* 1
* 100
* 2
*
* CLEAN 3400330d1dfc7f3f7f4b8d4d803dfcf6 832 21054
* DIRTY 335c4c6028171cfddfbaae1a9c313c52
* CLEAN 335c4c6028171cfddfbaae1a9c313c52 3934 2342
* REMOVE 335c4c6028171cfddfbaae1a9c313c52
* DIRTY 1ab96a171faeeee38496d8b330771a7a
* CLEAN 1ab96a171faeeee38496d8b330771a7a 1600 234
* READ 335c4c6028171cfddfbaae1a9c313c52
* READ 3400330d1dfc7f3f7f4b8d4d803dfcf6
*
* The first five lines of the journal form its header. They are the
* constant string "libcore.io.DiskLruCache", the disk cache's version,
* the application's version, the value count, and a blank line.
*
* Each of the subsequent lines in the file is a record of the state of a
* cache entry. Each line contains space-separated values: a state, a key,
* and optional state-specific values.
* o DIRTY lines track that an entry is actively being created or updated.
* Every successful DIRTY action should be followed by a CLEAN or REMOVE
* action. DIRTY lines without a matching CLEAN or REMOVE indicate that
* temporary files may need to be deleted.
* o CLEAN lines track a cache entry that has been successfully published
* and may be read. A publish line is followed by the lengths of each of
* its values.
* o READ lines track accesses for LRU.
* o REMOVE lines track entries that have been deleted.
*
* The journal file is appended to as cache operations occur. The journal may
* occasionally be compacted by dropping redundant lines. A temporary file named
* "journal.tmp" will be used during compaction; that file should be deleted if
* it exists when the cache is opened.
*/
private final File directory;
private final File journalFile;
private final File journalFileTmp;
private final File journalFileBackup;
private final int appVersion;
private long maxSize;
private int maxFileCount;
private final int valueCount;
private long size = 0;
private int fileCount = 0;
private Writer journalWriter;
private final LinkedHashMap<String, Entry> lruEntries =
new LinkedHashMap<String, Entry>(0, 0.75f, true);
private int redundantOpCount;
/**
* To differentiate between old and current snapshots, each entry is given
* a sequence number each time an edit is committed. A snapshot is stale if
* its sequence number is not equal to its entry's sequence number.
*/
private long nextSequenceNumber = 0;
/** This cache uses a single background thread to evict entries. */
final ThreadPoolExecutor executorService =
new ThreadPoolExecutor(0, 1, 60L, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>());
private final Callable<Void> cleanupCallable = new Callable<Void>() {
public Void call() throws Exception {
synchronized (DiskLruCache.this) {
if (journalWriter == null) {
return null; // Closed.
}
trimToSize();
trimToFileCount();
if (journalRebuildRequired()) {
rebuildJournal();
redundantOpCount = 0;
}
}
return null;
}
};
private DiskLruCache(File directory, int appVersion, int valueCount, long maxSize, int maxFileCount) {
this.directory = directory;
this.appVersion = appVersion;
this.journalFile = new File(directory, JOURNAL_FILE);
this.journalFileTmp = new File(directory, JOURNAL_FILE_TEMP);
this.journalFileBackup = new File(directory, JOURNAL_FILE_BACKUP);
this.valueCount = valueCount;
this.maxSize = maxSize;
this.maxFileCount = maxFileCount;
}
/**
* Opens the cache in {@code directory}, creating a cache if none exists
* there.
*
* @param directory a writable directory
* @param valueCount the number of values per cache entry. Must be positive.
* @param maxSize the maximum number of bytes this cache should use to store
* @param maxFileCount the maximum file count this cache should store
* @throws IOException if reading or writing the cache directory fails
*/
public static DiskLruCache open(File directory, int appVersion, int valueCount, long maxSize, int maxFileCount)
throws IOException {
if (maxSize <= 0) {
throw new IllegalArgumentException("maxSize <= 0");
}
if (maxFileCount <= 0) {
throw new IllegalArgumentException("maxFileCount <= 0");
}
if (valueCount <= 0) {
throw new IllegalArgumentException("valueCount <= 0");
}
// If a bkp file exists, use it instead.
File backupFile = new File(directory, JOURNAL_FILE_BACKUP);
if (backupFile.exists()) {
File journalFile = new File(directory, JOURNAL_FILE);
// If journal file also exists just delete backup file.
if (journalFile.exists()) {
backupFile.delete();
} else {
renameTo(backupFile, journalFile, false);
}
}
// Prefer to pick up where we left off.
DiskLruCache cache = new DiskLruCache(directory, appVersion, valueCount, maxSize, maxFileCount);
if (cache.journalFile.exists()) {
try {
cache.readJournal();
cache.processJournal();
cache.journalWriter = new BufferedWriter(
new OutputStreamWriter(new FileOutputStream(cache.journalFile, true), Util.US_ASCII));
return cache;
} catch (IOException journalIsCorrupt) {
System.out
.println("DiskLruCache "
+ directory
+ " is corrupt: "
+ journalIsCorrupt.getMessage()
+ ", removing");
cache.delete();
}
}
// Create a new empty cache.
directory.mkdirs();
cache = new DiskLruCache(directory, appVersion, valueCount, maxSize, maxFileCount);
cache.rebuildJournal();
return cache;
}
private void readJournal() throws IOException {
StrictLineReader reader = new StrictLineReader(new FileInputStream(journalFile), Util.US_ASCII);
try {
String magic = reader.readLine();
String version = reader.readLine();
String appVersionString = reader.readLine();
String valueCountString = reader.readLine();
String blank = reader.readLine();
if (!MAGIC.equals(magic)
|| !VERSION_1.equals(version)
|| !Integer.toString(appVersion).equals(appVersionString)
|| !Integer.toString(valueCount).equals(valueCountString)
|| !"".equals(blank)) {
throw new IOException("unexpected journal header: [" + magic + ", " + version + ", "
+ valueCountString + ", " + blank + "]");
}
int lineCount = 0;
while (true) {
try {
readJournalLine(reader.readLine());
lineCount++;
} catch (EOFException endOfJournal) {
break;
}
}
redundantOpCount = lineCount - lruEntries.size();
} finally {
Util.closeQuietly(reader);
}
}
private void readJournalLine(String line) throws IOException {
int firstSpace = line.indexOf(' ');
if (firstSpace == -1) {
throw new IOException("unexpected journal line: " + line);
}
int keyBegin = firstSpace + 1;
int secondSpace = line.indexOf(' ', keyBegin);
final String key;
if (secondSpace == -1) {
key = line.substring(keyBegin);
if (firstSpace == REMOVE.length() && line.startsWith(REMOVE)) {
lruEntries.remove(key);
return;
}
} else {
key = line.substring(keyBegin, secondSpace);
}
Entry entry = lruEntries.get(key);
if (entry == null) {
entry = new Entry(key);
lruEntries.put(key, entry);
}
if (secondSpace != -1 && firstSpace == CLEAN.length() && line.startsWith(CLEAN)) {
String[] parts = line.substring(secondSpace + 1).split(" ");
entry.readable = true;
entry.currentEditor = null;
entry.setLengths(parts);
} else if (secondSpace == -1 && firstSpace == DIRTY.length() && line.startsWith(DIRTY)) {
entry.currentEditor = new Editor(entry);
} else if (secondSpace == -1 && firstSpace == READ.length() && line.startsWith(READ)) {
// This work was already done by calling lruEntries.get().
} else {
throw new IOException("unexpected journal line: " + line);
}
}
/**
* Computes the initial size and collects garbage as a part of opening the
* cache. Dirty entries are assumed to be inconsistent and will be deleted.
*/
private void processJournal() throws IOException {
deleteIfExists(journalFileTmp);
for (Iterator<Entry> i = lruEntries.values().iterator(); i.hasNext(); ) {
Entry entry = i.next();
if (entry.currentEditor == null) {
for (int t = 0; t < valueCount; t++) {
size += entry.lengths[t];
fileCount++;
}
} else {
entry.currentEditor = null;
for (int t = 0; t < valueCount; t++) {
deleteIfExists(entry.getCleanFile(t));
deleteIfExists(entry.getDirtyFile(t));
}
i.remove();
}
}
}
/**
* Creates a new journal that omits redundant information. This replaces the
* current journal if it exists.
*/
private synchronized void rebuildJournal() throws IOException {
if (journalWriter != null) {
journalWriter.close();
}
Writer writer = new BufferedWriter(
new OutputStreamWriter(new FileOutputStream(journalFileTmp), Util.US_ASCII));
try {
writer.write(MAGIC);
writer.write("\n");
writer.write(VERSION_1);
writer.write("\n");
writer.write(Integer.toString(appVersion));
writer.write("\n");
writer.write(Integer.toString(valueCount));
writer.write("\n");
writer.write("\n");
for (Entry entry : lruEntries.values()) {
if (entry.currentEditor != null) {
writer.write(DIRTY + ' ' + entry.key + '\n');
} else {
writer.write(CLEAN + ' ' + entry.key + entry.getLengths() + '\n');
}
}
} finally {
writer.close();
}
if (journalFile.exists()) {
renameTo(journalFile, journalFileBackup, true);
}
renameTo(journalFileTmp, journalFile, false);
journalFileBackup.delete();
journalWriter = new BufferedWriter(
new OutputStreamWriter(new FileOutputStream(journalFile, true), Util.US_ASCII));
}
private static void deleteIfExists(File file) throws IOException {
if (file.exists() && !file.delete()) {
throw new IOException();
}
}
private static void renameTo(File from, File to, boolean deleteDestination) throws IOException {
if (deleteDestination) {
deleteIfExists(to);
}
if (!from.renameTo(to)) {
throw new IOException();
}
}
/**
* Returns a snapshot of the entry named {@code key}, or null if it doesn't
* exist is not currently readable. If a value is returned, it is moved to
* the head of the LRU queue.
*/
public synchronized Snapshot get(String key) throws IOException {
checkNotClosed();
validateKey(key);
Entry entry = lruEntries.get(key);
if (entry == null) {
return null;
}
if (!entry.readable) {
return null;
}
// Open all streams eagerly to guarantee that we see a single published
// snapshot. If we opened streams lazily then the streams could come
// from different edits.
File[] files = new File[valueCount];
InputStream[] ins = new InputStream[valueCount];
try {
File file;
for (int i = 0; i < valueCount; i++) {
file = entry.getCleanFile(i);
files[i] = file;
ins[i] = new FileInputStream(file);
}
} catch (FileNotFoundException e) {
// A file must have been deleted manually!
for (int i = 0; i < valueCount; i++) {
if (ins[i] != null) {
Util.closeQuietly(ins[i]);
} else {
break;
}
}
return null;
}
redundantOpCount++;
journalWriter.append(READ + ' ' + key + '\n');
if (journalRebuildRequired()) {
executorService.submit(cleanupCallable);
}
return new Snapshot(key, entry.sequenceNumber, files, ins, entry.lengths);
}
/**
* Returns an editor for the entry named {@code key}, or null if another
* edit is in progress.
*/
public Editor edit(String key) throws IOException {
return edit(key, ANY_SEQUENCE_NUMBER);
}
private synchronized Editor edit(String key, long expectedSequenceNumber) throws IOException {
checkNotClosed();
validateKey(key);
Entry entry = lruEntries.get(key);
if (expectedSequenceNumber != ANY_SEQUENCE_NUMBER && (entry == null
|| entry.sequenceNumber != expectedSequenceNumber)) {
return null; // Snapshot is stale.
}
if (entry == null) {
entry = new Entry(key);
lruEntries.put(key, entry);
} else if (entry.currentEditor != null) {
return null; // Another edit is in progress.
}
Editor editor = new Editor(entry);
entry.currentEditor = editor;
// Flush the journal before creating files to prevent file leaks.
journalWriter.write(DIRTY + ' ' + key + '\n');
journalWriter.flush();
return editor;
}
/** Returns the directory where this cache stores its data. */
public File getDirectory() {
return directory;
}
/**
* Returns the maximum number of bytes that this cache should use to store
* its data.
*/
public synchronized long getMaxSize() {
return maxSize;
}
/** Returns the maximum number of files that this cache should store */
public synchronized int getMaxFileCount() {
return maxFileCount;
}
/**
* Changes the maximum number of bytes the cache can store and queues a job
* to trim the existing store, if necessary.
*/
public synchronized void setMaxSize(long maxSize) {
this.maxSize = maxSize;
executorService.submit(cleanupCallable);
}
/**
* Returns the number of bytes currently being used to store the values in
* this cache. This may be greater than the max size if a background
* deletion is pending.
*/
public synchronized long size() {
return size;
}
/**
* Returns the number of files currently being used to store the values in
* this cache. This may be greater than the max file count if a background
* deletion is pending.
*/
public synchronized long fileCount() {
return fileCount;
}
private synchronized void completeEdit(Editor editor, boolean success) throws IOException {
Entry entry = editor.entry;
if (entry.currentEditor != editor) {
throw new IllegalStateException();
}
// If this edit is creating the entry for the first time, every index must have a value.
if (success && !entry.readable) {
for (int i = 0; i < valueCount; i++) {
if (!editor.written[i]) {
editor.abort();
throw new IllegalStateException("Newly created entry didn't create value for index " + i);
}
if (!entry.getDirtyFile(i).exists()) {
editor.abort();
return;
}
}
}
for (int i = 0; i < valueCount; i++) {
File dirty = entry.getDirtyFile(i);
if (success) {
if (dirty.exists()) {
File clean = entry.getCleanFile(i);
dirty.renameTo(clean);
long oldLength = entry.lengths[i];
long newLength = clean.length();
entry.lengths[i] = newLength;
size = size - oldLength + newLength;
fileCount++;
}
} else {
deleteIfExists(dirty);
}
}
redundantOpCount++;
entry.currentEditor = null;
if (entry.readable | success) {
entry.readable = true;
journalWriter.write(CLEAN + ' ' + entry.key + entry.getLengths() + '\n');
if (success) {
entry.sequenceNumber = nextSequenceNumber++;
}
} else {
lruEntries.remove(entry.key);
journalWriter.write(REMOVE + ' ' + entry.key + '\n');
}
journalWriter.flush();
if (size > maxSize || fileCount > maxFileCount || journalRebuildRequired()) {
executorService.submit(cleanupCallable);
}
}
/**
* We only rebuild the journal when it will halve the size of the journal
* and eliminate at least 2000 ops.
*/
private boolean journalRebuildRequired() {
final int redundantOpCompactThreshold = 2000;
return redundantOpCount >= redundantOpCompactThreshold //
&& redundantOpCount >= lruEntries.size();
}
/**
* Drops the entry for {@code key} if it exists and can be removed. Entries
* actively being edited cannot be removed.
*
* @return true if an entry was removed.
*/
public synchronized boolean remove(String key) throws IOException {
checkNotClosed();
validateKey(key);
Entry entry = lruEntries.get(key);
if (entry == null || entry.currentEditor != null) {
return false;
}
for (int i = 0; i < valueCount; i++) {
File file = entry.getCleanFile(i);
if (file.exists() && !file.delete()) {
throw new IOException("failed to delete " + file);
}
size -= entry.lengths[i];
fileCount--;
entry.lengths[i] = 0;
}
redundantOpCount++;
journalWriter.append(REMOVE + ' ' + key + '\n');
lruEntries.remove(key);
if (journalRebuildRequired()) {
executorService.submit(cleanupCallable);
}
return true;
}
/** Returns true if this cache has been closed. */
public synchronized boolean isClosed() {
return journalWriter == null;
}
private void checkNotClosed() {
if (journalWriter == null) {
throw new IllegalStateException("cache is closed");
}
}
/** Force buffered operations to the filesystem. */
public synchronized void flush() throws IOException {
checkNotClosed();
trimToSize();
trimToFileCount();
journalWriter.flush();
}
/** Closes this cache. Stored values will remain on the filesystem. */
public synchronized void close() throws IOException {
if (journalWriter == null) {
return; // Already closed.
}
for (Entry entry : new ArrayList<Entry>(lruEntries.values())) {
if (entry.currentEditor != null) {
entry.currentEditor.abort();
}
}
trimToSize();
trimToFileCount();
journalWriter.close();
journalWriter = null;
}
private void trimToSize() throws IOException {
while (size > maxSize) {
Map.Entry<String, Entry> toEvict = lruEntries.entrySet().iterator().next();
remove(toEvict.getKey());
}
}
private void trimToFileCount() throws IOException {
while (fileCount > maxFileCount) {
Map.Entry<String, Entry> toEvict = lruEntries.entrySet().iterator().next();
remove(toEvict.getKey());
}
}
/**
* Closes the cache and deletes all of its stored values. This will delete
* all files in the cache directory including files that weren't created by
* the cache.
*/
public void delete() throws IOException {
close();
Util.deleteContents(directory);
}
private void validateKey(String key) {
Matcher matcher = LEGAL_KEY_PATTERN.matcher(key);
if (!matcher.matches()) {
throw new IllegalArgumentException("keys must match regex [a-z0-9_-]{1,64}: \"" + key + "\"");
}
}
private static String inputStreamToString(InputStream in) throws IOException {
return Util.readFully(new InputStreamReader(in, Util.UTF_8));
}
/** A snapshot of the values for an entry. */
public final class Snapshot implements Closeable {
private final String key;
private final long sequenceNumber;
private File[] files;
private final InputStream[] ins;
private final long[] lengths;
private Snapshot(String key, long sequenceNumber, File[] files, InputStream[] ins, long[] lengths) {
this.key = key;
this.sequenceNumber = sequenceNumber;
this.files = files;
this.ins = ins;
this.lengths = lengths;
}
/**
* Returns an editor for this snapshot's entry, or null if either the
* entry has changed since this snapshot was created or if another edit
* is in progress.
*/
public Editor edit() throws IOException {
return DiskLruCache.this.edit(key, sequenceNumber);
}
/** Returns file with the value for {@code index}. */
public File getFile(int index) {
return files[index];
}
/** Returns the unbuffered stream with the value for {@code index}. */
public InputStream getInputStream(int index) {
return ins[index];
}
/** Returns the string value for {@code index}. */
public String getString(int index) throws IOException {
return inputStreamToString(getInputStream(index));
}
/** Returns the byte length of the value for {@code index}. */
public long getLength(int index) {
return lengths[index];
}
public void close() {
for (InputStream in : ins) {
Util.closeQuietly(in);
}
}
}
private static final OutputStream NULL_OUTPUT_STREAM = new OutputStream() {
@Override
public void write(int b) throws IOException {
// Eat all writes silently. Nom nom.
}
};
/** Edits the values for an entry. */
public final class Editor {
private final Entry entry;
private final boolean[] written;
private boolean hasErrors;
private boolean committed;
private Editor(Entry entry) {
this.entry = entry;
this.written = (entry.readable) ? null : new boolean[valueCount];
}
/**
* Returns an unbuffered input stream to read the last committed value,
* or null if no value has been committed.
*/
public InputStream newInputStream(int index) throws IOException {
synchronized (DiskLruCache.this) {
if (entry.currentEditor != this) {
throw new IllegalStateException();
}
if (!entry.readable) {
return null;
}
try {
return new FileInputStream(entry.getCleanFile(index));
} catch (FileNotFoundException e) {
return null;
}
}
}
/**
* Returns the last committed value as a string, or null if no value
* has been committed.
*/
public String getString(int index) throws IOException {
InputStream in = newInputStream(index);
return in != null ? inputStreamToString(in) : null;
}
/**
* Returns a new unbuffered output stream to write the value at
* {@code index}. If the underlying output stream encounters errors
* when writing to the filesystem, this edit will be aborted when
* {@link #commit} is called. The returned output stream does not throw
* IOExceptions.
*/
public OutputStream newOutputStream(int index) throws IOException {
synchronized (DiskLruCache.this) {
if (entry.currentEditor != this) {
throw new IllegalStateException();
}
if (!entry.readable) {
written[index] = true;
}
File dirtyFile = entry.getDirtyFile(index);
FileOutputStream outputStream;
try {
outputStream = new FileOutputStream(dirtyFile);
} catch (FileNotFoundException e) {
// Attempt to recreate the cache directory.
directory.mkdirs();
try {
outputStream = new FileOutputStream(dirtyFile);
} catch (FileNotFoundException e2) {
// We are unable to recover. Silently eat the writes.
return NULL_OUTPUT_STREAM;
}
}
return new FaultHidingOutputStream(outputStream);
}
}
/** Sets the value at {@code index} to {@code value}. */
public void set(int index, String value) throws IOException {
Writer writer = null;
try {
writer = new OutputStreamWriter(newOutputStream(index), Util.UTF_8);
writer.write(value);
} finally {
Util.closeQuietly(writer);
}
}
/**
* Commits this edit so it is visible to readers. This releases the
* edit lock so another edit may be started on the same key.
*/
public void commit() throws IOException {
if (hasErrors) {
completeEdit(this, false);
remove(entry.key); // The previous entry is stale.
} else {
completeEdit(this, true);
}
committed = true;
}
/**
* Aborts this edit. This releases the edit lock so another edit may be
* started on the same key.
*/
public void abort() throws IOException {
completeEdit(this, false);
}
public void abortUnlessCommitted() {
if (!committed) {
try {
abort();
} catch (IOException ignored) {
}
}
}
private class FaultHidingOutputStream extends FilterOutputStream {
private FaultHidingOutputStream(OutputStream out) {
super(out);
}
@Override public void write(int oneByte) {
try {
out.write(oneByte);
} catch (IOException e) {
hasErrors = true;
}
}
@Override public void write(byte[] buffer, int offset, int length) {
try {
out.write(buffer, offset, length);
} catch (IOException e) {
hasErrors = true;
}
}
@Override public void close() {
try {
out.close();
} catch (IOException e) {
hasErrors = true;
}
}
@Override public void flush() {
try {
out.flush();
} catch (IOException e) {
hasErrors = true;
}
}
}
}
private final class Entry {
private final String key;
/** Lengths of this entry's files. */
private final long[] lengths;
/** True if this entry has ever been published. */
private boolean readable;
/** The ongoing edit or null if this entry is not being edited. */
private Editor currentEditor;
/** The sequence number of the most recently committed edit to this entry. */
private long sequenceNumber;
private Entry(String key) {
this.key = key;
this.lengths = new long[valueCount];
}
public String getLengths() throws IOException {
StringBuilder result = new StringBuilder();
for (long size : lengths) {
result.append(' ').append(size);
}
return result.toString();
}
/** Set lengths using decimal numbers like "10123". */
private void setLengths(String[] strings) throws IOException {
if (strings.length != valueCount) {
throw invalidLengths(strings);
}
try {
for (int i = 0; i < strings.length; i++) {
lengths[i] = Long.parseLong(strings[i]);
}
} catch (NumberFormatException e) {
throw invalidLengths(strings);
}
}
private IOException invalidLengths(String[] strings) throws IOException {
throw new IOException("unexpected journal line: " + java.util.Arrays.toString(strings));
}
public File getCleanFile(int i) {
return new File(directory, key + "" + i);
}
public File getDirtyFile(int i) {
return new File(directory, key + "" + i + ".tmp");
}
}
}

View File

@@ -0,0 +1,101 @@
package com.mogo.och.taxi.passenger.utils.blur;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.text.TextUtils;
import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigInteger;
import java.security.MessageDigest;
/*******************************************************************************
* Description: 用于缓存经过高斯模糊的图片
*
* Author: Freeman
*
* Date: 2018/9/4
*
* Copyright: all rights reserved by Freeman.
*******************************************************************************/
public class DiskLruCacheManager {
private DiskLruCache diskLruCache;
private static DiskLruCacheManager instance;
private final int MAX_CACHE_SIZE = 64 * 1024 * 1024;
private DiskLruCacheManager(Context context) {
try {
diskLruCache = DiskLruCache.open(context.getCacheDir(), 1, 1,
MAX_CACHE_SIZE, Integer.MAX_VALUE);
} catch (Exception e) {
e.printStackTrace(System.err);
}
}
public static DiskLruCacheManager getInstance(Context context) {
if (instance == null) {
synchronized (DiskLruCacheManager.class) {
if (instance == null) {
instance = new DiskLruCacheManager(context.getApplicationContext());
}
}
}
return instance;
}
public void put(String url, Bitmap bitmap) {
if (TextUtils.isEmpty(url) || bitmap == null || bitmap.isRecycled()) {
return;
}
try {
DiskLruCache.Editor editor = diskLruCache.edit(getKey(url));
OutputStream outputStream = editor.newOutputStream(0);
if (bitmap.compress(Bitmap.CompressFormat.PNG, 100, outputStream)) {
editor.commit();
}
diskLruCache.flush();
} catch (Exception e) {
e.printStackTrace(System.err);
}
}
public Bitmap get(String url) {
try {
DiskLruCache.Snapshot snapshot = diskLruCache.get(getKey(url));
if (snapshot != null) {
InputStream inputStream = snapshot.getInputStream(0);
return BitmapFactory.decodeStream(inputStream);
}
} catch (Exception e) {
e.printStackTrace(System.err);
}
return null;
}
public static String getKey(String url) {
try {
MessageDigest digest = MessageDigest.getInstance("MD5");
byte[] md5 = digest.digest(url.getBytes());
BigInteger bigInteger = new BigInteger(1, md5);
return bigInteger.toString(16);
} catch (Exception e) {
e.printStackTrace(System.err);
}
return null;
}
public void close() {
try {
diskLruCache.close();
} catch (Exception e) {
e.printStackTrace(System.err);
}
}
}

View File

@@ -0,0 +1,191 @@
/*
* Copyright (C) 2012 The Android Open Source Project
*
* 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.mogo.och.taxi.passenger.utils.blur;
import java.io.ByteArrayOutputStream;
import java.io.Closeable;
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
/**
* Buffers input from an {@link InputStream} for reading lines.
*
* <p>This class is used for buffered reading of lines. For purposes of this class, a line ends
* with "\n" or "\r\n". End of input is reported by throwing {@code EOFException}. Unterminated
* line at end of input is invalid and will be ignored, the caller may use {@code
* hasUnterminatedLine()} to detect it after catching the {@code EOFException}.
*
* <p>This class is intended for reading input that strictly consists of lines, such as line-based
* cache entries or cache journal. Unlike the {@link java.io.BufferedReader} which in conjunction
* with {@link java.io.InputStreamReader} provides similar functionality, this class uses different
* end-of-input reporting and a more restrictive definition of a line.
*
* <p>This class supports only charsets that encode '\r' and '\n' as a single byte with value 13
* and 10, respectively, and the representation of no other character contains these values.
* We currently check in constructor that the charset is one of US-ASCII, UTF-8 and ISO-8859-1.
* The default charset is US_ASCII.
*/
class StrictLineReader implements Closeable {
private static final byte CR = (byte) '\r';
private static final byte LF = (byte) '\n';
private final InputStream in;
private final Charset charset;
/*
* Buffered data is stored in {@code buf}. As long as no exception occurs, 0 <= pos <= end
* and the data in the range [pos, end) is buffered for reading. At end of input, if there is
* an unterminated line, we set end == -1, otherwise end == pos. If the underlying
* {@code InputStream} throws an {@code IOException}, end may remain as either pos or -1.
*/
private byte[] buf;
private int pos;
private int end;
/**
* Constructs a new {@code LineReader} with the specified charset and the default capacity.
*
* @param in the {@code InputStream} to read data from.
* @param charset the charset used to decode data. Only US-ASCII, UTF-8 and ISO-8859-1 are
* supported.
* @throws NullPointerException if {@code in} or {@code charset} is null.
* @throws IllegalArgumentException if the specified charset is not supported.
*/
public StrictLineReader(InputStream in, Charset charset) {
this(in, 8192, charset);
}
/**
* Constructs a new {@code LineReader} with the specified capacity and charset.
*
* @param in the {@code InputStream} to read data from.
* @param capacity the capacity of the buffer.
* @param charset the charset used to decode data. Only US-ASCII, UTF-8 and ISO-8859-1 are
* supported.
* @throws NullPointerException if {@code in} or {@code charset} is null.
* @throws IllegalArgumentException if {@code capacity} is negative or zero
* or the specified charset is not supported.
*/
public StrictLineReader(InputStream in, int capacity, Charset charset) {
if (in == null || charset == null) {
throw new NullPointerException();
}
if (capacity < 0) {
throw new IllegalArgumentException("capacity <= 0");
}
if (!(charset.equals(Util.US_ASCII))) {
throw new IllegalArgumentException("Unsupported encoding");
}
this.in = in;
this.charset = charset;
buf = new byte[capacity];
}
/**
* Closes the reader by closing the underlying {@code InputStream} and
* marking this reader as closed.
*
* @throws IOException for errors when closing the underlying {@code InputStream}.
*/
public void close() throws IOException {
synchronized (in) {
if (buf != null) {
buf = null;
in.close();
}
}
}
/**
* Reads the next line. A line ends with {@code "\n"} or {@code "\r\n"},
* this end of line marker is not included in the result.
*
* @return the next line from the input.
* @throws IOException for underlying {@code InputStream} errors.
* @throws EOFException for the end of source stream.
*/
public String readLine() throws IOException {
synchronized (in) {
if (buf == null) {
throw new IOException("LineReader is closed");
}
// Read more data if we are at the end of the buffered data.
// Though it's an error to read after an exception, we will let {@code fillBuf()}
// throw again if that happens; thus we need to handle end == -1 as well as end == pos.
if (pos >= end) {
fillBuf();
}
// Try to find LF in the buffered data and return the line if successful.
for (int i = pos; i != end; ++i) {
if (buf[i] == LF) {
int lineEnd = (i != pos && buf[i - 1] == CR) ? i - 1 : i;
String res = new String(buf, pos, lineEnd - pos, charset.name());
pos = i + 1;
return res;
}
}
// Let's anticipate up to 80 characters on top of those already read.
ByteArrayOutputStream out = new ByteArrayOutputStream(end - pos + 80) {
@Override
public String toString() {
int length = (count > 0 && buf[count - 1] == CR) ? count - 1 : count;
try {
return new String(buf, 0, length, charset.name());
} catch (UnsupportedEncodingException e) {
throw new AssertionError(e); // Since we control the charset this will never happen.
}
}
};
while (true) {
out.write(buf, pos, end - pos);
// Mark unterminated line in case fillBuf throws EOFException or IOException.
end = -1;
fillBuf();
// Try to find LF in the buffered data and return the line if successful.
for (int i = pos; i != end; ++i) {
if (buf[i] == LF) {
if (i != pos) {
out.write(buf, pos, i - pos);
}
pos = i + 1;
return out.toString();
}
}
}
}
}
/**
* Reads new input data into the buffer. Call only with pos == end or end == -1,
* depending on the desired outcome if the function throws.
*/
private void fillBuf() throws IOException {
int result = in.read(buf, 0, buf.length);
if (result == -1) {
throw new EOFException();
}
pos = 0;
end = result;
}
}

View File

@@ -0,0 +1,76 @@
/*
* Copyright (C) 2010 The Android Open Source Project
*
* 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.mogo.och.taxi.passenger.utils.blur;
import java.io.Closeable;
import java.io.File;
import java.io.IOException;
import java.io.Reader;
import java.io.StringWriter;
import java.nio.charset.Charset;
/** Junk drawer of utility methods. */
final class Util {
static final Charset US_ASCII = Charset.forName("US-ASCII");
static final Charset UTF_8 = Charset.forName("UTF-8");
private Util() {
}
static String readFully(Reader reader) throws IOException {
try {
StringWriter writer = new StringWriter();
char[] buffer = new char[1024];
int count;
while ((count = reader.read(buffer)) != -1) {
writer.write(buffer, 0, count);
}
return writer.toString();
} finally {
reader.close();
}
}
/**
* Deletes the contents of {@code dir}. Throws an IOException if any file
* could not be deleted, or if {@code dir} is not a readable directory.
*/
static void deleteContents(File dir) throws IOException {
File[] files = dir.listFiles();
if (files == null) {
throw new IOException("not a readable directory: " + dir);
}
for (File file : files) {
if (file.isDirectory()) {
deleteContents(file);
}
if (!file.delete()) {
throw new IOException("failed to delete file: " + file);
}
}
}
static void closeQuietly(/*Auto*/Closeable closeable) {
if (closeable != null) {
try {
closeable.close();
} catch (RuntimeException rethrown) {
throw rethrown;
} catch (Exception ignored) {
}
}
}
}

View File

@@ -0,0 +1,55 @@
package com.mogo.och.taxi.passenger.utils.windowdispatch;
import android.graphics.Region;
import android.inputmethodservice.InputMethodService;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class OnComputeInternalInsetsListener implements InvocationHandler {
private Region touchRegion = null;
public Object getListener() {
Object target = null;
try {
Class class1 = Class.forName("android.view.ViewTreeObserver$OnComputeInternalInsetsListener");
target = Proxy.newProxyInstance(OnComputeInternalInsetsListener.class.getClassLoader(),
new Class[]{class1}, this);
} catch (Exception e) {
e.printStackTrace();
}
return target;
}
public Region getTouchRegion() {
return touchRegion;
}
public void setTouchRegion(Region touchRegion) {
this.touchRegion = touchRegion;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) {
try {
Field regionField = args[0].getClass()
.getDeclaredField("touchableRegion");
regionField.setAccessible(true);
Field insetField = args[0].getClass()
.getDeclaredField("mTouchableInsets");
insetField.setAccessible(true);
if (touchRegion != null) {
Region region = (Region) regionField.get(args[0]);
region.set(touchRegion);
insetField.set(args[0], InputMethodService.Insets.TOUCHABLE_INSETS_REGION);
} else {
insetField.set(args[0], InputMethodService.Insets.TOUCHABLE_INSETS_FRAME);
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}

View File

@@ -0,0 +1,51 @@
package com.mogo.och.taxi.passenger.utils.windowdispatch;
import android.view.ViewTreeObserver;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
public class ReflectionUtils {
private ReflectionUtils() {
}
public static void removeOnComputeInternalInsetsListener(ViewTreeObserver viewTree) {
if (viewTree == null) {
return;
}
try {
Class<?> clazz = Class.forName("android.view.ViewTreeObserver");
Field field = viewTree.getClass().getDeclaredField("mOnComputeInternalInsetsListeners");
field.setAccessible(true);
Object listenerList = field.get(viewTree);
Method method = listenerList.getClass().getDeclaredMethod("getArray");
method.setAccessible(true);
ArrayList<Object> list = (ArrayList<Object>) method.invoke(listenerList);
Class<?> classes[] = {Class.forName("android.view.ViewTreeObserver$OnComputeInternalInsetsListener")};
if (list != null && list.size() > 0) {
clazz.getDeclaredMethod("removeOnComputeInternalInsetsListener", classes).invoke(viewTree,
list.get(0));
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static void addOnComputeInternalInsetsListener(ViewTreeObserver viewTree, Object object) {
if (viewTree == null) {
return;
}
try {
Class<?> classes[] = {Class.forName("android.view.ViewTreeObserver$OnComputeInternalInsetsListener")};
Class<?> clazz = Class.forName("android.view.ViewTreeObserver");
clazz.getDeclaredMethod("addOnComputeInternalInsetsListener", classes).invoke(viewTree,
object);
} catch (Exception e) {
e.printStackTrace();
}
}
}

View File

@@ -81,8 +81,8 @@ public class TaxiNaviFragment extends BaseTaxiUIFragment implements AMapNaviView
aMap.setCustomMapStyle(
new CustomMapStyleOptions()
.setEnable(true)
.setStyleData(MapAssetStyleUtils.getAssetsStyle(getContext()))
.setStyleExtraData(MapAssetStyleUtils.getAssetsExtraStyle(getContext()))
.setStyleData(MapAssetStyleUtils.getAssetsStyle(getContext(), "small_map_style.data"))
.setStyleExtraData(MapAssetStyleUtils.getAssetsExtraStyle(getContext(), "small_map_style_extra.data"))
);
//设置希望展示的地图缩放级别

View File

@@ -6,7 +6,7 @@ ext {
independentApplicationId : "com.mogo.launcher.app",
fLauncherApplicationId : "com.mogo.launcher.f",
bydautoIndependentApplicationId: "com.mogo.launcher.app.bydauto",
fLauncherAmapApiValue : "aa2c8a0547378ead2f9a37762d9dd179",
fLauncherAmapApiValue : "ace34d685cc04836c03905e4d1536125",
bydautoIndependentApiValue : "b1e1d527b02a493913c50985827c943a",
commonLauncherAmapApiValue : "a36b9f7b086fa3951bb35338a5a06dd3",
commonIndependentAmapApiValue : "1c3fbc5f5e183619ffb1e7bc01e6751f",

View File

@@ -149,4 +149,9 @@ public class MoGoHandAdasMsgManager implements
@Override
public void onAutopilotDataException(long timestamp) {
}
@Override
public void onAutopilotAcc(float carAcc) {
}
}

View File

@@ -95,6 +95,7 @@ public class BindingcarProvider implements IMoGoBindingcarProvider {
private void driverScreen(String macAddress, String widevineIDWithMd5) {
long currentHour = System.currentTimeMillis() / (1000 * 60);
long oldHour = SharedPrefsMgr.getInstance(mContext).getLong("typeDriver", 0);
Log.d("liyz", "driverScreen --------> ");
//如果2分钟内频繁调需要拦截业务导致的会多次请求工控机信息
if (HmiBuildConfig.isShowSnBindingView) {
if (currentHour - oldHour > 1) {
@@ -107,6 +108,7 @@ public class BindingcarProvider implements IMoGoBindingcarProvider {
private void passengerScreen(String macAddress, String widevineIDWithMd5) {
long currentHour = System.currentTimeMillis() / (1000 * 60);
long oldHour = SharedPrefsMgr.getInstance(mContext).getLong("typePassenger", 0);
Log.d("liyz", "passengerScreen --------> ");
//如果2分钟内频繁调需要拦截业务导致的会多次请求工控机信息
if (HmiBuildConfig.isShowSnBindingView) {
if (currentHour - oldHour > 1) {

View File

@@ -66,6 +66,11 @@ internal class CanImpl(ctx: Context): IFlow<CanStatus>(ctx), IMoGoAutopilotVehic
send(CanStatus(false))
}
override fun onAutopilotAcc(carAcc: Float) {
send(CanStatus(isCanEnabled()))
timeOutCheck()
}
override fun onAutopilotGuardian(guardianInfo: MogoReportMessage?) {
super.onAutopilotGuardian(guardianInfo)
send(CanStatus(isCanEnabled()))

View File

@@ -1956,6 +1956,10 @@ class DebugSettingView @JvmOverloads constructor(
}
}
override fun onAutopilotAcc(carAcc: Float) {
}
/**
* 吐司提示
*/

View File

@@ -176,6 +176,15 @@ public class SteeringWheelView extends ConstraintLayout {
Log.d(TAG, "刹车灯:" + String.valueOf(brakeLight));
}
/**
* 车辆加速度
* @param carAcc
*/
@Override
public void onAutopilotAcc(float carAcc) {
}
/**
* 方向盘转向角 左+右-
* @param steering
@@ -223,7 +232,7 @@ public class SteeringWheelView extends ConstraintLayout {
ThreadUtils.runOnUiThread(new Runnable() {
@Override
public void run() {
Log.d(TAG, "档位" + gear.toString());
Log.d(TAG, "乘客屏档位" + gear.toString());
if (tapPositionView != null) {
tapPositionView.updateWithGear(gear);
}

View File

@@ -1,6 +1,7 @@
package com.mogo.eagle.core.function.hmi.ui.widget;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.util.AttributeSet;
import android.util.Log;
@@ -30,6 +31,7 @@ public class TapPositionView extends ConstraintLayout {
private TextView tabR;
private TextView tabN;
private TextView tabD;
private TypedArray typedArray;
public TapPositionView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
@@ -39,90 +41,48 @@ public class TapPositionView extends ConstraintLayout {
tabR = findViewById(R.id.tap_r);
tabN = findViewById(R.id.tap_n);
tabD = findViewById(R.id.tap_d);
typedArray = context.obtainStyledAttributes(attrs, R.styleable.TapPositionView);
}
public void updateWithGear(@NotNull Chassis.GearPosition gear) {
if (tabP != null && tabR != null && tabN != null && tabD != null) {
if (AppIdentityModeUtils.isTaxi(FunctionBuildConfig.appIdentityMode)) {
taxiGear(gear);
} else {
busGear(gear);
int defaultColor = typedArray.getColor(R.styleable.TapPositionView_defaultColor, -1);
int selectColor = typedArray.getColor(R.styleable.TapPositionView_selectColor, -1);
Log.d(TAG, "gear:" + gear);
switch (gear) {
case GEAR_NONE:
tabP.setTextColor(defaultColor);
tabR.setTextColor(defaultColor);
tabN.setTextColor(defaultColor);
tabD.setTextColor(defaultColor);
break;
case GEAR_P:
tabP.setTextColor(selectColor);
tabR.setTextColor(defaultColor);
tabN.setTextColor(defaultColor);
tabD.setTextColor(defaultColor);
break;
case GEAR_R:
tabR.setTextColor(selectColor);
tabP.setTextColor(defaultColor);
tabN.setTextColor(defaultColor);
tabD.setTextColor(defaultColor);
break;
case GEAR_N:
tabN.setTextColor(selectColor);
tabR.setTextColor(defaultColor);
tabP.setTextColor(defaultColor);
tabD.setTextColor(defaultColor);
break;
case GEAR_D:
tabD.setTextColor(selectColor);
tabN.setTextColor(defaultColor);
tabR.setTextColor(defaultColor);
tabP.setTextColor(defaultColor);
break;
default:
break;
}
}
}
private void busGear(@NotNull Chassis.GearPosition gear) {
switch (gear) {
case GEAR_NONE:
tabP.setTextColor(Color.parseColor("#6E8EC9"));
tabR.setTextColor(Color.parseColor("#6E8EC9"));
tabN.setTextColor(Color.parseColor("#6E8EC9"));
tabD.setTextColor(Color.parseColor("#6E8EC9"));
break;
case GEAR_P:
tabP.setTextColor(Color.parseColor("#0043FF"));
tabR.setTextColor(Color.parseColor("#6E8EC9"));
tabN.setTextColor(Color.parseColor("#6E8EC9"));
tabD.setTextColor(Color.parseColor("#6E8EC9"));
break;
case GEAR_R:
tabR.setTextColor(Color.parseColor("#0043FF"));
tabP.setTextColor(Color.parseColor("#6E8EC9"));
tabN.setTextColor(Color.parseColor("#6E8EC9"));
tabD.setTextColor(Color.parseColor("#6E8EC9"));
break;
case GEAR_N:
tabN.setTextColor(Color.parseColor("#0043FF"));
tabR.setTextColor(Color.parseColor("#6E8EC9"));
tabP.setTextColor(Color.parseColor("#6E8EC9"));
tabD.setTextColor(Color.parseColor("#6E8EC9"));
break;
case GEAR_D:
tabD.setTextColor(Color.parseColor("#0043FF"));
tabN.setTextColor(Color.parseColor("#6E8EC9"));
tabR.setTextColor(Color.parseColor("#6E8EC9"));
tabP.setTextColor(Color.parseColor("#6E8EC9"));
break;
default:
break;
}
}
private void taxiGear(@NotNull Chassis.GearPosition gear) {
switch (gear) {
case GEAR_NONE:
tabP.setTextColor(Color.parseColor("#FF6E8EC9"));
tabR.setTextColor(Color.parseColor("#FF6E8EC9"));
tabN.setTextColor(Color.parseColor("#FF6E8EC9"));
tabD.setTextColor(Color.parseColor("#FF6E8EC9"));
break;
case GEAR_P:
tabP.setTextColor(Color.parseColor("#FFFFFFFF"));
tabR.setTextColor(Color.parseColor("#FF6E8EC9"));
tabN.setTextColor(Color.parseColor("#FF6E8EC9"));
tabD.setTextColor(Color.parseColor("#FF6E8EC9"));
break;
case GEAR_R:
tabR.setTextColor(Color.parseColor("#FFFFFFFF"));
tabP.setTextColor(Color.parseColor("#FF6E8EC9"));
tabN.setTextColor(Color.parseColor("#FF6E8EC9"));
tabD.setTextColor(Color.parseColor("#FF6E8EC9"));
break;
case GEAR_N:
tabN.setTextColor(Color.parseColor("#FFFFFFFF"));
tabR.setTextColor(Color.parseColor("#FF6E8EC9"));
tabP.setTextColor(Color.parseColor("#FF6E8EC9"));
tabD.setTextColor(Color.parseColor("#FF6E8EC9"));
break;
case GEAR_D:
tabD.setTextColor(Color.parseColor("#FFFFFFFF"));
tabN.setTextColor(Color.parseColor("#FF6E8EC9"));
tabR.setTextColor(Color.parseColor("#FF6E8EC9"));
tabP.setTextColor(Color.parseColor("#FF6E8EC9"));
break;
default:
break;
}
}
}

View File

@@ -0,0 +1,173 @@
package com.mogo.eagle.core.function.hmi.ui.widget;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.constraintlayout.widget.ConstraintLayout;
import com.mogo.eagle.core.data.config.FunctionBuildConfig;
import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotVehicleStateListener;
import com.mogo.eagle.core.function.call.autopilot.CallerAutopilotVehicleStateListenerManager;
import com.mogo.eagle.core.function.hmi.R;
import com.mogo.eagle.core.utilcode.mogo.AppIdentityModeUtils;
import com.mogo.eagle.core.utilcode.util.ThreadUtils;
import org.jetbrains.annotations.NotNull;
import java.math.BigDecimal;
import chassis.Chassis;
/**
* @author Jing
* @description 速度 加速度 档位 刹车 油门状态值
* @since: 6/24/22
*/
public class TrafficDataView extends ConstraintLayout {
private static final String TAG = "TrafficDataView";
private TapPositionView tapPositionView;
private TextView speedTextView;
private TextView accTextView;
private ImageView speedImage;
//圆弧颜色
private int mArcColor;
public TrafficDataView(@NonNull Context context) {
super(context);
}
public TrafficDataView(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
initView(context);
CallerAutopilotVehicleStateListenerManager.INSTANCE.addListener(TAG, mIMoGoAutopilotVehicleStateListener);
}
public TrafficDataView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public TrafficDataView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
private void initView(@NonNull Context context) {
if (AppIdentityModeUtils.isBus(FunctionBuildConfig.appIdentityMode)) {
// LayoutInflater.from(context).inflate(R.layout.hmi_traffic_data, this);
} else {
}
LayoutInflater.from(context).inflate(R.layout.hmi_traffic_data, this);
tapPositionView = findViewById(R.id.traffic_position);
speedImage = findViewById(R.id.speedImage);
speedTextView = findViewById(R.id.speedTextView);
accTextView = findViewById(R.id.speedAccTextView);
}
private final IMoGoAutopilotVehicleStateListener mIMoGoAutopilotVehicleStateListener = new IMoGoAutopilotVehicleStateListener() {
/**
* 车辆转向灯
* @param lightSwitch
*/
@Override
public void onAutopilotLightSwitchData(@org.jetbrains.annotations.Nullable Chassis.LightSwitch lightSwitch) {
Log.d(TAG, "车辆转向灯:" + lightSwitch.toString());
}
/**
* 刹车灯
* @param brakeLight
*/
@Override
public void onAutopilotBrakeLightData(boolean brakeLight) {
Log.d(TAG, "刹车灯:" + String.valueOf(brakeLight));
}
/**
* 方向盘转向角 左+右-
* @param steering
*/
@Override
public void onAutopilotSteeringData(float steering) {
Log.d(TAG, "steering原始值====" + String.valueOf(steering));
if (Math.abs(steering) < 1) {
steering = 0;
}
float steeringValue = steering;
ThreadUtils.runOnUiThread(new Runnable() {
@Override
public void run() {
Log.d(TAG, "steering忽略小数点后====" + String.valueOf((int) steeringValue));
}
});
}
/**
* 档位
* @param gear
*/
@Override
public void onAutopilotGearData(@NotNull Chassis.GearPosition gear) {
ThreadUtils.runOnUiThread(new Runnable() {
@Override
public void run() {
Log.d(TAG, "司机屏档位" + gear.toString());
if (tapPositionView != null) {
tapPositionView.updateWithGear(gear);
}
}
});
}
@Override
public void onAutopilotDataException(long timestamp) {
}
@Override
public void onAutopilotAcc(float carAcc) {
Log.d(TAG, "司机屏加速度:" + carAcc);
java.text.DecimalFormat myformat = new java.text.DecimalFormat("0.00");
String accStr = myformat.format(carAcc);
accTextView.setText("a: " + accStr);
}
};
/**
* 设置弧形颜色
*
* @param value 颜色值
*/
public void setArcColor(int value) {
mArcColor = value;
}
/**
* 设置数据
*
* @param value 当前绘制的值
*/
public void setValues(int value) {
}
/**
* value呈现
*/
public void updateSpeedWithValue(int newSpeed) {
if (speedTextView != null) {
speedTextView.setText(String.valueOf(newSpeed));
}
if (speedImage != null) {
speedImage.setBackgroundResource(newSpeed > 60 ? R.drawable.traffic_data_speed_warning : R.drawable.traffic_data_speed);
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

View File

@@ -51,7 +51,7 @@
android:layout_marginTop="@dimen/dp_72"
android:layout_marginRight="-16px"
android:gravity="right"
android:text="180°"
android:text="0°"
android:textColor="#415479"
android:textSize="@dimen/dp_38"
android:visibility="invisible"
@@ -65,7 +65,7 @@
android:layout_marginLeft="-16px"
android:layout_marginTop="@dimen/dp_72"
android:gravity="left"
android:text="180°"
android:text="0°"
android:textColor="#415479"
android:textSize="@dimen/dp_38"
app:layout_constraintLeft_toRightOf="@+id/steering_circular"
@@ -87,6 +87,8 @@
android:layout_width="@dimen/dp_390"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/dp_42"
app:defaultColor = "@color/p_default_txt_color"
app:selectColor="@color/bus_p_select_txt_color"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"

View File

@@ -88,6 +88,8 @@
android:layout_width="@dimen/dp_272"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dp_30"
app:defaultColor="@color/p_default_txt_color"
app:selectColor="@color/dark_mode_select_txt_color"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@+id/steering_circular_alpha" />

View File

@@ -12,7 +12,7 @@
android:gravity="center"
android:text="P"
android:textAlignment="center"
android:textColor="#6E8EC9"
android:textColor="@color/p_default_txt_color"
android:textSize="@dimen/dp_46"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent"
@@ -27,7 +27,7 @@
android:gravity="center"
android:text="R"
android:textAlignment="center"
android:textColor="#6E8EC9"
android:textColor="@color/p_default_txt_color"
android:textSize="@dimen/dp_46"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent"
@@ -42,7 +42,7 @@
android:gravity="center"
android:text="N"
android:textAlignment="center"
android:textColor="#6E8EC9"
android:textColor="@color/p_default_txt_color"
android:textSize="@dimen/dp_46"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent"
@@ -57,7 +57,7 @@
android:gravity="center"
android:text="D"
android:textAlignment="center"
android:textColor="#0043FF"
android:textColor="@color/p_default_txt_color"
android:textSize="@dimen/dp_46"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent"

View File

@@ -0,0 +1,85 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="@dimen/dp_616"
android:layout_height="@dimen/dp_320"
android:background="@drawable/traffic_data_back">
<ImageView
android:id="@+id/speedImage"
android:layout_width="@dimen/dp_270"
android:layout_height="@dimen/dp_270"
android:layout_marginLeft="@dimen/dp_46"
android:background="@drawable/traffic_data_speed"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/speedTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="80px"
android:text="0"
android:textAlignment="center"
android:textColor="#fff"
android:textSize="@dimen/dp_70"
android:textStyle="bold"
app:layout_constraintLeft_toLeftOf="@+id/speedImage"
app:layout_constraintRight_toRightOf="@+id/speedImage"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/kmTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dp_176"
android:text="KM/H"
android:textAlignment="center"
android:textColor="#fff"
android:textSize="@dimen/dp_30"
android:textStyle="bold"
app:layout_constraintLeft_toLeftOf="@+id/speedImage"
app:layout_constraintRight_toRightOf="@+id/speedImage"
app:layout_constraintTop_toTopOf="parent" />
<com.mogo.eagle.core.function.hmi.ui.widget.TapPositionView
android:id="@+id/traffic_position"
android:layout_width="@dimen/dp_220"
app:defaultColor="@color/acc_default_txt_color"
app:selectColor="@color/dark_mode_select_txt_color"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/dp_28"
android:layout_marginTop="@dimen/dp_80"
android:layout_marginRight="@dimen/dp_80"
app:layout_constraintLeft_toRightOf="@+id/speedImage"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="@+id/brakeStatus"
android:layout_width="@dimen/dp_66"
android:layout_height="@dimen/dp_68"
android:layout_marginLeft="@dimen/dp_20"
android:layout_marginTop="@dimen/dp_174"
android:layout_marginBottom="@dimen/dp_57"
android:src="@drawable/traffic_data_empty"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toRightOf="@id/speedImage"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/speedAccTextView"
android:layout_width="wrap_content"
android:layout_height="@dimen/dp_56"
android:layout_marginLeft="@dimen/dp_42"
android:layout_marginTop="@dimen/dp_190"
android:text="a: "
android:textAlignment="viewStart"
android:textColor="#fff"
android:textSize="@dimen/dp_40"
app:layout_constraintLeft_toLeftOf="@+id/brakeStatus"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -6,4 +6,5 @@
<color name="notice_check_dialog_bg_color">#E63B4577</color>
<color name="notice_traffic_line">#555C7E</color>
<color name="notice_dialog_back">#3B4577</color>
<color name="acc_default_txt_color">#FF343C63</color>
</resources>

View File

@@ -49,4 +49,8 @@
<attr name="progress" format="integer" /> <!--圆环进度-->
</declare-styleable>
<declare-styleable name="TapPositionView">
<attr name="defaultColor" format="color"/> <!--档位默认色值-->
<attr name="selectColor" format="color"/> <!--当前档位色值-->
</declare-styleable>
</resources>

View File

@@ -60,4 +60,9 @@
<color name="hmi_light_blue_alpha_00">#D945D3FF</color>
<color name="hmi_light_blue_alpha_ff">#D93261B6</color>
<color name="hmi_clear_00">#00FFFFFF</color>
<color name="acc_default_txt_color">#FF343C63</color>
<color name="bus_p_select_txt_color">#0043FF</color>
<color name="p_default_txt_color">#FF6E8EC9</color>
<color name="dark_mode_select_txt_color">#FFFFFFFF</color>
</resources>

View File

@@ -211,6 +211,7 @@ public class MapFragment extends MvpFragment<MapView, MapPresenter>
@Override
public void onDestroyView() {
CallerSkinModeListenerManager.INSTANCE.removeListener(TAG);
CallerAutopilotPlanningListenerManager.INSTANCE.removeListener(TAG);
if (mMogoMapView != null) {
mMogoMapView.onDestroy();
mMogoMapView = null;

View File

@@ -203,7 +203,7 @@ public class AMapCustomView
// options.setTilt((int) tilt);
//自车车标
options.setCarBitmap(BitmapFactory.decodeResource(this.getResources(), R.drawable.module_small_map_view_my_location_logo));
// options.setFourCornersBitmap(BitmapFactory.decodeResource(this.getResources(), R.drawable.amap_custom_corner));
options.setFourCornersBitmap(BitmapFactory.decodeResource(this.getResources(), R.drawable.amap_custom_corner));
options.setStartPointBitmap(BitmapFactory.decodeResource(this.getResources(), R.drawable.module_small_map_view_dir_start));
options.setWayPointBitmap(BitmapFactory.decodeResource(this.getResources(), R.drawable.icon_module_small_map_four_corners));
options.setEndPointBitmap(BitmapFactory.decodeResource(this.getResources(), R.drawable.module_small_map_view_dir_end));
@@ -212,11 +212,11 @@ public class AMapCustomView
//路线纹理自定义
RouteOverlayOptions routeOverlayOptions = new RouteOverlayOptions();
routeOverlayOptions.setTurnArrowIs3D(false);
// routeOverlayOptions.setUnknownTraffic(BitmapFactory.decodeResource(getResources(), R.drawable.custtexture_no));//未知路段
// routeOverlayOptions.setSmoothTraffic(BitmapFactory.decodeResource(getResources(), R.drawable.amap_custom_smooth_route));
// routeOverlayOptions.setJamTraffic(BitmapFactory.decodeResource(getResources(), R.drawable.custtexture_bad));//拥堵路段
// routeOverlayOptions.setVeryJamTraffic(BitmapFactory.decodeResource(getResources(), R.drawable.custtexture_grayred));//超级拥堵路段
// routeOverlayOptions.setPassRoute(BitmapFactory.decodeResource(getResources(), R.drawable.amap_custom_pass_route));//走过的路段
routeOverlayOptions.setUnknownTraffic(BitmapFactory.decodeResource(getResources(), R.drawable.custtexture_no));//未知路段
routeOverlayOptions.setSmoothTraffic(BitmapFactory.decodeResource(getResources(), R.drawable.amap_custom_smooth_route));
routeOverlayOptions.setJamTraffic(BitmapFactory.decodeResource(getResources(), R.drawable.custtexture_bad));//拥堵路段
routeOverlayOptions.setVeryJamTraffic(BitmapFactory.decodeResource(getResources(), R.drawable.custtexture_grayred));//超级拥堵路段
routeOverlayOptions.setPassRoute(BitmapFactory.decodeResource(getResources(), R.drawable.amap_custom_pass_route));//走过的路段
options.setRouteOverlayOptions(routeOverlayOptions);
mAMapNaviView.setViewOptions(options);
}
@@ -691,8 +691,8 @@ public class AMapCustomView
// 加载自定义样式
CustomMapStyleOptions customMapStyleOptions = new CustomMapStyleOptions()
.setEnable(true)
.setStyleData(MapAssetStyleUtils.getAssetsStyle(getContext()))
.setStyleExtraData(MapAssetStyleUtils.getAssetsExtraStyle(getContext()));
.setStyleData(MapAssetStyleUtils.getAssetsStyle(getContext(),"over_view_style.data"))
.setStyleExtraData(MapAssetStyleUtils.getAssetsExtraStyle(getContext(),"over_view_style_extra.data"));
// 设置自定义样式
mAMap.setCustomMapStyle(customMapStyleOptions);
}

View File

@@ -0,0 +1,121 @@
package com.mogo.eagle.core.function.smp;
import com.amap.api.maps.AMapUtils;
import com.amap.api.maps.model.LatLng;
import com.amap.api.navi.model.NaviLatLng;
import com.autonavi.amap.mapcore.IPoint;
import com.autonavi.amap.mapcore.MapProjection;
/**
* 包名: com.amap.navi.demo.util
* <p>
* 创建时间2018/4/19
* 项目名称NaviDemo
*
* @author guibao.ggb
* @email guibao.ggb@alibaba-inc.com
* <p>
* 类说明:
*/
public class NaviUtil {
public static float calculateDistance(NaviLatLng start, NaviLatLng end) {
double x1 = start.getLongitude();
double y1 = start.getLatitude();
double x2 = end.getLongitude();
double y2 = end.getLatitude();
return AMapUtils.calculateLineDistance(new LatLng(y1, x1), new LatLng(y2, x2));
}
public static NaviLatLng getPointForDis(NaviLatLng sPt, NaviLatLng ePt, double dis) {
double lSegLength = calculateDistance(sPt, ePt);
NaviLatLng pt = new NaviLatLng();
double preResult = dis / lSegLength;
pt.setLatitude(((ePt.getLatitude() - sPt.getLatitude()) * preResult + sPt.getLatitude()));
pt.setLongitude(((ePt.getLongitude() - sPt.getLongitude()) * preResult + sPt.getLongitude()));
return pt;
}
/**
* 根据经纬度计算需要偏转的角度
*
* @param startPoi
* @param secondPoi
* @return
*/
public static float getRotate(NaviLatLng startPoi, NaviLatLng secondPoi) {
float rotate = 0;
try {
IPoint point1 = new IPoint();
IPoint point2 = new IPoint();
MapProjection.lonlat2Geo(startPoi.getLongitude(), startPoi.getLatitude(), point1);
MapProjection.lonlat2Geo(secondPoi.getLongitude(), secondPoi.getLatitude(), point2);
double x1 = point1.x;
double x2 = point2.x;
double y1 = point1.y;
double y2 = point2.y;
rotate = (float) (Math.atan2(y2 - y1, x2 - x1) / Math.PI * 180);
rotate = rotate + 90;
return rotate;
} catch (Exception e) {
e.printStackTrace();
}
return rotate;
}
public static final int MAXZOOMLEVEL = 20;
public static final int PIXELSPERTILE = 256;
public static final double MINLATITUDE = -85.0511287798;
public static final double MAXLATITUDE = 85.0511287798;
public static final double MINLONGITUDE = -180;
public static final double MAXLONGITUDE = 180;
public static final int EARTHRADIUSINMETERS = 6378137;
public static final int TILESPLITLEVEL = 0;
public static final double EarthCircumferenceInMeters = 2 * Math.PI
* EARTHRADIUSINMETERS;
public static double clip(double n, double minValue, double maxValue) {
return Math.min(Math.max(n, minValue), maxValue);
}
public static IPoint lonlat2Geo(double latitude, double longitude,
int levelOfDetail) {
IPoint rPnt = new IPoint();
latitude = clip(latitude, MINLATITUDE, MAXLATITUDE) * Math.PI / 180;
longitude = clip(longitude, MINLONGITUDE, MAXLONGITUDE) * Math.PI / 180;
double sinLatitude = Math.sin(latitude);
double xMeters = EARTHRADIUSINMETERS * longitude;
double lLog = Math.log((1 + sinLatitude) / (1 - sinLatitude));
double yMeters = EARTHRADIUSINMETERS / 2 * lLog;
long numPixels = (long) PIXELSPERTILE << levelOfDetail;
double metersPerPixel = EarthCircumferenceInMeters / numPixels;
rPnt.x = (int) clip((EarthCircumferenceInMeters / 2 + xMeters)
/ metersPerPixel + 0.5, 0, numPixels - 1);
long tmp = (long) (EarthCircumferenceInMeters / 2 - yMeters);
rPnt.y = (int) clip((double) tmp / metersPerPixel + 0.5, 0,
numPixels - 1);
return rPnt;
}
public static String formatKM(int d) {
if (d == 0) {
return "0米";
} else if (d < 100) {
return d + "";
} else if ((100 <= d) && (d < 1000)) {
return d + "";
} else if ((1000 <= d) && (d < 10000)) {
return (d / 10) * 10 / 1000.0D + "公里";
} else if ((10000 <= d) && (d < 100000)) {
return (d / 100) * 100 / 1000.0D + "公里";
}
return (d / 1000) + "公里";
}
}

View File

@@ -1,356 +0,0 @@
package com.mogo.eagle.core.function.smp;
import static com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.M_MAP;
import android.content.Context;
import android.graphics.Color;
import android.location.Location;
import android.os.Bundle;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.widget.RelativeLayout;
import androidx.annotation.Nullable;
import com.amap.api.maps.AMap;
import com.amap.api.maps.CameraUpdate;
import com.amap.api.maps.CameraUpdateFactory;
import com.amap.api.maps.CoordinateConverter;
import com.amap.api.maps.TextureMapView;
import com.amap.api.maps.UiSettings;
import com.amap.api.maps.model.BitmapDescriptorFactory;
import com.amap.api.maps.model.CameraPosition;
import com.amap.api.maps.model.CustomMapStyleOptions;
import com.amap.api.maps.model.LatLng;
import com.amap.api.maps.model.LatLngBounds;
import com.amap.api.maps.model.Marker;
import com.amap.api.maps.model.MarkerOptions;
import com.amap.api.maps.model.Polyline;
import com.amap.api.maps.model.PolylineOptions;
import com.mogo.cloud.commons.utils.CoordinateUtils;
import com.mogo.eagle.core.data.map.MogoLatLng;
import com.mogo.eagle.core.data.map.MogoLocation;
import com.mogo.eagle.core.function.api.map.listener.IMoGoMapLocationListener;
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger;
import com.mogo.eagle.core.function.call.map.CallerMapLocationListenerManager;
import com.mogo.eagle.core.function.map.R;
import com.mogo.eagle.core.utilcode.mogo.MapAssetStyleUtils;
import com.mogo.eagle.core.function.smp.view.ISmallMapDirectionView;
import com.mogo.eagle.core.widget.RoundLayout;
import com.mogo.module.common.utils.DrivingDirectionUtils;
import java.util.ArrayList;
import java.util.List;
/**
* 小地图的方向View
*
* @author donghongyu
* @date 12/14/20 4:40 PM
*/
public class SmallMapDirectionView
extends RelativeLayout
implements IMoGoMapLocationListener, ISmallMapDirectionView {
//小地图名称
public static final String TAG = "SmallMapDirectionView";
private RoundLayout rlSmallMapBorder;
private TextureMapView mAMapNaviView;
private AMap mAMap;
private Marker mCarMarker;
private Marker mStartMarker;
private Marker mEndMarker;
private int zoomLevel = 15;
private final List<LatLng> mCoordinatesLatLng = new ArrayList<>();
private final List<MogoLatLng> mCoordinatesLatLngCurrent = new ArrayList<>();
private Polyline mPolyline;
private CameraUpdate mCameraUpdate;
private Context mContext;
public SmallMapDirectionView(Context context) {
this(context, null);
}
public SmallMapDirectionView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public SmallMapDirectionView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
try {
initView(context);
} catch (Exception e) {
e.printStackTrace();
}
}
private void initView(Context context) {
mContext = context;
View smpView = LayoutInflater.from(context).inflate(R.layout.module_small_map_view, this);
mAMapNaviView = smpView.findViewById(R.id.aMapNaviView);
// rlSmallMapBorder = findViewById(R.id.rlSmallMapBorder);
// rlSmallMapBorder.addView(mAMapNaviView);
initAMapView();
// 注册定位监听
CallerMapLocationListenerManager.INSTANCE.addListener(TAG, this);
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
// 注册定位监听
CallerMapLocationListenerManager.INSTANCE.removeListener(TAG);
}
private void initAMapView() {
mCameraUpdate = CameraUpdateFactory.zoomTo(zoomLevel);
mAMap = mAMapNaviView.getMap();
// 关闭地图文字标注
mAMap.showMapText(false);
// 设置导航地图模式aMap是地图控制器对象。
mAMap.setMapType(AMap.MAP_TYPE_NIGHT);
// 关闭显示实时路况图层aMap是地图控制器对象。
mAMap.setTrafficEnabled(false);
// 设置 锚点 图标
mCarMarker = mAMap.addMarker(new MarkerOptions()
.icon(BitmapDescriptorFactory.fromResource(R.drawable.module_small_map_view_my_location_logo))
.anchor(0.5f, 0.5f));
mStartMarker = mAMap.addMarker(new MarkerOptions()
.icon(BitmapDescriptorFactory.fromResource(R.drawable.module_small_map_view_dir_start)));
mEndMarker = mAMap.addMarker(new MarkerOptions()
.icon(BitmapDescriptorFactory.fromResource(R.drawable.module_small_map_view_dir_end)));
// 加载自定义样式
CustomMapStyleOptions customMapStyleOptions = new CustomMapStyleOptions()
.setEnable(true)
.setStyleData(MapAssetStyleUtils.getAssetsStyle(getContext()))
.setStyleExtraData(MapAssetStyleUtils.getAssetsExtraStyle(getContext()));
// 设置自定义样式
mAMap.setCustomMapStyle(customMapStyleOptions);
//设置希望展示的地图缩放级别
mAMap.moveCamera(mCameraUpdate);
// 设置地图的样式
UiSettings uiSettings = mAMap.getUiSettings();
uiSettings.setZoomControlsEnabled(false);// 地图缩放级别的交换按钮
uiSettings.setAllGesturesEnabled(false);// 所有手势
uiSettings.setMyLocationButtonEnabled(false); // 显示默认的定位按钮
uiSettings.setLogoBottomMargin(-150); //设置Logo下边界距离屏幕底部的边距,设置为负值即可
mAMap.setOnMapLoadedListener(() -> {
CallerLogger.INSTANCE.d(M_MAP + TAG, "smp---onMapLoaded");
// 加载自定义样式
CustomMapStyleOptions customMapStyleOptions1 = new CustomMapStyleOptions()
.setEnable(true)
.setStyleData(MapAssetStyleUtils.getAssetsStyle(getContext()))
.setStyleExtraData(MapAssetStyleUtils.getAssetsExtraStyle(getContext()));
// 设置自定义样式
mAMap.setCustomMapStyle(customMapStyleOptions1);
mAMapNaviView.getMap().setPointToCenter(mAMapNaviView.getWidth() / 2, mAMapNaviView.getHeight() / 2);
});
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return true;
}
@Override
public void onLocationChanged(@org.jetbrains.annotations.Nullable MogoLocation location, int from) {
if (location == null) {
return;
}
if (mCarMarker == null){
mCarMarker = mAMap.addMarker(new MarkerOptions()
.icon(BitmapDescriptorFactory.fromResource(R.drawable.module_small_map_view_my_location_logo))
.anchor(0.5f, 0.5f));
}
if(mCarMarker == null){
return;
}
LatLng currentLatLng = new LatLng(location.getLatitude(), location.getLongitude());
//更新车辆位置
mCarMarker.setPosition(currentLatLng);
CameraPosition cameraPosition;
if (mCoordinatesLatLng.size() > 1) {
// mCoordinatesLatLngCurrent.clear();
// for (LatLng lng : mCoordinatesLatLng) {
// MogoLatLng mogoLatLng = new MogoLatLng(lng.latitude, lng.longitude);
// mCoordinatesLatLngCurrent.add(mogoLatLng);
// }
// removeLoction(latLng);
// 结束位置
LatLng endLatLng = mCoordinatesLatLng.get(mCoordinatesLatLng.size() - 1);
// 与结束位置进行 GeoHash 0-12
// GeoHash endGeoHash = GeoHash.withCharacterPrecision(endLatLng.latitude, endLatLng.longitude, 7);
// GeoHash currentGeoHash = GeoHash.withCharacterPrecision(currentLatLng.latitude, currentLatLng.longitude, 7);
float calculateDistance = CoordinateUtils.calculateLineDistance(
endLatLng.latitude, endLatLng.longitude,
currentLatLng.latitude, currentLatLng.longitude
);
CallerLogger.INSTANCE.d(M_MAP + TAG, "calculateDistance=" + calculateDistance);
if (calculateDistance <= 5) {
clearPolyline();
mCoordinatesLatLng.clear();
}
cameraPosition = new CameraPosition.Builder().target(mCarMarker.getPosition()).tilt(0).bearing(location.getBearing()).zoom(zoomLevel).build();
} else {
//设置希望展示的地图缩放级别
cameraPosition = new CameraPosition.Builder().target(mCarMarker.getPosition()).tilt(0).bearing(location.getBearing()).zoom(zoomLevel).build();
// mAMap.moveCamera(CameraUpdateFactory.newLatLngZoom(currentLatLng, zoomLevel));
}
mAMap.moveCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));
}
private void removeLocation(Location latLng) {
for (LatLng l : mCoordinatesLatLng) {
if (!isPointOnCarFront(latLng, l)) {
mCoordinatesLatLng.remove(l);
}
}
}
public static boolean isPointOnCarFront(Location carLocal, LatLng pointLocal) {
double carLon = carLocal.getLongitude();
double carLat = carLocal.getLatitude();
double poiLon = pointLocal.longitude;
double poiLat = pointLocal.latitude;
float carAngle = carLocal.getBearing();
// 计算车辆与点之间的夹角
int diffAngle = DrivingDirectionUtils.getDegreeOfCar2Poi(
carLon, carLat, poiLon, poiLat, (int) carAngle);
return diffAngle <= 90;
}
@Override
public void drawablePolyline() {
clearPolyline();
// mCoordinatesLatLng.clear();
// List<LatLng> latLngs = CoordinateConverterFrom84ForList(mContext,coordinates);
// mCoordinatesLatLng.addAll(latLngs);
// for (LatLng coordinate : mCoordinatesLatLng) {
// mCoordinatesLatLng.add(new LatLng(coordinate.getLat(), coordinate.getLon()));
// }
if (mAMap != null) {
if (mCoordinatesLatLng.size() > 2) {
// 设置开始结束Marker位置
mStartMarker.setPosition(mCoordinatesLatLng.get(0));
mEndMarker.setPosition(mCoordinatesLatLng.get(mCoordinatesLatLng.size() - 1));
mStartMarker.setToTop();
mStartMarker.setVisible(true);
mEndMarker.setVisible(true);
mEndMarker.setToTop();
//存放所有点的经纬度
LatLngBounds.Builder boundsBuilder = new LatLngBounds.Builder();
for (int i = 0; i < mCoordinatesLatLng.size(); i++) {
//把所有点都include进去LatLng类型
boundsBuilder.include(mCoordinatesLatLng.get(i));
}
//第二个参数为四周留空宽度
mAMap.animateCamera(CameraUpdateFactory.newLatLngBounds(boundsBuilder.build(), 30));
// 绘制线
mPolyline = mAMap.addPolyline(
new PolylineOptions()
.addAll(mCoordinatesLatLng)
.color(Color.argb(255, 31, 127, 255))
.width(12));
}
// else {
// //设置希望展示的地图缩放级别
// mAMap.moveCamera(CameraUpdateFactory.newLatLngZoom(mCoordinatesLatLng.get(0), zoomLevel));
// }
}
}
public LatLng CoordinateConverterFrom84(Context mContext, MogoLatLng mogoLatLng) {
CoordinateConverter mCoordinateConverter = new CoordinateConverter(mContext);
mCoordinateConverter.from(CoordinateConverter.CoordType.GPS);
mCoordinateConverter.coord(new LatLng(mogoLatLng.lat, mogoLatLng.lon));
return mCoordinateConverter.convert();
}
public List<LatLng> CoordinateConverterFrom84ForList(Context mContext, List<MogoLatLng> mogoLatLngList) {
List<LatLng> list = new ArrayList<>();
for (MogoLatLng m : mogoLatLngList) {
LatLng mogoLatLng = CoordinateConverterFrom84(mContext, m);
list.add(mogoLatLng);
}
return list;
}
@Override
public void clearPolyline() {
// mCoordinatesLatLng.clear();
if (mPolyline != null) {
mPolyline.remove();
}
if (mStartMarker != null) {
mStartMarker.setVisible(false);
}
if (mEndMarker != null) {
mEndMarker.setVisible(false);
}
}
public void resetPolyLine() {
mCoordinatesLatLng.clear();
if (mPolyline != null) {
mPolyline.remove();
}
if (mStartMarker != null) {
mStartMarker.setVisible(false);
}
if (mEndMarker != null) {
mEndMarker.setVisible(false);
}
}
public void onCreateView(Bundle savedInstanceState) {
if (mAMapNaviView != null) {
mAMapNaviView.onCreate(savedInstanceState);
}
}
public void onResume() {
if (mAMapNaviView != null) {
mAMapNaviView.onResume();
}
}
public void onPause() {
if (mAMapNaviView != null) {
mAMapNaviView.onPause();
}
}
public void onDestroy() {
if (mAMapNaviView != null) {
mAMapNaviView.onDestroy();
}
}
public void convert(List<MogoLatLng> coordinates) {
mCoordinatesLatLng.clear();
List<LatLng> latLngs = CoordinateConverterFrom84ForList(mContext, coordinates);
mCoordinatesLatLng.addAll(latLngs);
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 218 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 215 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 218 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 218 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 179 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 159 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 139 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 361 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.1 KiB

After

Width:  |  Height:  |  Size: 9.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.5 KiB

After

Width:  |  Height:  |  Size: 9.6 KiB

View File

@@ -4,7 +4,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.mogo.eagle.core.function.smp.SmallMapDirectionView
<com.mogo.eagle.core.function.smp.AMapCustomView
android:id="@+id/smallMapDirectionView"
android:layout_width="match_parent"
android:layout_height="match_parent"

View File

@@ -12,8 +12,8 @@
<dimen name="module_map_display_overview_right_margin">200px</dimen>
<dimen name="module_small_map_padding">40px</dimen>
<dimen name="module_small_map_view_border_width">400px</dimen>
<dimen name="module_small_map_view_border_width">700px</dimen>
<dimen name="module_small_map_border_view_width">550px</dimen>
<dimen name="module_small_map_view_width">360px</dimen>
<dimen name="module_small_map_view_width">660px</dimen>
</resources>

View File

@@ -12,7 +12,7 @@
<dimen name="module_map_display_overview_right_margin">100px</dimen>
<dimen name="module_small_map_padding">30px</dimen>
<dimen name="module_small_map_view_border_width">288px</dimen>
<dimen name="module_small_map_border_view_width">450px</dimen>
<dimen name="module_small_map_view_width">260px</dimen>
<dimen name="module_small_map_view_border_width">588px</dimen>
<dimen name="module_small_map_border_view_width">550px</dimen>
<dimen name="module_small_map_view_width">560px</dimen>
</resources>

View File

@@ -10,7 +10,7 @@ import com.mogo.eagle.core.data.R
object HdMapBuildConfig {
/**
* 自车模型(默认是出租车)
* 可以指定R.raw.chuzucheR.raw.xiaobache
* 可以指定R.raw.chuzucheR.raw.xiaobacheR.raw.hongqi
*/
@JvmField
var currentCarVrIconRes = R.raw.chuzuche

View File

@@ -1,6 +1,7 @@
package com.mogo.eagle.core.function.api.autopilot
import chassis.Chassis
import mogo.telematics.pad.MessagePad
/**
* 车辆底盘 数据 回调监听
@@ -36,4 +37,9 @@ interface IMoGoAutopilotVehicleStateListener {
* 没有自车状态数据
*/
fun onAutopilotDataException(timestamp: Long){}
/**
* 车辆加速度
*/
fun onAutopilotAcc(carAcc: Float)
}

View File

@@ -4,6 +4,7 @@ import androidx.annotation.Nullable
import chassis.Chassis
import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotVehicleStateListener
import com.mogo.eagle.core.function.call.base.CallerBase
import mogo.telematics.pad.MessagePad
import java.util.concurrent.ConcurrentHashMap
/**
@@ -100,6 +101,18 @@ object CallerAutopilotVehicleStateListenerManager : CallerBase() {
}
}
/**
* 车辆加速度
* acc 加速度
*/
fun invokeAutopilotAcc(carAcc: Float){
M_AUTOPILOT_VEHICLE_LISTENERS.forEach{
val listener = it.value
listener.onAutopilotAcc(carAcc)
}
}
/**
* 工控机时间回调
*/

BIN
core/mogo-core-res/src/main/res/raw/chuzuche.nt3d Executable file → Normal file

Binary file not shown.

View File

@@ -12,11 +12,11 @@ import java.io.InputStream;
*/
public class MapAssetStyleUtils {
public static byte[] getAssetsStyle(Context context) {
public static byte[] getAssetsStyle(Context context,String fileName) {
byte[] buffer1 = null;
InputStream is1 = null;
try {
is1 = context.getResources().getAssets().open("small_map_style.data");
is1 = context.getResources().getAssets().open(fileName); //eg. small_map_style.data
int lenght1 = is1.available();
buffer1 = new byte[lenght1];
is1.read(buffer1);
@@ -35,11 +35,11 @@ public class MapAssetStyleUtils {
}
public static byte[] getAssetsExtraStyle(Context context) {
public static byte[] getAssetsExtraStyle(Context context, String fileName) {
byte[] buffer1 = null;
InputStream is1 = null;
try {
is1 = context.getResources().getAssets().open("small_map_style_extra.data");
is1 = context.getResources().getAssets().open(fileName); //eg. small_map_style_extra.data
int lenght1 = is1.available();
buffer1 = new byte[lenght1];
is1.read(buffer1);

View File

@@ -178,6 +178,12 @@ public interface IMogoMapUIController {
*/
void setCarCursorOption(@Nullable CarCursorOption option);
/**
*
* @param type :车尾灯类型 time: 闪烁时间 最小500ms 小于500ms 默认为500ms
*/
void setCarLightsType(int type, int time);
/**
* 获取地图视图描述快照
*

View File

@@ -639,6 +639,17 @@ public class AMapViewWrapper implements IMogoMapView,
mMapView.getMapAutoViewHelper().setMyLocationStyle(style);
}
/**
* 设置转向灯和刹车灯
* @param type :车尾灯类型 time: 闪烁时间 最小500ms 小于500ms 默认为500ms
* @param time
*/
@Override
public void setCarLightsType(int type, int time) {
Log.d("liyz", "AMapViewWrapper setCarLightsType type = " + type + "---time = " + time);
mMapView.getMapAutoViewHelper().setTailLightsType(type, time);
}
@Override
public MapCameraPosition getMapCameraPosition() {
if (checkAMapView()) {

View File

@@ -3,6 +3,7 @@ package com.mogo.map;
import android.graphics.Point;
import android.graphics.Rect;
import android.location.Location;
import android.util.Log;
import android.view.View;
import com.mogo.eagle.core.data.map.CenterLine;
@@ -252,6 +253,15 @@ public class MogoMapUIController implements IMogoMapUIController {
}
}
@Override
public void setCarLightsType(int type, int time) {
initDelegate();
if (mDelegate != null) {
// Log.d("liyz", "MogoMapUIController type = " + type + "---time = " + time);
mDelegate.setCarLightsType(type, time);
}
}
@Override
public MapCameraPosition getMapCameraPosition() {
initDelegate();

View File

@@ -3,6 +3,7 @@ package com.mogo.map.uicontroller;
import android.graphics.Point;
import android.graphics.Rect;
import android.location.Location;
import android.util.Log;
import android.view.View;
import com.mogo.eagle.core.data.map.CenterLine;
@@ -220,6 +221,14 @@ public class AMapUIController implements IMogoMapUIController {
}
}
@Override
public void setCarLightsType(int type, int time) {
// Log.d("liyz", "AMapUIController type = " + type + "---time = " + time);
if (mClient != null) {
mClient.setCarLightsType(type, time);
}
}
@Override
public MapCameraPosition getMapCameraPosition() {
if (mClient != null) {

View File

@@ -3,8 +3,13 @@
<dimen name="dp_12">12px</dimen>
<dimen name="dp_20">20px</dimen>
<dimen name="dp_22">22px</dimen>
<dimen name="dp_43">43px</dimen>
<dimen name="dp_57">57px</dimen>
<dimen name="dp_72">72px</dimen>
<dimen name="dp_88">88px</dimen>
<dimen name="module_v2n_tip_text_margin_right">26px</dimen>
<dimen name="warning_distance_right">30px</dimen>
<dimen name="dp_270">270px</dimen>
<dimen name="dp_320">320px</dimen>
<dimen name="dp_630">630px</dimen>
</resources>