Android Tileservice (QuickSettings) вызывает error_camera_disabled при закрытии активностиAndroid

Форум для тех, кто программирует под Android
Ответить Пред. темаСлед. тема
Anonymous
 Android Tileservice (QuickSettings) вызывает error_camera_disabled при закрытии активности

Сообщение Anonymous »

Итак, я заметил странную ошибку на Android: когда у вас есть активность с предварительным просмотром камеры и кнопкой быстрых настроек (которая либо делает что -то не связанное с камерой, либо вообще ничего, как в образе, я предоставляю), может возникнуть следующая проблема:
Если Tileservice все еще жив (I.E. ESPORY не был вызван, и Decips>, и Decips, и Decips>, и Decips, и Decipment, и DiseStroy. вызывается), используя кнопку Back или Home, Cameradevice.stateCallback может запустить Onerror обратный вызов с помощью error_camera_disabled ().
Почему это происходит? Если есть даже объяснение. Я не уверен, что кто -то сообщил об этом на трекере выпуска Google - я попробовал Googling, но ничего не нашел. < /P>
Вот журналы, которые демонстрируют проблему: < /p>

Код: Выделить всё

01:50:45.787 [Test]TileService   D  onCreate
01:50:45.799 [Test]TileService   D  onStartListening
01:50:49.044 [Test]TileService   D  onStopListening
01:50:53.270 [Test]Activity      D  onCreate
01:50:53.289 [Test]Activity      D  onStart
01:50:53.356 [Test]Activity      D  Camera onOpened
01:50:56.965 [Test]Activity      D  onStop
01:50:58.745 [Test]Activity      D  onStart
01:50:58.764 [Test]Activity      D  Camera onOpened
01:51:00.724 [Test]Activity      D  onStop
01:51:00.937 [Test]Activity      E  Camera onError: 3
01:51:19.056 [Test]TileService   D  onDestroy
Вы никогда не получите камеру Onerror: 3 в этом примере, если Tileservice не работает (уничтожен). Вы получаете эту ошибку только в том случае, если служба жива. Вы можете сделать его активным, открыв панель уведомлений:

После некоторого времени он будет уничтожен в g -образе. Воспроизведите проблему (обязательно активируйте Tileservice , открыв панель уведомления системы, затем запустите приложение и попробуйте скрыть или закрыть его - иногда ошибка не может стрелять, поэтому необходимо больше попыток): compilesdk/targetsdk - 35 или 36

Код: Выделить всё

package com.cameradisabled.tileservice

import android.Manifest
import android.content.Context
import android.content.pm.PackageManager
import android.graphics.SurfaceTexture
import android.hardware.camera2.CameraCaptureSession
import android.hardware.camera2.CameraDevice
import android.hardware.camera2.CameraManager
import android.hardware.camera2.CaptureRequest
import android.os.Bundle
import android.util.Log
import android.view.Surface
import android.view.TextureView
import android.view.View
import android.widget.Button
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat

class MainActivity : AppCompatActivity() {
companion object {
private const val TAG = "[Test]Activity"
}

private lateinit var textureView: TextureView
private lateinit var btnRequest: Button

private lateinit var cameraManager: CameraManager

private val permissionLauncher = registerForActivityResult(
ActivityResultContracts.RequestPermission()
) { isGranted ->
Log.d(TAG, "Permission result: $isGranted")
if (isGranted) {
btnRequest.visibility = View.GONE
openCameraIfReady()
} else {
btnRequest.visibility = View.VISIBLE
}
}

private var cameraDevice: CameraDevice? = null
private var session: CameraCaptureSession? = null
private lateinit var previewRequestBuilder: CaptureRequest.Builder

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Log.d(TAG, "onCreate")
setContentView(R.layout.activity_main)

textureView = findViewById(R.id.texture_view)
btnRequest = findViewById(R.id.btn_request_permission)
cameraManager = getSystemService(CAMERA_SERVICE) as CameraManager

// Show button if permission not granted
if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA)
!= PackageManager.PERMISSION_GRANTED
) {
btnRequest.visibility = View.VISIBLE
}

btnRequest.setOnClickListener {
permissionLauncher.launch(Manifest.permission.CAMERA)
}

// TextureView listener
textureView.surfaceTextureListener = object : TextureView.SurfaceTextureListener {
override fun onSurfaceTextureAvailable(st: SurfaceTexture, w: Int, h: Int) {
openCameraIfReady()
}
override fun onSurfaceTextureSizeChanged(st: SurfaceTexture, w: Int, h: Int) {}
override fun onSurfaceTextureDestroyed(st: SurfaceTexture) = true
override fun onSurfaceTextureUpdated(st: SurfaceTexture) {}
}
}

override fun onStart() {
super.onStart()
Log.d(TAG, "onStart")
openCameraIfReady()
}

override fun onStop() {
Log.d(TAG, "onStop")
closeCamera()
super.onStop()
}

private fun openCameraIfReady() {
if (!textureView.isAvailable) return
if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA)
!= PackageManager.PERMISSION_GRANTED
) return

btnRequest.visibility = View.GONE
try {
val cameraId = cameraManager.cameraIdList.first()
cameraManager.openCamera(cameraId, stateCallback, null)
} catch (e: Exception) {
Log.e(TAG, "openCamera failed", e)
}
}

private val stateCallback = object : CameraDevice.StateCallback() {
override fun onOpened(device: CameraDevice) {
Log.d(TAG, "Camera onOpened")
cameraDevice = device
startPreview()
}

override fun onDisconnected(device: CameraDevice) {
Log.d(TAG, "Camera onDisconnected")
device.close()
cameraDevice = null
}

override fun onError(device: CameraDevice, error: Int) {
Log.e(TAG, "Camera onError:  $error") // ERROR_CAMERA_DISABLED
device.close()
cameraDevice = null
}
}

private fun startPreview() {
val device = cameraDevice ?: return
val texture = textureView.surfaceTexture ?: return

texture.setDefaultBufferSize(textureView.width, textureView.height)
val surface = Surface(texture)

previewRequestBuilder = device.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW).apply {
addTarget(surface)
}

device.createCaptureSession(listOf(surface), object : CameraCaptureSession.StateCallback() {
override fun onConfigured(sess: CameraCaptureSession) {
session = sess
sess.setRepeatingRequest(previewRequestBuilder.build(), null, null)
}
override fun onConfigureFailed(sess: CameraCaptureSession) {
Log.e(TAG, "Preview configure failed")
}
}, null)
}

private fun closeCamera() {
session?.close()
session = null
cameraDevice?.close()
cameraDevice = null
}
}
< /code>







< /code>
package com.cameradisabled.tileservice

import android.service.quicksettings.TileService
import android.util.Log

class MyTileService : TileService() {
companion object { private const val TAG = "[Test]TileService" }

override fun onCreate() {
super.onCreate()
Log.d(TAG, "onCreate")
}

override fun onDestroy() {
Log.d(TAG, "onDestroy")
super.onDestroy()
}

override fun onStartListening() {
super.onStartListening()
Log.d(TAG, "onStartListening")
}

override fun onStopListening() {
Log.d(TAG, "onStopListening")
super.onStopListening()
}

override fun onClick() {
super.onClick()
Log.d(TAG, "onClick")
}
}
< /code>
P.S. I have reproduced this on Android 15 using a Samsung S24 Ultra. More testing on different devices and Android versions is needed.
[b]Update[/b]:
It seems the Android system might think I'm trying to use the camera in the background simply because the TileService
Фоновая служба работает. Если это правда, это действительно плохой дизайн. Для записи я останавливаю камеру в методе Activity onstop () , так что все же почему? OnStart состояние жизненного цикла;

Код: Выделить всё

03:02:52.144 [Test]Activity     D  onCreate
03:02:52.195 [Test]Activity     D  onSurfaceTextureAvailable RESUMED
03:02:52.224 [Test]Activity     D  Camera onOpened
03:02:57.100 [Test]TileService  D  onCreate
03:02:57.103 [Test]TileService  D  onStartListening
03:02:58.563 [Test]TileService  D  onStopListening
03:03:02.253 [Test]Activity     D  onStop
03:03:02.464 [Test]Activity     E  Camera onError: 3
03:03:28.571 [Test]TileService  D  onDestroy
< /code>
override fun onSurfaceTextureAvailable(st: SurfaceTexture, w: Int, h: Int) {
Log.d(TAG, "onSurfaceTextureAvailable ${lifecycle.currentState }")
openCameraIfReady()
}
< /code>
[b]Update 3[/b]:
Even if I add stopRepeating()
и abortcaptures () in onstop () , это просто вызовет исключение при вызове сеанса? .stopRepeating () Поскольку камера уже была закрыта из -за ошибки камеры 3 и камеры Onerror: 3 журнал даже появляется ранее, тогда Onstop
vollop

Код: Выделить всё

03:19:21.367 [Test]Activity     D  onCreate
03:19:21.419 [Test]Activity     D  onSurfaceTextureAvailable RESUMED
03:19:21.445 [Test]Activity     D  Camera onOpened
03:19:24.481 [Test]TileService  D  onCreate
03:19:24.488 [Test]Activity     E  Camera onError: 3
03:19:24.678 [Test]TileService  D  onStartListening
03:19:24.725 [Test]Activity     D  onStop
03:19:24.725 AndroidRuntime     D  Shutting down VM
03:19:24.727 AndroidRuntime     E  FATAL EXCEPTION: main
Process: com.cameradisabled.tileservice, PID: 11118
java.lang.RuntimeException: Unable to stop activity {com.cameradisabled.tileservice/com.cameradisabled.tileservice.MainActivity}: java.lang.IllegalStateException: CameraDevice was already closed
at android.app.ActivityThread.callActivityOnStop(ActivityThread.java:6417)
at android.app.ActivityThread.performStopActivityInner(ActivityThread.java:6383)
at android.app.ActivityThread.handleStopActivity(ActivityThread.java:6453)
at android.app.servertransaction.TransactionExecutor.performLifecycleSequence(TransactionExecutor.java:285)
at android.app.servertransaction.TransactionExecutor.cycleToPath(TransactionExecutor.java:250)
at android.app.servertransaction.TransactionExecutor.executeLifecycleItem(TransactionExecutor.java:222)
at android.app.servertransaction.TransactionExecutor.executeTransactionItems(TransactionExecutor.java:107)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:81)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2895)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loopOnce(Looper.java:257)
at android.os.Looper.loop(Looper.java:342)
at android.app.ActivityThread.main(ActivityThread.java:9634)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:619)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:929)
Caused by: java.lang.IllegalStateException:  CameraDevice was already closed
at android.hardware.camera2.impl.CameraDeviceImpl.checkIfCameraClosedOrInError(CameraDeviceImpl.java:2609)
at android.hardware.camera2.impl.CameraDeviceImpl.stopRepeating(CameraDeviceImpl.java:1469)
at android.hardware.camera2.impl.CameraCaptureSessionImpl.stopRepeating(CameraCaptureSessionImpl.java:424)
at com.cameradisabled.tileservice.MainActivity.closeCamera(MainActivity.kt:160)
at com.cameradisabled.tileservice.MainActivity.onStop(MainActivity.kt:98)
at android.app.Instrumentation.callActivityOnStop(Instrumentation.java:1742)
at android.app.Activity.performStop(Activity.java:9635)
at android.app.ActivityThread.callActivityOnStop(ActivityThread.java:6409)
at android.app.ActivityThread.performStopActivityInner(ActivityThread.java:6383) 
at android.app.ActivityThread.handleStopActivity(ActivityThread.java:6453) 
at android.app.servertransaction.TransactionExecutor.performLifecycleSequence(TransactionExecutor.java:285) 
at android.app.servertransaction.TransactionExecutor.cycleToPath(TransactionExecutor.java:250) 
at android.app.servertransaction.TransactionExecutor.executeLifecycleItem(TransactionExecutor.java:222) 
at android.app.servertransaction.TransactionExecutor.executeTransactionItems(TransactionExecutor.java:107) 
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:81) 
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2895) 
at android.os.Handler.dispatchMessage(Handler.java:107) 
at android.os.Looper.loopOnce(Looper.java:257) 
at android.os.Looper.loop(Looper.java:342) 
at android.app.ActivityThread.main(ActivityThread.java:9634) 
at java.lang.reflect.Method.invoke(Native Method) 
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:619) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:929) 

< /code>
override fun onStop() {
Log.d(TAG, "onStop")
closeCamera()
super.onStop()
}

private fun closeCamera() {
session?.stopRepeating() // will crash here if TileService is alive
session?.abortCaptures()
session?.close()
session = null
cameraDevice?.close()
cameraDevice = null
}
< /code>
[b]Update 4[/b]:
The issue doesn't happen if I close the camera in onPause
while tileservice все еще жив:

Код: Выделить всё

/*override fun onStart() {
super.onStart()
Log.d(TAG, "Activity. onStart")
openCameraIfReady()
}

override fun onStop() {
Log.d(TAG, "Activity. onStop")
closeCamera()
super.onStop()
}*/

override fun onResume() {
super.onResume()
Log.d(TAG, "Activity. onResume")
openCameraIfReady()
}

override fun onPause() {
Log.d(TAG, "Activity. onPause")
closeCamera()
super.onPause()
}
< /code>
But this is not a solution.
[b]Update 5[/b]
If I remove TileService
и запустить свою собственную фоновую службу, тогда я не могу воспроизвести эту проблему, поэтому она определенно связана с Tileservice :
package com.cameradisabled.tileservice

import android.app.Service
import android.content.Intent
import android.os.IBinder
import android.util.Log

class MyBackgroundService : Service() {
companion object { private const val TAG = "[Test]Service" }

override fun onCreate() {
super.onCreate()
Log.d(TAG, "Service. onCreate")
}

override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
Log.d(TAG, "Service. onStartCommand")
// Do nothing
return START_STICKY
}

override fun onDestroy() {
Log.d(TAG, "Service. onDestroy")
super.onDestroy()
}

override fun onBind(intent: Intent?): IBinder? {
Log.d(TAG, "Service. onBind")
return null
}
}
< /code>
Manifest:



< /code>
class MainActivity : AppCompatActivity() {
...

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

// Start test background service
Intent(this, MyBackgroundService::class.java).also { intent ->
startService(intent)
Log.d(TAG, "MyBackgroundService startService called")
}
< /code>
Logs:
16:03:32.437 [Test]Activity D Activity. onCreate
16:03:32.455 [Test]Activity D MyBackgroundService startService called
16:03:32.457 [Test]Activity D Activity. onStart
16:03:32.493 [Test]Activity D Activity. onSurfaceTextureAvailable, lifecycle state: RESUMED
16:03:32.493 [Test]Activity D Activity. Camera try open, lifecycle state: RESUMED
16:03:32.516 [Test]Service D Service. onCreate
16:03:32.516 [Test]Service D Service. onStartCommand
16:03:32.524 [Test]Activity D Activity. Camera onOpened, lifecycle state: RESUMED
16:03:35.280 [Test]Activity D Activity. onStop
< /code>
Update 6:
I was able to reproduce this issue on the following real Samsung devices running Android 15:
  • Samsung S24 Ultra (Android 15)
  • Samsung S25 Ultra (Android 15)
I was not able to reproduce the issue on the following devices and Android versions:
  • Samsung S24 Ultra (Android 14)
  • Google Pixel 9 Pro (Android 15)
I also couldn’t reproduce the issue on Pixel emulators (Android 15).
So, this might be a Samsung specific issue on Android 15. I haven’t tested devices from other manufacturers yet.

Подробнее здесь: https://stackoverflow.com/questions/796 ... closing-th
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение
  • Android Tileservice (QuickSettings) вызывает error_camera_disabled при закрытии активности
    Anonymous » » в форуме Android
    0 Ответы
    6 Просмотры
    Последнее сообщение Anonymous
  • Почему моя привязка в закрытии вызывается от button.disabled () не обновляется?
    Anonymous » » в форуме IOS
    0 Ответы
    3 Просмотры
    Последнее сообщение Anonymous
  • Почему моя привязка в закрытии вызывается от button.disabled () не обновляется?
    Anonymous » » в форуме IOS
    0 Ответы
    2 Просмотры
    Последнее сообщение Anonymous
  • Запуск активности из TileService для Android 14 не разрешен
    Anonymous » » в форуме Android
    0 Ответы
    10 Просмотры
    Последнее сообщение Anonymous
  • Android Camera Camera Remissed отказано в гибридном приложении Maui с обнаружением позы MediaPipe JS
    Anonymous » » в форуме Android
    0 Ответы
    14 Просмотры
    Последнее сообщение Anonymous

Вернуться в «Android»