mirror of
https://github.com/KokaKiwi/BarInsta
synced 2024-11-26 00:27:30 +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()
|
|
||||||
.getMimeTypeFromExtension(Files.getFileExtension(photoFile.name))
|
|
||||||
MediaScannerConnection.scanFile(
|
|
||||||
this@CameraActivity,
|
|
||||||
arrayOf(photoFile.absolutePath),
|
|
||||||
arrayOf(mimeType)
|
|
||||||
) { _: String?, uri1: Uri? ->
|
|
||||||
Log.d(TAG, "onImageSaved: scan complete")
|
|
||||||
val intent = Intent()
|
val intent = Intent()
|
||||||
intent.data = uri1
|
intent.data = photoFile.uri
|
||||||
setResult(RESULT_OK, intent)
|
setResult(RESULT_OK, intent)
|
||||||
finish()
|
finish()
|
||||||
}
|
Log.d(TAG, "onImageSaved: " + photoFile.uri)
|
||||||
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
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -122,11 +112,10 @@ class DirectThreadViewModel(
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
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,36 +219,69 @@ 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(
|
||||||
|
Intent.FLAG_ACTIVITY_NEW_TASK
|
||||||
or Intent.FLAG_FROM_BACKGROUND
|
or Intent.FLAG_FROM_BACKGROUND
|
||||||
or Intent.FLAG_GRANT_READ_URI_PERMISSION
|
or Intent.FLAG_GRANT_READ_URI_PERMISSION
|
||||||
or Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
|
or Intent.FLAG_GRANT_WRITE_URI_PERMISSION
|
||||||
.putExtra(Intent.EXTRA_STREAM, uri)
|
)
|
||||||
|
.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 =
|
||||||
|
NotificationCompat.Builder(context, DOWNLOAD_CHANNEL_ID)
|
||||||
.setSmallIcon(R.drawable.ic_download)
|
.setSmallIcon(R.drawable.ic_download)
|
||||||
.setContentText(null)
|
.setContentText(null)
|
||||||
.setContentTitle(downloadComplete)
|
.setContentTitle(downloadComplete)
|
||||||
@ -257,14 +291,18 @@ class DownloadWorker(context: Context, workerParams: WorkerParameters) : Corouti
|
|||||||
.setGroup(NOTIF_GROUP_NAME + "_" + id)
|
.setGroup(NOTIF_GROUP_NAME + "_" + id)
|
||||||
.setGroupAlertBehavior(NotificationCompat.GROUP_ALERT_SUMMARY)
|
.setGroupAlertBehavior(NotificationCompat.GROUP_ALERT_SUMMARY)
|
||||||
.setContentIntent(pendingIntent)
|
.setContentIntent(pendingIntent)
|
||||||
.addAction(R.drawable.ic_delete,
|
.addAction(
|
||||||
|
R.drawable.ic_delete,
|
||||||
context.getString(R.string.delete),
|
context.getString(R.string.delete),
|
||||||
DeleteImageIntentService.pendingIntent(context, filePath, notificationId))
|
DeleteImageIntentService.pendingIntent(context, filePath, notificationId)
|
||||||
|
)
|
||||||
if (bitmap != null) {
|
if (bitmap != null) {
|
||||||
builder.setLargeIcon(bitmap)
|
builder.setLargeIcon(bitmap)
|
||||||
.setStyle(NotificationCompat.BigPictureStyle()
|
.setStyle(
|
||||||
|
NotificationCompat.BigPictureStyle()
|
||||||
.bigPicture(bitmap)
|
.bigPicture(bitmap)
|
||||||
.bigLargeIcon(null))
|
.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…
Reference in New Issue
Block a user