关于Android加快应用崩溃效率

Unity安卓无线调试实战:告别数据线,提升开发效率 Android Debug Bridge(ADB)是连接开发机与安卓设备的核心调试工具,它通过客户端-服务器架构实现命令交互与文件传输。传统USB调试依赖物理连接,而无线调试则利用TCP/IP协议,让ADB通过网络与设备通信,其技术价值在于摆脱线缆束缚,实现快速部署与实时调试。在游戏开发、应用测试等高频迭代场景中,无线调试能显著提升开发效率,尤其适用于UI调整与逻辑验证。本文聚焦于Unity引擎下的安卓开发环境,详细解析如何配置ADB无线连接,并针对夜神模拟器等常见平台,提供从原理到实践的完整解决方案,涵盖 阅读详情

关于Android加快应用崩溃效率

解决问题:Android应用崩溃后出现ANR

应用上线前遇到问题,在应用崩溃后发生了ANR,而且发生ANR的就是本来已经崩溃的应用。由于本次ANR发生在集成了新的crash日志手机模块,在经过过甩锅–打脸的流程后开始认真分析ANR的原因。
崩溃日志收集代码如下:

class MyApplication: Application {

    override fun onCreate() {
        super.onCreate()
        /** 
         * 经过分析发现在集成的sdk中也包含
         * Thread.setDefaultUncaughtExceptionHandler()代码,
         * 三方SDK也有手机崩溃日志的习惯。
         * 而本次更新的就是我“优化”过的CrashHandler3
         */
        Thread.setDefaultUncaughtExceptionHandler(CrashHandler1())
        Thread.setDefaultUncaughtExceptionHandler(CrashHandler2())
        Thread.setDefaultUncaughtExceptionHandler(CrashHandler3(this))

        sendCrashLogFileToServer()
    }

}

/** 
 * "优化"过的CrashHandler3
 * 逻辑很简单,判断此次崩溃有没有Throwable对象:
 * 有,就有本地处理,处理完3秒后结束进程;
 * 没有,就使用系统的崩溃日志收集
 */
CrashHandler3(var context: Context): 
Thread.UncaughtExceptionHandler {

    private var defaultCrashHandler: UncaughtExceptionHandler
    init {
        defaultCrashHandler = Thread.getDefaultUncaughtExceptionHandler()
    }
    override fun uncaughtException(t: Thread?, e: Throwable?) {

        if (!handlerExcception(e)) {
            defaultCrashHandler.uncaughtException(t, e)
        } else {
            try {
                Thread.sleep(3000)
            } catch (e: Exception?) {
                e?.printStackTrace()
            }
            android.os.Process.killProcess(android.os.Process.myPid())
            System.exit(1)
        }
        
    }


    private fun handlerException(e: Throwable?): Boolean {
        if (e == null) {
            return false
        } else {
            // TODO 显示Toast
            Handler(Looper.getMainLooper()).post {
                Toast.makeText(context, "应用崩溃", Toast.LENGTH_SHORT).show()
            }
            // TODO 从线程池中拿一个线程,来保存奔溃日志到文件
            saveCrashLogIntoFileWithThreadInThreadpool(e)
            return true
        }
    }
}

经过一宿的尝试,最终发现了问题在override fun uncaughtException(t: Thread?, e: Throwable?)方法上。

首先,查看Thread.setDefaultUncaughtExceptionHandler方法源码:

public class Thread implements Runnable {

    // other code ...


    private static volatile UncaughtExceptionHandler defaultUncaughtExceptionHandler;

    public static void setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler eh) {
        defaultUncaughtExceptionHandler = eh; 
    }

    public static UncaughtExceptionHandler getDefaultUncaughtExceptionHandler(){
        return defaultUncaughtExceptionHandler;
    }


    public interface UncaughtExceptionHandler {
        void uncaughtException(Thread t, Throwable e);
    }


     // other code ...
}

代码很明显的表示了CrashHandler保存在一个静态变量defaultUncaughtExceptionHandler里,每次调用setDefaultUncaughtExceptionHandler都会更新静态变量defaultUncaughtExceptionHandler,而在应用里有:

Thread.setDefaultUncaughtExceptionHandler(CrashHandler1())
Thread.setDefaultUncaughtExceptionHandler(CrashHandler2())
Thread.setDefaultUncaughtExceptionHandler(CrashHandler3(this))

最终确实CrashHandler1与CrashHandler2都能够执行,这是因为别人家的CrashHandler代码是这样:

class CrashHandler: Thread.UncaughtExceptionHandler {

    /** 
     * 定义UncaughtExceptionHandler类型的变量,用来保存当前线程的defaultCrashHandler,以后会用
     */
    private var defaultCrashHandler: UncaughtExceptionHandler
    init {
        defaultCrashHandler = Thread.getDefaultUncaughtExceptionHandler()
    }

    override fun uncaughtException(t: Thread?, e: Throwable?) {
        // custom handle crash exception

        handleException(e)

        /** 
         * 这里是关键点
         * 因为在初始化自定义的CrashHandler前,
         * 保存了上次setDefaultUncaughtExceptionHandler后的defaultCrashHandler值
         * 自定义处理完CrashException后,在defaultCrashHandler不为null的情况下,
         * 调用上一个defaultCrashHandler的uncaughtException方法
         * 这样就不会影响其他三方sdk的CrashHandler的逻辑。
         * 而且,最关键的是,如果不主动调用defaultCrashHandler.uncaughtException(t, e),
         * Android应用就会出现ANR
         */
        if (defaultCrashHandler != null) {
            defaultCrashHandler.uncaughtException(t, e)
        } else {
            try {
                Thread.sleep(3000)
            } catch (e: Exception?) {
                e?.printStackTrace()
            }
            android.os.Process.killProcess(android.os.Process.myPid())
            System.exit(1)
        }

    }
}

还有一个关键点, volatile字段的使用方法:
假如有代码:

private int i = 301;
i = 302;
i = 304;

编译器在编译代码时会做代码优化,发现如上代码最终编译后的代码会变成:

private int i = 304;

即,直接赋最终值。

但是如果使用volatile字段来修饰:

private volatile int i = 301;
i = 302;
i = 304;

编译器不会最任何优化,编译后的代码依旧是:

private volatile int i = 301;
i = 302;
i = 304;

总结,volatile字段修饰的变量,保证了变量操作的原子性。
volatile字段还有一个特性,即可见性,
例如有变量:

private volatile int i = 301;

有线程A在启动,在无限循环中不断输出变量i,
然后执行 i++操作,此时i的值应该为302,
而线程A输出的只也会变为302,
如果变量不加volatile字段,则线程A会一直输出301。
不使用volatile字段的变量,CPU在运行代码时,会先将变量从内存读取到CPU cache,然后每次读取用CPU cache中的值
使用volatile字段的变量,CPU在运行代码时,会先将变量从内存读取变量直接运行

Unity安卓构建R8强制启用:从原理到实战配置与优化指南 代码压缩与混淆是移动应用发布前的关键技术环节,旨在减小应用体积并保护代码逻辑。其核心原理是通过静态分析移除未使用的类、方法和字段,并对剩余代码标识符进行重命名。在Android生态中,这一任务经历了从ProGuard到R8的演进。R8作为官方替代方案,通过深度集成至构建系统并直接处理DEX字节码,实现了更快的编译速度和更优的代码优化效果,技术价值在于显著提升开发效率与发布应用质量。在Unity引擎的安卓应用开发场景中,构建流程最终由Gradle和Android Gradle Plugin接管,R8在此扮演了 阅读详情

相关推荐

Bugtags:提升Android应用测试效率的工具

在应用程序的测试和运维过程中,日志是不可或缺的资源,它可以提供关于应用程序运行状态的详细信息。自定义日志收集规则允许开发者和测试人员精确地定义哪些日志信息应当被捕捉并发送到Bugtags服务器。这些规则可以指定日志级别、关键词、日志标签等条件,以过滤出需要关注的日志信息。例如,可以设置规则来捕捉所有的错误和警告,或者只捕捉包含特定错误代码的日志条目。

weixin_42611177的博客 1045

getResources().getDimension引起的问题

getDimension()会自动把数值解析成xp单位,因为view的宽高本来接受的就是xp,所以不会变化,但是 setTextSize接受的单位默认是sp。相当于getDimension()把sp转成xp,会放大,setTextSize又会将转换后的值变成xp,又放大了。想着应该没问题吧,结果动态代设置的字体比xml中设置的大很多,而宽高确没变化。

xueyoubangbang的博客 375

为Windows 7 64位优化的Notepad++安卓日志工具包

本文还有配套的精品资源,点击获取 简介:本工具包专为Windows 7 64位操作系统用户设计,集成了用于Android日志记录的特定功能,并预配置了Notepad++编辑器。下载解压后即可直接使用,无需复杂设置。工具包内含NppLogcat等插件,可以与Android Debug Bridge(adb)集成,实现Logcat日志的实时查看与过滤,极大提升Android开发...

weixin_28746457的博客 1694

踩坑系列之---getIdentifier

int id=mContext.getResources().getIdentifier(item.getModelImg(),"mipmap",mContext.getPackageName()); 根据本地图片的名字,获取资源id,本以为会很爽,然而,打包发布后,我查,没有获取到图片,尼玛,啥情况?没打包之前,运行毫无问题,打包之后就有问题了,这时还无疑问和混淆配置有关啦! shr...

知识共享,你我皆是知识的搬运工 2703

避坑指南:PyCINRAD处理CINRAD雷达数据时遇到的5个典型报错及解决方案

本文针对使用PyCINRAD库处理CINRAD雷达基数据时常见的5个典型报错,提供了详细的解决方案。内容涵盖环境配置、数据读取、PPI可视化及性能优化等核心环节,重点解决了版本兼容性、数据异常处理和中文乱码等实际问题,帮助用户高效处理雷达基数据并生成准确的PPI图像。

cc789的博客 1068

华为硬件逻辑岗笔试题(一)

积少成多,集腋成裘,坚持!!! 目录 1. 进制转换 2. 状态机和编码方式 3. 存储器的分类 4. Verilog语法中的操作符 5. 对组合逻辑的认识 6. 对时序逻辑的认识 7. 竞争冒险的认识 8. 基本时序逻辑电路 9. 建立时间和保持时间 10. 同步时序电路 11. 组合逻辑和时序逻辑判断 13. 基本总线的理解 14.加法器 15.FPGA开发工具 1. 进制转换 1、十进制46.25对应的二进制表达式为( )。 A 101110.11...

qq_42235129的博客 1万+

使用getIdentifier()获取资源Id

使用getIdentifier()方法可以方便的获各应用包下的指定资源ID。 主要有两种方法: (1)方式一 Resources resources = context.getResources(); int indentify = resources.getIdentifier(org.loveandroid.androidtest:drawable/icon",null,null);

叶园 5万+

MCGS触摸屏Modbus TCP通讯实战:从寄存器写入到字符串处理的完整代码解析

本文详细解析了MCGS触摸屏通过Modbus TCP协议实现寄存器写入和字符串处理的完整代码,涵盖单寄存器写入、多寄存器写入及字符串传输等核心技术。文章还提供了MCGS组态环境中的实战配置步骤和常见问题排查方法,帮助开发者快速掌握工业自动化通讯的关键技术。

study的专栏 755

Android防止应用崩溃

原文https://www.jianshu.com/p/01b69d91a3a8 1 什么是Crash Crash,即闪退,多指在移动设备(如iOS、Android设备)中,在打开应用程序时出现的突然退出中断的情况(类似于Windows的应用程序崩溃)。 2 Crash的成本 假设公司安卓端的日活是20万(对于很多公司来说,要远远...

BeyondWorlds的专栏 6012

codesys【modbusRTU】主站

【代码】modbusRTU【codesys】

cfqq1989的博客 4371

Prokka实战:10分钟搞定细菌基因组注释(附详细参数解析)

本文深入解析Prokka细菌基因组注释工具的核心参数与实战策略。通过拆解其集成化工作流程,详细解读物种分类、功能注释、输出控制等关键参数,并提供快速初筛、高质量发表、质粒注释及批量处理四种典型场景的高效参数组合方案,帮助用户精准掌控注释过程,将原始序列转化为有价值的生物学见解。

weixin_29271053的博客 442

常见问题解决方案:Android Lite Go项目

常见问题解决方案:Android Lite Go项目 项目基础介绍与主要编程语言 Android Lite Go 是一个致力于为Android平台提供轻量级、高效率的基础库集合。该项目旨在解决常规Android应用在体积、运行效率等方面的挑战。通过该项目,开发者可以快速集成轻量级的库,来优化自己应用的性能和体积。该项目主要使用Java和Kotlin语言编写,并且遵循Android开发标准。 新手使...

gitblog_00116的博客 662

Spring AI 实战:第五章、Spring AI本地模型部署之省钱小能手

白嫖的快乐你想象不到经过这番折腾,我们成功实现了零成本使用大模型完全本地运行保障隐私可视化访问Java生态无缝集成但可能有的小伙伴要吐槽,怎么换个底层模型这次就新建一个工程了呢?不能在以前的工程上开发吗?这样也太不优雅了吧~,我知道你很急,但先别急,等下一章节再来解决这个问题。为什么程序员特别喜欢Ollama?因为它就像一只温顺的羊驼——不花钱还能24小时产出代码!

liaokailin的专栏 922

关于Android的效率(转)

<br />Android系统框架和上层应用是类java(不是正统的sun java)开发的,实现了自己的java虚拟机dalvik,既然用java虚拟机和java开发,一般都会认为效率低下。其实不然,在基本主流的智能手 机的软件平台上,android的执行速度是最快的。<br /><br />那么Android效率为什么这么的高呢?特别是一个应用程序的启动时间很短,本文主要从以下个八方面进行分析:<br /><br />1、 资源文件的优化读取。<br /><br />我们知道Android在UI开发时有

1686

基于DO-178C/331的飞控软件研发环境的研究

本研究提出了一套基于DO-178C/331标准的飞控系统软件开发和验证框架。通过优化模型库的设计、代码生成配置和测试验证流程,显著提升了飞控系统软件的开发效率和安全性。未来的研究可以进一步扩展模型库的功能,以适应更复杂的飞控系统需求。

qq_41854911的博客 561

关于如何在matlab中导入并翻译Hypemesh导出的大型刚度矩阵txt文本

如何将它翻译成matlab可以使用的矩阵变量,并参与运算。 由于这个大型刚度矩阵125万x125万≈1e12。matlab甚至其他计算软件无法保存这个大的一个矩阵文件。而这个刚度矩阵作为稀疏矩阵其中非零元素的数目只有有500多万。采用sparse稀疏矩阵技术是可以保存。 这里简单介绍一下这个Hypemesh导出的大型刚度矩阵txt文本。如图DMIG开头的标识符是换行符,后面两列是表示这条非零元素在刚度矩阵中列数的信息。我们已经将左边字母和符号等批量删除,得到了右边textread函数可以...

wenyusuran的专栏 1795

Windows 11安卓应用运行指南:WSA开发者资源全解析

想在Windows 11电脑上流畅运行安卓应用吗?Windows Subsystem for Android(WSA)为开发者提供了强大的跨平台解决方案,让你可以在电脑上直接调试和运行安卓应用。本文将为你详细介绍如何利用WSA开发者资源,从安装配置到高级调试技巧,帮助你快速上手这一革命性技术。 ## 🚀 快速入门:搭建WSA开发环境 ### 系统要求检查 在开始之前,请确保你的系统满足以下

gitblog_00291的博客 215

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

那么android效率为什么这么的高呢

<br /><br />ndroid系统框架和上层应用是类java(不是正统的sun java)开发的,实现了自己的java虚拟机dalvik,既然用java虚拟机和java开发,一般都会认为效率低下。其实不然,在基本主流的智能手 机的软件平台上,android的执行速度是最快的。 <br /><br />       那么android效率为什么这么的高呢?特别是一个应用程序的启动时间很短,本文主要从以下个八方面进行分析: <br /><br />1、 资源文件的优化读取。 <br /><br />我们知

因为了解所以无知 1572

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

Universal Android Debloater:无需Root的安卓设备瘦身终极指南,释放15GB存储空间与30%电池续航

Universal Android Debloater(简称UAD)是一款基于Rust开发的跨平台图形界面工具,通过ADB为非Root安卓设备提供安全、高效的预装应用清理方案。无需解锁Bootloader或获取Root权限,即可深度优化设备性能,提升隐私安全并显著延长电池续航时间。 ## 🔍 安卓设备臃肿现状:预装软件带来的三大痛点 现代安卓设备普遍面临"预装应用泛滥"的困扰,这些问题直接影

gitblog_00290的博客 824

Android应用进程内存管理

Android的原理-不需要太多的剩余内存       不用在意剩余内存的大小. Android大多应用没有退出的设计其实是有道理的,这和系统对进程的调度机制有关系.如果你知道Java,就能更清楚这机制了.其实和java的垃圾回收机制类似,系统有一个规则来回收内存.进行内存调度有个阀值,只有低于这个值系统才会按一个列表来关闭用户不需要的东西.当然这个值默认设置得很小,所以你会看到内存老在很少的数值...

zhwadezh的博客 1504

Android App 启动时立即崩溃无法debug的解决方法

方法一 在android开发者选项里,选择调试应用的列表里选择要调试的应用,然后把后面的等待调试器开关打开即可。 方法二 我们可以首先通过adb shell am set-debug-app -w ,然后再启动进程,系统会弹出一个Dialog提醒Application正在Waiting For Debugger。实际上这个时候应用程序进程已经fork出来了,只不过是阻塞在ActivityThread.handleBindApplication()方法里面,它通过调用Debug.waitForDebugg

编程之美 4473

Android tree应用框架

简介 一个好的Android应用开发框架,可以加快Android开发速度,今天笔记基于许多开源项目自写了一款Android应用框架。 内容 框架包括:界面管理(Activity管理)、数据库操作(orm框架、加密等)、http交互、缓存管理、下载管理、路径管理、日志输出、网络管理、系统命令、加解密、stl容器、任务管理、奔溃管理、存储管理、其它辅助管理…。 解决思路如下: 界面管理:使用Sta...

923723914 269

android效率为什么这么的高呢

Android系统框架和上层应用是类java(不是正统的sun java)开发的,实现了自己的java虚拟机dalvik,既然用java虚拟机和java开发,一般都会认为效率低下。其实不然,在基本主流的智能手 机的软件平台上,android的执行速度是最快的。         那么android效率为什么这么的高呢?特别是一个应用程序的启动时间很短,本文主要从以下个八方面进行分析: 

new_abc的专栏 1395

Android开发性能优化总结(一)

安卓开发应用首先要讲究良好的用户体验,如果一款软件卡顿现象严重,不流畅,经常崩溃,那么将给用户带来极不良好的体验,从而损失用户。 在实际开发和学习中,我总结了一下关于安卓性能的优化,供大家参考交流。 应用程序的性能问题体现在很多方面, 比如第一次启动速度慢,或者进入某一界面速度慢;动画执行过程不流畅,或者动画执行卡顿时间长;ListView列表滑动过程中卡顿,不流畅;应用程序自定义的某特定界面...

king的专栏 3万+

Android Studio 新版发布,可直接查看崩溃报告

导读:最新Android Studio稳定版来了,我们瞧瞧它有什么新鲜的。Android 开发团队在 11 月30日发布了用于构建 Android 应用程序的Android Studio的最新稳定版本:2023.11 。此版本的更新目标在增强应用程序性能和移动设备电池寿命,应用程序能够更轻松地升级到最新的 Android 版本,并加快使用 Jetpack Compose 的开发速度。Android...

weixin_38754349的博客 311

Google用AI革新安卓开发,减负增效可期?

谷歌正将AI拓展到整个Android Studio工作流程,旨在减少测试、更新等繁琐劳动,让开发者从‘如何做’转向‘做什么’。

IT界那些事儿 56
上一篇: c语言指针笔记
下一篇: 集成Flutter到现有项目
z529905310
博客等级 码龄10年 11粉丝 37原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值