Customize android contracts for selecting and taking images

By Published On: March 20, 2023Categories: Development

Hey folks,

I hope you are doing great.
I am here with a very interesting topic, and it may seem a nightmare for those who don’t want to update their legacy code or maintaining it.

 

Goodbye onActivityResult and welcome to ActivityResultContract

As you call know onActivityResult which is deprecated recently and android has come up with a better solution obviously. Whenever there is a deprecation that means there was something bad with the existing API so android authorities thought let’s replace this with a new API.

Let’s discuss those problems.

  • Tightly coupled code with a view
  • Bad API design
  • Hard to test
  • Multiple responsibilities (Violating single responsibility principle :D)
  • Hard to maintain
  • Readability issues
  • Oldie 😀

I am not going into details of these but I’ll highly recommend you to check them or if you are experienced guy you must have gone through above problems

Let’s talk about onActivityResult which is there in android from API level 1 and almost all apps use this API for communication with other parts of the app, external APIs communication, and third-party callbacks like Stripe payment callback, Image cropping, etc. So having said that it’s so widely used it is going to have a huge impact on apps which are being maintained for a long time now.

Enough words !! Come to the business. In this article, I am not going to explain the basics of new contracts API rather I’ll be writing a custom reusable contract that is being widely used in android to extract images from galleries and cameras.

In OLD time we used to startActivity for result with a Flag as a parameter and explicit or implicit intent with given details and then there was a famous on onActivityResult call back sitting waiting for something to catch for you and all of your events with given flags were received at one place.

Now we will write a specific contract for single work with a good design having only one job to do 😉

In this example, I am going to write some extensions for URI so don’t get confused about where these methods are coming from I’ve got an extension file available in the GitHub code repo.

We are going to write a content provider for accessing files in Manifest so if you want to upload the image somewhere you will get a resolved image Uri which can be accessed as a file as well. Don’t worry, its implementation is also available.

There is a list of pre-built contracts to deal with. in this example we will see both Built-in contracts and customized ones too.

Changes you need to make in the Manifest file

Here comes custom contract

open class GetContentFileUri : ActivityResultContract<String, Uri?>() {

    //I'll keep context reference in Weak wrapper
    var contextRef: WeakReference? = null

    @CallSuper
    override fun createIntent(context: Context, input: String): Intent {
        contextRef = WeakReference(context)

        return Intent(Intent.ACTION_GET_CONTENT)
            .addCategory(Intent.CATEGORY_OPENABLE)
            .setType(input)
    }

    final override fun getSynchronousResult(
        context: Context,
        input: String
    ): SynchronousResult<Uri?>? = null

    override fun parseResult(resultCode: Int, intent: Intent?): Uri? {
        return contextRef?.get()?.let {
            intent.takeIf { resultCode == Activity.RESULT_OK }?.data?.getFilePathContentResolverFromUri(it)
        }
    }
}

Don’t get confused by getFilePathContentResolverFromUri method this method is available in GitHub source code in the extension file

Let’s see a snippet of how we will use this contract

 private fun onGalleryClick() {
      getContent.launch("image/*")
 }
 
 private val getContent = registerForActivityResult(GetContentFileUri()) { uri: Uri? ->
      uri?.let { u ->
          backgroundImageView.setImageURI(u)
          val file = File(u.path)
     }
}

Simple and precise. There are other contracts available but this contract will use a content provider behind the scene to get access for the file system to read/create a file for you if you want to share this file with your API or another app etc

Here is a working example of my snippets

All code for this example is available where I’ve covered both Gallery and Camera image picker using content provider if you want to use files for further use.

I hope you liked this article if you do so don’t forget to clap twice 😉 and subscribe to my account if you want more articles related to android or general programming practices.

See you next time with another topic. till then bye-bye.

Share this article

Written by : admin

Leave A Comment

Latest Articles