diff --git a/app/src/main/java/com/example/myapplication/Compressor.kt b/app/src/main/java/com/example/myapplication/Compressor.kt deleted file mode 100644 index ed4c476..0000000 --- a/app/src/main/java/com/example/myapplication/Compressor.kt +++ /dev/null @@ -1,11 +0,0 @@ -package com.example.myapplication - -import java.io.FileDescriptor - -class Compressor { - - fun compressFile(fileDescriptor: FileDescriptor) { - - - } -} \ No newline at end of file diff --git a/app/src/main/java/com/example/myapplication/MainActivity.kt b/app/src/main/java/com/example/myapplication/MainActivity.kt index aa396e2..c1d5577 100644 --- a/app/src/main/java/com/example/myapplication/MainActivity.kt +++ b/app/src/main/java/com/example/myapplication/MainActivity.kt @@ -1,11 +1,13 @@ package com.example.myapplication import android.Manifest -import android.content.ContentResolver +import android.annotation.SuppressLint import android.content.Intent import android.content.pm.PackageManager import android.net.Uri import android.os.Bundle +import android.os.Handler +import android.os.Looper import android.provider.MediaStore import android.util.Log import android.view.Menu @@ -14,20 +16,17 @@ import android.widget.Toast import androidx.activity.result.contract.ActivityResultContracts import androidx.appcompat.app.AppCompatActivity import androidx.core.app.ActivityCompat -import androidx.core.net.toUri import androidx.navigation.findNavController import androidx.navigation.ui.AppBarConfiguration import androidx.navigation.ui.setupActionBarWithNavController import androidx.navigation.ui.setupWithNavController import com.arthenica.ffmpegkit.FFmpegKit import com.arthenica.ffmpegkit.FFmpegKitConfig -import com.arthenica.ffmpegkit.FFmpegSession import com.example.myapplication.databinding.ActivityMainBinding import com.example.myapplication.ui.compressing.CompressingAdapter import com.example.myapplication.ui.compressing.CompressingItem import com.google.android.material.bottomnavigation.BottomNavigationView import java.io.File -import java.io.FileInputStream import java.util.* class MainActivity : AppCompatActivity() { @@ -101,6 +100,7 @@ class MainActivity : AppCompatActivity() { } //grabs output from pressing files, used for grabbing URI + @SuppressLint("NotifyDataSetChanged") // Needed because of custom adapter private var resultLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> if (result.resultCode == RESULT_OK) { @@ -109,27 +109,6 @@ class MainActivity : AppCompatActivity() { val inUri = FFmpegKitConfig.getSafParameterForRead(this, data) - - - - val outputFile = File(this.filesDir, "output.mp4") - - if(outputFile.createNewFile()) { - Log.i("Tag", "File created") - } else { - Log.i("Tag", "File not created") - } - - - val outUri = FFmpegKitConfig.getSafParameter(this, outputFile.toUri(), "rw") - - val command = "-i $inUri -c:v mpeg4 $outUri -y" - val session = FFmpegKit.execute(command) - - Log.i("Tag", Arrays.deepToString(session.arguments)) - Log.i("Tag", session.output) - - val cursor = contentResolver.query(data!!, null, null, null, null) cursor?.moveToFirst() @@ -137,7 +116,33 @@ class MainActivity : AppCompatActivity() { val fileDate = Date(System.currentTimeMillis()) val fileName = cursor?.getString(cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DISPLAY_NAME)) - compressingItems.add(CompressingItem(fileName!!, 0.0, fileDate)) + val item = CompressingItem(fileName!!, 0.0, fileDate) + + val outputFile = File(this.getExternalFilesDir(null), "converted_$fileName") + + compressingItems.add(item) + + val handler = Handler(Looper.getMainLooper()) + + + val command = "-i $inUri -c:v mpeg4 ${outputFile.absolutePath} -y" + val session = FFmpegKit.executeAsync(command) { + compressingItems.remove(item) + + handler.post { + Toast.makeText(this, "Finished converting $fileName", Toast.LENGTH_SHORT).show() + adapter.notifyDataSetChanged() + } + } + + + Log.i("Tag", Arrays.deepToString(session.arguments)) + Log.i("Tag", session.output) + + + + + adapter.notifyDataSetChanged() } @@ -145,6 +150,7 @@ class MainActivity : AppCompatActivity() { companion object { val compressingItems: MutableList = mutableListOf() + val adapter = CompressingAdapter(compressingItems) } } \ No newline at end of file diff --git a/app/src/main/java/com/example/myapplication/utils/FileUtils.java b/app/src/main/java/com/example/myapplication/utils/FileUtils.java deleted file mode 100644 index ea00cf3..0000000 --- a/app/src/main/java/com/example/myapplication/utils/FileUtils.java +++ /dev/null @@ -1,413 +0,0 @@ -package com.example.myapplication.utils; - -import android.annotation.SuppressLint; -import android.content.ContentUris; -import android.content.Context; -import android.database.Cursor; -import android.net.Uri; -import android.os.Build; -import android.os.Environment; -import android.provider.DocumentsContract; -import android.provider.MediaStore; -import android.provider.OpenableColumns; -import android.text.TextUtils; -import android.util.Log; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.InputStream; -import java.util.UUID; - -public class FileUtils { - public static String FALLBACK_COPY_FOLDER = "upload_part"; - - private static String TAG = "FileUtils"; - - private static Uri contentUri = null; - - Context context; - - public FileUtils(Context context) { - this.context = context; - } - - @SuppressLint("NewApi") - public String getPath(final Uri uri) { - // check here to KITKAT or new version - final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT; - String selection = null; - String[] selectionArgs = null; - // DocumentProvider - - if (isKitKat) { - // ExternalStorageProvider - - if (isExternalStorageDocument(uri)) { - final String docId = DocumentsContract.getDocumentId(uri); - final String[] split = docId.split(":"); - final String type = split[0]; - - String fullPath = getPathFromExtSD(split); - - if (fullPath == null || !fileExists(fullPath)) { - Log.d(TAG, "Copy files as a fallback"); - fullPath = copyFileToInternalStorage(uri, FALLBACK_COPY_FOLDER); - } - - if (fullPath != "") { - return fullPath; - } else { - return null; - } - } - - - // DownloadsProvider - - if (isDownloadsDocument(uri)) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - final String id; - Cursor cursor = null; - try { - cursor = context.getContentResolver().query(uri, new String[] { - MediaStore.MediaColumns.DISPLAY_NAME - }, null, null, null); - if (cursor != null && cursor.moveToFirst()) { - String fileName = cursor.getString(0); - String path = Environment.getExternalStorageDirectory().toString() + "/Download/" + fileName; - if (!TextUtils.isEmpty(path)) { - return path; - } - } - } finally { - if (cursor != null) - cursor.close(); - } - id = DocumentsContract.getDocumentId(uri); - - if (!TextUtils.isEmpty(id)) { - if (id.startsWith("raw:")) { - return id.replaceFirst("raw:", ""); - } - String[] contentUriPrefixesToTry = new String[] { - "content://downloads/public_downloads", - "content://downloads/my_downloads" - }; - - for (String contentUriPrefix: contentUriPrefixesToTry) { - try { - final Uri contentUri = ContentUris.withAppendedId(Uri.parse(contentUriPrefix), Long.valueOf(id)); - - return getDataColumn(context, contentUri, null, null); - } catch (NumberFormatException e) { - //In Android 8 and Android P the id is not a number - return uri.getPath().replaceFirst("^/document/raw:", "").replaceFirst("^raw:", ""); - } - } - } - } else { - final String id = DocumentsContract.getDocumentId(uri); - - if (id.startsWith("raw:")) { - return id.replaceFirst("raw:", ""); - } - try { - contentUri = ContentUris.withAppendedId( - Uri.parse("content://downloads/public_downloads"), Long.valueOf(id)); - } catch (NumberFormatException e) { - e.printStackTrace(); - } - - if (contentUri != null) - return getDataColumn(context, contentUri, null, null); - } - } - - - // MediaProvider - if (isMediaDocument(uri)) { - final String docId = DocumentsContract.getDocumentId(uri); - final String[] split = docId.split(":"); - final String type = split[0]; - - Log.d(TAG, "MEDIA DOCUMENT TYPE: " + type); - - Uri contentUri = null; - - if ("image".equals(type)) { - contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI; - } else if ("video".equals(type)) { - contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI; - } else if ("audio".equals(type)) { - contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI; - } else if ("document".equals(type)) { - contentUri = MediaStore.Files.getContentUri(MediaStore.getVolumeName(uri)); - } - - selection = "_id=?"; - selectionArgs = new String[] { - split[1] - }; - - - return getDataColumn(context, contentUri, selection, selectionArgs); - } - - if (isGoogleDriveUri(uri)) { - return getDriveFilePath(uri); - } - - if (isWhatsAppFile(uri)) { - return getFilePathForWhatsApp(uri); - } - - if ("content".equalsIgnoreCase(uri.getScheme())) { - if (isGooglePhotosUri(uri)) { - return uri.getLastPathSegment(); - } - - if (isGoogleDriveUri(uri)) { - return getDriveFilePath(uri); - } - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { - // return getFilePathFromURI(context,uri); - return copyFileToInternalStorage(uri, FALLBACK_COPY_FOLDER); - // return getRealPathFromURI(context,uri); - } else { - return getDataColumn(context, uri, null, null); - } - - } - - if ("file".equalsIgnoreCase(uri.getScheme())) { - return uri.getPath(); - } - } else { - if (isWhatsAppFile(uri)) { - return getFilePathForWhatsApp(uri); - } - - if ("content".equalsIgnoreCase(uri.getScheme())) { - String[] projection = { - MediaStore.Images.Media.DATA - }; - Cursor cursor = null; - - try { - cursor = context.getContentResolver() - .query(uri, projection, selection, selectionArgs, null); - int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA); - - if (cursor.moveToFirst()) { - return cursor.getString(column_index); - } - } catch (Exception e) { - e.printStackTrace(); - } - } - } - - return copyFileToInternalStorage(uri, FALLBACK_COPY_FOLDER); - } - - private static boolean fileExists(String filePath) { - File file = new File(filePath); - - return file.exists(); - } - - private static String getPathFromExtSD(String[] pathData) { - final String type = pathData[0]; - final String relativePath = File.separator + pathData[1]; - String fullPath = ""; - - - Log.d(TAG, "MEDIA EXTSD TYPE: " + type); - Log.d(TAG, "Relative path: " + relativePath); - // on my Sony devices (4.4.4 & 5.1.1), `type` is a dynamic string - // something like "71F8-2C0A", some kind of unique id per storage - // don't know any API that can get the root path of that storage based on its id. - // - // so no "primary" type, but let the check here for other devices - if ("primary".equalsIgnoreCase(type)) { - fullPath = Environment.getExternalStorageDirectory() + relativePath; - if (fileExists(fullPath)) { - return fullPath; - } - } - - if ("home".equalsIgnoreCase(type)) { - fullPath = "/storage/emulated/0/Documents" + relativePath; - if (fileExists(fullPath)) { - return fullPath; - } - } - - // Environment.isExternalStorageRemovable() is `true` for external and internal storage - // so we cannot relay on it. - // - // instead, for each possible path, check if file exists - // we'll start with secondary storage as this could be our (physically) removable sd card - fullPath = System.getenv("SECONDARY_STORAGE") + relativePath; - if (fileExists(fullPath)) { - return fullPath; - } - - fullPath = System.getenv("EXTERNAL_STORAGE") + relativePath; - if (fileExists(fullPath)) { - return fullPath; - } - - return null; - } - - private String getDriveFilePath(Uri uri) { - Uri returnUri = uri; - Cursor returnCursor = context.getContentResolver().query(returnUri, null, null, null, null); - /* - * Get the column indexes of the data in the Cursor, - * * move to the first row in the Cursor, get the data, - * * and display it. - * */ - int nameIndex = returnCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME); - int sizeIndex = returnCursor.getColumnIndex(OpenableColumns.SIZE); - returnCursor.moveToFirst(); - String name = (returnCursor.getString(nameIndex)); - String size = (Long.toString(returnCursor.getLong(sizeIndex))); - File file = new File(context.getCacheDir(), name); - try { - InputStream inputStream = context.getContentResolver().openInputStream(uri); - FileOutputStream outputStream = new FileOutputStream(file); - int read = 0; - int maxBufferSize = 1 * 1024 * 1024; - int bytesAvailable = inputStream.available(); - - //int bufferSize = 1024; - int bufferSize = Math.min(bytesAvailable, maxBufferSize); - - final byte[] buffers = new byte[bufferSize]; - while ((read = inputStream.read(buffers)) != -1) { - outputStream.write(buffers, 0, read); - } - Log.e(TAG, "Size " + file.length()); - inputStream.close(); - outputStream.close(); - Log.e(TAG, "Path " + file.getPath()); - Log.e(TAG, "Size " + file.length()); - } catch (Exception e) { - Log.e(TAG, e.getMessage()); - } - - return file.getPath(); - } - - /*** - * Used for Android Q+ - * @param uri - * @param newDirName if you want to create a directory, you can set this variable - * @return - */ - private String copyFileToInternalStorage(Uri uri, String newDirName) { - Uri returnUri = uri; - - Cursor returnCursor = context.getContentResolver().query(returnUri, new String[] { - OpenableColumns.DISPLAY_NAME, OpenableColumns.SIZE - }, null, null, null); - - - /* - * Get the column indexes of the data in the Cursor, - * * move to the first row in the Cursor, get the data, - * * and display it. - * */ - int nameIndex = returnCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME); - int sizeIndex = returnCursor.getColumnIndex(OpenableColumns.SIZE); - returnCursor.moveToFirst(); - String name = (returnCursor.getString(nameIndex)); - String size = (Long.toString(returnCursor.getLong(sizeIndex))); - - File output; - if (!newDirName.equals("")) { - String random_collision_avoidance = UUID.randomUUID().toString(); - - File dir = new File(context.getFilesDir() + File.separator + newDirName + File.separator + random_collision_avoidance); - if (!dir.exists()) { - dir.mkdirs(); - } - output = new File(context.getFilesDir() + File.separator + newDirName + File.separator + random_collision_avoidance + File.separator + name); - } else { - output = new File(context.getFilesDir() + File.separator + name); - } - - try { - InputStream inputStream = context.getContentResolver().openInputStream(uri); - FileOutputStream outputStream = new FileOutputStream(output); - int read = 0; - int bufferSize = 1024; - final byte[] buffers = new byte[bufferSize]; - - while ((read = inputStream.read(buffers)) != -1) { - outputStream.write(buffers, 0, read); - } - - inputStream.close(); - outputStream.close(); - } catch (Exception e) { - Log.e(TAG, e.getMessage()); - } - - return output.getPath(); - } - - private String getFilePathForWhatsApp(Uri uri) { - return copyFileToInternalStorage(uri, "whatsapp"); - } - - private String getDataColumn(Context context, Uri uri, String selection, String[] selectionArgs) { - Cursor cursor = null; - final String column = "_data"; - final String[] projection = { - column - }; - - try { - cursor = context.getContentResolver().query(uri, projection, - selection, selectionArgs, null); - - if (cursor != null && cursor.moveToFirst()) { - final int index = cursor.getColumnIndexOrThrow(column); - return cursor.getString(index); - } - } finally { - if (cursor != null) - cursor.close(); - } - - return null; - } - - private static boolean isExternalStorageDocument(Uri uri) { - return "com.android.externalstorage.documents".equals(uri.getAuthority()); - } - - private static boolean isDownloadsDocument(Uri uri) { - return "com.android.providers.downloads.documents".equals(uri.getAuthority()); - } - - private boolean isMediaDocument(Uri uri) { - return "com.android.providers.media.documents".equals(uri.getAuthority()); - } - - private boolean isGooglePhotosUri(Uri uri) { - return "com.google.android.apps.photos.content".equals(uri.getAuthority()); - } - - public boolean isWhatsAppFile(Uri uri) { - return "com.whatsapp.provider.media".equals(uri.getAuthority()); - } - - private boolean isGoogleDriveUri(Uri uri) { - return "com.google.android.apps.docs.storage".equals(uri.getAuthority()) || "com.google.android.apps.docs.storage.legacy".equals(uri.getAuthority()); - } -} \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_compressing.xml b/app/src/main/res/layout/fragment_compressing.xml index fe873fe..115f498 100644 --- a/app/src/main/res/layout/fragment_compressing.xml +++ b/app/src/main/res/layout/fragment_compressing.xml @@ -1,13 +1,18 @@ - - - - - + + + + + \ No newline at end of file