解决百度地图在模拟器上运行报 java.lang.IllegalArgumentException: No config chosen问题

news2024/9/26 5:15:46

解决百度地图在模拟器上运行报 java.lang.IllegalArgumentException: No config chosen 问题

1. 问题复现

在近期公司使用模拟器(网易MuMu)进行项目演示时,在进入存在百度地图(Android版本 7.4.2版本)之后,页面出现奔溃,后台日志为:

Back traces starts.
java.lang.IllegalArgumentException: No config chosen
com.baidu.platform.comapi.map.h$a.chooseConfig(GLTextureView.java:655)
com.baidu.platform.comapi.map.h$e.a(GLTextureView.java:789)
com.baidu.platform.comapi.map.h$f.l(GLTextureView.java:1164)
com.baidu.platform.comapi.map.h$f.run(GLTextureView.java:1002)

2. 查找源码,定位问题

经过问题的复盘,找到了是位于源码位置报错的:

com.baidu.platform.comapi.map.h$a.chooseConfig(GLTextureView.java:655)

具体代码位置如下:

com.baidu.platform.comapi.map.h

类下面的一个抽象类 a ,实现了EGLConfigChooser 接口,在实现chooseConfig接口时报错:

private abstract class a implements EGLConfigChooser {
        protected int[] a;

        public a(int[] configSpec) {
            this.a = this.a(configSpec);
        }

        public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) {            
         		 // 代码省略... 
             EGLConfig config = this.a(egl, display, configs);
             if (config == null) {
                throw new IllegalArgumentException("No config chosen");
             } else {
                return config;
             }
        }
  	
      abstract EGLConfig a(EGL10 var1, EGLDisplay var2, EGLConfig[] var3);

}

我们可以看到 EGLConfig这个类是由a方法返回的,我们可以看到,当config==null 时,会直接报出异常IllegalArgumentException,那么我们可以查看一下这个抽象类a是由谁来集成的?

通过搜索源码,它的继承方式是这样的:

package com.baidu.platform.comapi.map;

public class h extends TextureView {
  
  private abstract class a implements EGLConfigChooser {
    
  }
  
  private class b extends com.baidu.platform.comapi.map.h.a {
        private int[] j = new int[1];
        protected int c;
        protected int d;
        protected int e;
        protected int f;
        protected int g;
        protected int h;

        public b(int redSize, int greenSize, int blueSize, int alphaSize, int depthSize, int stencilSize) {
            super(new int[]{12324, redSize, 12323, greenSize, 12322, blueSize, 12321, alphaSize, 12325, depthSize, 12326, stencilSize, 12344});
            this.c = redSize;
            this.d = greenSize;
            this.e = blueSize;
            this.f = alphaSize;
            this.g = depthSize;
            this.h = stencilSize;
        }

        public EGLConfig a(EGL10 egl, EGLDisplay display, EGLConfig[] configs) {
            EGLConfig[] var4 = configs;
            int var5 = configs.length;

            for(int var6 = 0; var6 < var5; ++var6) {
                EGLConfig config = var4[var6];
                int d = this.a(egl, display, config, 12325, 0);
                int s = this.a(egl, display, config, 12326, 0);
                if (d >= this.g && s >= this.h) {
                    int r = this.a(egl, display, config, 12324, 0);
                    int g = this.a(egl, display, config, 12323, 0);
                    int b = this.a(egl, display, config, 12322, 0);
                    int a = this.a(egl, display, config, 12321, 0);
                    if (r == this.c && g == this.d && b == this.e && a == this.f) {
                        return config;
                    }
                }
            }

            return null;
        }

        private int a(EGL10 egl, EGLDisplay display, EGLConfig config, int attribute, int defaultValue) {
            return egl.eglGetConfigAttrib(display, config, attribute, this.j) ? this.j[0] : defaultValue;
        }
  }
  
  private class i extends com.baidu.platform.comapi.map.h.b {
        public i(boolean withDepthBuffer) {
            super(8, 8, 8, 0, withDepthBuffer ? 16 : 0, 0);
        }
    }
  
}

综上所属,h下面的a,bi的关系为:

我们可以看到 h.c中其实没有a方法实现的,那么a方法的实现就是在h.b中了,我们可以来简单看一下h.b方法的实现:

        public EGLConfig a(EGL10 egl, EGLDisplay display, EGLConfig[] configs) {
            EGLConfig[] var4 = configs;
            int var5 = configs.length;

            for(int var6 = 0; var6 < var5; ++var6) {
                EGLConfig config = var4[var6];
                int d = this.a(egl, display, config, 12325, 0);
                int s = this.a(egl, display, config, 12326, 0);
                if (d >= this.g && s >= this.h) {
                    int r = this.a(egl, display, config, 12324, 0);
                    int g = this.a(egl, display, config, 12323, 0);
                    int b = this.a(egl, display, config, 12322, 0);
                    int a = this.a(egl, display, config, 12321, 0);
                    if (r == this.c && g == this.d && b == this.e && a == this.f) {
                        return config;
                    }
                }
            }

            return null;
        }

        private int a(EGL10 egl, EGLDisplay display, EGLConfig config, int attribute, int defaultValue) {
            return egl.eglGetConfigAttrib(display, config, attribute, this.j) ? this.j[0] : defaultValue;
        }

这里我们可以看到,当执行r == this.c && g == this.d && b == this.e && a == this.f为真时,才能返回对应的config对象,如果都不匹配,那么将会导致返回null·,今儿导致程序奔溃。问题找到了,我们应该怎么去改它呢?

3. 通过源码去修复它

我也不拐弯抹角了,经过对源码的分析,列举一下自己对这个问题修复的看法。首先,我们知道了问题所在的地方,那么我们是否在方法类b中的a方法永远不返回null,那样就不会导致出现No config chosen异常,虽然这种方法会导致所选择的EGLConfig和所需要的config不匹配,导致页面存在拉伸或者压缩的问题,但是这相比于奔溃,应该会好很多。那么就按照这个说的干吧。

首先,要修改返回值,使用它原有的逻辑肯定是不行的,但是我们返现这个 h.a抽象类实现的是 EGLConfigChooser,它是来自android.opengl.GLSurfaceView下的一个接口,比较熟悉openGL的人应该比较熟悉它:

    public interface EGLConfigChooser {
        /**
         * Choose a configuration from the list. Implementors typically
         * implement this method by calling
         * {@link EGL10#eglChooseConfig} and iterating through the results. Please consult the
         * EGL specification available from The Khronos Group to learn how to call eglChooseConfig.
         * @param egl the EGL10 for the current display.
         * @param display the current display.
         * @return the chosen configuration.
         */
        EGLConfig chooseConfig(EGL10 egl, EGLDisplay display);
    }

那我能不能自定义一下我们的h.ah.bh.i类呢,把源码拷一遍,然后把a方法返回值修改一下即可,好,那么说干就干:

h.a类如下:

public abstract class ParentEGLConfigChooser implements GLSurfaceView.EGLConfigChooser {

    protected int[] a;

    public ParentEGLConfigChooser(int[] configSpec) {
        this.a = this.a(configSpec);
    }

    public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) {
        int[] num_config = new int[1];
        if (!egl.eglChooseConfig(display, this.a, (EGLConfig[])null, 0, num_config)) {
            throw new IllegalArgumentException("eglChooseConfig failed");
        } else {
            int numConfigs = num_config[0];
            if (numConfigs <= 0) {
                throw new IllegalArgumentException("No configs match configSpec");

            } else {
                EGLConfig[] configs = new EGLConfig[numConfigs];
                if (!egl.eglChooseConfig(display, this.a, configs, numConfigs, num_config)) {
                    throw new IllegalArgumentException("eglChooseConfig#2 failed");
                } else {
                    EGLConfig config = this.a(egl, display, configs);
                    if (config == null) {
                        throw new IllegalArgumentException("No config chosen");
                    } else {
                        return config;
                    }
                }
            }
        }
    }

    abstract EGLConfig a(EGL10 var1, EGLDisplay var2, EGLConfig[] var3);


    private int[] a(int[] configSpec) {
        int len = configSpec.length;
        int[] newConfigSpec = new int[len + 2];

        System.arraycopy(configSpec, 0, newConfigSpec, 0, len - 1);
        newConfigSpec[len - 1] = 12352;
        newConfigSpec[len] = 4;
        newConfigSpec[len + 1] = 12344;
        return newConfigSpec;

    }

}

对于h.b类,我们可以实现如下:

public class SubEGLConfigChooser extends ParentEGLConfigChooser {

    private final int[] j = new int[1];
    protected int c;
    protected int d;
    protected int e;
    protected int f;
    protected int g;
    protected int h;

    public SubEGLConfigChooser(int redSize, int greenSize, int blueSize, int alphaSize, int depthSize, int stencilSize) {
        super(new int[]{12324, redSize, 12323, greenSize, 12322, blueSize, 12321, alphaSize, 12325, depthSize, 12326, stencilSize, 12344});
        this.c = redSize;
        this.d = greenSize;
        this.e = blueSize;
        this.f = alphaSize;
        this.g = depthSize;
        this.h = stencilSize;
    }

    public EGLConfig a(EGL10 egl, EGLDisplay display, EGLConfig[] configs) {

        BaseLog.i("----show the a------>>" + egl + "---->>" + display + "---->>" + Arrays.toString(configs));

        for (EGLConfig config : configs) {
            int d = this.a(egl, display, config, 12325);
            int s = this.a(egl, display, config, 12326);
            if (d >= this.g && s >= this.h) {
                int r = this.a(egl, display, config, 12324);
                int g = this.a(egl, display, config, 12323);
                int b = this.a(egl, display, config, 12322);
                int a = this.a(egl, display, config, 12321);
                if (r == this.c && g == this.d && b == this.e && a == this.f) {
                    return config;
                }
            }
        }

        //TODO 直接修改这里,返回第一个 configs[0], 暂时还未发现任何异常
        return configs[0];
    }

    private int a(EGL10 egl, EGLDisplay display, EGLConfig config, int attribute) {
        return egl.eglGetConfigAttrib(display, config, attribute, this.j) ? this.j[0] : 0;
    }
}

同样,对于h.i类,我们可以自定义类为:

public class TargetEGLConfigChooser extends SubEGLConfigChooser{
    
    public TargetEGLConfigChooser() {
        super(8, 8, 8, 0, 16 , 0);
    }
}

这三个类我们已经写好了,那么如何将我们的TargetEGLConfigChooser 替换成目标h.i方法呢?这个可能要花一些时间,我们来大致了解一下 BaiduMap的基础架构,我们以 TextureMapView为例子:

TextureMapView是继承自ViewGroup, 它有一个私有属性值b,其类型为MapTextureView, 属性bTextureMapView的初始化方法中被初始化:

MapTextureView中,首先它是继承自com.baidu.platform.comapi.map.h的:

同时,我们在h类中找到了h,h是一个EGLConfigChooser类型的接口,

在这里插入图片描述

通过程序分析, 那么这个h的实现类就是咋们的h.i. 主要问题分析完成了,那么就好做了,直接使用反射,将我们的h的实现类直接由h.i替换成我们的 TargetEGLConfigChooser即可,代码很简单,就几行:

public class TextureMapViewFix {

    public static void tryToFixException(TextureMapView mapView) {

        try {
            Field b = mapView.getClass().getDeclaredField("b");  // 找到b
            b.setAccessible(true);

            Object bObject = b.get(mapView);
            BaseLog.i("bObject = " + bObject);

            if (null == bObject) {
                BaseLog.i("bObject is null and return");
                return;
            }

            Field h = bObject.getClass().getSuperclass().getDeclaredField("h"); //找到其父类,然后查找子元素h
            h.setAccessible(true);

            Object aObject = h.get(bObject);
            BaseLog.i("aObject = " + aObject);

            h.set(bObject, new TargetEGLConfigChooser());  //替换成咋们自定义的目标类  TargetEGLConfigChooser
            
            Object aObject1 = h.get(bObject);
            BaseLog.i("aObject1 = " + aObject1);  //检查是否更新成功
            
        }catch (Exception e) {
            e.printStackTrace();
        }
    }
}

4. 总结

可能baidu地图的源码是混淆的,所以啃起来不是特别的顺利,还是耐着性子看完了,问题其实并不复杂,弄清楚逻辑就比较简单了,可能就是java的反射需要点功底,其它的都好说。如果有任何问题,可以add v:javainstalling,备注:baidu.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1396977.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

比吸收率(SAR)

本文旨在介绍比吸收率&#xff08;Specific Absorption Rate&#xff09;的基本知识。搬运自https://www.antenna-theory.com。英语够用的朋友可以直接移步。感谢网站创始人Peter Joseph Bevelacqua教授的无私奉献。 ------------------我是分隔线------------------- 比吸收…

Halcon 一维测量

文章目录 算子矩形算子弧形算子移动到新的参考点 Halcon 案例测量保险丝的宽度&#xff08;边缘对测量&#xff09;使用助手进行测量 halcon 案例获取芯片引脚的个数平均宽度距离&#xff0c;连续两个边缘的距离&#xff08;measure_pos &#xff09;halcon 定位测量Halcon 测量…

23 SEMC外扩SDRAM

文章目录 23.1 SDRAM 控制原理23.2 SEMC 简介 23.1 SDRAM 控制原理 RT1052 系列芯片扩展内存时可以选择 SRAM 和 SDRAM 由于 SDRAM 的“容量/价格”比较高&#xff0c;即使用 SDRAM 要比 SRAM 要划算得多。 给 RT1052 芯片扩展内存与给 PC 扩展内存的原理是一样的 PC 上一般…

庞伟:《一本书读懂企业破产法》——企业危机解决之道

在当今复杂多变的市场环境中&#xff0c;企业破产问题日益凸显。如何妥善解决企业危机&#xff0c;保障各方利益&#xff0c;成为了业界关注的焦点恰逢北京市亿达律师事务所成功入选第一届北京市破产管理人协会并成为会员单位之际&#xff0c;为此&#xff0c;北京市亿达律师事…

(2023版)斯坦福CS231n学习笔记:DL与CV教程 (56) | 卷积神经网络

前言 &#x1f4da; 笔记专栏&#xff1a;斯坦福CS231N&#xff1a;面向视觉识别的卷积神经网络&#xff08;23&#xff09;&#x1f517; 课程链接&#xff1a;https://www.bilibili.com/video/BV1xV411R7i5&#x1f4bb; CS231n: 深度学习计算机视觉&#xff08;2017&#xf…

多目标优化中常用的差分进化算法DE【2】

# 多目标优化中常用的进化算法 1、链接一 2、链接二 #后续继续补充多目标的差分进化算法MODE的应用 此链接介绍很详细&#xff0c;此处用来分享学习&#xff0c;后续有问题会继续进行补充。 如果你觉得不错&#xff0c;佛系随缘打赏&#xff0c;感谢&#xff0c;你的支持是…

(六)深入理解Bluez协议栈之“GATT Client Profile”

前言: 本章节我们继续介绍GATT Client Profile的实现,参考的程序是tools\btgatt-client.c,需要注意的一点,在./configure时,需要添加 --enable-test --enable-testing才会编译该c文件,编译完成后,生成的可执行程序为btgatt-client。本文主要以btgatt-client运行时可能会…

分布式ID(2):雪花算法生成ID

1 雪花算法简介 这种方案大致来说是一种以划分命名空间(UUID也算,由于比较常见,所以单独分析)来生成ID的一种算法,这种方案把64-bit分别划分成多段,分开来标示机器、时间等,比如在snowflake中的64-bit分别表示如下图(图片来自网络)所示: 41-bit的时间可以表示(1L&l…

ARM 1.16

TCP的特点 面向连接 面向连接&#xff0c;是指发送数据之前必须在两端建立连接。建立连接的方法是“三次握手”&#xff0c;这样能建立可靠的连接。建立连接&#xff0c;是为数据的可靠传输打下了基础。 仅支持单播传输 每条TCP传输连接只能有两个端点&#…

面试题16.15.珠玑妙算

前言 这两天突然发现力扣上还是有我能写出来的题的&#xff0c;虽说都是简单级别的&#xff08;以及一道中等的题&#xff09;&#xff0c;但是能写出来力扣真的太开心了&#xff0c;&#xff08;大佬把我这段话当个玩笑就行了&#xff09;&#xff0c;于是乎&#xff0c;我觉…

linux单机部署mysql(离线环境解压即可)

一、下载官网压缩包&#xff08;tar.gz&#xff09; MySQL :: Download MySQL Community Serverhttps://dev.mysql.com/downloads/mysql/根据自己的操作系统发行版本、位数、gclib版本、mysql版本来选择对应的压缩包 比如我是 linux系统debian10&#xff08;官网只有linux ge…

Doris配置外表以及多个Hive外表的配置

1.场景分析 以Clickhouse、Doris、Starrocks等为代表的mpp分析数据库正在快速的兴起&#xff0c;以其高效查询、跨库整合能力收到广大技术人员的喜爱。本文主要浅显介绍下作者在使用Doris时&#xff0c;通过建立catlog进行跨库查询。 废话不多少&#xff0c;直接上代码 2.相关…

RIP基础实验配置

要使用RIP完成以上命令需求 1&#xff0c;首先划分ip地址 有图可见有四个网段需要划分 192.168.1.0/26 192.168.3.0/26 192.168.7.0/26 192.168.5.0/26 给两个骨干网段&#xff0c;给两个环回接口&#xff0c;由下图所示&#xff1a; 其次&#xff0c;规划好ip后在各个接口…

hash应用

目录 一、位图 1.1、引出位图 1.2、位图的概念 1.3、位图的应用 1.4、位图模拟实现 二、布隆过滤器 2.1、什么是布隆过滤器 2.2、布隆过滤器应用的场景 2.3、布隆过滤器的原理 2.4、布隆过滤器的查找 2.5、布隆过滤器的插入 2.6、布隆过滤器的删除 2.7、布隆过滤器…

操作系统-操作系统的运行机制(内核程序 应用程序 特权指令 非特权指令 内核态 用户态 变态)

文章目录 总览预备知识&#xff1a;程序是如何运行的&#xff1f;内核程序vs应用程序特权指令vs非特权指令内核态vs用户态用户态&#xff0c;内核态的切换小结 总览 预备知识&#xff1a;程序是如何运行的&#xff1f; 转换为机器码放入内存&#xff0c;然后按顺序执行 内核…

跟着pink老师前端入门教程-day06

十一、CSS 的背景 通过CSS背景属性&#xff0c;可以给页面元素添加背景样式 背景属性可以设置背景颜色、背景图片、背景平铺、背景图片位置、背景图像固定等。 11.1 背景颜色 background-color 属性定义了元素的背景颜色 一般情况下元素背景颜色默认值是transparent&…

[足式机器人]Part2 Dr. CAN学习笔记- Kalman Filter卡尔曼滤波器Ch05-1+2

本文仅供学习使用 本文参考&#xff1a; B站&#xff1a;DR_CAN Dr. CAN学习笔记 - Kalman Filter卡尔曼滤波器 Ch05-12 1. Recursive Algirithm 递归算法2. Data Fusion 数据融合Covarince Matrix协方差矩阵State Space状态空间方程 Observation观测器 1. Recursive Algirithm…

[力扣 Hot100]Day7 接雨水

题目描述 给定 n 个非负整数表示每个宽度为 1 的柱子的高度图&#xff0c;计算按此排列的柱子&#xff0c;下雨之后能接多少雨水。 出处 思路 就是寻找“凹”形区间&#xff0c;找使得左右两端点为最大的两个值的最长区间。这里我分了两种情况&#xff0c;右边大于等于左边…

【前端设计】输入框

欢迎来到前端设计专栏&#xff0c;本专栏收藏了一些好看且实用的前端作品&#xff0c;使用简单的html、css语法打造创意有趣的作品&#xff0c;为网站加入更多高级创意的元素。 html <!DOCTYPE html> <html lang"en"> <head><meta charset&quo…

Message queue 消息队列--RabbitMQ 【基础入门】

一&#xff0c;Message queue介绍&#xff1a; 1.1使用消息队列的优点&#xff1a; 服务之间最常见的通信方式是直接调用彼此来通信,消息从一端发出后立即就可以达到另一端,称为即时消息通讯(同步通信) 消息从某一端发出后,首先进入一个容器进行临时存储,当达到某种条件后,再由…