移动感知终端软件发布过程中遇到的问题以及解决方案

一.软件发布

软件的效果展示在文章:

网络图谱构建系统目前已实现的功能-CSDN博客

在android studio编写完程序之后,要打包并发布软件,供其他用户使用,以下几篇文章给出了方法:

Android Studio使用签名打包发布APP(安卓生成apk文件)_generate signed bundle or apk-CSDN博客

Android Studio 打包APK(详细版)_as打包apk-CSDN博客

二.安装后初次打开设备信息显示不全

软件在手机安装之后,首先询问权限,当权限全部允许之后,点击顶部菜单栏按钮,在滑动菜单中

并没有显示全设备信息,博主查看了该部分代码:

 //设备信息与网络信息提取
    private void getDeviceInfo() {
        // 设备运营商名称
        networkOperatorName = telephonyManager.getNetworkOperatorName();
 
 
        // 设备品牌
        deviceBrand = android.os.Build.BRAND;
 
 
        // 设备型号
        deviceModel = android.os.Build.MODEL;
 
        // SIM卡国别
        simCountry = telephonyManager.getSimCountryIso();
 
 
        // SIM卡当前状态
        deviceStatus = telephonyManager.getSimState() == TelephonyManager.SIM_STATE_READY ? "Ready" : "Not Ready";
   
 
     // 网络类型
        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) {
            // TODO: Consider calling
            //    ActivityCompat#requestPermissions
            // here to request the missing permissions, and then overriding
            //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
            //                                          int[] grantResults)
            // to handle the case where the user grants the permission. See the documentation
            // for ActivityCompat#requestPermissions for more details.
            return;
        }
 
 
        NetworkType = telephonyManager.getNetworkType();
        switch (NetworkType) {
            case TelephonyManager.NETWORK_TYPE_GPRS:
            case TelephonyManager.NETWORK_TYPE_EDGE:
            case TelephonyManager.NETWORK_TYPE_CDMA:
            case TelephonyManager.NETWORK_TYPE_1xRTT:
            case TelephonyManager.NETWORK_TYPE_IDEN:
                networkType = "2G";
                break;
            case TelephonyManager.NETWORK_TYPE_UMTS:
            case TelephonyManager.NETWORK_TYPE_EVDO_0:
            case TelephonyManager.NETWORK_TYPE_EVDO_A:
            case TelephonyManager.NETWORK_TYPE_HSDPA:
            case TelephonyManager.NETWORK_TYPE_HSUPA:
            case TelephonyManager.NETWORK_TYPE_HSPA:
            case TelephonyManager.NETWORK_TYPE_EVDO_B:
            case TelephonyManager.NETWORK_TYPE_EHRPD:
            case TelephonyManager.NETWORK_TYPE_HSPAP:
                networkType = "3G";
                break;
            case TelephonyManager.NETWORK_TYPE_LTE:
                networkType = "4G";
                break;
            case TelephonyManager.NETWORK_TYPE_NR:
                networkType = "5G";
            default:
                networkType = "未知";
                break;
        }
 
}

发现只有网络类型没有显示出来,又去onCreate中查看了权限询问代码和显示设备信息的代码:

 
        //判断单个权限是否已经允许
        if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            permissionList.add(Manifest.permission.ACCESS_FINE_LOCATION);
 
        }
 
        if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) {
            permissionList.add(Manifest.permission.READ_PHONE_STATE);
        }
 
//        NetworkType = telephonyManager.getNetworkType();
 
        if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
            permissionList.add(Manifest.permission.READ_EXTERNAL_STORAGE);
        }
 
        if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.ACTIVITY_RECOGNITION) != PackageManager.PERMISSION_GRANTED) {
            permissionList.add(Manifest.permission.ACTIVITY_RECOGNITION);
        }
 
        if (!permissionList.isEmpty()) {
            String[] permissions = permissionList.toArray(new String[permissionList.size()]);
            ActivityCompat.requestPermissions(MainActivity.this, permissions, 1);
 
        } else {
            requestLocation();      //请求位置信息
        }
 
 
 
    //获取设备信息
        getDeviceInfo();
 
 
 
        //刷新设备信息
        ShowEquipMessage.setText("运营商名称: " + networkOperatorName + '\n' + "设备品牌名称: " + deviceBrand + '\n' + "设备型号: " + deviceModel
                + '\n' + "网络类型: " + networkType + '\n' + "SIM卡国别: " + simCountry + '\n' + "SIM卡当前状态: " + deviceStatus);

按照代码中调用的顺序,感觉很合理,首先询问权限,然后获取设备信息,最后打印在控件中,但是就是没有显示网络类型,博主猜测可能与获取网络类型信息之前的权限验证有关,如何解决这个问题呢,博主在网络上看到有文章提到在询问权限的弹窗出来之后,活动实际上已经失去焦点,进入Pause状态,当通过所有权限,弹窗消失之后,活动调用onResume函数恢复焦点。

那么如果在onResume()中再次刷新一次设备信息,也就是让权限询问结束后再刷新一次设备信息,是否就能让网络类型显示出来呢?

    @Override
    protected void onResume() {
        super.onResume();
        //获取设备信息
        getDeviceInfo();
 
        //刷新设备信息
        ShowEquipMessage.setText("运营商名称: " + networkOperatorName + '\n' + "设备品牌名称: " + deviceBrand + '\n' + "设备型号: " + deviceModel
                + '\n' + "网络类型: " + networkType + '\n' + "SIM卡国别: " + simCountry + '\n' + "SIM卡当前状态: " + deviceStatus);
     
 
        mMapView.onResume();
    }

运行之后果然网络类型可以显示出来了。

三.启动软件后定位到经纬度都是0的地区

软件安装到手机之后,通过各种权限后,发现定位到了几内亚湾,也就是经纬度都是0的地方,卡片上显示的经纬度都是0,也就是没获取到正确地理坐标,但是过一会之后,正确的地理坐标就传过来了,这中间的时间有长有短,如图:

作者以为是软件启动后获取到定位信息比较慢,可能是编写定位函数时忘写了什么,导致百度地图SDK没有被及时调用。但是无论怎样修改代码也还是这个问题。

在最开始编写百度地图定位功能时,为了测试结果,博主让定位结果返回码打印到日志中:

     int locType = location.getLocType();
     Log.d("定位结果返回码", String.valueOf(locType));

博主偶然看到定位结果返回码在软件刚启动时返回的是505,然后过一会才是61。

按照百度地图提供的表:

返回值 定位类型 详细说明
61 卫星定位结果 卫星定位成功
62 定位失败 无法获取有效定位依据,请检查运营商网络或者WiFi网络是否正常开启,尝试重新请求定位
63 网络异常 没有成功向服务器发起请求,请确认当前测试手机网络是否通畅,尝试重新请求定位
66 离线定位结果 通过requestOfflineLocaiton调用时对应的返回结果
67 离线定位失败  
161 网络定位结果 网络定位成功
162 请求串密文解析失败 一般是由于客户端SO文件加载失败造成,请严格参照开发指南或demo开发,放入对应SO文件
167 服务端定位失败 请您检查是否禁用获取位置信息权限,尝试重新请求定位
505 AK不存在或者非法 请按照说明文档重新申请AK
69 定位开关未打开 定位失败,请检查定位服务开关是否打开
70 无定位权限 定位失败,请检查是否授予定位权限
71 定位开关未打开且无定位权限 定位失败,请检查定位服务开关是否打开,以及是否授予定位权限

发现505是AK的问题,但是我已经申请过了AK,忽然想到申请AK时,填写的SHA1分为开发版SHA1和发布版SHA1 ,当时两个填写的都一样,我现在打包成发布版软件,应该是发布版的SHA1出了问题,按照文章:

Android Studio获取开发版SHA1和发布版SHA1_如何在android studio获取开发版sha1-CSDN博客

的指引获取到了发布版SHA1,重新填到AK配置中,再次运行软件,启动后就定位成功。

四.部分类型手机闪退问题

出现在真我、荣耀等手机上,真机调试报错:

Caused by: java.lang.IllegalStateException: This Activity already has an action bar supplied by the window decor. Do not request Window.FEATURE_SUPPORT_ACTION_BAR and set windowActionBar to false in your theme to use a Toolbar instead.

原因以及解决方法见文章:

java.lang.IllegalStateException: This Activity already has an action bar supplied by the window decor. Do not request Window.FEATURE_SUPPORT_ACTION_BAR and set windowActionBar to false in your theme t - leihupqrst - 博客园 (cnblogs.com)

五.5G网络信号强度获取不到的问题

4G网络信号强度获取方法:

 Method[] methods = android.telephony.SignalStrength.class.getMethods();
            for (Method mthd : methods) {
                //4G信号强度获取
//                System.out.println("类型都有: "+mthd.getName());
                if (mthd.getName().equals(LTE_SIGNAL_STRENGTH)) {
                    Object result = mthd.invoke(signalStrength);
                    if (result instanceof List) {
                        List<?> signalStrengthList = (List<?>) result;
                        for (Object obj : signalStrengthList) {
                            //如果是4G类型
                            if (obj instanceof android.telephony.CellSignalStrengthLte) {
                                android.telephony.CellSignalStrengthLte lteSignalStrength = (android.telephony.CellSignalStrengthLte) obj;
 
                                Method getRsrpMethod = lteSignalStrength.getClass().getMethod("getRsrp");
                                rsrpValue = (int) getRsrpMethod.invoke(lteSignalStrength);
                                ShowCellSignalStrength.setText(rsrpValue+"dBm");
 
                            }
                    }
            }
        }
    }
通过反射获取到getRsrp()方法,来获取网络信号强度。

但是5G不行,Android 中用于表示5G NR网络信号强度的类CellSignalStrengthNr中并没有getRsrp()方法。

查找android开发文档:

[CellSignalStrengthNr Android Developers](https://developer.android.com/reference/android/telephony/CellSignalStrengthNr)

找到一个 getDbm()方法

反射获取getDbm()方法,即可提取5G网络信号强度。