@@ -27,9 +27,12 @@ import android.view.Menu
2727import android.view.MenuItem
2828import android.view.MotionEvent
2929import android.view.View
30+ import android.webkit.MimeTypeMap
3031import android.widget.PopupMenu
3132import android.widget.ToggleButton
3233import androidx.activity.OnBackPressedCallback
34+ import androidx.activity.result.ActivityResultLauncher
35+ import androidx.activity.result.contract.ActivityResultContracts
3336import androidx.appcompat.app.AlertDialog
3437import androidx.appcompat.app.AppCompatActivity
3538import androidx.appcompat.content.res.AppCompatResources
@@ -237,10 +240,6 @@ open class MainActivity : AppCompatActivity(),
237240 private val MEDIA_CAMERA_VIDEO_PERMISSION_REQUEST_CODE : Int = 1002
238241 private val MEDIA_PHOTOS_PERMISSION_REQUEST_CODE : Int = 1003
239242 private val MEDIA_VIDEOS_PERMISSION_REQUEST_CODE : Int = 1004
240- private val REQUEST_MEDIA_CAMERA_PHOTO : Int = 2001
241- private val REQUEST_MEDIA_CAMERA_VIDEO : Int = 2002
242- private val REQUEST_MEDIA_PHOTO : Int = 2003
243- private val REQUEST_MEDIA_VIDEO : Int = 2004
244243
245244 protected lateinit var aztec: Aztec
246245 private lateinit var mediaFile: String
@@ -255,58 +254,10 @@ open class MainActivity : AppCompatActivity(),
255254 private var mIsKeyboardOpen = false
256255 private var mHideActionBarOnSoftKeyboardUp = false
257256
258- override fun onActivityResult (requestCode : Int , resultCode : Int , data : Intent ? ) {
259- if (resultCode == Activity .RESULT_OK ) {
260- when (requestCode) {
261- REQUEST_MEDIA_CAMERA_PHOTO -> {
262- // By default, BitmapFactory.decodeFile sets the bitmap's density to the device default so, we need
263- // to correctly set the input density to 160 ourselves.
264- val options = BitmapFactory .Options ()
265- options.inDensity = DisplayMetrics .DENSITY_DEFAULT
266- val bitmap = BitmapFactory .decodeFile(mediaPath, options)
267- Log .d(" MediaPath" , mediaPath)
268- insertImageAndSimulateUpload(bitmap, mediaPath)
269- }
270- REQUEST_MEDIA_PHOTO -> {
271- mediaPath = data?.data.toString()
272- val stream = contentResolver.openInputStream(Uri .parse(mediaPath))
273- // By default, BitmapFactory.decodeFile sets the bitmap's density to the device default so, we need
274- // to correctly set the input density to 160 ourselves.
275- val options = BitmapFactory .Options ()
276- options.inDensity = DisplayMetrics .DENSITY_DEFAULT
277- val bitmap = BitmapFactory .decodeStream(stream, null , options)
278-
279- insertImageAndSimulateUpload(bitmap, mediaPath)
280- }
281- REQUEST_MEDIA_CAMERA_VIDEO -> {
282- mediaPath = data?.data.toString()
283- }
284- REQUEST_MEDIA_VIDEO -> {
285- mediaPath = data?.data.toString()
286-
287- aztec.visualEditor.videoThumbnailGetter?.loadVideoThumbnail(mediaPath, object : Html .VideoThumbnailGetter .Callbacks {
288- override fun onThumbnailFailed () {
289- }
290-
291- override fun onThumbnailLoaded (drawable : Drawable ? ) {
292- val conf = Bitmap .Config .ARGB_8888 // see other conf types
293- val bitmap = Bitmap .createBitmap(drawable!! .intrinsicWidth, drawable.intrinsicHeight, conf)
294- val canvas = Canvas (bitmap)
295- drawable.setBounds(0 , 0 , canvas.width, canvas.height)
296- drawable.draw(canvas)
297-
298- insertVideoAndSimulateUpload(bitmap, mediaPath)
299- }
300-
301- override fun onThumbnailLoading (drawable : Drawable ? ) {
302- }
303- }, this .resources.displayMetrics.widthPixels)
304- }
305- }
306- }
307-
308- super .onActivityResult(requestCode, resultCode, data)
309- }
257+ private lateinit var requestMediaPhoto: ActivityResultLauncher <Intent >
258+ private lateinit var requestMediaCameraPhoto: ActivityResultLauncher <Uri >
259+ private lateinit var requestMediaVideo: ActivityResultLauncher <Intent >
260+ private lateinit var requestMediaCameraVideo: ActivityResultLauncher <Uri >
310261
311262 private fun insertImageAndSimulateUpload (bitmap : Bitmap ? , mediaPath : String ) {
312263 val bitmapResized = ImageUtils .getScaledBitmapAtLongestSide(bitmap, aztec.visualEditor.maxImagesWidth)
@@ -498,6 +449,79 @@ open class MainActivity : AppCompatActivity(),
498449
499450 invalidateOptionsHandler = Handler (Looper .getMainLooper())
500451 invalidateOptionsRunnable = Runnable { invalidateOptionsMenu() }
452+
453+ requestMediaPhoto = registerForActivityResult(ActivityResultContracts .StartActivityForResult ()) { result ->
454+ val uri = result?.data?.data
455+ if (result.resultCode == Activity .RESULT_OK && uri != null ) {
456+ mediaPath = result.data.toString()
457+ val stream = contentResolver.openInputStream(uri)
458+ // By default, BitmapFactory.decodeFile sets the bitmap's density to the device default so, we need
459+ // to correctly set the input density to 160 ourselves.
460+ val options = BitmapFactory .Options ()
461+ options.inDensity = DisplayMetrics .DENSITY_DEFAULT
462+ val bitmap = BitmapFactory .decodeStream(stream, null , options)
463+
464+ insertImageAndSimulateUpload(bitmap, mediaPath)
465+ }
466+ }
467+
468+ requestMediaCameraPhoto = registerForActivityResult(
469+ ActivityResultContracts .TakePicture ()
470+ ) { success ->
471+ if (success) {
472+ // By default, BitmapFactory.decodeFile sets the bitmap's density to the device default so, we need
473+ // to correctly set the input density to 160 ourselves.
474+ val options = BitmapFactory .Options ()
475+ options.inDensity = DisplayMetrics .DENSITY_DEFAULT
476+ val bitmap = BitmapFactory .decodeFile(mediaPath, options)
477+ Log .d(" MediaPath" , mediaPath)
478+ insertImageAndSimulateUpload(bitmap, mediaPath)
479+ }
480+ }
481+
482+ requestMediaVideo = registerForActivityResult(ActivityResultContracts .StartActivityForResult ()) { result ->
483+ val uri = result?.data?.data
484+ if (result.resultCode == Activity .RESULT_OK && uri != null ) {
485+ val type = contentResolver?.getType(uri) ? : return @registerForActivityResult
486+ val extension = MimeTypeMap .getSingleton().getExtensionFromMimeType(type)
487+
488+ mediaFile = " wp-" + System .currentTimeMillis()
489+ val file = File .createTempFile(
490+ mediaFile,
491+ extension,
492+ getExternalFilesDir(Environment .DIRECTORY_PICTURES )
493+ )
494+ mediaPath = file.absolutePath
495+ file.outputStream().use { outputStream ->
496+ contentResolver.openInputStream(uri).use { inputStream ->
497+ inputStream?.copyTo(outputStream)
498+ }
499+ }
500+ aztec.visualEditor.videoThumbnailGetter?.loadVideoThumbnail(mediaPath, object : Html .VideoThumbnailGetter .Callbacks {
501+ override fun onThumbnailFailed () {
502+ }
503+
504+ override fun onThumbnailLoaded (drawable : Drawable ? ) {
505+ val conf = Bitmap .Config .ARGB_8888 // see other conf types
506+ val bitmap = Bitmap .createBitmap(drawable!! .intrinsicWidth, drawable.intrinsicHeight, conf)
507+ val canvas = Canvas (bitmap)
508+ drawable.setBounds(0 , 0 , canvas.width, canvas.height)
509+ drawable.draw(canvas)
510+
511+ insertVideoAndSimulateUpload(bitmap, mediaPath)
512+ }
513+
514+ override fun onThumbnailLoading (drawable : Drawable ? ) {
515+ }
516+ }, this .resources.displayMetrics.widthPixels)
517+ }
518+ }
519+
520+ requestMediaCameraVideo = registerForActivityResult(
521+ ActivityResultContracts .CaptureVideo ()
522+ ) {
523+ // do nothing
524+ }
501525 }
502526
503527 override fun onPause () {
@@ -628,9 +652,9 @@ open class MainActivity : AppCompatActivity(),
628652 return true
629653 }
630654
631- override fun onPrepareOptionsMenu (menu : Menu ? ): Boolean {
632- menu? .findItem(R .id.redo)?.isEnabled = aztec.visualEditor.history.redoValid()
633- menu? .findItem(R .id.undo)?.isEnabled = aztec.visualEditor.history.undoValid()
655+ override fun onPrepareOptionsMenu (menu : Menu ): Boolean {
656+ menu.findItem(R .id.redo)?.isEnabled = aztec.visualEditor.history.redoValid()
657+ menu.findItem(R .id.undo)?.isEnabled = aztec.visualEditor.history.undoValid()
634658 return super .onPrepareOptionsMenu(menu)
635659 }
636660
@@ -650,49 +674,54 @@ open class MainActivity : AppCompatActivity(),
650674
651675 private fun onCameraPhotoMediaOptionSelected () {
652676 if (PermissionUtils .checkAndRequestCameraAndStoragePermissions(this , MEDIA_CAMERA_PHOTO_PERMISSION_REQUEST_CODE )) {
653- val intent = Intent (MediaStore .ACTION_IMAGE_CAPTURE )
654-
655- if (Build .VERSION .SDK_INT >= Build .VERSION_CODES .Q ) {
656- mediaFile = " wp-" + System .currentTimeMillis()
657- mediaPath = File .createTempFile(
658- mediaFile,
659- " .jpg" ,
660- getExternalFilesDir(Environment .DIRECTORY_PICTURES )
661- ).absolutePath
662-
663- } else {
664- mediaFile = " wp-" + System .currentTimeMillis() + " .jpg"
665- @Suppress(" DEPRECATION" )
666- mediaPath = Environment .getExternalStoragePublicDirectory(Environment .DIRECTORY_DCIM ).toString() +
667- File .separator + " Camera" + File .separator + mediaFile
668- }
669- intent.putExtra(MediaStore .EXTRA_OUTPUT , FileProvider .getUriForFile(this ,
670- BuildConfig .APPLICATION_ID + " .provider" , File (mediaPath)))
677+ val uriForFile = createTempMediaFile(" .jpg" )
671678
672679 if (intent.resolveActivity(packageManager) != null ) {
673- startActivityForResult(intent, REQUEST_MEDIA_CAMERA_PHOTO )
680+ requestMediaCameraPhoto.launch(uriForFile )
674681 }
675682 }
676683 }
677684
685+ private fun createTempMediaFile (suffix : String ): Uri {
686+ if (Build .VERSION .SDK_INT >= Build .VERSION_CODES .Q ) {
687+ mediaFile = " wp-" + System .currentTimeMillis()
688+ mediaPath = File .createTempFile(
689+ mediaFile,
690+ suffix,
691+ getExternalFilesDir(Environment .DIRECTORY_PICTURES )
692+ ).absolutePath
693+
694+ } else {
695+ mediaFile = " wp-" + System .currentTimeMillis() + suffix
696+ @Suppress(" DEPRECATION" )
697+ mediaPath = Environment .getExternalStoragePublicDirectory(Environment .DIRECTORY_DCIM ).toString() +
698+ File .separator + " Camera" + File .separator + mediaFile
699+ }
700+ return FileProvider .getUriForFile(this ,
701+ BuildConfig .APPLICATION_ID + " .provider" , File (mediaPath))
702+ }
703+
678704 private fun onCameraVideoMediaOptionSelected () {
679705 if (PermissionUtils .checkAndRequestCameraAndStoragePermissions(this , MEDIA_CAMERA_PHOTO_PERMISSION_REQUEST_CODE )) {
680- val intent = Intent ( MediaStore . INTENT_ACTION_VIDEO_CAMERA )
706+ val uriForFile = createTempMediaFile( " .mp4 " )
681707
682708 if (intent.resolveActivity(packageManager) != null ) {
683- startActivityForResult(intent, REQUEST_MEDIA_CAMERA_VIDEO )
709+ requestMediaCameraVideo.launch(uriForFile )
684710 }
685711 }
686712 }
687713
688714 private fun onPhotosMediaOptionSelected () {
689715 if (PermissionUtils .checkAndRequestStoragePermission(this , MEDIA_PHOTOS_PERMISSION_REQUEST_CODE )) {
690- val intent = Intent (Intent .ACTION_OPEN_DOCUMENT )
691- intent.addCategory(Intent .CATEGORY_OPENABLE )
692- intent.type = " image/*"
716+ val intent = Intent (
717+ Intent .ACTION_PICK
718+ ).setDataAndType(MediaStore .Images .Media .EXTERNAL_CONTENT_URI , " image/*" )
719+ .apply {
720+ putExtra(Intent .EXTRA_MIME_TYPES , arrayOf(" image/jpeg" , " image/jpg" ))
721+ }
693722
694723 try {
695- startActivityForResult (intent, REQUEST_MEDIA_PHOTO )
724+ requestMediaPhoto.launch (intent)
696725 } catch (exception: ActivityNotFoundException ) {
697726 AppLog .e(AppLog .T .EDITOR , exception.message)
698727 ToastUtils .showToast(this , getString(R .string.error_chooser_photo), ToastUtils .Duration .LONG )
@@ -707,7 +736,7 @@ open class MainActivity : AppCompatActivity(),
707736 intent.type = " video/*"
708737
709738 try {
710- startActivityForResult (intent, REQUEST_MEDIA_VIDEO )
739+ requestMediaVideo.launch (intent)
711740 } catch (exception: ActivityNotFoundException ) {
712741 AppLog .e(AppLog .T .EDITOR , exception.message)
713742 ToastUtils .showToast(this , getString(R .string.error_chooser_video), ToastUtils .Duration .LONG )
0 commit comments