Android Sleep Api Exception: com.google.android.gms.common.api.ApiException: 16:

Viewed 197

I am trying to run the Sleep Sample app provided by the android team to showcase the use of the new Sleep API. The app runs fine on some devices(OnePlus, Pixel, Nokia) but shows the error "com.google.android.gms.common.api.ApiException: 16:" on some devices(Samsung). I thought this had to do something with Google Play Services So I already updated it. My phone is running Samsung Color OS with Android 11. It has the latest version of GooglePlay and Google Play services. This problem tends to occur only on Samsung devices(Among the devices I have tested this on)

    package com.android.example.sleepcodelab
    import android.Manifest.permission
    import android.annotation.SuppressLint
    import android.app.PendingIntent
    import android.content.Context
    import android.content.Intent
    import android.content.pm.PackageManager
    import android.net.Uri
    import android.os.Bundle
    import android.provider.Settings
    import android.util.Log
    import android.view.View
    import androidx.activity.result.ActivityResultLauncher
    import androidx.activity.result.contract.ActivityResultContracts
    import androidx.appcompat.app.AppCompatActivity
    import androidx.core.content.ContextCompat
    import com.android.example.sleepcodelab.databinding.ActivityMainBinding
    import com.android.example.sleepcodelab.receiver.SleepReceiver
    import com.google.android.gms.location.ActivityRecognition
    import com.google.android.gms.location.SleepSegmentRequest
    import com.google.android.material.snackbar.Snackbar
    import java.util.Calendar


    class MainActivity : AppCompatActivity() {

    private lateinit var binding: ActivityMainBinding

    private val mainViewModel: MainViewModel by lazy {
        MainViewModel((application as MainApplication).repository)
    }

    
    private var sleepSegmentOutput: String = ""
    private var sleepClassifyOutput: String = ""

    private var subscribedToSleepData = false
        set(newSubscribedToSleepData) {
            field = newSubscribedToSleepData
            if (newSubscribedToSleepData) {
                binding.button.text = getString(R.string.sleep_button_unsubscribe_text)
            } else {
                binding.button.text = getString(R.string.sleep_button_subscribe_text)
            }
            updateOutput()
        }

    private lateinit var sleepPendingIntent: PendingIntent

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)

        mainViewModel.subscribedToSleepDataLiveData.observe(this) { newSubscribedToSleepData ->
            if (subscribedToSleepData != newSubscribedToSleepData) {
                subscribedToSleepData = newSubscribedToSleepData
            }
        }

       
        mainViewModel.allSleepSegments.observe(this) { sleepSegmentEventEntities ->
            Log.d(TAG, "sleepSegmentEventEntities: $sleepSegmentEventEntities")

            if (sleepSegmentEventEntities.isNotEmpty()) {
                
                sleepSegmentOutput = sleepSegmentEventEntities.joinToString {
                    "\t$it\n"
                }
                updateOutput()
            }
        }

        mainViewModel.allSleepClassifyEventEntities.observe(this) {
                sleepClassifyEventEntities ->
            Log.d(TAG, "sleepClassifyEventEntities: $sleepClassifyEventEntities")

            if (sleepClassifyEventEntities.isNotEmpty()) {
                sleepClassifyOutput = sleepClassifyEventEntities.joinToString {
                    "\t$it\n"
                }
                updateOutput()
            }
        }

        sleepPendingIntent =
            SleepReceiver.createSleepReceiverPendingIntent(context = applicationContext)
    }

    fun onClickRequestSleepData(view: View) {
        if (activityRecognitionPermissionApproved()) {
            if (subscribedToSleepData) {
                unsubscribeToSleepSegmentUpdates(applicationContext, sleepPendingIntent)
            } else {
                subscribeToSleepSegmentUpdates(applicationContext, sleepPendingIntent)
            }
        } else {
            requestPermissionLauncher.launch(permission.ACTIVITY_RECOGNITION)
        }
    }

    @SuppressLint("MissingPermission")
    private fun subscribeToSleepSegmentUpdates(context: Context, pendingIntent: PendingIntent) {
        Log.d(TAG, "requestSleepSegmentUpdates()")
        val task = ActivityRecognition.getClient(context).requestSleepSegmentUpdates(
            pendingIntent,
            SleepSegmentRequest.getDefaultSleepSegmentRequest()
        )

        task.addOnSuccessListener {
            mainViewModel.updateSubscribedToSleepData(true)
            Log.d(TAG, "Successfully subscribed to sleep data.")
        }
        task.addOnFailureListener { exception ->
            Log.d(TAG, "Exception when subscribing to sleep data: $exception")
        }
    }

    private fun unsubscribeToSleepSegmentUpdates(context: Context, pendingIntent: PendingIntent) {
        Log.d(TAG, "unsubscribeToSleepSegmentUpdates()")
        val task = ActivityRecognition.getClient(context).removeSleepSegmentUpdates(pendingIntent)

        task.addOnSuccessListener {
            mainViewModel.updateSubscribedToSleepData(false)
            Log.d(TAG, "Successfully unsubscribed to sleep data.")
        }
        task.addOnFailureListener { exception ->
            Log.d(TAG, "Exception when unsubscribing to sleep data: $exception")
        }
    }

    private fun activityRecognitionPermissionApproved(): Boolean {
        
        return PackageManager.PERMISSION_GRANTED == ContextCompat.checkSelfPermission(
            this,
            permission.ACTIVITY_RECOGNITION
        )
    }

    private val requestPermissionLauncher: ActivityResultLauncher<String> =
        registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted ->
            if (!isGranted) {
                displayPermissionSettingsSnackBar()
            } else {
                binding.outputTextView.text = getString(R.string.permission_approved)
            }
        }

    private fun displayPermissionSettingsSnackBar() {
        Snackbar.make(
            binding.mainActivity,
            R.string.permission_rational,
            Snackbar.LENGTH_LONG
        )
            .setAction(R.string.action_settings) {
                val intent = Intent()
                intent.action = Settings.ACTION_APPLICATION_DETAILS_SETTINGS
                val uri = Uri.fromParts(
                    "package",
                    BuildConfig.APPLICATION_ID,
                    null
                )
                intent.data = uri
                intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
                startActivity(intent)
            }
            .show()
    }

    
    private fun updateOutput() {
        Log.d(TAG, "updateOutput()")

        val header = if (subscribedToSleepData) {
            val timestamp = Calendar.getInstance().time.toString()
            getString(R.string.main_output_header1_subscribed_sleep_data, timestamp)
        } else {
            getString(R.string.main_output_header1_unsubscribed_sleep_data)
        }

        val sleepData = getString(
            R.string.main_output_header2_and_sleep_data,
            sleepSegmentOutput,
            sleepClassifyOutput
        )

        val newOutput = header + sleepData
        binding.outputTextView.text = newOutput
    }

    companion object {
        private const val TAG = "MainActivity"
    }
}

Whenever I click on subscribe to sleep data button, it has " Exception when subscribing to sleep data: com.google.android.gms.common.api.ApiException: 16: " in logcat.

enter image description here

enter image description here

0 Answers
Related