我想得到的帧从RTSP视频使用ffmpeg。但对于android 10以上版本,我得到的错误如下所示。
E/FFmpeg: Exception while trying to run: [Ljava.lang.String;@55e447f
java.io.IOException: Cannot run program "/data/user/0/com.example.downloadimagefromurl/files/ffmpeg": error=13, Permission denied
at java.lang.ProcessBuilder.start(ProcessBuilder.java:1050)
at java.lang.Runtime.exec(Runtime.java:698)
at java.lang.Runtime.exec(Runtime.java:563)
at com.github.hiteshsondhi88.libffmpeg.ShellCommand.run(ShellCommand.java:10)
at com.github.hiteshsondhi88.libffmpeg.FFmpegExecuteAsyncTask.doInBackground(FFmpegExecuteAsyncTask.java:38)
at com.github.hiteshsondhi88.libffmpeg.FFmpegExecuteAsyncTask.doInBackground(FFmpegExecuteAsyncTask.java:10)
at android.os.AsyncTask$3.call(AsyncTask.java:378)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:289)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:919)
Caused by: java.io.IOException: error=13, Permission denied
at java.lang.UNIXProcess.forkAndExec(Native Method)
at java.lang.UNIXProcess.<init>(UNIXProcess.java:133)根据@Saurabh Thorat提供的答案,Google不允许应用程序运行/data/user目录中的二进制文件。
据我所知,一个糟糕的解决方案是将compileSdkVersion和targetSdkVersion更改为28或更低,然后重新发布我的应用程序,这是不推荐的。
因此,我也在为未来的版本寻找更可行的解决方案。
任何提示,链接或建议将受到高度赞赏。提前谢谢。
发布于 2020-02-24 14:28:58
从Android Q开始,你不能在你的应用的私有数据目录中执行二进制文件。
来自issuetracker:https://issuetracker.google.com/issues/128554619
在targetAPI >= Q的应用程序数据文件上对数据块exec()所做的更改按预期工作。有关此更改的背景信息,请参阅https://android-review.googlesource.com/c/platform/system/sepolicy/+/804149。对可写应用程序文件调用exec()违反了W^X (https://en.wikipedia.org/wiki/W%5EX),并代表了一种不安全的应用程序实践。可执行代码应始终从应用程序APK加载。
虽然exec()不再对应用程序主目录中的文件起作用,但它仍然支持只读/data/app目录中的文件。特别是,应该可以将二进制文件打包到应用程序的本机libs目录中并启用android:extractNativeLibs=true,然后对/data/app工件调用exec()。https://developer.android.com/ndk/guides/wrap-script#packaging_wrapsh中记录的wrap.sh功能也采用了类似的方法。
此外,请注意,通过exec()执行的可执行文件不会根据Android进程生命周期进行管理,一般来说,不建议在Android应用程序中使用exec()。虽然不是Android文档,但Using "exec()" with NDK详细介绍了这一点。在未来的安卓版本中依赖exec()可能会有问题。
发布于 2020-03-25 13:54:32
仅更改Build.gradle文件上的 targetSdkVersion 29至28并在您的设备上重新安装您的应用程序-临时解决了您的权限问题,因为发布的build on play商店需要targetSdkVersion 29平台,所以我建议您使用此库,它支持目标Sdk 30
发布于 2020-03-12 20:05:25
earlier answer正确地解释了您遇到的问题。这也是去年9月提出的一个open issue,在您正在使用的库的论坛上进行了讨论(从堆栈跟踪中我可以看到)。
为SDK 29编译的解决方案是停止将二进制文件放在/data/目录中,并确保它们在本机libs目录中。这是在非根设备上安装并解压缩APK后无法实现的,因此在准备Android项目时应该正确完成(例如通过gradle设置),并确保在安装时正确解压内容:android:extractNativeLibs=true。
在您的示例中,此代码将打包为“assets”的二进制文件移动到用户数据目录中:
这是一个安全问题,在可读/可写的位置运行任何可执行文件。我链接到上面的源代码需要删除,取而代之的是打包在/libs中的本机二进制文件。更改更安全,因为应用程序安装目录中的/libs位置是可执行的,但不可写。
总而言之,第三方库需要解决它,或者你可以这样做,并贡献一个拉取请求。或者自己创建fork,然后自己重新编译。
如果你的应用程序在安装后真的下载了内容,并且希望执行任何下载,这仍然是一个问题。据我所知,这在Android10中是不可能实现的。
面向未来的解决方案是停止使用外部二进制文件,并将依赖项编译为NDK项目。他们将需要jni包装器来包装本机代码(需要一些工作)。我知道有个a related project你可以查一下。
https://stackoverflow.com/questions/60370424
复制相似问题