项目场景:
车载项目,ATC8257-Android9.0系统平台,福田汽车P3系列项目
项目使用高德公版地图前提是无法获得任何高德定制服务,每次刷完机去切换语言系统会弹出"高德地图已停止运行"弹窗,严重影响用户使用体验
问题描述
项目使用高德公版地图前提是无法获得任何高德定制服务,每次刷完机去切换语言系统会弹出"高德地图已停止运行",但是刷完机先把高德打开一次再去切换语言就不会有这个问题,报错内容如下:
07-02 16:17:41.637 4482 4482 D AndroidRuntime: Shutting down VM
07-02 16:17:41.638 4482 4482 E AndroidRuntime: FATAL EXCEPTION: main
07-02 16:17:41.638 4482 4482 E AndroidRuntime: Process: com.autonavi.amapauto, PID: 4482
07-02 16:17:41.638 4482 4482 E AndroidRuntime: java.lang.UnsatisfiedLinkError: No implementation found for void com.autonavi.amapauto.utils.LanguageUtils.nativeNotifyLangChange(java.lang.String) (tried Java_com_autonavi_amapauto_utils_LanguageUtils_nativeNotifyLangChange and Java_com_autonavi_amapauto_utils_LanguageUtils_nativeNotifyLangChange__Ljava_lang_String_2)
07-02 16:17:41.638 4482 4482 E AndroidRuntime: at com.autonavi.amapauto.utils.LanguageUtils.nativeNotifyLangChange(Native Method)
07-02 16:17:41.638 4482 4482 E AndroidRuntime: at com.autonavi.amapauto.utils.LanguageUtils.notifyLanageChange(LanguageUtils.java:4)
07-02 16:17:41.638 4482 4482 E AndroidRuntime: at com.autonavi.amapauto.common.LanguageChangeReceiver.onReceive(LanguageChangeReceiver.java:4)
07-02 16:17:41.638 4482 4482 E AndroidRuntime: at android.app.ActivityThread.handleReceiver(ActivityThread.java:3410)
07-02 16:17:41.638 4482 4482 E AndroidRuntime: at android.app.ActivityThread.access$1300(ActivityThread.java:206)
07-02 16:17:41.638 4482 4482 E AndroidRuntime: at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1689)
07-02 16:17:41.638 4482 4482 E AndroidRuntime: at android.os.Handler.dispatchMessage(Handler.java:106)
07-02 16:17:41.638 4482 4482 E AndroidRuntime: at android.os.Looper.loop(Looper.java:193)
07-02 16:17:41.638 4482 4482 E AndroidRuntime: at android.app.ActivityThread.main(ActivityThread.java:6702)
07-02 16:17:41.638 4482 4482 E AndroidRuntime: at java.lang.reflect.Method.invoke(Native Method)
07-02 16:17:41.638 4482 4482 E AndroidRuntime: at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
07-02 16:17:41.638 4482 4482 E AndroidRuntime: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:994)
原因分析:
验证过刷完机先把高德打开一次再去切换语言就不会有这个问题,结合上面报错内容,分析是刷完机后高德接收语言切换的广播代码没有主动完成初始化,当系统切换语言的广播发送后高德无法处理导致弹出“高德地图已停止运行”弹窗。
解决方案:
授人以鱼不如授人以渔
1.既然出现这种系统弹窗,我思索的是能不能在系统里面把高德包名过滤掉,弹窗的地方先获取包名是高德包名就return,有了这种思路后第一步还是借助万能网络,很自然就搜到这篇CSDN博客
屏蔽弹出停止运行对话框
修改位置:frameworks\base\services\core\java\com\android\server\am\AppErrors.java
这篇博客给出了修改方法,但是并没有说在具体哪个代码块里面改,我们通过里面的mService.killAppAtUsersRequest(proc, null)这行代码去AppErrors.java里面搜索,发现handleShowAnrUi方法里面有一处,按照博客的方法这样加
void handleShowAnrUi(Message msg) {
Slog.w(TAG, "------------------handleShowAnrUi");
Dialog dialogToShow = null;
synchronized (mService) {
//此处省略部分系统代码
if(dialogToShow != null){// For don't show gaode-map <Stop running> dialog
Slog.w(TAG, "------------------handleShowAnrUi ");
if(proc != null && proc.info.packageName.equals("com.autonavi.amapauto")){
Slog.w(TAG, "------------------Current app is gaode map, don't show <Stop running> dialog");
dialogToShow = null;
// Just kill the app if there is no dialog to be shown.
mService.killAppAtUsersRequest(proc, null);
}
}
}
// If we've created a crash dialog, show it without the lock held
if (dialogToShow != null) {
dialogToShow.show();
}
}
从上面博客里知道修改的位置是frameworks\base\services\core\java\com\android\server\am\AppErrors.java,修改后我们可以在Android目录下单编这个模块
android$ mmm frameworks/base/services
编译好后去out/target/product/ac8257_demo/system/framework/目录里面找services.jar,然后推到机器system/framework/下面替换原来的,reboot后执行切换语言高德仍然弹窗报错,查看我们加在handleShowAnrUi方法里面的打印没走,但是看另一条打印
01-01 08:01:01.931 589 748 I AppErrors: Showing crash dialog for package com.autonavi.amapauto u0
2.照例去AppErrors.java里面搜关键字,发现这条打印在handleShowAppErrorUi方法里面,遂在该方法里面添加代码如下
void handleShowAppErrorUi(Message msg) {
AppErrorDialog.Data data = (AppErrorDialog.Data) msg.obj;
boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
AppErrorDialog dialogToShow = null;
final String packageName;
final int userId;
synchronized (mService) {
//此处省略部分系统代码
if(dialogToShow != null){// For don't show gaode-map <Stop running> dialog
Slog.w(TAG, "handleShowAppErrorUi ------------------");
if(proc != null && proc.info.packageName.equals("com.autonavi.amapauto")){
Slog.w(TAG, "Current app is gaode map, don't show <Stop running> dialog ------------------");
dialogToShow = null;
// Just kill the app if there is no dialog to be shown.
mService.killAppAtUsersRequest(proc, null);
}
}
}
// If we've created a crash dialog, show it without the lock held
if (dialogToShow != null) {
Slog.i(TAG, "Showing crash dialog for package " + packageName + " u" + userId);
dialogToShow.show();
}
}
执行单编services.jar后推到机器,重启切换语言没有"高德地图已停止运行"弹窗了
3.后面考虑到高德地图用的公版,如果出现anr我们也得不到任何支援,所以把handleShowAnrUi和handleShowAppErrorUi两处屏蔽高德报错弹窗的代码都保留了,复盘方法名handleShowAnrUi明显就是应用出现anr时弹窗的位置。
总结:
絮絮叨叨的写这么多,实际是想更详尽的说明我解决问题的思路,套用前辈的一句话——编程是一种思维,编程思维需要慢慢培养。
所以我的博客都会详细的说明我的解决过程,过程中遇到了那些问题,遇到问题要怎么转换思路,大概如是……
-----------------------毕竟授人以鱼不如授人以渔。