mirror of
				https://github.com/KokaKiwi/BarInsta
				synced 2025-10-30 19:15:35 +00:00 
			
		
		
		
	made pr buildable (not functional)
This commit is contained in:
		
							parent
							
								
									d9da069d57
								
							
						
					
					
						commit
						b287f96415
					
				| @ -4,22 +4,19 @@ import android.content.Intent | |||||||
| import android.content.res.Configuration | import android.content.res.Configuration | ||||||
| import android.hardware.display.DisplayManager | import android.hardware.display.DisplayManager | ||||||
| import android.hardware.display.DisplayManager.DisplayListener | import android.hardware.display.DisplayManager.DisplayListener | ||||||
| import android.media.MediaScannerConnection |  | ||||||
| import android.net.Uri |  | ||||||
| import android.os.Bundle | import android.os.Bundle | ||||||
| import android.util.Log | import android.util.Log | ||||||
| import android.view.LayoutInflater | import android.view.LayoutInflater | ||||||
| import android.webkit.MimeTypeMap |  | ||||||
| import androidx.camera.core.* | import androidx.camera.core.* | ||||||
| import androidx.camera.lifecycle.ProcessCameraProvider | import androidx.camera.lifecycle.ProcessCameraProvider | ||||||
| import androidx.core.content.ContextCompat | import androidx.core.content.ContextCompat | ||||||
|  | import androidx.documentfile.provider.DocumentFile | ||||||
| import awais.instagrabber.databinding.ActivityCameraBinding | import awais.instagrabber.databinding.ActivityCameraBinding | ||||||
| import awais.instagrabber.utils.DirectoryUtils | import awais.instagrabber.utils.DownloadUtils | ||||||
| import awais.instagrabber.utils.PermissionUtils | import awais.instagrabber.utils.PermissionUtils | ||||||
| import awais.instagrabber.utils.Utils | import awais.instagrabber.utils.Utils | ||||||
| import awais.instagrabber.utils.extensions.TAG | import awais.instagrabber.utils.extensions.TAG | ||||||
| import com.google.common.io.Files | import java.io.IOException | ||||||
| import java.io.File |  | ||||||
| import java.text.SimpleDateFormat | import java.text.SimpleDateFormat | ||||||
| import java.util.* | import java.util.* | ||||||
| import java.util.concurrent.ExecutionException | import java.util.concurrent.ExecutionException | ||||||
| @ -28,10 +25,10 @@ import java.util.concurrent.Executors | |||||||
| 
 | 
 | ||||||
| class CameraActivity : BaseLanguageActivity() { | class CameraActivity : BaseLanguageActivity() { | ||||||
|     private lateinit var binding: ActivityCameraBinding |     private lateinit var binding: ActivityCameraBinding | ||||||
|     private lateinit var outputDirectory: File |  | ||||||
|     private lateinit var displayManager: DisplayManager |     private lateinit var displayManager: DisplayManager | ||||||
|     private lateinit var cameraExecutor: ExecutorService |     private lateinit var cameraExecutor: ExecutorService | ||||||
| 
 | 
 | ||||||
|  |     private var outputDirectory: DocumentFile? = null | ||||||
|     private var imageCapture: ImageCapture? = null |     private var imageCapture: ImageCapture? = null | ||||||
|     private var displayId = -1 |     private var displayId = -1 | ||||||
|     private var cameraProvider: ProcessCameraProvider? = null |     private var cameraProvider: ProcessCameraProvider? = null | ||||||
| @ -55,7 +52,7 @@ class CameraActivity : BaseLanguageActivity() { | |||||||
|         setContentView(binding.root) |         setContentView(binding.root) | ||||||
|         Utils.transparentStatusBar(this, true, false) |         Utils.transparentStatusBar(this, true, false) | ||||||
|         displayManager = getSystemService(DISPLAY_SERVICE) as DisplayManager |         displayManager = getSystemService(DISPLAY_SERVICE) as DisplayManager | ||||||
|         outputDirectory = DirectoryUtils.getOutputMediaDirectory(this, "Camera") |         outputDirectory = DownloadUtils.getCameraDir() | ||||||
|         cameraExecutor = Executors.newSingleThreadExecutor() |         cameraExecutor = Executors.newSingleThreadExecutor() | ||||||
|         displayManager.registerDisplayListener(displayListener, null) |         displayManager.registerDisplayListener(displayListener, null) | ||||||
|         binding.viewFinder.post { |         binding.viewFinder.post { | ||||||
| @ -176,33 +173,28 @@ class CameraActivity : BaseLanguageActivity() { | |||||||
| 
 | 
 | ||||||
|     private fun takePhoto() { |     private fun takePhoto() { | ||||||
|         if (imageCapture == null) return |         if (imageCapture == null) return | ||||||
|         val photoFile = File(outputDirectory, simpleDateFormat.format(System.currentTimeMillis()) + ".jpg") |         val fileName = simpleDateFormat.format(System.currentTimeMillis()) + ".jpg" | ||||||
|         val outputFileOptions = ImageCapture.OutputFileOptions.Builder(photoFile).build() |         val mimeType = "image/jpg" | ||||||
|  |         val photoFile = outputDirectory?.createFile(mimeType, fileName)?.let { it } ?: return | ||||||
|  |         val outputStream = contentResolver.openOutputStream(photoFile.uri)?.let { it } ?: return | ||||||
|  |         val outputFileOptions = ImageCapture.OutputFileOptions.Builder(outputStream).build() | ||||||
|         imageCapture?.takePicture( |         imageCapture?.takePicture( | ||||||
|             outputFileOptions, |             outputFileOptions, | ||||||
|             cameraExecutor, |             cameraExecutor, | ||||||
|             object : ImageCapture.OnImageSavedCallback { |             object : ImageCapture.OnImageSavedCallback { | ||||||
|                 @Suppress("UnstableApiUsage") |                 @Suppress("UnstableApiUsage") | ||||||
|                 override fun onImageSaved(outputFileResults: ImageCapture.OutputFileResults) { |                 override fun onImageSaved(outputFileResults: ImageCapture.OutputFileResults) { | ||||||
|                     val uri = Uri.fromFile(photoFile) |                     try { outputStream.close() } catch (ignored: IOException) {} | ||||||
|                     val mimeType = MimeTypeMap.getSingleton() |                     val intent = Intent() | ||||||
|                         .getMimeTypeFromExtension(Files.getFileExtension(photoFile.name)) |                     intent.data = photoFile.uri | ||||||
|                     MediaScannerConnection.scanFile( |                     setResult(RESULT_OK, intent) | ||||||
|                         this@CameraActivity, |                     finish() | ||||||
|                         arrayOf(photoFile.absolutePath), |                     Log.d(TAG, "onImageSaved: " + photoFile.uri) | ||||||
|                         arrayOf(mimeType) |  | ||||||
|                     ) { _: String?, uri1: Uri? -> |  | ||||||
|                         Log.d(TAG, "onImageSaved: scan complete") |  | ||||||
|                         val intent = Intent() |  | ||||||
|                         intent.data = uri1 |  | ||||||
|                         setResult(RESULT_OK, intent) |  | ||||||
|                         finish() |  | ||||||
|                     } |  | ||||||
|                     Log.d(TAG, "onImageSaved: $uri") |  | ||||||
|                 } |                 } | ||||||
| 
 | 
 | ||||||
|                 override fun onError(exception: ImageCaptureException) { |                 override fun onError(exception: ImageCaptureException) { | ||||||
|                     Log.e(TAG, "onError: ", exception) |                     Log.e(TAG, "onError: ", exception) | ||||||
|  |                     try { outputStream.close() } catch (ignored: IOException) {} | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|         ) |         ) | ||||||
|  | |||||||
| @ -39,7 +39,7 @@ public class DirectorySelectActivity extends BaseLanguageActivity { | |||||||
|         viewModel = new ViewModelProvider(this).get(DirectorySelectActivityViewModel.class); |         viewModel = new ViewModelProvider(this).get(DirectorySelectActivityViewModel.class); | ||||||
|         setupObservers(); |         setupObservers(); | ||||||
|         binding.selectDir.setOnClickListener(v -> openDirectoryChooser()); |         binding.selectDir.setOnClickListener(v -> openDirectoryChooser()); | ||||||
|         AppExecutors.getInstance().mainThread().execute(() -> viewModel.setInitialUri(getIntent())); |         AppExecutors.INSTANCE.getMainThread().execute(() -> viewModel.setInitialUri(getIntent())); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private void setupObservers() { |     private void setupObservers() { | ||||||
| @ -81,7 +81,7 @@ public class DirectorySelectActivity extends BaseLanguageActivity { | |||||||
|             showErrorDialog(getString(R.string.select_a_folder)); |             showErrorDialog(getString(R.string.select_a_folder)); | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
|         AppExecutors.getInstance().mainThread().execute(() -> { |         AppExecutors.INSTANCE.getMainThread().execute(() -> { | ||||||
|             try { |             try { | ||||||
|                 viewModel.setupSelectedDir(data); |                 viewModel.setupSelectedDir(data); | ||||||
|                 final Intent intent = new Intent(this, MainActivity.class); |                 final Intent intent = new Intent(this, MainActivity.class); | ||||||
|  | |||||||
| @ -207,8 +207,7 @@ public class CreateBackupDialogFragment extends DialogFragment { | |||||||
|         Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT); |         Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT); | ||||||
|         intent.addCategory(Intent.CATEGORY_OPENABLE); |         intent.addCategory(Intent.CATEGORY_OPENABLE); | ||||||
|         intent.setType("application/octet-stream"); |         intent.setType("application/octet-stream"); | ||||||
|         final Date now = new Date(); |         final String fileName = String.format("barinsta_%s.backup", LocalDateTime.now().format(BACKUP_FILE_DATE_TIME_FORMAT)); | ||||||
|         final String fileName = String.format("barinsta_%s.backup", BACKUP_FILE_DATE_TIME_FORMAT.format(now)); |  | ||||||
|         intent.putExtra(Intent.EXTRA_TITLE, fileName); |         intent.putExtra(Intent.EXTRA_TITLE, fileName); | ||||||
| 
 | 
 | ||||||
|         // Optionally, specify a URI for the directory that should be opened in |         // Optionally, specify a URI for the directory that should be opened in | ||||||
|  | |||||||
| @ -115,7 +115,7 @@ public class RestoreBackupDialogFragment extends DialogFragment { | |||||||
|             binding.btnRestore.setEnabled(true); |             binding.btnRestore.setEnabled(true); | ||||||
|         } |         } | ||||||
|         uri = data.getData(); |         uri = data.getData(); | ||||||
|         AppExecutors.getInstance().mainThread().execute(() -> { |         AppExecutors.INSTANCE.getMainThread().execute(() -> { | ||||||
|             Cursor c = null; |             Cursor c = null; | ||||||
|             try { |             try { | ||||||
|                 String[] projection = {MediaStore.Files.FileColumns.DISPLAY_NAME}; |                 String[] projection = {MediaStore.Files.FileColumns.DISPLAY_NAME}; | ||||||
|  | |||||||
| @ -183,11 +183,12 @@ public class ImageEditFragment extends Fragment { | |||||||
|             if (context == null) return; |             if (context == null) return; | ||||||
|             final Uri resultUri = viewModel.getResultUri().getValue(); |             final Uri resultUri = viewModel.getResultUri().getValue(); | ||||||
|             if (resultUri == null) return; |             if (resultUri == null) return; | ||||||
|             Utils.mediaScanFile(context, new File(resultUri.toString()), (path, uri) -> AppExecutors.INSTANCE.getMainThread().execute(() -> { |             AppExecutors.INSTANCE.getMainThread().execute(() -> { | ||||||
|                 final NavController navController = NavHostFragment.findNavController(this); |                 final NavController navController = NavHostFragment.findNavController(this); | ||||||
|                 setNavControllerResult(navController, resultUri); |                 setNavControllerResult(navController, resultUri); | ||||||
|                 navController.navigateUp(); |                 navController.navigateUp(); | ||||||
|             })); |             }); | ||||||
|  |             // Utils.mediaScanFile(context, new File(resultUri.toString()), (path, uri) -> ); | ||||||
|         }); |         }); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -19,6 +19,7 @@ object PreferenceKeys { | |||||||
|     const val APP_THEME = "app_theme_v19" |     const val APP_THEME = "app_theme_v19" | ||||||
|     const val APP_LANGUAGE = "app_language_v19" |     const val APP_LANGUAGE = "app_language_v19" | ||||||
|     const val STORY_SORT = "story_sort" |     const val STORY_SORT = "story_sort" | ||||||
|  |     const val PREF_BARINSTA_DIR_URI = "barinsta_dir_uri" | ||||||
| 
 | 
 | ||||||
|     // set string prefs |     // set string prefs | ||||||
|     const val KEYWORD_FILTERS = "keyword_filters" |     const val KEYWORD_FILTERS = "keyword_filters" | ||||||
|  | |||||||
| @ -8,6 +8,7 @@ import android.net.Uri | |||||||
| import android.util.Log | import android.util.Log | ||||||
| import android.util.LruCache | import android.util.LruCache | ||||||
| import androidx.core.util.Pair | import androidx.core.util.Pair | ||||||
|  | import androidx.documentfile.provider.DocumentFile | ||||||
| import awais.instagrabber.utils.extensions.TAG | import awais.instagrabber.utils.extensions.TAG | ||||||
| import kotlinx.coroutines.Dispatchers | import kotlinx.coroutines.Dispatchers | ||||||
| import kotlinx.coroutines.withContext | import kotlinx.coroutines.withContext | ||||||
| @ -192,9 +193,9 @@ object BitmapUtils { | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @Throws(IOException::class) |     @Throws(IOException::class) | ||||||
|     fun convertToJpegAndSaveToFile(bitmap: Bitmap, file: File?): File { |     fun convertToJpegAndSaveToFile(contentResolver: ContentResolver, bitmap: Bitmap, file: DocumentFile?): DocumentFile { | ||||||
|         val tempFile = file ?: DownloadUtils.getTempFile() |         val tempFile = file ?: DownloadUtils.getTempFile(null, "jpg") | ||||||
|         FileOutputStream(tempFile).use { output -> |         contentResolver.openOutputStream(tempFile.uri).use { output -> | ||||||
|             val compressResult = bitmap.compress(Bitmap.CompressFormat.JPEG, 100, output) |             val compressResult = bitmap.compress(Bitmap.CompressFormat.JPEG, 100, output) | ||||||
|             if (!compressResult) { |             if (!compressResult) { | ||||||
|                 throw RuntimeException("Compression failed!") |                 throw RuntimeException("Compression failed!") | ||||||
|  | |||||||
| @ -89,4 +89,5 @@ object Constants { | |||||||
|     const val DM_THREAD_ACTION_EXTRA_THREAD_ID = "thread_id" |     const val DM_THREAD_ACTION_EXTRA_THREAD_ID = "thread_id" | ||||||
|     const val DM_THREAD_ACTION_EXTRA_THREAD_TITLE = "thread_title" |     const val DM_THREAD_ACTION_EXTRA_THREAD_TITLE = "thread_title" | ||||||
|     const val X_IG_APP_ID = "936619743392459" |     const val X_IG_APP_ID = "936619743392459" | ||||||
|  |     const val EXTRA_INITIAL_URI = "initial_uri" | ||||||
| } | } | ||||||
| @ -4,6 +4,7 @@ import android.content.ContentResolver; | |||||||
| import android.content.Context; | import android.content.Context; | ||||||
| import android.content.DialogInterface; | import android.content.DialogInterface; | ||||||
| import android.content.UriPermission; | import android.content.UriPermission; | ||||||
|  | import android.Manifest; | ||||||
| import android.net.Uri; | import android.net.Uri; | ||||||
| import android.util.Log; | import android.util.Log; | ||||||
| import android.webkit.MimeTypeMap; | import android.webkit.MimeTypeMap; | ||||||
| @ -59,6 +60,9 @@ public final class DownloadUtils { | |||||||
| 
 | 
 | ||||||
|     private static DocumentFile root; |     private static DocumentFile root; | ||||||
| 
 | 
 | ||||||
|  |     public static final String WRITE_PERMISSION = Manifest.permission.WRITE_EXTERNAL_STORAGE; | ||||||
|  |     public static final String[] PERMS = new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}; | ||||||
|  | 
 | ||||||
|     public static void init(@NonNull final Context context) throws ReselectDocumentTreeException { |     public static void init(@NonNull final Context context) throws ReselectDocumentTreeException { | ||||||
|         final String barinstaDirUri = Utils.settingsHelper.getString(PREF_BARINSTA_DIR_URI); |         final String barinstaDirUri = Utils.settingsHelper.getString(PREF_BARINSTA_DIR_URI); | ||||||
|         if (TextUtils.isEmpty(barinstaDirUri)) { |         if (TextUtils.isEmpty(barinstaDirUri)) { | ||||||
| @ -177,7 +181,7 @@ public final class DownloadUtils { | |||||||
| 
 | 
 | ||||||
|     private static List<String> getSubPathForUserFolder(final String username) { |     private static List<String> getSubPathForUserFolder(final String username) { | ||||||
|         final List<String> list = new ArrayList<>(); |         final List<String> list = new ArrayList<>(); | ||||||
|         if (!Utils.settingsHelper.getBoolean(Constants.DOWNLOAD_USER_FOLDER) || TextUtils.isEmpty(username)) { |         if (!Utils.settingsHelper.getBoolean(PreferenceKeys.DOWNLOAD_USER_FOLDER) || TextUtils.isEmpty(username)) { | ||||||
|             list.add(DIR_DOWNLOADS); |             list.add(DIR_DOWNLOADS); | ||||||
|             return list; |             return list; | ||||||
|         } |         } | ||||||
| @ -425,7 +429,7 @@ public final class DownloadUtils { | |||||||
|         final String extension = DownloadUtils.getFileExtensionFromUrl(url); |         final String extension = DownloadUtils.getFileExtensionFromUrl(url); | ||||||
|         final String baseFileName = storyModel.getStoryMediaId() + "_" |         final String baseFileName = storyModel.getStoryMediaId() + "_" | ||||||
|                 + storyModel.getTimestamp() + extension; |                 + storyModel.getTimestamp() + extension; | ||||||
|         final String usernamePrepend = Utils.settingsHelper.getBoolean(Constants.DOWNLOAD_PREPEND_USER_NAME) |         final String usernamePrepend = Utils.settingsHelper.getBoolean(PreferenceKeys.DOWNLOAD_PREPEND_USER_NAME) | ||||||
|                                                && storyModel.getUsername() != null ? storyModel.getUsername() + "_" : ""; |                                                && storyModel.getUsername() != null ? storyModel.getUsername() + "_" : ""; | ||||||
|         final String fileName = usernamePrepend + baseFileName; |         final String fileName = usernamePrepend + baseFileName; | ||||||
|         DocumentFile saveFile = downloadDir.findFile(fileName); |         DocumentFile saveFile = downloadDir.findFile(fileName); | ||||||
| @ -501,7 +505,7 @@ public final class DownloadUtils { | |||||||
|                         if (childPositionIfSingle >= 0 && feedModels.size() == 1 && i != childPositionIfSingle) continue; |                         if (childPositionIfSingle >= 0 && feedModels.size() == 1 && i != childPositionIfSingle) continue; | ||||||
|                         final Media child = sliderItems.get(i); |                         final Media child = sliderItems.get(i); | ||||||
|                         final String url = getUrlOfType(child); |                         final String url = getUrlOfType(child); | ||||||
|                         final String usernamePrepend = Utils.settingsHelper.getBoolean(Constants.DOWNLOAD_PREPEND_USER_NAME) && mediaUser != null |                         final String usernamePrepend = Utils.settingsHelper.getBoolean(PreferenceKeys.DOWNLOAD_PREPEND_USER_NAME) && mediaUser != null | ||||||
|                                                        ? mediaUser.getUsername() |                                                        ? mediaUser.getUsername() | ||||||
|                                                        : ""; |                                                        : ""; | ||||||
|                         final Pair<List<String>, String> pair = getDownloadChildSavePaths( |                         final Pair<List<String>, String> pair = getDownloadChildSavePaths( | ||||||
|  | |||||||
| @ -3,6 +3,7 @@ package awais.instagrabber.utils | |||||||
| import android.content.ContentResolver | import android.content.ContentResolver | ||||||
| import android.graphics.Bitmap | import android.graphics.Bitmap | ||||||
| import android.net.Uri | import android.net.Uri | ||||||
|  | import androidx.documentfile.provider.DocumentFile | ||||||
| import awais.instagrabber.models.UploadVideoOptions | import awais.instagrabber.models.UploadVideoOptions | ||||||
| import awais.instagrabber.webservices.interceptors.AddCookiesInterceptor | import awais.instagrabber.webservices.interceptors.AddCookiesInterceptor | ||||||
| import kotlinx.coroutines.Dispatchers | import kotlinx.coroutines.Dispatchers | ||||||
| @ -12,8 +13,6 @@ import okio.BufferedSink | |||||||
| import okio.Okio | import okio.Okio | ||||||
| import org.json.JSONObject | import org.json.JSONObject | ||||||
| import ru.gildor.coroutines.okhttp.await | import ru.gildor.coroutines.okhttp.await | ||||||
| import java.io.File |  | ||||||
| import java.io.FileInputStream |  | ||||||
| import java.io.IOException | import java.io.IOException | ||||||
| import java.io.InputStream | import java.io.InputStream | ||||||
| 
 | 
 | ||||||
| @ -29,20 +28,23 @@ object MediaUploader { | |||||||
|     ): MediaUploadResponse = withContext(Dispatchers.IO) { |     ): MediaUploadResponse = withContext(Dispatchers.IO) { | ||||||
|         val bitmapResult = BitmapUtils.loadBitmap(contentResolver, uri, 1000f, false) |         val bitmapResult = BitmapUtils.loadBitmap(contentResolver, uri, 1000f, false) | ||||||
|         val bitmap = bitmapResult?.bitmap ?: throw IOException("bitmap is null") |         val bitmap = bitmapResult?.bitmap ?: throw IOException("bitmap is null") | ||||||
|         uploadPhoto(bitmap) |         uploadPhoto(contentResolver, bitmap) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @Suppress("BlockingMethodInNonBlockingContext") |     @Suppress("BlockingMethodInNonBlockingContext") | ||||||
|     private suspend fun uploadPhoto( |     private suspend fun uploadPhoto( | ||||||
|  |         contentResolver: ContentResolver, | ||||||
|         bitmap: Bitmap, |         bitmap: Bitmap, | ||||||
|     ): MediaUploadResponse = withContext(Dispatchers.IO) { |     ): MediaUploadResponse = withContext(Dispatchers.IO) { | ||||||
|         val file: File = BitmapUtils.convertToJpegAndSaveToFile(bitmap, null) |         val file: DocumentFile = BitmapUtils.convertToJpegAndSaveToFile(contentResolver, bitmap, null) | ||||||
|         val byteLength: Long = file.length() |         val byteLength: Long = file.length() | ||||||
|         val options = createUploadPhotoOptions(byteLength) |         val options = createUploadPhotoOptions(byteLength) | ||||||
|         val headers = getUploadPhotoHeaders(options) |         val headers = getUploadPhotoHeaders(options) | ||||||
|         val url = HOST + "/rupload_igphoto/" + options.name + "/" |         val url = HOST + "/rupload_igphoto/" + options.name + "/" | ||||||
|         try { |         try { | ||||||
|             FileInputStream(file).use { input -> upload(input, url, headers) } |             contentResolver.openInputStream(file.uri).use { input -> | ||||||
|  |                 upload(input!!, url, headers) | ||||||
|  |             } | ||||||
|         } finally { |         } finally { | ||||||
|             file.delete() |             file.delete() | ||||||
|         } |         } | ||||||
|  | |||||||
| @ -57,7 +57,7 @@ public final class MediaUtils { | |||||||
|     public static void getVoiceInfo(@NonNull final ContentResolver contentResolver, |     public static void getVoiceInfo(@NonNull final ContentResolver contentResolver, | ||||||
|                                     @NonNull final Uri uri, |                                     @NonNull final Uri uri, | ||||||
|                                     @NonNull final OnInfoLoadListener<VideoInfo> listener) { |                                     @NonNull final OnInfoLoadListener<VideoInfo> listener) { | ||||||
|         AppExecutors.getInstance().tasksThread().submit(() -> { |         AppExecutors.INSTANCE.getTasksThread().submit(() -> { | ||||||
|             try (ParcelFileDescriptor parcelFileDescriptor = contentResolver.openFileDescriptor(uri, "r")) { |             try (ParcelFileDescriptor parcelFileDescriptor = contentResolver.openFileDescriptor(uri, "r")) { | ||||||
|                 if (parcelFileDescriptor == null) { |                 if (parcelFileDescriptor == null) { | ||||||
|                     listener.onLoad(null); |                     listener.onLoad(null); | ||||||
|  | |||||||
| @ -1,6 +1,7 @@ | |||||||
| package awais.instagrabber.utils; | package awais.instagrabber.utils; | ||||||
| 
 | 
 | ||||||
| import android.app.Application; | import android.app.Application; | ||||||
|  | import android.content.ContentResolver; | ||||||
| import android.media.MediaRecorder; | import android.media.MediaRecorder; | ||||||
| import android.os.Handler; | import android.os.Handler; | ||||||
| import android.os.Message; | import android.os.Message; | ||||||
| @ -44,7 +45,7 @@ public class VoiceRecorder { | |||||||
|         this.callback = callback; |         this.callback = callback; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public void startRecording(final Application application) { |     public void startRecording(final ContentResolver contentResolver) { | ||||||
|         stopped = false; |         stopped = false; | ||||||
|         ParcelFileDescriptor parcelFileDescriptor = null; |         ParcelFileDescriptor parcelFileDescriptor = null; | ||||||
|         try { |         try { | ||||||
| @ -53,7 +54,7 @@ public class VoiceRecorder { | |||||||
|             recorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4); |             recorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4); | ||||||
|             deleteTempAudioFile(); |             deleteTempAudioFile(); | ||||||
|             audioTempFile = getAudioRecordFile(); |             audioTempFile = getAudioRecordFile(); | ||||||
|             parcelFileDescriptor = application.getContentResolver().openFileDescriptor(audioTempFile.getUri(), "rwt"); |             parcelFileDescriptor = contentResolver.openFileDescriptor(audioTempFile.getUri(), "rwt"); | ||||||
|             recorder.setOutputFile(parcelFileDescriptor.getFileDescriptor()); |             recorder.setOutputFile(parcelFileDescriptor.getFileDescriptor()); | ||||||
|             recorder.setAudioEncoder(MediaRecorder.AudioEncoder.HE_AAC); |             recorder.setAudioEncoder(MediaRecorder.AudioEncoder.HE_AAC); | ||||||
|             recorder.setAudioEncodingBitRate(AUDIO_BIT_RATE); |             recorder.setAudioEncodingBitRate(AUDIO_BIT_RATE); | ||||||
|  | |||||||
| @ -1,10 +1,10 @@ | |||||||
| package awais.instagrabber.viewmodels | package awais.instagrabber.viewmodels | ||||||
| 
 | 
 | ||||||
|  | import android.R.attr | ||||||
| import android.app.Application | import android.app.Application | ||||||
| import android.content.ContentResolver | import android.content.ContentResolver | ||||||
| import android.media.MediaScannerConnection |  | ||||||
| import android.net.Uri | import android.net.Uri | ||||||
| import android.util.Log | import androidx.documentfile.provider.DocumentFile | ||||||
| import androidx.lifecycle.* | import androidx.lifecycle.* | ||||||
| import awais.instagrabber.customviews.emoji.Emoji | import awais.instagrabber.customviews.emoji.Emoji | ||||||
| import awais.instagrabber.managers.DirectMessagesManager | import awais.instagrabber.managers.DirectMessagesManager | ||||||
| @ -23,10 +23,9 @@ import awais.instagrabber.utils.MediaUtils.OnInfoLoadListener | |||||||
| import awais.instagrabber.utils.MediaUtils.VideoInfo | import awais.instagrabber.utils.MediaUtils.VideoInfo | ||||||
| import awais.instagrabber.utils.VoiceRecorder.VoiceRecorderCallback | import awais.instagrabber.utils.VoiceRecorder.VoiceRecorderCallback | ||||||
| import awais.instagrabber.utils.VoiceRecorder.VoiceRecordingResult | import awais.instagrabber.utils.VoiceRecorder.VoiceRecordingResult | ||||||
| import awais.instagrabber.utils.extensions.TAG |  | ||||||
| import java.io.File |  | ||||||
| import java.util.* | import java.util.* | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| class DirectThreadViewModel( | class DirectThreadViewModel( | ||||||
|     application: Application, |     application: Application, | ||||||
|     val threadId: String, |     val threadId: String, | ||||||
| @ -37,7 +36,7 @@ class DirectThreadViewModel( | |||||||
| 
 | 
 | ||||||
|     // private static final String ERROR_INVALID_THREAD = "Invalid thread"; |     // private static final String ERROR_INVALID_THREAD = "Invalid thread"; | ||||||
|     private val contentResolver: ContentResolver = application.contentResolver |     private val contentResolver: ContentResolver = application.contentResolver | ||||||
|     private val recordingsDir: File = DirectoryUtils.getOutputMediaDirectory(application, "Recordings") |     private val recordingsDir: DocumentFile? = DownloadUtils.getRecordingsDir() | ||||||
|     private var voiceRecorder: VoiceRecorder? = null |     private var voiceRecorder: VoiceRecorder? = null | ||||||
|     private lateinit var threadManager: ThreadManager |     private lateinit var threadManager: ThreadManager | ||||||
| 
 | 
 | ||||||
| @ -87,33 +86,24 @@ class DirectThreadViewModel( | |||||||
| 
 | 
 | ||||||
|     fun startRecording(): LiveData<Resource<Any?>> { |     fun startRecording(): LiveData<Resource<Any?>> { | ||||||
|         val data = MutableLiveData<Resource<Any?>>() |         val data = MutableLiveData<Resource<Any?>>() | ||||||
|         voiceRecorder = VoiceRecorder(recordingsDir, object : VoiceRecorderCallback { |         voiceRecorder = VoiceRecorder(recordingsDir!!, object : VoiceRecorderCallback { | ||||||
|             override fun onStart() {} |             override fun onStart() {} | ||||||
|             override fun onComplete(result: VoiceRecordingResult) { |             override fun onComplete(result: VoiceRecordingResult) { | ||||||
|                 Log.d(TAG, "onComplete: recording complete. Scanning file...") |                 // Log.d(TAG, "onComplete: recording complete. Scanning file..."); | ||||||
|                 MediaScannerConnection.scanFile( |                 MediaUtils.getVoiceInfo( | ||||||
|                     getApplication(), |                     contentResolver, | ||||||
|                     arrayOf(result.file.absolutePath), |                     result.file.uri, | ||||||
|                     arrayOf(result.mimeType) |                     object : OnInfoLoadListener<VideoInfo?> { | ||||||
|                 ) { _: String?, uri: Uri? -> |  | ||||||
|                     if (uri == null) { |  | ||||||
|                         val msg = "Scan failed!" |  | ||||||
|                         Log.e(TAG, msg) |  | ||||||
|                         data.postValue(error(msg, null)) |  | ||||||
|                         return@scanFile |  | ||||||
|                     } |  | ||||||
|                     Log.d(TAG, "onComplete: scan complete") |  | ||||||
|                     MediaUtils.getVoiceInfo(contentResolver, uri, object : OnInfoLoadListener<VideoInfo?> { |  | ||||||
|                         override fun onLoad(videoInfo: VideoInfo?) { |                         override fun onLoad(videoInfo: VideoInfo?) { | ||||||
|                             if (videoInfo == null) return |                             if (videoInfo == null) return | ||||||
|                             threadManager.sendVoice( |                             threadManager.sendVoice( | ||||||
|                                 data, |                                 data, | ||||||
|                                 uri, |                                 result.file.uri, | ||||||
|                                 result.waveform, |                                 result.waveform, | ||||||
|                                 result.samplingFreq, |                                 result.samplingFreq, | ||||||
|                                 videoInfo.duration, |                                 videoInfo.duration, | ||||||
|                                 videoInfo.size, |                                 result.file.length(), | ||||||
|                                 viewModelScope, |                                 viewModelScope | ||||||
|                             ) |                             ) | ||||||
|                         } |                         } | ||||||
| 
 | 
 | ||||||
| @ -121,12 +111,11 @@ class DirectThreadViewModel( | |||||||
|                             data.postValue(error(t.message, null)) |                             data.postValue(error(t.message, null)) | ||||||
|                         } |                         } | ||||||
|                     }) |                     }) | ||||||
|                 } |  | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             override fun onCancel() {} |             override fun onCancel() {} | ||||||
|         }) |         }) | ||||||
|         voiceRecorder?.startRecording() |         voiceRecorder?.startRecording(contentResolver) | ||||||
|         return data |         return data | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -24,6 +24,8 @@ import awais.instagrabber.utils.DownloadUtils; | |||||||
| import awais.instagrabber.utils.TextUtils; | import awais.instagrabber.utils.TextUtils; | ||||||
| import awais.instagrabber.utils.Utils; | import awais.instagrabber.utils.Utils; | ||||||
| 
 | 
 | ||||||
|  | import static awais.instagrabber.fragments.settings.PreferenceKeys.FOLDER_PATH; | ||||||
|  | 
 | ||||||
| public class DirectorySelectActivityViewModel extends AndroidViewModel { | public class DirectorySelectActivityViewModel extends AndroidViewModel { | ||||||
|     private static final String TAG = DirectorySelectActivityViewModel.class.getSimpleName(); |     private static final String TAG = DirectorySelectActivityViewModel.class.getSimpleName(); | ||||||
| 
 | 
 | ||||||
| @ -67,7 +69,7 @@ public class DirectorySelectActivityViewModel extends AndroidViewModel { | |||||||
| 
 | 
 | ||||||
|     private void setMessage(@Nullable final Uri initialUri) { |     private void setMessage(@Nullable final Uri initialUri) { | ||||||
|         if (initialUri == null) { |         if (initialUri == null) { | ||||||
|             final String prevVersionFolderPath = Utils.settingsHelper.getString(Constants.FOLDER_PATH); |             final String prevVersionFolderPath = Utils.settingsHelper.getString(FOLDER_PATH); | ||||||
|             if (TextUtils.isEmpty(prevVersionFolderPath)) { |             if (TextUtils.isEmpty(prevVersionFolderPath)) { | ||||||
|                 // default message |                 // default message | ||||||
|                 message.postValue(getApplication().getString(R.string.dir_select_default_message)); |                 message.postValue(getApplication().getString(R.string.dir_select_default_message)); | ||||||
|  | |||||||
| @ -6,8 +6,8 @@ import android.content.ContentResolver | |||||||
| import android.content.Context | import android.content.Context | ||||||
| import android.content.Intent | import android.content.Intent | ||||||
| import android.graphics.Bitmap | import android.graphics.Bitmap | ||||||
|  | import android.graphics.BitmapFactory | ||||||
| import android.media.MediaMetadataRetriever | import android.media.MediaMetadataRetriever | ||||||
| import android.media.MediaScannerConnection |  | ||||||
| import android.net.Uri | import android.net.Uri | ||||||
| import android.os.Build | import android.os.Build | ||||||
| import android.os.Handler | import android.os.Handler | ||||||
| @ -15,7 +15,7 @@ import android.os.Looper | |||||||
| import android.util.Log | import android.util.Log | ||||||
| import androidx.core.app.NotificationCompat | import androidx.core.app.NotificationCompat | ||||||
| import androidx.core.app.NotificationManagerCompat | import androidx.core.app.NotificationManagerCompat | ||||||
| import androidx.core.content.FileProvider | import androidx.documentfile.provider.DocumentFile | ||||||
| import androidx.work.CoroutineWorker | import androidx.work.CoroutineWorker | ||||||
| import androidx.work.Data | import androidx.work.Data | ||||||
| import androidx.work.ForegroundInfo | import androidx.work.ForegroundInfo | ||||||
| @ -37,13 +37,12 @@ import kotlinx.coroutines.withContext | |||||||
| import org.apache.commons.imaging.formats.jpeg.iptc.JpegIptcRewriter | import org.apache.commons.imaging.formats.jpeg.iptc.JpegIptcRewriter | ||||||
| import java.io.BufferedInputStream | import java.io.BufferedInputStream | ||||||
| import java.io.File | import java.io.File | ||||||
| import java.io.FileInputStream |  | ||||||
| import java.io.FileOutputStream |  | ||||||
| import java.net.URL | import java.net.URL | ||||||
| import java.util.* | import java.util.* | ||||||
| import java.util.concurrent.ExecutionException | import java.util.concurrent.ExecutionException | ||||||
| import kotlin.math.abs | import kotlin.math.abs | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| class DownloadWorker(context: Context, workerParams: WorkerParameters) : CoroutineWorker(context, workerParams) { | class DownloadWorker(context: Context, workerParams: WorkerParameters) : CoroutineWorker(context, workerParams) { | ||||||
|     private val notificationManager: NotificationManagerCompat = NotificationManagerCompat.from(context) |     private val notificationManager: NotificationManagerCompat = NotificationManagerCompat.from(context) | ||||||
| 
 | 
 | ||||||
| @ -89,15 +88,15 @@ class DownloadWorker(context: Context, workerParams: WorkerParameters) : Corouti | |||||||
|         return Result.success() |         return Result.success() | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private suspend fun download(urlToFilePathMap: Map<String, String>) { |     private suspend fun download(urlToFilePathMap: Map<String, DocumentFile>) { | ||||||
|         val notificationId = notificationId |         val notificationId = notificationId | ||||||
|         val entries = urlToFilePathMap.entries |         val entries = urlToFilePathMap.entries | ||||||
|         var count = 1 |         var count = 1 | ||||||
|         val total = urlToFilePathMap.size |         val total = urlToFilePathMap.size | ||||||
|         for ((url, value) in entries) { |         for ((url, file) in entries) { | ||||||
|             updateDownloadProgress(notificationId, count, total, 0f) |             updateDownloadProgress(notificationId, count, total, 0f) | ||||||
|             withContext(Dispatchers.IO) { |             withContext(Dispatchers.IO) { | ||||||
|                 download(notificationId, count, total, url, value) |                 download(notificationId, count, total, url, file) | ||||||
|             } |             } | ||||||
|             count++ |             count++ | ||||||
|         } |         } | ||||||
| @ -111,47 +110,49 @@ class DownloadWorker(context: Context, workerParams: WorkerParameters) : Corouti | |||||||
|         position: Int, |         position: Int, | ||||||
|         total: Int, |         total: Int, | ||||||
|         url: String, |         url: String, | ||||||
|         filePath: String, |         filePath: DocumentFile, | ||||||
|     ) { |     ) { | ||||||
|         val isJpg = filePath.endsWith("jpg") |         val context = applicationContext.let { it } | ||||||
|  |         val contentResolver = context.contentResolver?.let { it } ?: return | ||||||
|  |         val filePathType = filePath.type?.let { it } ?: return | ||||||
|  |         val isJpg = filePathType.startsWith("image") | ||||||
|         // using temp file approach to remove IPTC so that download progress can be reported |         // using temp file approach to remove IPTC so that download progress can be reported | ||||||
|         val outFile = if (isJpg) DownloadUtils.getTempFile() else File(filePath) |         val outFile = if (isJpg) DownloadUtils.getTempFile(null, "jpg") else filePath | ||||||
|         try { |         try { | ||||||
|             val urlConnection = URL(url).openConnection() |             val urlConnection = URL(url).openConnection() | ||||||
|             val fileSize = if (Build.VERSION.SDK_INT >= 24) urlConnection.contentLengthLong else urlConnection.contentLength.toLong() |             val fileSize = if (Build.VERSION.SDK_INT >= 24) urlConnection.contentLengthLong else urlConnection.contentLength.toLong() | ||||||
|             var totalRead = 0f |             var totalRead = 0f | ||||||
|             try { |             try { | ||||||
|                 BufferedInputStream(urlConnection.getInputStream()).use { bis -> |                 BufferedInputStream(urlConnection.getInputStream()).use { bis -> | ||||||
|                     FileOutputStream(outFile).use { fos -> |                     contentResolver.openOutputStream(outFile.uri).use { fos -> | ||||||
|                         val buffer = ByteArray(0x2000) |                         val buffer = ByteArray(0x2000) | ||||||
|                         var count: Int |                         var count: Int | ||||||
|                         while (bis.read(buffer, 0, 0x2000).also { count = it } != -1) { |                         while (bis.read(buffer, 0, 0x2000).also { count = it } != -1) { | ||||||
|                             totalRead += count |                             totalRead += count | ||||||
|                             fos.write(buffer, 0, count) |                             fos!!.write(buffer, 0, count) | ||||||
|                             setProgressAsync(Data.Builder().putString(URL, url) |                             setProgressAsync(Data.Builder().putString(URL, url) | ||||||
|                                 .putFloat(PROGRESS, totalRead * 100f / fileSize) |                                 .putFloat(PROGRESS, totalRead * 100f / fileSize) | ||||||
|                                 .build()) |                                 .build()) | ||||||
|                             updateDownloadProgress(notificationId, position, total, totalRead * 100f / fileSize) |                             updateDownloadProgress(notificationId, position, total, totalRead * 100f / fileSize) | ||||||
|                         } |                         } | ||||||
|                         fos.flush() |                         fos!!.flush() | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|             } catch (e: Exception) { |             } catch (e: Exception) { | ||||||
|                 Log.e(TAG, "Error while writing data from url: " + url + " to file: " + outFile.absolutePath, e) |                 Log.e(TAG, "Error while writing data from url: " + url + " to file: " + outFile.name, e) | ||||||
|             } |             } | ||||||
|             if (isJpg) { |             if (isJpg) { | ||||||
|                 val finalFile = File(filePath) |  | ||||||
|                 try { |                 try { | ||||||
|                     FileInputStream(outFile).use { fis -> |                     contentResolver.openInputStream(outFile.uri).use { fis -> | ||||||
|                         FileOutputStream(finalFile).use { fos -> |                         contentResolver.openOutputStream(filePath.uri).use { fos -> | ||||||
|                             val jpegIptcRewriter = JpegIptcRewriter() |                             val jpegIptcRewriter = JpegIptcRewriter() | ||||||
|                             jpegIptcRewriter.removeIPTC(fis, fos) |                             jpegIptcRewriter.removeIPTC(fis, fos) | ||||||
|                         } |                         } | ||||||
|                     } |                     } | ||||||
|                 } catch (e: Exception) { |                 } catch (e: Exception) { | ||||||
|                     Log.e(TAG, "Error while removing iptc: url: " + url |                     Log.e(TAG, "Error while removing iptc: url: " + url | ||||||
|                                + ", tempFile: " + outFile.absolutePath |                                + ", tempFile: " + outFile.name | ||||||
|                                + ", finalFile: " + finalFile.absolutePath, e) |                                + ", finalFile: " + filePath.name, e) | ||||||
|                 } |                 } | ||||||
|                 val deleted = outFile.delete() |                 val deleted = outFile.delete() | ||||||
|                 if (!deleted) { |                 if (!deleted) { | ||||||
| @ -218,53 +219,90 @@ class DownloadWorker(context: Context, workerParams: WorkerParameters) : Corouti | |||||||
|         return builder.build() |         return builder.build() | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private fun showSummary(urlToFilePathMap: Map<String, String>?) { |     private fun showSummary(urlToFilePathMap: Map<String, DocumentFile>?) { | ||||||
|         val context = applicationContext |         val context = applicationContext | ||||||
|         val filePaths = urlToFilePathMap!!.values |         val filePaths = urlToFilePathMap!!.values | ||||||
|         val notifications: MutableList<NotificationCompat.Builder> = LinkedList() |         val notifications: MutableList<NotificationCompat.Builder> = LinkedList() | ||||||
|         val notificationIds: MutableList<Int> = LinkedList() |         val notificationIds: MutableList<Int> = LinkedList() | ||||||
|         var count = 1 |         var count = 1 | ||||||
|         for (filePath in filePaths) { |         for (filePath: DocumentFile in filePaths) { | ||||||
|             val file = File(filePath) |             // final File file = new File(filePath); | ||||||
|             context.sendBroadcast(Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.fromFile(file))) |             // context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, filePath.getUri())); | ||||||
|             MediaScannerConnection.scanFile(context, arrayOf(file.absolutePath), null, null) |             // Utils.scanDocumentFile(context, filePath, (path, uri) -> {}); | ||||||
|             val uri = FileProvider.getUriForFile(context, BuildConfig.APPLICATION_ID + ".provider", file) |             // final Uri uri = FileProvider.getUriForFile(context, BuildConfig.APPLICATION_ID + ".provider", file); | ||||||
|             val contentResolver = context.contentResolver |             val contentResolver = context.contentResolver | ||||||
|             val bitmap = getThumbnail(context, file, uri, contentResolver) |             var bitmap: Bitmap? = null | ||||||
|  |             val mimeType = filePath.type // Utils.getMimeType(uri, contentResolver); | ||||||
|  |             if (!isEmpty(mimeType)) { | ||||||
|  |                 if (mimeType!!.startsWith("image")) { | ||||||
|  |                     try { | ||||||
|  |                         contentResolver.openInputStream(filePath.uri).use { inputStream -> | ||||||
|  |                             bitmap = BitmapFactory.decodeStream(inputStream) | ||||||
|  |                         } | ||||||
|  |                     } catch (e: java.lang.Exception) { | ||||||
|  |                         if (BuildConfig.DEBUG) Log.e(TAG, "", e) | ||||||
|  |                     } | ||||||
|  |                 } else if (mimeType.startsWith("video")) { | ||||||
|  |                     val retriever = MediaMetadataRetriever() | ||||||
|  |                     try { | ||||||
|  |                         try { | ||||||
|  |                             retriever.setDataSource(context, filePath.uri) | ||||||
|  |                         } catch (e: java.lang.Exception) { | ||||||
|  |                             // retriever.setDataSource(file.getAbsolutePath()); | ||||||
|  |                             Log.e(TAG, "showSummary: ", e) | ||||||
|  |                         } | ||||||
|  |                         bitmap = retriever.frameAtTime | ||||||
|  |                         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) try { | ||||||
|  |                             retriever.close() | ||||||
|  |                         } catch (e: java.lang.Exception) { | ||||||
|  |                             Log.e(TAG, "showSummary: ", e) | ||||||
|  |                         } | ||||||
|  |                     } catch (e: java.lang.Exception) { | ||||||
|  |                         Log.e(TAG, "", e) | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|             val downloadComplete = context.getString(R.string.downloader_complete) |             val downloadComplete = context.getString(R.string.downloader_complete) | ||||||
|             val intent = Intent(Intent.ACTION_VIEW, uri) |             val intent = Intent(Intent.ACTION_VIEW, filePath.uri) | ||||||
|                 .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK |                 .addFlags( | ||||||
|                         or Intent.FLAG_FROM_BACKGROUND |                     Intent.FLAG_ACTIVITY_NEW_TASK | ||||||
|                         or Intent.FLAG_GRANT_READ_URI_PERMISSION |                             or Intent.FLAG_FROM_BACKGROUND | ||||||
|                         or Intent.FLAG_GRANT_WRITE_URI_PERMISSION) |                             or Intent.FLAG_GRANT_READ_URI_PERMISSION | ||||||
|                 .putExtra(Intent.EXTRA_STREAM, uri) |                             or Intent.FLAG_GRANT_WRITE_URI_PERMISSION | ||||||
|  |                 ) | ||||||
|  |                 .putExtra(Intent.EXTRA_STREAM, filePath.uri) | ||||||
|             val pendingIntent = PendingIntent.getActivity( |             val pendingIntent = PendingIntent.getActivity( | ||||||
|                 context, |                 context, | ||||||
|                 DOWNLOAD_NOTIFICATION_INTENT_REQUEST_CODE, |                 DOWNLOAD_NOTIFICATION_INTENT_REQUEST_CODE, | ||||||
|                 intent, |                 intent, | ||||||
|                 PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_ONE_SHOT |                 PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_ONE_SHOT | ||||||
|             ) |             ) | ||||||
|             val notificationId = notificationId + count |             val notificationId: Int = notificationId + count | ||||||
|             notificationIds.add(notificationId) |             notificationIds.add(notificationId) | ||||||
|             count++ |             count++ | ||||||
|             val builder: NotificationCompat.Builder = NotificationCompat.Builder(context, DOWNLOAD_CHANNEL_ID) |             val builder: NotificationCompat.Builder = | ||||||
|                 .setSmallIcon(R.drawable.ic_download) |                 NotificationCompat.Builder(context, DOWNLOAD_CHANNEL_ID) | ||||||
|                 .setContentText(null) |                     .setSmallIcon(R.drawable.ic_download) | ||||||
|                 .setContentTitle(downloadComplete) |                     .setContentText(null) | ||||||
|                 .setWhen(System.currentTimeMillis()) |                     .setContentTitle(downloadComplete) | ||||||
|                 .setOnlyAlertOnce(true) |                     .setWhen(System.currentTimeMillis()) | ||||||
|                 .setAutoCancel(true) |                     .setOnlyAlertOnce(true) | ||||||
|                 .setGroup(NOTIF_GROUP_NAME + "_" + id) |                     .setAutoCancel(true) | ||||||
|                 .setGroupAlertBehavior(NotificationCompat.GROUP_ALERT_SUMMARY) |                     .setGroup(NOTIF_GROUP_NAME + "_" + id) | ||||||
|                 .setContentIntent(pendingIntent) |                     .setGroupAlertBehavior(NotificationCompat.GROUP_ALERT_SUMMARY) | ||||||
|                 .addAction(R.drawable.ic_delete, |                     .setContentIntent(pendingIntent) | ||||||
|                     context.getString(R.string.delete), |                     .addAction( | ||||||
|                     DeleteImageIntentService.pendingIntent(context, filePath, notificationId)) |                         R.drawable.ic_delete, | ||||||
|  |                         context.getString(R.string.delete), | ||||||
|  |                         DeleteImageIntentService.pendingIntent(context, filePath, notificationId) | ||||||
|  |                     ) | ||||||
|             if (bitmap != null) { |             if (bitmap != null) { | ||||||
|                 builder.setLargeIcon(bitmap) |                 builder.setLargeIcon(bitmap) | ||||||
|                     .setStyle(NotificationCompat.BigPictureStyle() |                     .setStyle( | ||||||
|                         .bigPicture(bitmap) |                         NotificationCompat.BigPictureStyle() | ||||||
|                         .bigLargeIcon(null)) |                             .bigPicture(bitmap) | ||||||
|  |                             .bigLargeIcon(null) | ||||||
|  |                     ) | ||||||
|                     .setBadgeIconType(NotificationCompat.BADGE_ICON_SMALL) |                     .setBadgeIconType(NotificationCompat.BADGE_ICON_SMALL) | ||||||
|             } |             } | ||||||
|             notifications.add(builder) |             notifications.add(builder) | ||||||
| @ -344,16 +382,16 @@ class DownloadWorker(context: Context, workerParams: WorkerParameters) : Corouti | |||||||
|         return bitmap |         return bitmap | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     class DownloadRequest private constructor(val urlToFilePathMap: Map<String, String>) { |     class DownloadRequest private constructor(val urlToFilePathMap: Map<String, DocumentFile>) { | ||||||
| 
 | 
 | ||||||
|         class Builder { |         class Builder { | ||||||
|             private var urlToFilePathMap: MutableMap<String, String> = mutableMapOf() |             private var urlToFilePathMap: MutableMap<String, DocumentFile> = mutableMapOf() | ||||||
|             fun setUrlToFilePathMap(urlToFilePathMap: MutableMap<String, String>): Builder { |             fun setUrlToFilePathMap(urlToFilePathMap: MutableMap<String, DocumentFile>): Builder { | ||||||
|                 this.urlToFilePathMap = urlToFilePathMap |                 this.urlToFilePathMap = urlToFilePathMap | ||||||
|                 return this |                 return this | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             fun addUrl(url: String, filePath: String): Builder { |             fun addUrl(url: String, filePath: DocumentFile): Builder { | ||||||
|                 urlToFilePathMap[url] = filePath |                 urlToFilePathMap[url] = filePath | ||||||
|                 return this |                 return this | ||||||
|             } |             } | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user