Search code examples
javaandroidkotlindefault

I'm getting RESULT_CANCELED from startActivityForResult()


I'm trying to set my app as the default phone app in Android 10 and above and when I say default "phone app" is the one that you find when you go to Settings > Apps > Default Apps > Phone I have this main activity class:

@RequiresApi(Build.VERSION_CODES.Q)
class MainActivity : ComponentActivity() {

    private lateinit var setPhoneAppLauncher: ActivityResultLauncher<Intent>
    private val roleManager: RoleManager by lazy {
        getSystemService(Context.ROLE_SERVICE) as RoleManager
    }

    private val permissions = arrayOf(
        android.Manifest.permission.READ_PHONE_STATE,
        android.Manifest.permission.CALL_PHONE,
        android.Manifest.permission.ANSWER_PHONE_CALLS,
        android.Manifest.permission.READ_CALL_LOG,
        android.Manifest.permission.WRITE_CALL_LOG,
        android.Manifest.permission.READ_CONTACTS
    )
    private val requestCode = 201002
    //    private val REQUESTCODESETDEFAULTDIALER = 1
    private lateinit var contactLoader: ContactLoader
    private val contactDisplayUI = ContactDisplayUI(activity = this)

    companion object {
        const val PERMISSIONS_REQUEST_READ_CONTACTS = 100
        const val REQUESTCODESETDEFAULTDIALER = 1
        const val role = RoleManager.ROLE_DIALER
    }


    @OptIn(ExperimentalMaterial3Api::class)
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        setPhoneAppLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
            if (it.resultCode == RESULT_CANCELED) {
                // Permission granted, proceed with your logic here.
                Log.d("MainActivity", "Success?")
               // checkDefaultDialer()
            } else {
                // Handle other possible result codes if needed.
                Log.d("MainActivity", it.resultCode.toString())
                Log.d("YourActivity", "Something went wrong.")
            }
        }

        checkAndRequestPermissions()

    }


    private fun selectRegisterLogic() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            Log.d("YourActivity", "HereQ.")
            registerAsDefaultDialerQ()
        } else {
            Log.d("YourActivity", "HereL.")
            registerAsDefaultDialerLegacy()
        }
    }

    @RequiresApi(Build.VERSION_CODES.Q)
    private fun registerAsDefaultDialerQ() {
        val roleManager = getSystemService(Context.ROLE_SERVICE) as RoleManager
        if (roleManager.isRoleAvailable(RoleManager.ROLE_DIALER)) {
            // ... rest of your code
            Log.d("MainActivity", "Role Manager is available on this device.")
            if (!roleManager.isRoleHeld(RoleManager.ROLE_DIALER)) {
                val intent = roleManager.createRequestRoleIntent(RoleManager.ROLE_DIALER)
                Log.d("MainActivity", "Requesting ROLE_DIALER intent: $intent")

                setPhoneAppLauncher.launch(intent)
            } else {
                // Your app already holds the role, proceed with your logic here.
                Log.e("MainActivity", "It is the default.")
            }
        } else {
            Log.e("MainActivity", "Role Manager not available on this device.")
        }
    }




    private fun registerAsDefaultDialerLegacy() {

        val telecomManager = getSystemService(Context.TELECOM_SERVICE) as TelecomManager
        if (!packageName.equals(telecomManager.defaultDialerPackage)) {
            val intent = Intent(TelecomManager.ACTION_CHANGE_DEFAULT_DIALER)
            intent.putExtra(
                TelecomManager.EXTRA_CHANGE_DEFAULT_DIALER_PACKAGE_NAME,
                packageName
            )
            startActivity(intent)
        }

    }

    //    @RequiresApi(Build.VERSION_CODES.Q)
    private fun checkDefaultDialer() {
        val telecomManager = getSystemService(TelecomManager::class.java)
        if (packageName == telecomManager.defaultDialerPackage) {
            // Your app is the default dialer, proceed with your logic here.
            Log.d("YourActivity", "Phone app is the default dialer.")
        } else {
            // Your app is not the default dialer, handle this case.
            selectRegisterLogic()
            Log.d("YourActivity", "Phone app is NOT the default dialer.")
//
        }
    }

    private fun checkAndRequestPermissions() {
        val permissionsToRequest = permissions.filter {
            ContextCompat.checkSelfPermission(this, it) != PackageManager.PERMISSION_GRANTED
        }

        if (permissionsToRequest.isNotEmpty()) {
            // Request missing permissions using the ActivityResultLauncher
            requestPermissionLauncher.launch(permissionsToRequest.toTypedArray())
        } else {

            Log.d("somelog", "yeas")
        }
    }


    private val requestPermissionLauncher = registerForActivityResult(
        ActivityResultContracts.RequestMultiplePermissions()
    ) { permissions ->
        val allPermissionsGranted = permissions.all { it.value }
        if (allPermissionsGranted) {
            Log.d("somelog", allPermissionsGranted.toString())
            // Permissions granted, register as the default dialer
            selectRegisterLogic()
        } else {
            // Handle case when permissions are not granted
        }
    }
}

Since I want to handle from Android API level 23 and above I set some if else logic to handle necessary things. And I think I have set the necessary permissions in the AndroidManifest.xml file. What's going wrong?


Solution

  • To all the people that might want to get past this and want their app to be registered as the default phone app, they need to follow this very important doc from Android. These are quite important:

    In order to fill the RoleManager.ROLE_DIALER role, an app must meet a number of requirements:

    • It must handle the Intent#ACTION_DIAL intent. This means the app must provide a dial pad UI for the user to initiate outgoing calls.
    • It must fully implement the InCallService API and provide both an incoming call UI, as well as an ongoing call UI.

    If you do these two things Android is going to ask the user which to set for default dialer and you are all set!