欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

整理更新 MuPDF 和修改相关 C 代码过程中遇到的问题。

最编程 2024-05-02 12:18:10
...

问题起源

  • 项目中涉及到PDF阅读器并需在原有基础上添加解密的模块,所以之前的开发人员在MuPDF的读取数据流原逻辑上添加了解密模块,然后重新生成SO库之后再配合业务来进行使用。(16年期间开发的,期间未曾改动)
  • 近期APP用户在使用时打开PDF文件过程中白屏或闪退出现频率严重,所以不得不重视以及快速更新优化。更新过程中难免会遇到些问题,而这些问题又会牵连到新的问题,目前所要做的呢,就是根据更新过程中产生的新旧问题一个个的解决,不能有丝毫模糊的解决与处理,因为模糊的解决方案势必会引导新的问题产生,反而会得不偿失。

更新过程中所涉及到的官方文档及资源链接

  • MuPDF官方文档及涉及的项目地址
    • mupdf.com/
    • mupdf.com/docs/androi…
    • www.mupdf.com/downloads/i…
    • Git 地址,recursive介绍(git-scm.com/book/zh/v2/…)
      • git clone --recursive git://git.ghostscript.com/mupdf-android-fitz.git
      • git clone --recursive git://git.ghostscript.com/mupdf-android-viewer.git
      • git clone --recursive git://git.ghostscript.com/mupdf-android-viewer-mini.git
  • Cygwin官方地址及安装介绍(因为我是Windows操作系统,使用虚拟机装了Unbtun后操作发现需要移植过多资源,并且我目前问题的终极目的只是需要编译下C库,那么Cygwin完全可以胜任,也省去了我移植Android开发环境与数据传送的时间)
    • www.cygwin.com/
    • blog.****.net/lvsehaiyang…
  • Android NDK官方地址及对应配置文档(降旧版本NDK主要是因为R17及以上版本已移除了armeabi的ABI)
    • developer.android.com/ndk/downloa…
    • developer.android.com/ndk/guides/…
    • developer.android.com/ndk/guides/…

从零开始更新(看似漫漫之路,实而不过如此)

  • 一,MuPDF项目库不做任何改动的情况下生产SO库,想解决这次问题,那么就需要清晰整套流程,先从简单的步骤做起。
    • 若读者当前系统环境是Mac或Linux就用不到Cygwin,(一般自带CMake环境,若没有请自行查阅解决),直接可以使用CMake相关的指令。
    • 生成SO库的所需的C文件,以下是我的项目路径,请自行对应更改。
      • 通过 make generate 指令生成所需C文件:
    • 自己简单搭建Android PDF阅读器,我使用的是1.16.1版本的MuPDF代码
      • 在此之前,你需要搞清楚MuPDF在Android项目中所需依赖的子项目及其关系。
        • 官方介绍:
      • 它们关系也就是:app(PDF展示层) --> mupdfLib(UI封装层) --> mupdfJni(C核心库逻辑层)
      • MuPDFSimpleDemo项目地址:
        • github.com/GenialSir/M…
  • 二,现在已经生成好最基本的MuPDF的环境,现在我需要做的就是在原有MuPDF的逻辑上进行适合自身项目的读取解密的操作。
    • 这块我遇到了个棘手的问题,本原想将git链接到的mupdf-android-viewer项目直接放在Android Studio上面运行,但是在运行过程中出现如下图的问题:
      • 总的来说还是,对mk文件这块不够了解,若有解决的同学请评论下面留言,不胜感激。
    • 那么无法通过Android Studio运行1.16.1版本的mupdf-android-viewer项目,那我如果想修改库的C代码逻辑还有什么其它的方案呢?答案当然是有的,那就需要使用对C/C++等语言开发相较于Android Studio更专业的工具Visual Studio了,我这次用的是VS2019版本。
      • 在MuPDF官方分别下载1.10.0版本至1.16.1版本,通过每个版本尝试,发现1.13.0以上版本在Visual Studio上无法编译通过,具体解决繁琐且不明确产生问题,然后调至1.10.0版本进行编译运行,从而达到调试修改MuPDF项目中源代码逻辑。测试在1.10.0版本解密成功后将改动代码移植到1.16.1的MuPDF,然后通过CMake指令来生成SO库,也就规避了1.13.0以上版本在VS编译受阻的问题。
        • Visutal Studio运行MuPDF的入口,点击mupdf.sln自动导入即可:
        • 然后在具体的C代码及头文件位置进行自己的解密算法处理,本篇文章只阐述改动代码后生成SO遇到的问题及思路,因涉及非个人的项目,所以不会公开改动的代码。
  • 三,现所需更新的MuPDF项目及其增添的解密逻辑添加且已经生成SO库(C解密逻辑受到公司连老师的大力帮助,若只靠自己对C的片面了解只会越改越糟,避免了很多的试错、改错的时间成本),因为公司项目的所有SO库只有对armeabi的支持,所以在更新替换过程中产生了以下几点问题:
    1. 目前我的开发环境NDK是紧跟官方更新版本,那么就需要自身降到r17以下的版本,所以我将r17之前的旧版本NDK都下载下来,以防对应NDK版本对C99、C11的兼容各不同所遇到自身不能解决的问题而“卡壳”。
      • 官方在NDKr17版本中已经完全移除armeabi。
      • NDKr17及以上版本已无法生存armeabi的ABI,此次我选择NDKr15c版本
      • 通过命令ndk-build来执行,因为要频繁更换NDK版本,所以这块我没有直接使用设置好的系统环境变量,而是直接指定当前ndk所在的路径, G:/ndk_64version/android-ndk-r15c/ndk-build APP_BUILD_SCRIPT=libmupdf/platform/java/Android.mk APP_ABI=armeabi
        • 如图:使用APP_ABI指定当前所需生成的ABI类型,如果生成全部则不用追加。
        • 若指定多种ABI使用逗号间隔即可:
    2. 将在MuPDF1.16.1版本改动后的SO放在自己用来测试的项目MuPDFSimpleDemo上后,出现了个小插曲(测试手机用的是小米8,处理器为高通骁龙845,64位处理器),在使用arm64-v8a的SO库阅读PDF时一切正常,但使用armeabi的SO库时,打开PDF文件时会白屏闪退掉。
    3. 因为没有对应的日志,我无法定位问题,所以我假想应该不会是java.lang.UnsatisfiedLinkError这个找不到对应SO库文件的问题,我还特意写了个简单的Demo,配置了对应Android.mk及gradle文件测试,用来排查问题。
      • 为了排除不是externalNativeBuild没有在64位处理器上兼容armeabi的问题,我在MuPDFSimpleDemo使用 ndk{} 这种形式来指定
      • 然而经过以上处理后在MuPDFSimpleDemo项目中采用刚指定armeabi的ABI情况下打开PDF文件,依旧白屏闪退,也无法定位到问题日志,配置上arm64-v8a的SO库及指定后则正常。(那么依照这种现象说明这块应该是自己追加的解密C代码标准化版本的问题,以至于NDKr15c版本编译MuPDF1.16.1时在armeabi的ABI解释上产生了问题?因为在AndroidStudio中缺少有效C代码日志,无法定位到具体的问题。
      • 此问题已超出了目前我知识所了解的范围,并且给的开发周期也不允许我再有过多的时间去调研了。
    4. 通过以上遇到的问题,我只能先放弃完美的迭代新版本MuPDF的想法( 即更新MuPDF的官方版本,又更新原开发添加在MuPDF解密算法。 因为目前使用的是16年的,已经有3年之差了。),进行MuPDF降版本处理,也就是说只更新原项目MuPDF的SO库解密算法,不更新MuPDF官方版本 。
    5. 因此我准备将在1.16.1版本上添加的C解密逻辑移植到之前项目所用的MuPDF版本,所幸的是MuPDF这3年期间的大幅度更新并未在读取数据流这块有大变动,从而也方便了我从高版本往低版本的移植。在低版本的MuPDF读取加密PDF测试通过后,我将优化解密算法后的SO库移植到公司项目经测试后,解决了因几百页或更多页数的PDF文件因加密后再次解密读取中频繁导致白屏或闪退的问题。

总结(改变我所能改变的,舍弃我所能舍弃的)

  • 项目这次PDF频繁出现白屏与闪退的原因,是因为解密算法读取规则方式不严谨导致。如果是文件资源较小的PDF,则会很少几率出现,若随着PDF资源的变大,解密读取的不规则的问题也就会被放大化。
  • 总的来说,难预计、难估期的项目大多数还是因为自身能力欠缺,简明的说就是缺知识
  • 解决任何问题都不能一厢情愿的去莽撞处理,要多考虑到时间、环境、人力、以及可行性等多种因素。也要多会借助外部的力量,毕竟独木不成林。

推荐阅读