Android 9环境下GPL Ghostscript在adb Shell正常运行但Runtime.getRuntime().exec调用报错(退出码255)原因咨询
Ghostscript在Android应用中无法创建临时文件的问题分析与解决
首先还原你遇到的错误信息:
GPL Ghostscript 9.50: **** Could not open temporary file /tmp/gs_ptKBo1
GPL Ghostscript 9.50: Could not open the scratch file /tmp/gs_ptKBo1.
./base/gdevp14.c:6710: gs_pdf14_device_push(): Fatal
GPL Ghostscript 9.50: Unrecoverable error, exit code 255
问题根源
这事儿本质是Android应用的沙箱权限限制在搞怪:
- 你在
adb shell里跑gs命令时,身份是系统级的shell用户(甚至可能是root),这个用户能自由访问系统全局的/tmp目录,所以Ghostscript能顺利创建临时文件。 - 但Android应用是跑在独立的沙箱进程里,默认只能读写自己的私有目录(比如
/data/data/你的应用包名/cache/或者files/),根本没有权限碰系统的/tmp目录——而Ghostscript默认会把临时文件丢在/tmp下,这就直接导致了创建临时文件失败的致命错误。
解决办法
核心思路就是让Ghostscript用你的应用有权访问的目录存临时文件,具体操作如下:
- 给Ghostscript指定临时目录参数
Ghostscript支持通过-sTMPDIR参数自定义临时文件的存放路径,我们可以把这个路径设为应用的私有缓存目录(这个目录是Android专门给应用存临时文件用的,自带读写权限)。
先在代码里拿到应用的缓存目录:
File cacheDir = getCacheDir(); // 获取应用私有缓存目录 String tmpDirPath = cacheDir.getAbsolutePath();
然后修改你的gs命令,加上-sTMPDIR参数,同时还要注意输出文件11.pcl也得放在应用有权限的目录下(不然还会踩权限坑):
// 用字符串数组传递命令,避免空格等特殊字符导致的解析错误 String[] gsCommand = new String[]{ "gs", "-dNOPAUSE", "-dNOSAFER", "-dBATCH", "-dPARANOIDSAFER", "-dNOINTERPOLATE", "-sDEVICE=pxlmono", "-sTMPDIR=" + tmpDirPath, "-sOutputFile=" + tmpDirPath + "/11.pcl", "/path/to/your/22.pdf" // 这里要替换成22.pdf的实际可访问路径 }; Runtime.getRuntime().exec(gsCommand);
- 确保输入输出文件的路径合法
- 输入的
22.pdf不能放在系统目录或者其他应用的私有目录里,必须放在你的应用能访问的地方:比如自身的files目录、你申请了权限的外部存储路径,或者公共存储目录。 - 如果是用外部存储的文件,记得在Android 9里要提前申请
READ_EXTERNAL_STORAGE/WRITE_EXTERNAL_STORAGE权限,并且做动态权限申请(API 23及以上都需要)。
内容的提问来源于stack exchange,提问作者ghost314
相关产品推荐
相关产品推荐

