diff --git a/README.md b/README.md index c8c9eae..840fb23 100644 --- a/README.md +++ b/README.md @@ -146,6 +146,22 @@ dependencies { } ``` +## Proguard ## + + ``` + ### RxJava, RxAndroid for media-picker-android library + -keepclassmembers class rx.internal.util.unsafe.*ArrayQueue*Field* { + long producerIndex; + long consumerIndex; + } + + ### mp4parser + -keep class * implements com.coremedia.iso.boxes.Box {* ; } + -dontwarn com.coremedia.iso.boxes.* + -dontwarn com.googlecode.mp4parser.authoring.tracks.mjpeg.** + -dontwarn com.googlecode.mp4parser.authoring.tracks.ttml.** + ``` + ## Requirements ## - Android 4.1+ diff --git a/app/build.gradle b/app/build.gradle index 1160f2f..c914382 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -3,25 +3,34 @@ apply plugin: 'kotlin-android' apply plugin: 'kotlin-android-extensions' android { - compileSdkVersion 29 + compileSdkVersion 30 buildToolsVersion "29.0.3" - +// 0123456789 defaultConfig { applicationId "com.ahmedbadereldin.videotrimmerapplication" minSdkVersion 19 - targetSdkVersion 29 + targetSdkVersion 30 versionCode 1 versionName "1.0" - testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } + buildTypes { release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + debuggable false + minifyEnabled true + shrinkResources true + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } + debug { + debuggable true + minifyEnabled true + shrinkResources true + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } + compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 @@ -43,8 +52,6 @@ dependencies { implementation 'com.github.fccaikai:AndroidPermissionX:1.0.0' - implementation 'com.googlecode.mp4parser:isoparser:1.1.22' - implementation 'iam.void.mediapicker:mediapicker:0.2.3' implementation 'io.reactivex:rxjava:1.3.5' implementation 'io.reactivex:rxandroid:1.2.1' @@ -53,6 +60,5 @@ dependencies { exclude group: "com.android.support" } annotationProcessor 'com.github.bumptech.glide:compiler:4.11.0' - implementation project(':videotrimmer') } \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro index 481bb43..9981bd4 100644 --- a/app/proguard-rules.pro +++ b/app/proguard-rules.pro @@ -1,21 +1,5 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle. -# -# For more details, see -# http://developer.android.com/guide/developing/tools/proguard.html - -# If your project uses WebView with JS, uncomment the following -# and specify the fully qualified class name to the JavaScript interface -# class: -#-keepclassmembers class fqcn.of.javascript.interface.for.webview { -# public *; -#} - -# Uncomment this to preserve the line number information for -# debugging stack traces. -#-keepattributes SourceFile,LineNumberTable - -# If you keep the line number information, uncomment this to -# hide the original source file name. -#-renamesourcefileattribute SourceFile \ No newline at end of file +### RxJava, RxAndroid (https://gist.github.com/kosiara/487868792fbd3214f9c9) +-keepclassmembers class rx.internal.util.unsafe.*ArrayQueue*Field* { + long producerIndex; + long consumerIndex; +} diff --git a/app/src/main/java/com/ahmedbadereldin/videotrimmerapplication/NewPostActivity.java b/app/src/main/java/com/ahmedbadereldin/videotrimmerapplication/NewPostActivity.java index 1dffb36..280618c 100644 --- a/app/src/main/java/com/ahmedbadereldin/videotrimmerapplication/NewPostActivity.java +++ b/app/src/main/java/com/ahmedbadereldin/videotrimmerapplication/NewPostActivity.java @@ -49,14 +49,14 @@ protected void onCreate(final Bundle savedInstanceState) { setContentView(R.layout.activity_new_post); initViews(); - setSharedInentData(getIntent()); + setSharedIntentData(getIntent()); initClicks(); } @Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); - setSharedInentData(intent); + setSharedIntentData(intent); } private void initViews() { @@ -66,20 +66,18 @@ private void initViews() { cancelImgBtn = findViewById(R.id.cancelImgBtn); } - private void setSharedInentData(Intent sharedInentData) { + private void setSharedIntentData(Intent sharedIntentData) { - String receivedAction = sharedInentData.getAction(); - String receivedType = sharedInentData.getType(); + String receivedAction = sharedIntentData.getAction(); + String receivedType = sharedIntentData.getType(); if (receivedAction != null && receivedAction.equals(Intent.ACTION_SEND)) { - //content is being shared - assert receivedType != null; if (receivedType.startsWith("image/")) { //handle sent image - uriPostImg = sharedInentData.getParcelableExtra(Intent.EXTRA_STREAM); + uriPostImg = sharedIntentData.getParcelableExtra(Intent.EXTRA_STREAM); if (uriPostImg != null) { - hideSoftKeyboard(this, 0); + hideSoftKeyboard(this); pathPostImg = null; Glide.with(this) @@ -89,9 +87,8 @@ private void setSharedInentData(Intent sharedInentData) { } } else if (receivedType.startsWith("video/")) { -// GlobalData.Toast("video"); //handle sent video - uriPostImg = sharedInentData.getParcelableExtra(Intent.EXTRA_STREAM); + uriPostImg = sharedIntentData.getParcelableExtra(Intent.EXTRA_STREAM); if (uriPostImg != null) { //set the video //RESAMPLE YOUR IMAGE DATA BEFORE DISPLAYING @@ -106,7 +103,6 @@ private void setSharedInentData(Intent sharedInentData) { } private void initClicks() { - cancelImgBtn.setOnClickListener(view -> { uriPostImg = null; pathPostImg = null; @@ -115,7 +111,6 @@ private void initClicks() { videoBtn.setOnClickListener(view -> { try { - PermissionCompat.Builder builder = new PermissionCompat.Builder(this); builder.addPermissions(new String[]{Manifest.permission.CAMERA, Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE}); builder.addPermissionRationale(getString(R.string.should_allow_permission)); @@ -147,8 +142,8 @@ public void onDenied(String permission) { private void loadImage(Uri filepath) { // MEDIA GALLERY String path = getPath(filepath); - Uri filea = Uri.fromFile(new File(path)); - String fileExt = MimeTypeMap.getFileExtensionFromUrl(filea.toString()); + Uri uriFile = Uri.fromFile(new File(path)); + String fileExt = MimeTypeMap.getFileExtensionFromUrl(uriFile.toString()); if (fileExt.equalsIgnoreCase("MP4")) { File file = new File(path); @@ -175,7 +170,6 @@ protected void onActivityResult(int requestCode, int resultCode, Intent data) { String path = getPath(selectedImageUri); Uri uriFile = Uri.fromFile(new File(path)); String fileExtension = MimeTypeMap.getFileExtensionFromUrl(uriFile.toString()); - Log.d(TAG, "onActivityResult: " + fileExtension); if (fileExtension.equalsIgnoreCase("MP4")) { File file = new File(path); @@ -324,17 +318,12 @@ private boolean isExternalStorageDocument(Uri uri) { return "com.android.externalstorage.documents".equals(uri.getAuthority()); } - public static void hideSoftKeyboard(Activity activity, int show) { - try { - InputMethodManager inputMethodManager = - (InputMethodManager) activity.getSystemService( - Activity.INPUT_METHOD_SERVICE); - assert inputMethodManager != null; - inputMethodManager.hideSoftInputFromWindow( - Objects.requireNonNull(activity.getCurrentFocus()).getWindowToken(), 0); - } catch (Exception e) { -// e.printStackTrace(); - } + public static void hideSoftKeyboard(Activity activity) { + InputMethodManager inputMethodManager = + (InputMethodManager) activity.getSystemService( + Activity.INPUT_METHOD_SERVICE); + assert inputMethodManager != null; + inputMethodManager.hideSoftInputFromWindow(Objects.requireNonNull(activity.getCurrentFocus()).getWindowToken(), 0); } } diff --git a/app/src/main/java/com/ahmedbadereldin/videotrimmerapplication/VideoTrimmerActivity.java b/app/src/main/java/com/ahmedbadereldin/videotrimmerapplication/VideoTrimmerActivity.java index 775ff1d..8e2db63 100644 --- a/app/src/main/java/com/ahmedbadereldin/videotrimmerapplication/VideoTrimmerActivity.java +++ b/app/src/main/java/com/ahmedbadereldin/videotrimmerapplication/VideoTrimmerActivity.java @@ -16,9 +16,11 @@ import android.widget.TextView; import android.widget.Toast; import android.widget.VideoView; + import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.appcompat.app.AppCompatActivity; + import com.ahmedbadereldin.videotrimmer.Utility; import com.ahmedbadereldin.videotrimmer.customVideoViews.BackgroundTask; import com.ahmedbadereldin.videotrimmer.customVideoViews.BarThumb; @@ -26,9 +28,11 @@ import com.ahmedbadereldin.videotrimmer.customVideoViews.OnRangeSeekBarChangeListener; import com.ahmedbadereldin.videotrimmer.customVideoViews.OnVideoTrimListener; import com.ahmedbadereldin.videotrimmer.customVideoViews.TileView; + import java.io.File; import java.util.Date; import java.util.Locale; +import java.util.Objects; public class VideoTrimmerActivity extends AppCompatActivity implements View.OnClickListener { @@ -61,12 +65,14 @@ public class VideoTrimmerActivity extends AppCompatActivity implements View.OnCl @Override public void onTrimStarted() { // Create an indeterminate progress dialog + mProgressDialog = new ProgressDialog(VideoTrimmerActivity.this); mProgressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER); mProgressDialog.setTitle(getString(R.string.save)); mProgressDialog.setIndeterminate(true); mProgressDialog.setCancelable(false); mProgressDialog.show(); + } @Override @@ -199,7 +205,7 @@ public void onClick(View view) { mediaMetadataRetriever = new MediaMetadataRetriever(); mediaMetadataRetriever.setDataSource(VideoTrimmerActivity.this, Uri.parse(srcFile)); final File file = new File(srcFile); - Log.d("fileLength", "onClick: " + file.length() + " " + file.canExecute()); + //notify that video trimming started if (mOnVideoTrimListener != null) mOnVideoTrimListener.onTrimStarted(); @@ -208,11 +214,9 @@ public void onClick(View view) { @Override public void execute() { try { - Log.d("executeAAAA", "execute: " + "Aaaa" + file.length() + " " + dstFile + " " + mStartPosition + " " + mEndPosition + " " + mOnVideoTrimListener); - Utility.startTrim(file, dstFile, mStartPosition * 1000, mEndPosition * 1000, mOnVideoTrimListener); } catch (final Throwable e) { - Thread.getDefaultUncaughtExceptionHandler().uncaughtException(Thread.currentThread(), e); + Objects.requireNonNull(Thread.getDefaultUncaughtExceptionHandler()).uncaughtException(Thread.currentThread(), e); } } } diff --git a/trim.jks b/trim.jks new file mode 100644 index 0000000..4b7a03d Binary files /dev/null and b/trim.jks differ diff --git a/videotrimmer/build.gradle b/videotrimmer/build.gradle index a44f976..a4fe4cd 100644 --- a/videotrimmer/build.gradle +++ b/videotrimmer/build.gradle @@ -3,19 +3,16 @@ apply plugin: 'kotlin-android' apply plugin: 'kotlin-android-extensions' android { - compileSdkVersion 29 + compileSdkVersion 30 buildToolsVersion "29.0.3" - defaultConfig { minSdkVersion 19 - targetSdkVersion 29 + targetSdkVersion 30 versionCode 1 versionName "1.0" - testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" consumerProguardFiles "consumer-rules.pro" } - buildTypes { release { minifyEnabled false diff --git a/videotrimmer/consumer-rules.pro b/videotrimmer/consumer-rules.pro index e69de29..ff6f661 100644 --- a/videotrimmer/consumer-rules.pro +++ b/videotrimmer/consumer-rules.pro @@ -0,0 +1,5 @@ +### mp4parser +-keep class * implements com.coremedia.iso.boxes.Box {* ; } +-dontwarn com.coremedia.iso.boxes.* +-dontwarn com.googlecode.mp4parser.authoring.tracks.mjpeg.** +-dontwarn com.googlecode.mp4parser.authoring.tracks.ttml.** diff --git a/videotrimmer/proguard-rules.pro b/videotrimmer/proguard-rules.pro index 481bb43..e69de29 100644 --- a/videotrimmer/proguard-rules.pro +++ b/videotrimmer/proguard-rules.pro @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle. -# -# For more details, see -# http://developer.android.com/guide/developing/tools/proguard.html - -# If your project uses WebView with JS, uncomment the following -# and specify the fully qualified class name to the JavaScript interface -# class: -#-keepclassmembers class fqcn.of.javascript.interface.for.webview { -# public *; -#} - -# Uncomment this to preserve the line number information for -# debugging stack traces. -#-keepattributes SourceFile,LineNumberTable - -# If you keep the line number information, uncomment this to -# hide the original source file name. -#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/videotrimmer/src/main/java/com/ahmedbadereldin/videotrimmer/Utility.java b/videotrimmer/src/main/java/com/ahmedbadereldin/videotrimmer/Utility.java index b32aebc..68f630a 100644 --- a/videotrimmer/src/main/java/com/ahmedbadereldin/videotrimmer/Utility.java +++ b/videotrimmer/src/main/java/com/ahmedbadereldin/videotrimmer/Utility.java @@ -32,15 +32,18 @@ public class Utility { public static void startTrim(@NonNull File src, @NonNull String dst, long startMs, long endMs, @NonNull OnVideoTrimListener callback) throws IOException { final String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.US).format(new Date()); - File file = new File(dst); file.getParentFile().mkdirs(); Log.d(TAG, "Generated file path " + dst); generateVideo(src, file, startMs, endMs, callback); + + } private static void generateVideo(@NonNull File src, @NonNull File dst, long startMs, long endMs, @NonNull OnVideoTrimListener callback) throws IOException { + + // NOTE: Switched to using FileDataSourceViaHeapImpl since it does not use memory mapping (VM). // Otherwise we get OOM with large movie files. Movie movie = MovieCreator.build(new FileDataSourceViaHeapImpl(src.getAbsolutePath())); @@ -108,6 +111,7 @@ private static void generateVideo(@NonNull File src, @NonNull File dst, long sta fos.close(); if (callback != null) callback.getResult(Uri.parse(dst.toString())); + }