导航协议实现导航时悬浮显示车速
背景某导航巡航时才能悬浮车速,导航时是不能悬浮车速的。本人不太喜欢全屏导航,因此就写了个app自己用。
原始巡航图,带车速的。
,本来导航要是有这个车速就很好,可惜官方没有。那就自己动手咯。
目前软件已开车实测500公里,无闪退问题。下面贴下核心代码。
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Color;
import android.graphics.PixelFormat;
import android.os.Build;
import android.os.IBinder;
import android.util.Log;
import android.view.*;
import android.widget.TextView;
import com.hd.hdcart.amap.AMapCartReceiver;
import com.hd.hdcart.event.AMapAreaInfoMessageEvent;
import com.hd.hdcart.event.AMapFloatingWindowSettingsChangeMessageEvent;
import com.hd.hdcart.event.FloatShowEnableEvent;
import com.hd.hdcart.utils.SharedPreUtil;
import com.hd.hdcart.utils.TaskExecutor;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
import java.util.concurrent.ScheduledFuture;
public class AMapCartService extends Service
{
private static final String TAG = "AMapCartService";
public static final String RECEIVE_ACTION = "AUTONAVI_STANDARD_BROADCAST_SEND";
public static final String SEND_ACTION = "AUTONAVI_STANDARD_BROADCAST_RECV";
public static final String KEY_TYPE = "KEY_TYPE";
private WindowManager windowManager;
private WindowManager.LayoutParams layoutParams;
private View displayView;
public int curSpeed = 0;//时速
public String road = "";//道路
public String sourceArea = "";//行政区
public double ecurSpeed = 0.0d;
public double cameraSpeed = 0.0d;
public double limitSpeed = 0.0d;
public final double lowerLimit = 10.0d;
double proportion = 0.0d;
private AMapCartReceiver aMapCartReceiver;
public AMapCartService()
{
}
@Override
public IBinder onBind(Intent intent)
{
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId)
{
if (!EventBus.getDefault().isRegistered(this)) {
EventBus.getDefault().register(this);
}
registerAMapReceiver();
startSendAMapAreaInfoReceiverTask();
windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
if (SharedPreUtil.getBoolean("FLOATING_WINDOW_AMAP_AREA_ENABLE", false)) {
initLayoutParams();
showFloatView();
}
return super.onStartCommand(intent, flags, startId);
}
/**
* 注册监听高德广播
*/
private void registerAMapReceiver()
{
aMapCartReceiver = new AMapCartReceiver();
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(RECEIVE_ACTION);
intentFilter.addAction(SEND_ACTION);
unregisterReceiver();
registerReceiver(aMapCartReceiver, intentFilter);//再进行监听
}
/**
* 请求高德行政区域信息
*
* @Param context
*/
public static void sendAMapAreaInfoReceiver(Context context)
{
Intent intent = new Intent();
intent.setAction(SEND_ACTION);
intent.putExtra(KEY_TYPE, 10029);
context.sendBroadcast(intent);
}
/**
* 取消监听高德广播
*/
private void unregisterReceiver()
{
try {
if (aMapCartReceiver != null) {
unregisterReceiver(aMapCartReceiver);//先取消监听
}
} catch (Exception exception) {
}
}
ScheduledFuture<?> scheduledFuture;
/**
* 开启定时发送高德行政区域信息
*/
public void startSendAMapAreaInfoReceiverTask()
{
scheduledFuture = TaskExecutor.self().repeatRun(() -> {
sendAMapAreaInfoReceiver(this);
}, 90 * 1000);
}
public void stopSendAMapAreaInfoReceiverTask()
{
if (scheduledFuture != null) {
scheduledFuture.cancel(true);
}
}
/**
* 初始化悬浮窗参数
*/
private void initLayoutParams()
{
layoutParams = new WindowManager.LayoutParams();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
layoutParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
} else {
layoutParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
}
layoutParams.format = PixelFormat.RGBA_8888;
//设置透明度
layoutParams.alpha = 0.65f;
layoutParams.gravity = Gravity.LEFT | Gravity.TOP;
layoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
layoutParams.width = SharedPreUtil.getInteger("FLOATING_WINDOW_AMAP_AREA_CONTAINER_WIDTH", 424);
layoutParams.height = SharedPreUtil.getInteger("FLOATING_WINDOW_AMAP_AREA_CONTAINER_HEIGHT", 162);
layoutParams.x = SharedPreUtil.getInteger("FLOATING_WINDOW_AMAP_AREA_CONTAINER_X", 300);
layoutParams.y = SharedPreUtil.getInteger("FLOATING_WINDOW_AMAP_AREA_CONTAINER_Y", 300);
}
/**
* 显示悬浮窗
*/
private void showFloatView()
{
LayoutInflater layoutInflater = LayoutInflater.from(this);
displayView = layoutInflater.inflate(R.layout.amap_area_floating_window, null);
if (layoutParams == null) {
initLayoutParams();
}
displayView.setOnTouchListener(new View.OnTouchListener()
{
@Override
public boolean onTouch(View v, MotionEvent event)
{
if (layoutParams != null) {
layoutParams.x = (int) event.getRawX() - displayView.getMeasuredWidth() / 2;
layoutParams.y = (int) event.getRawY() - displayView.getMeasuredHeight() / 2;
SharedPreUtil.saveInteger("FLOATING_WINDOW_AMAP_AREA_CONTAINER_X", layoutParams.x);
SharedPreUtil.saveInteger("FLOATING_WINDOW_AMAP_AREA_CONTAINER_Y", layoutParams.y);
windowManager.updateViewLayout(displayView, layoutParams);
}
return false;
}
});
TextView txtCurSpeed = (TextView) displayView.findViewById(R.id.txtCurSpeed);
txtCurSpeed.setText(curSpeed+ " km/h");
txtCurSpeed.setTextSize(SharedPreUtil.getInteger("FLOATING_WINDOW_AMAP_SD_FONT_SIZE", 40));
TextView txtArea = (TextView) displayView.findViewById(R.id.txtArea);
if (sourceArea != null && !sourceArea.equals("")) {
txtArea.setText(sourceArea);
} else {
txtArea.setText("waiting...");
}
txtArea.setTextSize(SharedPreUtil.getInteger("FLOATING_WINDOW_AMAP_AREA_FONT_SIZE", 20));
TextView txtRoad = (TextView) displayView.findViewById(R.id.txtRoad);
txtRoad.setText(road);
txtRoad.setTextSize(SharedPreUtil.getInteger("FLOATING_WINDOW_AMAP_AREA_FONT_SIZE", 20));
windowManager.addView(displayView, layoutParams);
}
/**
* 接收高德行政区域信息
*
* @param event
*/
@Subscribe(threadMode = ThreadMode.MAIN)
public void onAMapAreaInfoMessageEvent(AMapAreaInfoMessageEvent event)
{
if (event.getType().equals("10030")) {
if (!sourceArea.equals(event.toString())) {
updateFloatViewContent(event.toString());
sourceArea = event.toString();
}
} else if (event.getType().equals("10065")) {
TextView txtCcurSpeed = (TextView) displayView.findViewById(R.id.txtCurSpeed);
txtCcurSpeed.setText(event.getCurSpeed() + " km/h");
}else {
updateFloatViewcurSpeed(event);
}
}
/**
* 更新悬浮窗文本内容
*
* @param content
*/
private void updateFloatViewContent(String content)
{
if (displayView != null) {
TextView txtArea = (TextView) displayView.findViewById(R.id.txtArea);
txtArea.setText(content);
}
}
/**
* 更新悬浮窗的车速
*
* @param event
*/
private void updateFloatViewcurSpeed(AMapAreaInfoMessageEvent event)
{
ecurSpeed = Double.valueOf(event.getCurSpeed());
cameraSpeed = Double.valueOf(event.getCameraSpeed());
limitSpeed = Double.valueOf(event.getLimitedSpeed());
curSpeed = event.getCurSpeed();
if (displayView != null) {
TextView txtCcurSpeed = (TextView) displayView.findViewById(R.id.txtCurSpeed);
txtCcurSpeed.setText(curSpeed + " km/h");
TextView txtRoad = (TextView) displayView.findViewById(R.id.txtRoad);
if (cameraSpeed <= 0) {
cameraSpeed = limitSpeed;
}
proportion = (ecurSpeed - cameraSpeed) / cameraSpeed * 100;
String tempStr = event.getCurRoadName() + " 无限速 ";
txtCcurSpeed.setTextColor(Color.WHITE);
if (cameraSpeed > 0 && proportion < lowerLimit) {
txtCcurSpeed.setTextColor(Color.MAGENTA); //无测速
tempStr = event.getCurRoadName() + " 限速 " + cameraSpeed + "km/h ";
} else if (cameraSpeed > 0 && proportion >= lowerLimit) {
String num = String.format("%.0f", proportion);
tempStr = event.getCurRoadName() + " 限速 " + cameraSpeed + " km/h 已超速" + num + "%";
txtCcurSpeed.setTextColor(Color.RED); //有测速
}
txtRoad.setText(tempStr);
road = tempStr;
}
}
/**
* 接收悬浮窗设置变化
*
* @param event
*/
@Subscribe(threadMode = ThreadMode.MAIN)
public void updateFloatView(AMapFloatingWindowSettingsChangeMessageEvent event)
{
if (layoutParams != null && displayView != null) {
layoutParams.width = SharedPreUtil.getInteger("FLOATING_WINDOW_AMAP_AREA_CONTAINER_WIDTH", 424);
layoutParams.height = SharedPreUtil.getInteger("FLOATING_WINDOW_AMAP_AREA_CONTAINER_HEIGHT", 162);
layoutParams.x = SharedPreUtil.getInteger("FLOATING_WINDOW_AMAP_AREA_CONTAINER_X", 300);
layoutParams.y = SharedPreUtil.getInteger("FLOATING_WINDOW_AMAP_AREA_CONTAINER_Y", 300);
// GradientDrawable drawable = (GradientDrawable) displayView.getBackground();
// drawable.setColor(SharedPreUtil.getInteger("FLOATING_WINDOW_AMAP_AREA_CONTAINER_BACKGROUND_COLOR", Color.parseColor("#060E19")));
// displayView.setBackground(drawable);
//当前车速
TextView curSpeed = displayView.findViewById(R.id.txtCurSpeed);
curSpeed.setTextSize(SharedPreUtil.getInteger("FLOATING_WINDOW_AMAP_SD_FONT_SIZE", 40));
//
TextView txtArea = displayView.findViewById(R.id.txtArea);
txtArea.setTextSize(SharedPreUtil.getInteger("FLOATING_WINDOW_AMAP_AREA_FONT_SIZE", 20));
windowManager.updateViewLayout(displayView, layoutParams);
}
}
/**
* 隐藏悬浮窗
*/
private void hideFloatView()
{
if (displayView != null) {
windowManager.removeView(displayView);
}
}
//FloatShowEnableEvent
@Subscribe(threadMode = ThreadMode.MAIN)
public void onFloatShowEnableEvent(FloatShowEnableEvent event)
{
if (event.isEnable()) {
showFloatView();
} else {
hideFloatView();
}
}
@Override
public void onDestroy()
{
if (!EventBus.getDefault().isRegistered(this)) {
EventBus.getDefault().unregister(this);
}
unregisterReceiver();
stopSendAMapAreaInfoReceiverTask();
hideFloatView();
}
} 027rainguai 发表于 2024-2-22 09:38
必须可以,但是这个玩意是调用了高德的私有广播接口,不方便提供成品,大厂不敢搞它
:lol这个倒没问题的,我自己修改了高德6.5.5的渠道版本变成全功能版,然后询问过高德产品经理,产品经理说只要不拿来盈利,分享完全没问题,后来发到了高德车机官方论坛里,已经回帖30多页了,搜索引擎搜到的6.5.5修改版,就是我发布的:lol 027rainguai 发表于 2024-2-22 09:37
好像有成品吧,有个博主叫沉默,他搞过
是的,市面上的悬浮基本都是chemo大佬的,我就是想知道,除了地图包,还有没有其他要支持的,比如什么协议之类的,我是别克车型,直接用飞屏的包不成功,只有原厂的百度可以三指飞屏 这个!! 搞个HUD比这个好吧 有些车型方向盘遮挡仪表没发看见时速 导航时速又小很 不错 牛逼啊,自己动手,丰衣足食 怎么用啊?
这个不错 谢谢大佬 大佬江夏的啊, 我也是江夏的 cl19980429 发表于 2023-9-12 15:18
大佬江夏的啊, 我也是江夏的
嗯呢,江夏的。 楼主幸福安康,可惜不会用