应用程序在三星设备上拍照后崩溃

问题描述 投票:0回答:4

我的应用程序允许用户使用设备的默认相机应用程序拍照,如下所示:

    private void takePhoto(Uri outputUri) {
        Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        intent.putExtra(MediaStore.EXTRA_OUTPUT, outputUri);
        startActivityForResult(intent, TAKE_PHOTO_REQUEST_CODE);
    }

查看崩溃日志,我看到很多应用程序崩溃发生在应用程序似乎在拍照后恢复的情况下。
异常和堆栈跟踪:

Fatal Exception: android.view.ViewRootImpl$CalledFromWrongThreadException
Only the original thread that created a view hierarchy can touch its views.
android.view.ViewRootImpl.checkThread (ViewRootImpl.java:11379)
android.view.ViewRootImpl.requestLayout (ViewRootImpl.java:2562)
android.view.ViewRootImpl.updateConfiguration (ViewRootImpl.java:6324)
android.app.ActivityThread.handleActivityConfigurationChanged (ActivityThread.java:6925)
android.app.servertransaction.ActivityConfigurationChangeItem.execute (ActivityConfigurationChangeItem.java:53)
android.app.servertransaction.ActivityTransactionItem.execute (ActivityTransactionItem.java:45)
android.app.servertransaction.TransactionExecutor.executeCallbacks (TransactionExecutor.java:135)
android.app.servertransaction.TransactionExecutor.execute (TransactionExecutor.java:95)
android.app.ActivityThread$H.handleMessage (ActivityThread.java:2571)
android.os.Handler.dispatchMessage (Handler.java:106)
android.os.Looper.loopOnce (Looper.java:226)
android.os.Looper.loop (Looper.java:313)
android.app.ActivityThread.main (ActivityThread.java:8741)
java.lang.reflect.Method.invoke (Method.java)
com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:571)
com.android.internal.os.ZygoteInit.main (ZygoteInit.java:1067)

堆栈跟踪有几个不同的变体,但它们都经历了一些配置更改,这让我相信用户必须在拍照时旋转设备,并且当它以不同的方向返回前台时应用程序崩溃.
我的应用程序的活动在其清单中有

android:configChanges="orientation|screenSize"
,因为它包含一个WebView,但它在
onConfigurationChanged
期间没有做任何事情。
在调查崩溃时,我添加了日志以将线程名称和 ID 打印到主要生命周期方法以及
onConfigurationChanged
。我发现
onConfigurationChanged
在应用程序崩溃之前在与
onCreate
调用相同的主线程上调用。
onStart
onResume
在崩溃前没有被调用。
为了给整个事情增加更多的神秘感,崩溃只发生在三星设备上(但在真实的手机/桌子型号上)。
尽管我认为我的应用程序没有做任何独特或不寻常的事情,但我在网上找不到任何类似的报告。

任何想法/建议将不胜感激!

编辑
添加更多堆栈跟踪变体:

Fatal Exception: android.view.ViewRootImpl$CalledFromWrongThreadException
Only the original thread that created a view hierarchy can touch its views.
android.view.ViewRootImpl.checkThread (ViewRootImpl.java:11586)
android.view.ViewRootImpl.requestLayout (ViewRootImpl.java:2648)
android.view.View.requestLayout (View.java:27612)
android.view.View.requestLayout (View.java:27612)
android.view.View.requestLayout (View.java:27612)
android.view.View.requestLayout (View.java:27612)
android.view.View.requestLayout (View.java:27612)
android.view.View.requestLayout (View.java:27612)
android.view.View.requestLayout (View.java:27612)
android.widget.TextView.onConfigurationChanged (TextView.java:4706)
android.view.View.dispatchConfigurationChanged (View.java:16145)
android.view.ViewGroup.dispatchConfigurationChanged (ViewGroup.java:1654)
android.view.ViewGroup.dispatchConfigurationChanged (ViewGroup.java:1654)
android.view.ViewGroup.dispatchConfigurationChanged (ViewGroup.java:1654)
android.view.ViewGroup.dispatchConfigurationChanged (ViewGroup.java:1654)
android.view.ViewGroup.dispatchConfigurationChanged (ViewGroup.java:1654)
android.view.ViewGroup.dispatchConfigurationChanged (ViewGroup.java:1654)
android.view.ViewRootImpl.updateConfiguration (ViewRootImpl.java:6502)
android.app.ActivityThread.handleActivityConfigurationChanged (ActivityThread.java:6941)
android.app.servertransaction.ActivityConfigurationChangeItem.execute (ActivityConfigurationChangeItem.java:53)
android.app.servertransaction.ActivityTransactionItem.execute (ActivityTransactionItem.java:45)
android.app.servertransaction.TransactionExecutor.executeCallbacks (TransactionExecutor.java:135)
android.app.servertransaction.TransactionExecutor.execute (TransactionExecutor.java:95)
android.app.ActivityThread$H.handleMessage (ActivityThread.java:2574)
android.os.Handler.dispatchMessage (Handler.java:106)
android.os.Looper.loopOnce (Looper.java:226)
android.os.Looper.loop (Looper.java:313)
android.app.ActivityThread.main (ActivityThread.java:8757)
java.lang.reflect.Method.invoke (Method.java)
com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:571)
com.android.internal.os.ZygoteInit.main (ZygoteInit.java:1067)
Fatal Exception: android.view.ViewRootImpl$CalledFromWrongThreadException
Only the original thread that created a view hierarchy can touch its views.
android.view.ViewRootImpl.checkThread (ViewRootImpl.java:11586)
android.view.ViewRootImpl.requestLayout (ViewRootImpl.java:2648)
android.view.View.requestLayout (View.java:27612)
android.view.View.requestLayout (View.java:27612)
android.view.View.requestLayout (View.java:27612)
android.view.View.requestLayout (View.java:27612)
android.view.View.requestLayout (View.java:27612)
android.view.View.requestLayout (View.java:27612)
android.view.View.requestLayout (View.java:27612)
android.widget.TextView.onConfigurationChanged (TextView.java:4706)
android.view.View.dispatchConfigurationChanged (View.java:16145)
android.view.ViewGroup.dispatchConfigurationChanged (ViewGroup.java:1654)
android.view.ViewGroup.dispatchConfigurationChanged (ViewGroup.java:1654)
android.view.ViewGroup.dispatchConfigurationChanged (ViewGroup.java:1654)
android.view.ViewGroup.dispatchConfigurationChanged (ViewGroup.java:1654)
android.view.ViewGroup.dispatchConfigurationChanged (ViewGroup.java:1654)
android.view.ViewGroup.dispatchConfigurationChanged (ViewGroup.java:1654)
android.view.ViewRootImpl.updateConfiguration (ViewRootImpl.java:6502)
android.app.ActivityThread.handleActivityConfigurationChanged (ActivityThread.java:6941)
android.app.ActivityThread$ActivityClientRecord$1.onConfigurationChanged (ActivityThread.java:797)
android.view.ViewRootImpl.performConfigurationChange (ViewRootImpl.java:6462)
android.view.ViewRootImpl.handleResized (ViewRootImpl.java:2424)
android.view.ViewRootImpl.-$$Nest$mhandleResized
android.view.ViewRootImpl$ViewRootHandler.handleMessageImpl (ViewRootImpl.java:6728)
android.view.ViewRootImpl$ViewRootHandler.handleMessage (ViewRootImpl.java:6697)
android.os.Handler.dispatchMessage (Handler.java:106)
android.os.Looper.loopOnce (Looper.java:226)
android.os.Looper.loop (Looper.java:313)
android.app.ActivityThread.main (ActivityThread.java:8757)
java.lang.reflect.Method.invoke (Method.java)
com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:571)
com.android.internal.os.ZygoteInit.main (ZygoteInit.java:1067)
java android samsung-mobile
4个回答
0
投票

通常这个错误发生在网络处理等后台任务中,所以他们使用不同的线程。因此,要解决此问题,请使用

Activity.runOnUiThread
视图原始活动中的方法。


0
投票

使用下面的代码。它应该工作正常。无论如何,startActivityForResult() 已被弃用。

ActivityResultLauncher<Intent> cameraActivityResultLauncher;

cameraActivityResultLauncher = registerForActivityResult(
            new ActivityResultContracts.StartActivityForResult(),
            new ActivityResultCallback<ActivityResult>() {
                @Override
                public void onActivityResult(ActivityResult result) {
                    if (result.getResultCode() == Activity.RESULT_OK) {
                        // There are no request codes
                        Intent data = result.getData();
                        Bitmap img = (Bitmap)data.getExtras().get("data");
                        imageView.setImageBitmap(img);
                    }
                }
            });

Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
cameraActivityResultLauncher.launch(cameraIntent);

0
投票

您可以尝试调试。由于某种原因,ViewRootImpl 实例中的 mThread 字段与通知配置更改的线程不同。这是抛出异常的方法:

void checkThread() {
        if (mThread != Thread.currentThread()) {
            throw new CalledFromWrongThreadException(
                    "Only the original thread that created a view hierarchy can touch its views.");
        }
    }

可能是该字段被设置为空或更改,或者线程确实发生了更改。也许三星已经修改了上述课程。

也尝试在不离开应用程序的情况下触发配置更改,看看会发生什么。


0
投票

是的。它确实只发生在三星设备上。我曾经遇到过这个问题。

这是您拍摄照片时发生的情况

  1. Open a camara intent to capture a picture
  2. Take picture
  3. Return to your activity or fragment
  4. Get captured image & use it

这是使用设备相机拍摄图像的通常生命周期。

现在运行在 android 13 上的三星设备(不知道低版本,我没有低版本的,所以)有一个问题,如果你使用 camera intent 纵向拍照,然后返回活动或具有横向方向的片段,然后它会在配置更改时破坏以前的对象。

即使您以纵向拍摄照片,然后在横向模式下旋转设备,然后再次将其旋转到纵向模式并返回活动,也会发生这种情况,因为如上所述配置更改。

所以,这是我对工作正常的看法。我现在将它应用于我所有包含此类功能的应用程序。

1。使用传统方法固定清单中的活动方向,根据您的需要提供固定屏幕方向

portrait
landscape

<activity
    android:name=".activity.MainActivity"
    android:screenOrientation="portrait" />

2。如果您的响应式屏幕在设备方向更改时可以是纵向或横向,则将此

config
添加到Manifest
中的
activity tag

<activity
    android:name=".activity.MainActivity"
    android:configChanges="orientation|screenSize"/>

现在,当您在拍照后返回您的 Activity 时,您将在启动相机意图之前创建的对象不会被破坏。

© www.soinside.com 2019 - 2024. All rights reserved.