簡體   English   中英

使用 Android Q ffmpeg 拒絕權限“:錯誤 = 13,權限被拒絕

[英]permission is denied using Android Q ffmpeg": error=13, Permission denied

我想使用 ffmpeg 從 RTSP 視頻中獲取幀。 但是對於上面的 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 或更低,然后重新發布我不推薦的應用程序。

因此,我也在為未來的版本尋找更可行的解決方案。

任何提示、鏈接或建議將不勝感激。 提前致謝。

從 Android Q 開始,您無法在應用的私有數據目錄中執行二進制文件。

來自問題跟蹤器: 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()。 使用 wrap.sh 功能完成了類似的方法,記錄在https://developer.android.com/ndk/guides/wrap-script#packaging_wrapsh

此外,請注意通過 exec() 執行的可執行文件不是根據 Android 進程生命周期管理的,一般來說,Android 應用程序不鼓勵 exec()。 雖然不是 Android 文檔,但在NDK 中使用“exec()”對此進行了一些詳細說明。 依賴 exec() 在未來的 Android 版本中可能會出現問題。

將 Build.gradle 文件targetSdkVersion 29更改為 28並在您的設備上重新安裝您的應用程序 - 由於 targetSdkVersion 29 是在 Play 商店發布構建所需的平台,因此暫時解決了您的權限問題,因此我建議您使用它庫,支持目標Sdk 30

https://github.com/SimformSolutionsPvtLtd/SSffmpegVideoOperation

較早的答案正確地解釋了您遇到的問題。 這也是去年 9 月提出的一個 懸而未決的問題,在您使用的庫的論壇上進行了討論(從我在堆棧跟蹤中看到的內容)。

為 SDK 29 編譯的解決方案是停止將二進制文件放在 /data/ 目錄中,並確保它們位於本機 libs 目錄中。 在非 root 設備上安裝和解壓 APK 后無法實現,因此在准備 Android 項目時應正確完成(例如通過 gradle 設置),並確保在安裝時正確解壓內容: android:extractNativeLibs=true

在您的情況下,此代碼將打包為“資產”的二進制文件移動到用戶數據目錄中:

https://github.com/WritingMinds/ffmpeg-android-java/blob/master/FFmpegAndroid/src/main/java/com/github/hiteshsondhi88/libffmpeg/FileUtils.java

這是在可讀/可寫位置運行任何可執行文件的安全問題。 我上面鏈接的源代碼需要刪除,而是打包在 /libs 中的本機二進制文件。 由於應用程序安裝目錄中的 /libs 位置是可執行的但不可寫,因此更改更加安全。

總之,第 3 方庫需要解決它,或者您可以這樣做並貢獻一個拉取請求。 或者 fork 自己的並為自己重新編譯。

如果您的應用程序在安裝后實際下載內容,並希望執行任何下載,那么仍然存在問題。 據我所知,現在在 Android 10 中這是不可能的。

面向未來的解決方案是停止使用外部二進制文件,並將依賴項編譯為 NDK 項目。 他們將需要圍繞本機代碼的 jni 包裝器(一些工作)。 我知道你可以研究 一個相關的項目

我在使用FFmpeg-Android-Java時遇到了同樣的情況。 似乎不再支持這個庫......所以我只是轉移到MobileFFmpeg並且工作起來很有魅力!

如果您使用 gradle 插件 4.0.0(及更高版本),則唯一需要注意的是在模塊級 build.gradle 中添加以下內容:

android {
    packagingOptions {
        pickFirst 'lib/x86/libc++_shared.so'
        pickFirst 'lib/x86_64/libc++_shared.so'
        pickFirst 'lib/armeabi-v7a/libc++_shared.so'
        pickFirst 'lib/arm64-v8a/libc++_shared.so'
    }
}

根據@Saurabh Thorat 的回答,我提出了一個解決問題的拉取請求。 你可以在這里找到它。

快速總結:

將 ffmpeg 二進制文件移動到 libs 文件夾並將android:extractNativeLibs = "true"到清單,以便它可以將自身復制到/data/app/{package_name}/lib/{arch}/然后從那里執行它(支持在 Android 上 10)。

編輯(一般使用):為了將可執行文件復制到/data/app/{package_name}/lib/{arch}/ ,文件名必須是lib(something).so 如果名稱不以lib開頭並以.so結尾,則不會復制它們。

您可以使用 // implementation 'com.arthenica:mobile-ffmpeg-full:4.4' implementation 'com.arthenica:mobile-ffmpeg-full:4.2.LTS'

我知道這已經晚了,但您甚至可以使用 gradle 任務將所有內容從特定目錄復制到 apk 中特定於架構的 lib 文件夾

使用 android 安裝程序在安裝時可以將所有庫提取到/data/app文件夾的hacky 技巧,這個地方是可執行的(即使在 Android Q 之后)!

然后你可以在 /data/app 目錄中執行你的文件! 有關更多信息,請訪問文章鏈接 - https://withme.skullzbones.com/blog/programming/execute-native-binaries-android-q-no-root/

根據ffmpeg-android-java 拉取請求,有一個解決方法來支持 Android 10,但是具有該解決方法的 APK 可能會被 Play 商店拒絕(有關詳細信息,請參閱拉取請求)。

另一種方法是切換到更新的 Android ffmpeg 庫。 截至 2022 年 7 月, ffmpeg-kit是一個積極貢獻的庫,作為ffmpeg-android-java的替代品,它與我的項目配合得很好。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM