Annyce Davis

Davis Technology Consulting

  • Home
  • About Me
  • Blog
  • Courses
  • Newsletter

How to fix common Android API deprecations

August 19, 2022 by Annyce Davis

Each year there’s a new version of the Android SDK released. Along with the myriad of new features come deprecations. When something is deprecated, although it’s still available, it’s best to migrate to the recommended new API. With that being said here are some common deprecations I encountered in my company’s Android codebase and how to fix them.

Deprecated Menu APIs on Fragments

The Fragment APIs for providing a menu to your activity’s ActionBar have been deprecated as they tightly couple your fragment to your activity and are not testable in isolation. The new MenuHost and MenuProvider APIs provide a testable, lifecycle-aware equivalent API surface that fragments should use instead.

Previous

Previously, in the onViewCreated method, you’d make a call to setHasOptionsMenu().

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
   ...
    setHasOptionsMenu(true)
}    

Current

Now, you let your fragment implement the MenuProvider interface. Then inside of the onViewCreated method, you can set the fragment as the menu provider for your menu host.

class MyFragment : Fragment(), MenuProvider {

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        ...
        val menuHost: MenuHost = requireActivity() as MenuHost
        menuHost.addMenuProvider(
            this, viewLifecycleOwner, State.RESUMED
        )
    }
}

Finally, implement the following methods of the MenuProvider interface. The naming is similar to the previous functions that you would use for the action bar.

override fun onCreateMenu(menu: Menu, menuInflater: MenuInflater) {
    menuInflater.inflate(R.menu.menu_event_comment_post, menu)
}

override fun onPrepareMenu(menu: Menu) {
    ...
}

override fun onMenuItemSelected(item: MenuItem): Boolean =
    when {
        ...
    }

Deprecated Handler constructor

This is a simple one. A Handler allows you to send and process Message and Runnable objects on Android. In our application, handlers are mostly used in legacy portions of the codebase to perform a delayed action.

Previous

You could implicitly choose a Looper during Handler construction by not providing any value to the constructor. This could easily lead to bugs, crashes, or race conditions.

private val handler = Handler()

Current

To help protect us from ourselves, the default constructor is now deprecated. Instead, you should use an Executor or specify the Looper explicitly. Here’s an example where we specify the main looper.

private val handler = Handler(Looper.getMainLooper())

Deprecated startActivityForResult APIs

The startActivityForResult method allows you to start another activity either from your own app or another and get some type of result back. This is common for things like taking a picture, opening a document, or asking for a permission.

Previous

Previously, you would call a method on the activity startActivityForResult and then override the onActivityResult method to listen for the result. And this worked fine. Here’s an example of starting an activity to edit a user’s profile. And then listening for a successful result and refreshing the screen.

startActivityForResult(
    Intents.editProfile(activity, false, null, memberId),
    EDIT_PROFILE
)

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    if (requestCode == EDIT_PROFILE && resultCode == RESULT_OK) {
        onRefresh()
    }
}

Current

However, it’s now recommended to use the Activity Result APIs. The Activity Result APIs provide components for registering for a result, launching the result, and handling the result once it is dispatched by the system.

Now, to do the same thing as we did previously, you create a property in the class, often denoted as a launcher. This launcher does the same behavior as the onActivityResult callback. Finally, you call launch on the launcher property when you’re ready to start the other activity.

private val editProfileLauncher = registerForActivityResult(StartActivityForResult()) { result: ActivityResult ->
    if (result.resultCode == RESULT_OK) {
        onRefresh()
    }
}

editProfileLauncher.launch(Intents.editProfile(activity, false, null, memberId))

Keeping up-to-date with the ever-changing Android APIs doesn’t have to be a daunting task. In fact, you can often make these types of changes quickly with IntelliJ’s Structural Search and Replace feature.

Hope you found this helpful!

Share this:

  • Click to share on LinkedIn (Opens in new window) LinkedIn
  • Click to share on Mastodon (Opens in new window) Mastodon
  • Click to share on Bluesky (Opens in new window) Bluesky
  • Click to share on WhatsApp (Opens in new window) WhatsApp
  • Click to share on Reddit (Opens in new window) Reddit

Related

Filed Under: Android, Kotlin Tagged With: Android, Deprecated, Kotlin

Follow Me

  • Bluesky

Categories

  • Android (60)
  • Career (5)
  • Communication (4)
  • Flutter (1)
  • Git (4)
  • Gradle (4)
  • Grails (23)
  • iOS (1)
  • Java (8)
  • JavaScript (6)
  • Kotlin (17)
  • Life (5)
  • Public Speaking (26)
  • Revenue (2)
  • RxJava (1)
  • Software Development (13)
  • Twitter (3)
  • Uncategorized (11)
  • Video Course (5)

Follow Me

  • Bluesky

Copyright © 2025 · All Rights Reserved · Log in

 

Loading Comments...