Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

I want to get the frames from the RTSP video using ffmpeg. But for android 10 above I am getting error as below.

 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)

As the answer provided by @Saurabh Thorat, Google doesn't allow apps to run binary files from /data/user directory.

One bad solution that I know is to change compileSdkVersion and targetSdkVersion to 28 or below and re-release my application which is not recommended.

Hence, I am looking for more viable solutions for future releases as well.

Any hint, links or suggestion would be highly appreciated. Thanks in advance.

like image 717
v teja Avatar asked Feb 24 '20 06:02

v teja


People also ask

Why am I getting permission denied for FFmpeg?

If file permissions look OK and you're still getting permission denied running ffmpeg, you should also check where ffmpeg is installed on your system by executing: it means ffmpeg was installed using the snap package manager and that might be causing the permission denied error.

Why can't I run FFmpeg on Android?

Apparently in Android that does not allow to execute the FFmpeg codes. Or if you need to keep running your app with API> = 29, try using this library: MobileFFmpeg Important: If you are going to use READ or WRITE permissions, don't forget to use android:requestLegacyExternalStorage="true" in your android manifest.

Does FFmpeg-Android-Java support Android 10?

Per the ffmpeg-android-java pull request, there is a workaround to support Android 10, but the APK with that workaround may get rejected by Play Store (see pull request for details). An alternative is to switch to a newer Android ffmpeg library.


3 Answers

From Android Q onwards, you cannot execute binaries in your app's private data directory.

From the issuetracker: https://issuetracker.google.com/issues/128554619

The change to block exec() on application data files for targetAPI >= Q is working-as-intended. Please see https://android-review.googlesource.com/c/platform/system/sepolicy/+/804149 for background on this change. Calling exec() on writable application files is a W^X (https://en.wikipedia.org/wiki/W%5EX) violation and represents an unsafe application practice. Executable code should always be loaded from the application APK.

While exec() no longer works on files within the application home directory, it continues to be supported for files within the read-only /data/app directory. In particular, it should be possible to package the binaries into your application's native libs directory and enable android:extractNativeLibs=true, and then call exec() on the /data/app artifacts. A similar approach is done with the wrap.sh functionality, documented at https://developer.android.com/ndk/guides/wrap-script#packaging_wrapsh .

Additionally, please be aware that executables executed via exec() are not managed according to the Android process lifecycle, and generally speaking, exec() is discouraged from Android applications. While not Android documentation, Using "exec()" with NDK covers this in some detail. Relying on exec() may be problematic in future Android versions.

like image 54
Saurabh Thorat Avatar answered Oct 26 '22 21:10

Saurabh Thorat


Change only on Build.gradle file targetSdkVersion 29 to 28 and Re-Install your app on your device - It is resolved your permission issue for temporary because of the targetSdkVersion 29 is required platform for released build on play store so I suggest to you use this library, It is support the target Sdk 30

https://github.com/SimformSolutionsPvtLtd/SSffmpegVideoOperation

like image 9
Ashwin Vavaliya Avatar answered Oct 26 '22 21:10

Ashwin Vavaliya


The earlier answer correctly explains the problem you are hitting. This is also an open issue raised last September, discussed on the forum of the library you are using (from what I can see in the stack trace).

The solution to compile for SDK 29 would be to stop putting binaries in the /data/ directory, and ensure they are in the native libs directory. That can't be achieved after the APK is installed and unpacked on non-rooted devices, and so should be done correctly when preparing the Android project (e.g. through gradle settings), and to make sure that upon installation the contents get properly unpacked: android:extractNativeLibs=true.

In your case, this code moves binaries that are packaged as 'assets' into the users data directory:

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

That's a security concern running any executables in a location that is read/writeable. That source code I linked to above would need to be removed, instead, the native binaries packaged in /libs. The change is more secure as the /libs location inside your apps install directory is executable but not writable.

In summary, the 3rd party lib needs to address it, or you could do it and contribute a pull request. Or fork your own and recompile it for yourself.

There's still a problem, if your app actually downloads content after it is installed, and expects to execute any downloads. That's now impossible as far as I can tell in Android 10.

The future-proof solution is to stop using external binaries, and to compile the dependencies as NDK projects. They will need jni wrappers around native code (a bit of work). There is a related project I know of you could look into.

like image 7
dr_g Avatar answered Oct 26 '22 19:10

dr_g