吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 2692|回复: 38
收起左侧

[Java 原创] 导航协议实现导航时悬浮显示车速

[复制链接]
027rainguai 发表于 2023-9-12 14:04
背景
某导航巡航时才能悬浮车速,导航时是不能悬浮车速的。本人不太喜欢全屏导航,因此就写了个app自己用。
原始巡航图,带车速的。
1694498299475.png
,本来导航要是有这个车速就很好,可惜官方没有。那就自己动手咯。
643780a2344c5a35c4d8d9098f3a389.jpg

8f31b5d3e05dd27886e38f2a67748c7.jpg

目前软件已开车实测500公里,无闪退问题。下面贴下核心代码。


[Java] 纯文本查看 复制代码


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);//再进行监听
    }

    /**
     * 请求高德行政区域信息
     *
     * [url=home.php?mod=space&uid=952169]@Param[/url] 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();
    }
}

免费评分

参与人数 7吾爱币 +13 热心值 +6 收起 理由
junjia215 + 1 + 1 用心讨论,共获提升!
boy2918 + 1 + 1 用心讨论,共获提升!
wystudio + 2 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
wushaominkk + 7 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
SZnA1 + 1 很棒的工具
skiss + 1 + 1 谢谢@Thanks!
wuming4 + 1 用心讨论,共获提升!

查看全部评分

本帖被以下淘专辑推荐:

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

woshilizibenren 发表于 2024-3-28 08:51
027rainguai 发表于 2024-2-22 09:38
必须可以,但是这个玩意是调用了高德的私有广播接口,不方便提供成品,大厂不敢搞它

这个倒没问题的,我自己修改了高德6.5.5的渠道版本变成全功能版,然后询问过高德产品经理,产品经理说只要不拿来盈利,分享完全没问题,后来发到了高德车机官方论坛里,已经回帖30多页了,搜索引擎搜到的6.5.5修改版,就是我发布的
梦毁他城 发表于 2024-2-23 12:39
027rainguai 发表于 2024-2-22 09:37
好像有成品吧,有个博主叫沉默,他搞过

是的,市面上的悬浮基本都是chemo大佬的,我就是想知道,除了地图包,还有没有其他要支持的,比如什么协议之类的,我是别克车型,直接用飞屏的包不成功,只有原厂的百度可以三指飞屏
Kls673M 发表于 2023-9-12 14:19
to0716 发表于 2023-9-12 14:22
  有些车型方向盘遮挡仪表没发看见时速      导航时速又小很   不错
smaxlyb 发表于 2023-9-12 14:33
牛逼啊,自己动手,丰衣足食
huaibeilifei 发表于 2023-9-12 14:55
怎么用啊?
ouzhenwei 发表于 2023-9-12 14:55
这个不错
Wapj0018 发表于 2023-9-12 15:17
谢谢大佬
cl19980429 发表于 2023-9-12 15:18
大佬江夏的啊, 我也是江夏的

免费评分

参与人数 1吾爱币 -8 收起 理由
wushaominkk -8 请勿灌水,提高回帖质量是每位会员应尽的义务!

查看全部评分

 楼主| 027rainguai 发表于 2023-9-12 15:27
cl19980429 发表于 2023-9-12 15:18
大佬江夏的啊, 我也是江夏的

嗯呢,江夏的。
熊猫咖啡 发表于 2023-9-12 18:25
楼主幸福安康,可惜不会用
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则 警告:本版块禁止灌水或回复与主题无关内容,违者重罚!

快速回复 收藏帖子 返回列表 搜索

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-4-30 04:11

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表