From b26683ba3a32907e5cca22135c7f183ae26423ce Mon Sep 17 00:00:00 2001 From: scmfaria Date: Mon, 26 Oct 2020 17:39:58 -0300 Subject: [PATCH 1/3] bug fix: permission is denied using Android 10 --- android-ffmpeg/build.gradle | 8 ++++++-- .../assets/arm/ffmpeg => libs/arm/libffmpeg.so} | Bin .../assets/arm/ffprobe => libs/arm/libffprobe.so} | Bin .../assets/x86/ffmpeg => libs/x86/libffmpeg.so} | Bin .../assets/x86/ffprobe => libs/x86/libffprobe.so} | Bin .../main/java/nl/bravobit/ffmpeg/CpuArchHelper.java | 2 +- .../src/main/java/nl/bravobit/ffmpeg/FFmpeg.java | 4 ++-- .../src/main/java/nl/bravobit/ffmpeg/FFprobe.java | 4 ++-- .../src/main/java/nl/bravobit/ffmpeg/FileUtils.java | 4 ++-- 9 files changed, 13 insertions(+), 9 deletions(-) rename android-ffmpeg/{src/main/assets/arm/ffmpeg => libs/arm/libffmpeg.so} (100%) rename android-ffmpeg/{src/main/assets/arm/ffprobe => libs/arm/libffprobe.so} (100%) rename android-ffmpeg/{src/main/assets/x86/ffmpeg => libs/x86/libffmpeg.so} (100%) rename android-ffmpeg/{src/main/assets/x86/ffprobe => libs/x86/libffprobe.so} (100%) diff --git a/android-ffmpeg/build.gradle b/android-ffmpeg/build.gradle index ad8a65e..a494c70 100644 --- a/android-ffmpeg/build.gradle +++ b/android-ffmpeg/build.gradle @@ -22,11 +22,11 @@ ext { } android { - compileSdkVersion 28 + compileSdkVersion 29 defaultConfig { minSdkVersion 16 - targetSdkVersion 28 + targetSdkVersion 29 versionCode 17 versionName "1.1.7" } @@ -40,6 +40,10 @@ android { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + + ndk { + abiFilters "armeabi-v7a", "x86" + } } } diff --git a/android-ffmpeg/src/main/assets/arm/ffmpeg b/android-ffmpeg/libs/arm/libffmpeg.so similarity index 100% rename from android-ffmpeg/src/main/assets/arm/ffmpeg rename to android-ffmpeg/libs/arm/libffmpeg.so diff --git a/android-ffmpeg/src/main/assets/arm/ffprobe b/android-ffmpeg/libs/arm/libffprobe.so similarity index 100% rename from android-ffmpeg/src/main/assets/arm/ffprobe rename to android-ffmpeg/libs/arm/libffprobe.so diff --git a/android-ffmpeg/src/main/assets/x86/ffmpeg b/android-ffmpeg/libs/x86/libffmpeg.so similarity index 100% rename from android-ffmpeg/src/main/assets/x86/ffmpeg rename to android-ffmpeg/libs/x86/libffmpeg.so diff --git a/android-ffmpeg/src/main/assets/x86/ffprobe b/android-ffmpeg/libs/x86/libffprobe.so similarity index 100% rename from android-ffmpeg/src/main/assets/x86/ffprobe rename to android-ffmpeg/libs/x86/libffprobe.so diff --git a/android-ffmpeg/src/main/java/nl/bravobit/ffmpeg/CpuArchHelper.java b/android-ffmpeg/src/main/java/nl/bravobit/ffmpeg/CpuArchHelper.java index ed63c82..54d228d 100644 --- a/android-ffmpeg/src/main/java/nl/bravobit/ffmpeg/CpuArchHelper.java +++ b/android-ffmpeg/src/main/java/nl/bravobit/ffmpeg/CpuArchHelper.java @@ -3,7 +3,7 @@ import android.os.Build; public class CpuArchHelper { - public static final String X86_CPU = "x86"; + public static final String X86_CPU = "libs/x86"; public static final String X86_64_CPU = "x86_64"; public static final String ARM_64_CPU = "arm64-v8a"; public static final String ARM_V7_CPU = "armeabi-v7a"; diff --git a/android-ffmpeg/src/main/java/nl/bravobit/ffmpeg/FFmpeg.java b/android-ffmpeg/src/main/java/nl/bravobit/ffmpeg/FFmpeg.java index 0adb87e..4c312cd 100644 --- a/android-ffmpeg/src/main/java/nl/bravobit/ffmpeg/FFmpeg.java +++ b/android-ffmpeg/src/main/java/nl/bravobit/ffmpeg/FFmpeg.java @@ -55,9 +55,9 @@ public boolean isSupported() { // check if ffmpeg file exists if (!ffmpeg.exists() || version < VERSION) { - String prefix = "arm/"; + String prefix = "libs/arm/"; if (cpuArch == CpuArch.x86) { - prefix = "x86/"; + prefix = "libs/x86/"; } Log.d("file does not exist, creating it..."); diff --git a/android-ffmpeg/src/main/java/nl/bravobit/ffmpeg/FFprobe.java b/android-ffmpeg/src/main/java/nl/bravobit/ffmpeg/FFprobe.java index b1002d2..b66cd7f 100644 --- a/android-ffmpeg/src/main/java/nl/bravobit/ffmpeg/FFprobe.java +++ b/android-ffmpeg/src/main/java/nl/bravobit/ffmpeg/FFprobe.java @@ -55,9 +55,9 @@ public boolean isSupported() { // check if ffprobe file exists if (!ffprobe.exists() || version < VERSION) { - String prefix = "arm/"; + String prefix = "libs/arm/"; if (cpuArch == CpuArch.x86) { - prefix = "x86/"; + prefix = "libs/x86/"; } Log.d("file does not exist, creating it..."); diff --git a/android-ffmpeg/src/main/java/nl/bravobit/ffmpeg/FileUtils.java b/android-ffmpeg/src/main/java/nl/bravobit/ffmpeg/FileUtils.java index b0c40bc..e2d5752 100644 --- a/android-ffmpeg/src/main/java/nl/bravobit/ffmpeg/FileUtils.java +++ b/android-ffmpeg/src/main/java/nl/bravobit/ffmpeg/FileUtils.java @@ -10,8 +10,8 @@ import java.io.OutputStream; class FileUtils { - private static final String FFMPEG_FILE_NAME = "ffmpeg"; - private static final String FFPROBE_FILE_NAME = "ffprobe"; + private static final String FFMPEG_FILE_NAME = "libffmpeg.so"; + private static final String FFPROBE_FILE_NAME = "libffprobe.so"; static File getFFmpeg(Context context) { File folder = context.getFilesDir(); From f6d9dc823d2ce0dca4225ed5c9ec6ad1a64e7eb7 Mon Sep 17 00:00:00 2001 From: scmfaria Date: Tue, 27 Oct 2020 14:44:45 -0300 Subject: [PATCH 2/3] bug fix: bug fix: permission is denied using AndroidX --- android-ffmpeg/build.gradle | 9 +- .../main/java/nl/bravobit/ffmpeg/FFmpeg.java | 79 ++--------------- .../main/java/nl/bravobit/ffmpeg/FFprobe.java | 80 ++---------------- .../java/nl/bravobit/ffmpeg/FileUtils.java | 32 +------ .../main/jniLibs/armeabi-v7a/lib..ffmpeg..so} | Bin .../jniLibs/armeabi-v7a/lib..ffprobe..so} | Bin .../main/jniLibs/x86/lib..ffmpeg..so} | Bin .../main/jniLibs/x86/lib..ffprobe..so} | Bin build.gradle | 2 +- gradle/wrapper/gradle-wrapper.properties | 2 +- sample/build.gradle | 6 +- sample/src/main/AndroidManifest.xml | 1 + 12 files changed, 21 insertions(+), 190 deletions(-) rename android-ffmpeg/{libs/arm/libffmpeg.so => src/main/jniLibs/armeabi-v7a/lib..ffmpeg..so} (100%) rename android-ffmpeg/{libs/arm/libffprobe.so => src/main/jniLibs/armeabi-v7a/lib..ffprobe..so} (100%) rename android-ffmpeg/{libs/x86/libffmpeg.so => src/main/jniLibs/x86/lib..ffmpeg..so} (100%) rename android-ffmpeg/{libs/x86/libffprobe.so => src/main/jniLibs/x86/lib..ffprobe..so} (100%) diff --git a/android-ffmpeg/build.gradle b/android-ffmpeg/build.gradle index a494c70..a95be9d 100644 --- a/android-ffmpeg/build.gradle +++ b/android-ffmpeg/build.gradle @@ -40,19 +40,13 @@ android { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - - ndk { - abiFilters "armeabi-v7a", "x86" - } } } } dependencies { - implementation fileTree(dir: 'libs', include: ['*.jar']) - - implementation 'androidx.appcompat:appcompat:1.0.2' + implementation 'androidx.appcompat:appcompat:1.1.0' } apply plugin: 'com.github.dcendents.android-maven' @@ -102,7 +96,6 @@ version = libraryVersion task sourcesJar(type: Jar) { from android.sourceSets.main.java.srcDirs - classifier = 'sources' } task javadoc(type: Javadoc) { diff --git a/android-ffmpeg/src/main/java/nl/bravobit/ffmpeg/FFmpeg.java b/android-ffmpeg/src/main/java/nl/bravobit/ffmpeg/FFmpeg.java index 4c312cd..17c1731 100644 --- a/android-ffmpeg/src/main/java/nl/bravobit/ffmpeg/FFmpeg.java +++ b/android-ffmpeg/src/main/java/nl/bravobit/ffmpeg/FFmpeg.java @@ -1,18 +1,13 @@ package nl.bravobit.ffmpeg; import android.content.Context; -import android.content.SharedPreferences; import android.os.AsyncTask; import java.io.File; import java.io.IOException; -import java.io.InputStream; -import java.lang.reflect.Array; import java.util.Map; public class FFmpeg implements FFbinaryInterface { - private static final int VERSION = 17; // up this version when you add a new ffmpeg build - private static final String KEY_PREF_VERSION = "ffmpeg_version"; private final FFbinaryContextProvider context; @@ -40,67 +35,14 @@ public Context provide() { @Override public boolean isSupported() { - // check if arch is supported - CpuArch cpuArch = CpuArchHelper.getCpuArch(); - if (cpuArch == CpuArch.NONE) { - Log.e("arch not supported"); - return false; - } - // get ffmpeg file File ffmpeg = FileUtils.getFFmpeg(context.provide()); - SharedPreferences settings = context.provide().getSharedPreferences("ffmpeg_prefs", Context.MODE_PRIVATE); - int version = settings.getInt(KEY_PREF_VERSION, 0); - - // check if ffmpeg file exists - if (!ffmpeg.exists() || version < VERSION) { - String prefix = "libs/arm/"; - if (cpuArch == CpuArch.x86) { - prefix = "libs/x86/"; - } - Log.d("file does not exist, creating it..."); - - try { - InputStream inputStream = context.provide().getAssets().open(prefix + "ffmpeg"); - if (!FileUtils.inputStreamToFile(inputStream, ffmpeg)) { - return false; - } - - Log.d("successfully wrote ffmpeg file!"); - - settings.edit().putInt(KEY_PREF_VERSION, VERSION).apply(); - } catch (IOException e) { - Log.e("error while opening assets", e); - return false; - } - } - // check if ffmpeg can be executed if (!ffmpeg.canExecute()) { // try to make executable - try { - try { - Runtime.getRuntime().exec("chmod -R 777 " + ffmpeg.getAbsolutePath()).waitFor(); - } catch (InterruptedException e) { - Log.e("interrupted exception", e); - return false; - } catch (IOException e) { - Log.e("io exception", e); - return false; - } - - if (!ffmpeg.canExecute()) { - // our last hope! - if (!ffmpeg.setExecutable(true)) { - Log.e("unable to make executable"); - return false; - } - } - } catch (SecurityException e) { - Log.e("security exception", e); - return false; - } + Log.e("ffmpeg cannot execute"); + return false; } Log.d("ffmpeg is ready!"); @@ -111,8 +53,9 @@ public boolean isSupported() { @Override public FFtask execute(Map environvenmentVars, String[] cmd, FFcommandExecuteResponseHandler ffmpegExecuteResponseHandler) { if (cmd.length != 0) { - String[] ffmpegBinary = new String[]{FileUtils.getFFmpeg(context.provide()).getAbsolutePath()}; - String[] command = concatenate(ffmpegBinary, cmd); + final String[] command = new String[cmd.length + 1]; + command[0] = FileUtils.getFFmpeg(context.provide()).getAbsolutePath(); + System.arraycopy(cmd, 0, command, 1, cmd.length); FFcommandExecuteAsyncTask task = new FFcommandExecuteAsyncTask(command, environvenmentVars, timeout, ffmpegExecuteResponseHandler); task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); return task; @@ -121,18 +64,6 @@ public FFtask execute(Map environvenmentVars, String[] cmd, FFco } } - private static T[] concatenate(T[] a, T[] b) { - int aLen = a.length; - int bLen = b.length; - - @SuppressWarnings("unchecked") - T[] c = (T[]) Array.newInstance(a.getClass().getComponentType(), aLen + bLen); - System.arraycopy(a, 0, c, 0, aLen); - System.arraycopy(b, 0, c, aLen, bLen); - - return c; - } - @Override public FFtask execute(String[] cmd, FFcommandExecuteResponseHandler ffmpegExecuteResponseHandler) { return execute(null, cmd, ffmpegExecuteResponseHandler); diff --git a/android-ffmpeg/src/main/java/nl/bravobit/ffmpeg/FFprobe.java b/android-ffmpeg/src/main/java/nl/bravobit/ffmpeg/FFprobe.java index b66cd7f..447229d 100644 --- a/android-ffmpeg/src/main/java/nl/bravobit/ffmpeg/FFprobe.java +++ b/android-ffmpeg/src/main/java/nl/bravobit/ffmpeg/FFprobe.java @@ -1,18 +1,12 @@ package nl.bravobit.ffmpeg; import android.content.Context; -import android.content.SharedPreferences; import android.os.AsyncTask; import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.lang.reflect.Array; import java.util.Map; public class FFprobe implements FFbinaryInterface { - private static final int VERSION = 17; // up this version when you add a new ffprobe build - private static final String KEY_PREF_VERSION = "ffprobe_version"; private final FFbinaryContextProvider context; @@ -40,67 +34,14 @@ public Context provide() { @Override public boolean isSupported() { - // check if arch is supported - CpuArch cpuArch = CpuArchHelper.getCpuArch(); - if (cpuArch == CpuArch.NONE) { - Log.e("arch not supported"); - return false; - } - // get ffprobe file File ffprobe = FileUtils.getFFprobe(context.provide()); - SharedPreferences settings = context.provide().getSharedPreferences("ffmpeg_prefs", Context.MODE_PRIVATE); - int version = settings.getInt(KEY_PREF_VERSION, 0); - - // check if ffprobe file exists - if (!ffprobe.exists() || version < VERSION) { - String prefix = "libs/arm/"; - if (cpuArch == CpuArch.x86) { - prefix = "libs/x86/"; - } - Log.d("file does not exist, creating it..."); - - try { - InputStream inputStream = context.provide().getAssets().open(prefix + "ffprobe"); - if (!FileUtils.inputStreamToFile(inputStream, ffprobe)) { - return false; - } - - Log.d("successfully wrote ffprobe file!"); - - settings.edit().putInt(KEY_PREF_VERSION, VERSION).apply(); - } catch (IOException e) { - Log.e("error while opening assets", e); - return false; - } - } - // check if ffprobe can be executed if (!ffprobe.canExecute()) { // try to make executable - try { - try { - Runtime.getRuntime().exec("chmod -R 777 " + ffprobe.getAbsolutePath()).waitFor(); - } catch (InterruptedException e) { - Log.e("interrupted exception", e); - return false; - } catch (IOException e) { - Log.e("io exception", e); - return false; - } - - if (!ffprobe.canExecute()) { - // our last hope! - if (!ffprobe.setExecutable(true)) { - Log.e("unable to make executable"); - return false; - } - } - } catch (SecurityException e) { - Log.e("security exception", e); - return false; - } + Log.e("ffprobe cannot execute"); + return false; } Log.d("ffprobe is ready!"); @@ -111,8 +52,9 @@ public boolean isSupported() { @Override public FFtask execute(Map environvenmentVars, String[] cmd, FFcommandExecuteResponseHandler ffcommandExecuteResponseHandler) { if (cmd.length != 0) { - String[] ffprobeBinary = new String[]{FileUtils.getFFprobe(context.provide()).getAbsolutePath()}; - String[] command = concatenate(ffprobeBinary, cmd); + final String[] command = new String[cmd.length + 1]; + command[0] = FileUtils.getFFprobe(context.provide()).getAbsolutePath(); + System.arraycopy(cmd, 0, command, 1, cmd.length); FFcommandExecuteAsyncTask task = new FFcommandExecuteAsyncTask(command, environvenmentVars, timeout, ffcommandExecuteResponseHandler); task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); return task; @@ -121,18 +63,6 @@ public FFtask execute(Map environvenmentVars, String[] cmd, FFco } } - private static T[] concatenate(T[] a, T[] b) { - int aLen = a.length; - int bLen = b.length; - - @SuppressWarnings("unchecked") - T[] c = (T[]) Array.newInstance(a.getClass().getComponentType(), aLen + bLen); - System.arraycopy(a, 0, c, 0, aLen); - System.arraycopy(b, 0, c, aLen, bLen); - - return c; - } - @Override public FFtask execute(String[] cmd, FFcommandExecuteResponseHandler ffcommandExecuteResponseHandler) { return execute(null, cmd, ffcommandExecuteResponseHandler); diff --git a/android-ffmpeg/src/main/java/nl/bravobit/ffmpeg/FileUtils.java b/android-ffmpeg/src/main/java/nl/bravobit/ffmpeg/FileUtils.java index e2d5752..94f7942 100644 --- a/android-ffmpeg/src/main/java/nl/bravobit/ffmpeg/FileUtils.java +++ b/android-ffmpeg/src/main/java/nl/bravobit/ffmpeg/FileUtils.java @@ -2,43 +2,19 @@ import android.content.Context; -import java.io.BufferedInputStream; import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; class FileUtils { - private static final String FFMPEG_FILE_NAME = "libffmpeg.so"; - private static final String FFPROBE_FILE_NAME = "libffprobe.so"; + private static final String FFMPEG_FILE_NAME = "lib..ffmpeg..so"; + private static final String FFPROBE_FILE_NAME = "lib..ffprobe..so"; static File getFFmpeg(Context context) { - File folder = context.getFilesDir(); + File folder = new File(context.getApplicationInfo().nativeLibraryDir); return new File(folder, FFMPEG_FILE_NAME); } static File getFFprobe(Context context) { - File folder = context.getFilesDir(); + File folder = new File(context.getApplicationInfo().nativeLibraryDir); return new File(folder, FFPROBE_FILE_NAME); } - - static boolean inputStreamToFile(InputStream stream, File file) { - try { - InputStream input = new BufferedInputStream(stream); - OutputStream output = new FileOutputStream(file); - byte[] buffer = new byte[1024]; - int bytesRead; - while ((bytesRead = input.read(buffer, 0, buffer.length)) >= 0) { - output.write(buffer, 0, bytesRead); - } - output.flush(); - output.close(); - input.close(); - return true; - } catch (IOException e) { - Log.e("error while writing ff binary file", e); - } - return false; - } } \ No newline at end of file diff --git a/android-ffmpeg/libs/arm/libffmpeg.so b/android-ffmpeg/src/main/jniLibs/armeabi-v7a/lib..ffmpeg..so similarity index 100% rename from android-ffmpeg/libs/arm/libffmpeg.so rename to android-ffmpeg/src/main/jniLibs/armeabi-v7a/lib..ffmpeg..so diff --git a/android-ffmpeg/libs/arm/libffprobe.so b/android-ffmpeg/src/main/jniLibs/armeabi-v7a/lib..ffprobe..so similarity index 100% rename from android-ffmpeg/libs/arm/libffprobe.so rename to android-ffmpeg/src/main/jniLibs/armeabi-v7a/lib..ffprobe..so diff --git a/android-ffmpeg/libs/x86/libffmpeg.so b/android-ffmpeg/src/main/jniLibs/x86/lib..ffmpeg..so similarity index 100% rename from android-ffmpeg/libs/x86/libffmpeg.so rename to android-ffmpeg/src/main/jniLibs/x86/lib..ffmpeg..so diff --git a/android-ffmpeg/libs/x86/libffprobe.so b/android-ffmpeg/src/main/jniLibs/x86/lib..ffprobe..so similarity index 100% rename from android-ffmpeg/libs/x86/libffprobe.so rename to android-ffmpeg/src/main/jniLibs/x86/lib..ffprobe..so diff --git a/build.gradle b/build.gradle index 137022d..6f2a40a 100644 --- a/build.gradle +++ b/build.gradle @@ -6,7 +6,7 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:3.4.0' + classpath 'com.android.tools.build:gradle:3.4.2' classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.8.4' classpath 'com.github.dcendents:android-maven-gradle-plugin:2.1' } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 64a2787..2c736ee 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-all.zip diff --git a/sample/build.gradle b/sample/build.gradle index 00149f5..5debe93 100644 --- a/sample/build.gradle +++ b/sample/build.gradle @@ -1,12 +1,12 @@ apply plugin: 'com.android.application' android { - compileSdkVersion 28 + compileSdkVersion 29 defaultConfig { applicationId "nl.bravobit.ffmpeg.example" - minSdkVersion 16 - targetSdkVersion 28 + minSdkVersion 19 + targetSdkVersion 29 versionCode 1 versionName "1.0.1" } diff --git a/sample/src/main/AndroidManifest.xml b/sample/src/main/AndroidManifest.xml index f15a5c6..084e232 100644 --- a/sample/src/main/AndroidManifest.xml +++ b/sample/src/main/AndroidManifest.xml @@ -12,6 +12,7 @@ android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:largeHeap="true" + android:extractNativeLibs="true" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> From ef865bd5494861be0e29247963d087a8f0e79bce Mon Sep 17 00:00:00 2001 From: scmfaria Date: Tue, 27 Oct 2020 16:33:45 -0300 Subject: [PATCH 3/3] bug fix: android 10 --- android-ffmpeg/build.gradle | 7 +++++-- sample/build.gradle | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/android-ffmpeg/build.gradle b/android-ffmpeg/build.gradle index a95be9d..c1a4b2f 100644 --- a/android-ffmpeg/build.gradle +++ b/android-ffmpeg/build.gradle @@ -27,8 +27,8 @@ android { defaultConfig { minSdkVersion 16 targetSdkVersion 29 - versionCode 17 - versionName "1.1.7" + versionCode 18 + versionName "1.2.1" } compileOptions { @@ -46,6 +46,8 @@ android { } dependencies { + implementation fileTree(dir: 'libs', include: ['*.jar']) + implementation 'androidx.appcompat:appcompat:1.1.0' } @@ -96,6 +98,7 @@ version = libraryVersion task sourcesJar(type: Jar) { from android.sourceSets.main.java.srcDirs + classifier = 'sources' } task javadoc(type: Javadoc) { diff --git a/sample/build.gradle b/sample/build.gradle index 5debe93..15448dc 100644 --- a/sample/build.gradle +++ b/sample/build.gradle @@ -5,7 +5,7 @@ android { defaultConfig { applicationId "nl.bravobit.ffmpeg.example" - minSdkVersion 19 + minSdkVersion 16 targetSdkVersion 29 versionCode 1 versionName "1.0.1"