diff --git a/android-ffmpeg/build.gradle b/android-ffmpeg/build.gradle index ad8a65e..a95be9d 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" } @@ -46,9 +46,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' @@ -98,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/CpuArch.java b/android-ffmpeg/src/main/java/nl/bravobit/ffmpeg/CpuArch.java deleted file mode 100644 index 77ddd8f..0000000 --- a/android-ffmpeg/src/main/java/nl/bravobit/ffmpeg/CpuArch.java +++ /dev/null @@ -1,5 +0,0 @@ -package nl.bravobit.ffmpeg; - -public enum CpuArch { - ARMv7, x86, NONE -} diff --git a/android-ffmpeg/src/main/java/nl/bravobit/ffmpeg/CpuArchHelper.java b/android-ffmpeg/src/main/java/nl/bravobit/ffmpeg/CpuArchHelper.java deleted file mode 100644 index ed63c82..0000000 --- a/android-ffmpeg/src/main/java/nl/bravobit/ffmpeg/CpuArchHelper.java +++ /dev/null @@ -1,25 +0,0 @@ -package nl.bravobit.ffmpeg; - -import android.os.Build; - -public class CpuArchHelper { - public static final String X86_CPU = "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"; - - public static CpuArch getCpuArch() { - Log.d("Build.CPU_ABI : " + Build.CPU_ABI); - - switch (Build.CPU_ABI) { - case X86_CPU: - case X86_64_CPU: - return CpuArch.x86; - case ARM_64_CPU: - case ARM_V7_CPU: - return CpuArch.ARMv7; - default: - return CpuArch.NONE; - } - } -} 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..d2b4398 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,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 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 +34,15 @@ 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..fe21960 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,13 @@ 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 +51,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 +62,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..5a6e65e 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 old mode 100755 new mode 100644 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 old mode 100755 new mode 100644 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 old mode 100755 new mode 100644 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 old mode 100755 new mode 100644 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..c91e6db 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" } @@ -25,10 +25,9 @@ android { } dependencies { - implementation fileTree(dir: 'libs', include: ['*.jar']) // Android libraries - implementation 'androidx.appcompat:appcompat:1.0.2' + implementation 'androidx.appcompat:appcompat:1.1.0' // Misc implementation 'com.jakewharton.timber:timber:4.7.1' diff --git a/sample/src/main/AndroidManifest.xml b/sample/src/main/AndroidManifest.xml index f15a5c6..4c1f8ec 100644 --- a/sample/src/main/AndroidManifest.xml +++ b/sample/src/main/AndroidManifest.xml @@ -13,6 +13,7 @@ android:label="@string/app_name" android:largeHeap="true" android:roundIcon="@mipmap/ic_launcher_round" + android:extractNativeLibs="true" android:supportsRtl="true" android:theme="@style/AppTheme">