diff --git a/android-ffmpeg/build.gradle b/android-ffmpeg/build.gradle index ad8a65e..c1a4b2f 100644 --- a/android-ffmpeg/build.gradle +++ b/android-ffmpeg/build.gradle @@ -22,13 +22,13 @@ ext { } android { - compileSdkVersion 28 + compileSdkVersion 29 defaultConfig { minSdkVersion 16 - targetSdkVersion 28 - versionCode 17 - versionName "1.1.7" + targetSdkVersion 29 + versionCode 18 + versionName "1.2.1" } compileOptions { @@ -48,7 +48,7 @@ android { 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' 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..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 = "arm/"; - if (cpuArch == CpuArch.x86) { - prefix = "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 b1002d2..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 = "arm/"; - if (cpuArch == CpuArch.x86) { - prefix = "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 b0c40bc..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 = "ffmpeg"; - private static final String FFPROBE_FILE_NAME = "ffprobe"; + 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/src/main/assets/arm/ffmpeg b/android-ffmpeg/src/main/jniLibs/armeabi-v7a/lib..ffmpeg..so similarity index 100% rename from android-ffmpeg/src/main/assets/arm/ffmpeg rename to android-ffmpeg/src/main/jniLibs/armeabi-v7a/lib..ffmpeg..so diff --git a/android-ffmpeg/src/main/assets/arm/ffprobe b/android-ffmpeg/src/main/jniLibs/armeabi-v7a/lib..ffprobe..so similarity index 100% rename from android-ffmpeg/src/main/assets/arm/ffprobe rename to android-ffmpeg/src/main/jniLibs/armeabi-v7a/lib..ffprobe..so diff --git a/android-ffmpeg/src/main/assets/x86/ffmpeg b/android-ffmpeg/src/main/jniLibs/x86/lib..ffmpeg..so similarity index 100% rename from android-ffmpeg/src/main/assets/x86/ffmpeg rename to android-ffmpeg/src/main/jniLibs/x86/lib..ffmpeg..so diff --git a/android-ffmpeg/src/main/assets/x86/ffprobe b/android-ffmpeg/src/main/jniLibs/x86/lib..ffprobe..so similarity index 100% rename from android-ffmpeg/src/main/assets/x86/ffprobe 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..15448dc 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 + 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">