onBackPressed() deprecated, What is the alternative?

Viewed 6156

I have upgraded targetSdkVersion and compileSdkVersion to 33.

Now getting warning onBackPressed is deprecated.

It is suggested to use use OnBackInvokedCallback or androidx.activity.OnBackPressedCallback to handle back navigation instead. Anyone can help me to use the updated method.

Example:

onBackPressedDeprecated

Use Case: I use if (isTaskRoot) {} inside onBackPressed(){} method to check activity is last on the activity-stack.

override fun onBackPressed() {
    if (isTaskRoot) { // Check this activity is last on the activity-stack.(Check Whether This activity opened from Push-Notification)
        startActivity(Intent(mContext, Dashboard::class.java))
        finish()
    } else {
        finishWithResultOK()
    }
}
5 Answers

According your API level register:

This requires to at least use appcompat:1.6.0-alpha03; the current is 1.6.0-alpha04:

 implementation 'androidx.appcompat:appcompat:1.6.0-alpha04'
// kotlin
import androidx.activity.addCallback

if (BuildCompat.isAtLeastT()) {
    onBackInvokedDispatcher.registerOnBackInvokedCallback(
        OnBackInvokedDispatcher.PRIORITY_DEFAULT
    ) {
        // Back is pressed... Finishing the activity
        finish()
    }
} else {
    onBackPressedDispatcher.addCallback(this /* lifecycle owner */, object : OnBackPressedCallback(true) {
        override fun handleOnBackPressed() {
            // Back is pressed... Finishing the activity
            finish()
        }
    })
}

UPDATE:

Thanks to @ianhanniballake comment; you can just use OnBackPressedDispatcher even in API level 33+

The OnBackPressedDispatcher is already going to be using the Android T specific API internally when using Activity 1.6+,

So, you can just do:

// kotlin
import androidx.activity.addCallback

onBackPressedDispatcher.addCallback(this /* lifecycle owner */, object : OnBackPressedCallback(true) {
    override fun handleOnBackPressed() {
        // Back is pressed... Finishing the activity
        finish()
    }
})


// java
import androidx.activity.OnBackPressedCallback;

getOnBackPressedDispatcher().addCallback(this, new OnBackPressedCallback(true) {
    @Override
    public void handleOnBackPressed() {
        // Back is pressed... Finishing the activity
        finish();
    }
});

Note that you shouldn't override the onBackPressed() as that will make the onBackPressedDispatcher callback not to fire; check this answer for clarifying that.

You can use the OnBackInvokedCallback

OnBackInvokedCallback as described in the documentation and follow this guide here to update your code

You could use the onBackPressedDispatcher

onBackPressedDispatcher.addCallback(this, object : OnBackPressedCallback(true) {
    override fun handleOnBackPressed() {
         
    }
})

in here "this" means the lifeCycleOwner

Use like below,

override fun onClick(v: View?) {
        when (v?.id) {
            R.id.iv_back -> onBackPressedMethod()
        }
    }

and now create that method for handling back event

private fun onBackPressedMethod(){
        if (Build.VERSION.SDK_INT >= 33) {
            onBackInvokedDispatcher.registerOnBackInvokedCallback(
                OnBackInvokedDispatcher.PRIORITY_DEFAULT) {
                // back button pressed... finishing the activity
                finish()
            }
        } else {
            onBackPressedDispatcher.addCallback(
                this,
                object : OnBackPressedCallback(true) {
                    override fun handleOnBackPressed() {
                    // back button pressed... finishing the activity
                    finish()
                    }
                })
        }
    }

That's it!

Bonus: To close DrawerLayout when onBackPressed use like below (according to this I/O talk),

val callback = onBackPressedDispatcher.addCallback(this, false) {
    binding.drawerLayout.closeDrawer(GravityCompat.START)
}
            
binding.drawerLayout.addDrawerListener(object : DrawerListener {  
        
    override fun onDrawerOpened(drawerView: View) {
        callback.isEnabled = true
    }
        
    override fun onDrawerClosed(drawerView: View) {
        callback.isEnabled = false
    }

    override fun onDrawerSlide(drawerView: View, slideOffset: Float) = Unit    
    override fun onDrawerStateChanged(newState: Int) = Unit
})
Related