Cameraview: On Android 6.0 infinity start onResume, onPause after deny permissions of camera

Created on 25 Dec 2019  路  6Comments  路  Source: natario1/CameraView

Android Studio 3.6, Android 6.0

in app/build.gradle:

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.google.android.material:material:1.2.0-alpha03'
    implementation 'com.google.android.gms:play-services-maps:17.0.0'
    implementation "com.otaliastudios:cameraview:2.5.0"
    implementation('com.crashlytics.sdk.android:crashlytics:2.10.1@aar') { transitive = true; }
    implementation 'com.google.firebase:firebase-ml-vision:24.0.1'
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
    implementation 'com.synnapps:carouselview:0.1.4'
    implementation 'androidx.appcompat:appcompat:1.1.0'

Here my xml layout:

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">

    <data>

    </data>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <include
            android:id="@+id/profileDetailsToolbar"
            layout="@layout/tool_bar"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:title="@{@string/scan_check}" />

        <com.otaliastudios.cameraview.CameraView
            android:id="@+id/cameraView"
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:keepScreenOn="true"
            app:cameraAudio="off"
            app:cameraPictureFormat="jpeg"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/profileDetailsToolbar" />

        <com.google.android.material.button.MaterialButton
            android:id="@+id/detectButton"
            android:layout_width="0dp"
            android:layout_height="@dimen/button_height"
            android:layout_margin="@dimen/default_margin"
            android:text="@string/get"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent" />


    </androidx.constraintlayout.widget.ConstraintLayout>

</layout>

Here my activity:

import android.content.Intent
import android.graphics.Bitmap
import android.os.Bundle
import android.widget.Toast
import androidx.databinding.DataBindingUtil
import com.google.firebase.ml.vision.FirebaseVision
import com.google.firebase.ml.vision.common.FirebaseVisionImage
import com.google.firebase.ml.vision.text.FirebaseVisionText
import com.myproject.R
import com.myproject.api.model.Check
import com.myproject.common.util.Debug
import com.myproject.common.util.GsonUtil
import com.myproject.databinding.ScanCheckActivityBinding
import java.io.File.separator
import java.io.File
import java.io.FileNotFoundException
import java.io.FileOutputStream
import java.io.IOException
import com.otaliastudios.cameraview.CameraListener
import com.otaliastudios.cameraview.PictureResult

class ScanCheckActivity : RootActivity() {
    private lateinit var dataBinding: ScanCheckActivityBinding

    companion object {
        val TAG = ScanCheckActivity::class.java.name
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        Debug.d(TAG, "onCreate")
        dataBinding = DataBindingUtil.setContentView(this, R.layout.scan_check_activity)
        init()
    }

    private fun init() {
        setSupportActionBar(findViewById(R.id.toolBar))
        getSupportActionBar()?.setDisplayHomeAsUpEnabled(true)
        getSupportActionBar()?.setHomeButtonEnabled(true)
        getSupportActionBar()?.setDisplayShowTitleEnabled(false)

        dataBinding.cameraView.setLifecycleOwner(this);

        initLogic()
    }

    private fun initLogic() {
        dataBinding.detectButton.setOnClickListener({
            Debug.d(TAG, "detectButton: onClick:")
            dataBinding.cameraView.addCameraListener(object : CameraListener() {

                override fun onPictureTaken(result: PictureResult) {
                    Debug.d(TAG, "detectButton: onPictureTaken: result = $result")
                    // If planning to show a Bitmap, we will take care of
                    // EXIF rotation and background threading for you...
                    result.toBitmap(
                        dataBinding.cameraView.width,
                        dataBinding.cameraView.height,
                        {
                            runDetector(it)
                        });
                }
            })
            Debug.d(TAG, "detectButton: takePicture:")
            dataBinding.cameraView.takePicture()
        })
    }

    override fun onResume() {
        super.onResume()
        Debug.d(TAG, "onResume:")
        dataBinding.cameraView.open();
    }

    override fun onPause() {
        super.onPause()
        Debug.d(TAG, "onPause:")
        dataBinding.cameraView.close();
    }

    override fun onDestroy() {
        super.onDestroy()
        Debug.d(TAG, "onDestroy:")
        dataBinding.cameraView.destroy();
    }

When I start app activity first time I get permission dialog.

image

I press "Deny"

Then show another dialog:

image

I checked "Never ask again" and press "Deny" button.

After that show INFINITY THE NEXT MESSAGES:

12-25 12:17:33.930 D/com.myproejct.activity.ScanCheckActivity( 5005): onPause:
12-25 12:17:33.935 V/FA      ( 5005): Screen exposed for less than 1000 ms. Event not sent. time: 43
12-25 12:17:33.954 V/FA      ( 5005): Activity paused, time: 53318489
12-25 12:17:33.976 W/InputMethodManagerService(  663): Window already focused, ignoring focus gain of: com.android.internal.view.IInputMethodClient$Stub$Proxy@3e5d334 attribute=null, token = android.os.BinderProxy@18fb14a
12-25 12:17:33.990 D/com.myproejct.activity.ScanCheckActivity( 5005): onResume:
12-25 12:17:33.995 V/FA      ( 5005): Activity resumed, time: 53318550
12-25 12:17:33.997 I/ActivityManager(  663): START u0 {act=android.content.pm.action.REQUEST_PERMISSIONS pkg=com.google.android.packageinstaller cmp=com.google.android.packageinstaller/com.android.packageinstaller.permission.ui.GrantPermissionsActivity (has extras)} from uid 11633 on display 0
12-25 12:17:34.012 W/Activity( 5005): Can reqeust only one set of permissions at a time
12-25 12:17:34.033 D/com.myproejct.activity.ScanCheckActivity( 5005): onPause:
12-25 12:17:34.035 V/FA      ( 5005): Screen exposed for less than 1000 ms. Event not sent. time: 42
12-25 12:17:34.038 V/FA      ( 5005): Activity paused, time: 53318592
12-25 12:17:34.078 W/InputMethodManagerService(  663): Window already focused, ignoring focus gain of: com.android.internal.view.IInputMethodClient$Stub$Proxy@7a6eea0 attribute=null, token = android.os.BinderProxy@18fb14a
12-25 12:17:34.091 D/com.myproejct.activity.ScanCheckActivity( 5005): onResume:

And as result I can't do anything. Button "Back" not work. Nothing not work.

If I remove app from memory (by application manager) and again start app and start my activity I again get this infinity message. And again nothing not work!!!

How I can fix this?

question

All 6 comments

In the next version, you can use app:cameraRequestPermissions="false" and request permissions yourself, until we implement a better permission strategy.

I update version

implementation "com.otaliastudios:cameraview:2.6.0"

And now I can set app:cameraRequestPermissions="false"
As result the dialog of request permissions is not show.
So how this flag can help me to fix my problem ? Infinity call onPause and onResume

You simply request permissions yourself. And use setLifecycleOwner

You simply request permissions yourself. And use setLifecycleOwner

Here my solution:

implementation "com.otaliastudios:cameraview:2.6.0"

In my xml layout:
```
android:id="@+id/cameraView"
android:layout_width="0dp"
android:layout_height="0dp"
android:keepScreenOn="true"
app:cameraAudio="off"
app:cameraPictureFormat="jpeg"
app:cameraRequestPermissions="false"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/profileDetailsToolbar" />


in my Activity:

private var isPermissionGranted: Boolean = false

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Debug.d(TAG, "onCreate")
dataBinding = DataBindingUtil.setContentView(this, R.layout.scan_check_activity)
init()
}

private fun init() {
    setSupportActionBar(findViewById(R.id.toolBar))
    getSupportActionBar()?.setDisplayHomeAsUpEnabled(true)
    getSupportActionBar()?.setHomeButtonEnabled(true)
    getSupportActionBar()?.setDisplayShowTitleEnabled(false)
    isPermissionGranted = isPermissionGranted()
    dataBinding.cameraView.setLifecycleOwner(this);
    if (!isPermissionGranted) {
        requestPermission();
    }
    initLogic()

}

private fun requestPermission() {
// my logic to request camera's permission
}

override fun onResume() {
super.onResume()
Debug.d(TAG, "onResume: ")
dataBinding.cameraView.open();
}

override fun onPause() {
    super.onPause()
    Debug.d(TAG, "onPause:")
    dataBinding.cameraView.close();
}

override fun onDestroy() {
    super.onDestroy()
    Debug.d(TAG, "onDestroy: ")
    dataBinding.cameraView.destroy();

}
```

As you can see:

  1. use flag: app:cameraRequestPermissions="false"
  2. Use my custom method to request camera's permissions: requestPermission()

And now as result the methods onResume()and onPause() not call INFINITY times (as in version 2.5.0).

Nice. This flag app:cameraRequestPermissions="false"fix my problem.

Thanks.

If you use the lifecycle owner you can remove onStart/onPause/onDestroy.

You could also call camera.open() during onPermissionRequestResults() but in practice this is not needed because when the permission dialog is closed, your UI receives a resume call.

If you use the lifecycle owner you can remove onStart/onPause/onDestroy.

You could also call camera.open() during onPermissionRequestResults() but in practice this is not needed because when the permission dialog is closed, your UI receives a resume call.

Do you mean this?

private var isPermissionGranted: Boolean = false

 override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        Debug.d(TAG, "onCreate")
        dataBinding = DataBindingUtil.setContentView(this, R.layout.scan_check_activity)
        init()
    }

   private fun init() {
       dataBinding.cameraView.setLifecycleOwner(this);
        if (!isPermissionGranted) {
            requestPermission();
        }
        initLogic()
    }

private fun requestPermission() {
  // my logic to request camera's permission
}

 override fun onResume() {
        super.onResume()
        Debug.d(TAG, "onResume: ")
        dataBinding.cameraView.open();
    }

}

Not need call onPause/onDestroy()

?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

therealshabi picture therealshabi  路  10Comments

Cutta picture Cutta  路  3Comments

YumcoderCom picture YumcoderCom  路  5Comments

gabriel-TheCode picture gabriel-TheCode  路  8Comments

vedmedenko picture vedmedenko  路  9Comments