3

Android中各种Exception错误小结

 1 year ago
source link: https://www.51cto.com/article/743697.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Android中各种Exception错误小结

作者:Zinyan 2022-12-31 09:32:15
通过Binding方式获取的PreviewView对象不存在。我们布局中如果是存在该View,但是仍然出现这个错误。那么只有一种情况。就是viewBinding还没有来得及初始化之前,就调用了viewBinding的方法去获取PreviewView对象了。就会出现上面的问题了。

汇总了部分的崩溃异常日志内容,以及相关问题的解决方法。希望给大家一点参考。

问题都比较简单。

2. Exception

简单汇总一些常见的异常情况,以及相关的解决方法

2.1 IllegalArgumentException错误

IllegalArgumentException:非法数据异常。

java.lang.IllegalArgumentException: The key must be an application-specific resource id.

The key must be an application-specific resource id:密钥必须是特定于应用程序的资源id。

出现问题的原因在于我们给View添加Tag内容时,其中的Key的值并不能随便写个int值,如果随便写个int值就会出现上面的错误了。

我们必须在xml文件中创建一个id值,然后再填写到key中。

错误写法:

binding.tvState.setTag(101, data);

正确写法:

<?xml version="1.0" encoding="utf-8"?>
<resources>
<item name="key_task" type="id" />
</resources>
   
   
binding.tvState.setTag(R.id.key_task, data);
java.lang.IllegalArgumentException: Trying to create LifecycleCamera with destroyed lifecycle.

试图创建生命周期被破坏的LifecycleCamera。

也就说我们在调用cameraProvider.bindToLifecycle的时候。中间步骤出现了崩溃或其他问题。

造成lifecycle被销毁了。然后出现的错误。检测出现的代码。

2.2 ExifInterface 异常

在新项目中使用Glide库进行图片下载的时候,每加载一次图片都会出现下面的异常:

W/ExifInterface: Invalid image: ExifInterface got an unsupported image format file(ExifInterface supports JPEG and some RAW image formats only) or a corrupted JPEG file to ExifInterface.
java.io.IOException: Invalid byte order: ffff8950
at android.media.ExifInterface.readByteOrder(ExifInterface.java:3128)
at android.media.ExifInterface.isOrfFormat(ExifInterface.java:2443)
at android.media.ExifInterface.getMimeType(ExifInterface.java:2321)
at android.media.ExifInterface.loadAttributes(ExifInterface.java:1755)
at android.media.ExifInterface.<init>(ExifInterface.java:1449)
at com.bumptech.glide.load.resource.bitmap.ExifInterfaceImageHeaderParser.getOrientation(ExifInterfaceImageHeaderParser.java:40)
at com.bumptech.glide.load.ImageHeaderParserUtils.getOrientation(ImageHeaderParserUtils.java:92)
at com.bumptech.glide.load.resource.bitmap.Downsampler.decodeFromWrappedStreams(Downsampler.java:269)
at com.bumptech.glide.load.resource.bitmap.Downsampler.decode(Downsampler.java:224)
at com.bumptech.glide.load.resource.bitmap.Downsampler.decode(Downsampler.java:173)
at com.bumptech.glide.load.resource.bitmap.ByteBufferBitmapDecoder.decode(ByteBufferBitmapDecoder.java:31)
at com.bumptech.glide.load.resource.bitmap.ByteBufferBitmapDecoder.decode(ByteBufferBitmapDecoder.java:14)
at com.bumptech.glide.load.engine.DecodePath.decodeResourceWithList(DecodePath.java:92)
at com.bumptech.glide.load.engine.DecodePath.decodeResource(DecodePath.java:70)
at com.bumptech.glide.load.engine.DecodePath.decode(DecodePath.java:59)
at com.bumptech.glide.load.engine.LoadPath.loadWithExceptionList(LoadPath.java:76)
at com.bumptech.glide.load.engine.LoadPath.load(LoadPath.java:57)
at com.bumptech.glide.load.engine.DecodeJob.runLoadPath(DecodeJob.java:524)
at com.bumptech.glide.load.engine.DecodeJob.decodeFromFetcher(DecodeJob.java:488)
at com.bumptech.glide.load.engine.DecodeJob.decodeFromData(DecodeJob.java:474)
at com.bumptech.glide.load.engine.DecodeJob.decodeFromRetrievedData(DecodeJob.java:426)
at com.bumptech.glide.load.engine.DecodeJob.onDataFetcherReady(DecodeJob.java:390)
at com.bumptech.glide.load.engine.DataCacheGenerator.onDataReady(DataCacheGenerator.java:94)
at com.bumptech.glide.load.model.ByteBufferFileLoader$ByteBufferFetcher.loadData(ByteBufferFileLoader.java:70)
at com.bumptech.glide.load.engine.DataCacheGenerator.startNext(DataCacheGenerator.java:74)
at com.bumptech.glide.load.engine.DecodeJob.runGenerators(DecodeJob.java:310)
at com.bumptech.glide.load.engine.DecodeJob.runWrapped(DecodeJob.java:276)
at com.bumptech.glide.load.engine.DecodeJob.run(DecodeJob.java:234)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:919)
at com.bumptech.glide.load.engine.executor.GlideExecutor$DefaultThreadFactory$1.run(GlideExecutor.java:431)

然后图片仍然是能够进行加载显示的。发现只有链接地址是https的图片才会出现上面的错误。而http请求反而不会出现异常。

运行设备为:Android 10 API 29

解决方法:将Glide插件的版本进行了升级,该错误打印就没有了。

implementation 'com.github.bumptech.glide:glide:4.10.0'
implementation 'com.github.bumptech.glide:glide:4.14.2'

问题得到了解决。

2.3 RuntimeException

RuntimeException:运行时异常。只有当程序运行到该行代码的时候,才会被触发的异常情况。

java.lang.RuntimeException: Unable to start activity ComponentInfo{com.xxx.xxx/com.xxx.xx.activity.login.XXXX}: java.lang.NullPointerException: Attempt to read from field 'androidx.camera.view.PreviewView com.xxx.xxx.databinding.XXXXXXXeBinding.previewView' on a null object reference

完整错误通常如下:

java.lang.RuntimeException: Unable to start activity ComponentInfo{com.xxx.xxx/com.xxx.xx.activity.login.XXXX}: java.lang.NullPointerException: Attempt to read from field 'androidx.camera.view.PreviewView com.xxx.xxx.databinding.XXXXXXXeBinding.previewView' on a null object reference
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3298)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3437)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2041)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7386)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:980)

通过Binding方式获取的PreviewView对象不存在。我们布局中如果是存在该View,但是仍然出现这个错误。

那么只有一种情况。就是viewBinding还没有来得及初始化之前,就调用了viewBinding的方法去获取PreviewView对象了。就会出现上面的问题了。

通常情况下,我们可能是在View初始化之前,调用了动态权限判断,而动态权限判断通过后就直接开启相机了。

而在这个时候我们View还没有来得及binding获取。

通过Binding 方法调用触发view绑定,也是有执行顺序和时间的。

运行时崩溃异常如下:

java.lang.RuntimeException: Unable to start activity ComponentInfo{com.xx.xx/com.xxx.xx.xx.login.xxx}: java.lang.IllegalArgumentException: Provided camera selector unable to resolve a camera for the given use case
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2671)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2732)
at android.app.ActivityThread.-wrap12(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1483)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6141)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:912)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:802)
 Caused by: java.lang.IllegalArgumentException: Provided camera selector unable to resolve a camera for the given use case
at androidx.camera.lifecycle.ProcessCameraProvider.bindToLifecycle(ProcessCameraProvider.java:470)
at androidx.camera.lifecycle.ProcessCameraProvider.bindToLifecycle(ProcessCameraProvider.java:360)

关键内容为:Provided camera selector unable to resolve a camera for the given use case翻译后显示:提供的摄像机选择器无法解析给定用例的摄像机.

问题在于,我们使用CameraX的时候,设备主机没有找到摄像头。通常手机是不会出现这个问题的,只是可能在其他Android主板系统中进行开发时,可能当前硬件还没有来得及配置上摄像头,而我们的app调用到了摄像头相关代码。就会触发上面的错误了。

而CameraX本身默认是会自动选择摄像头的。但是我们定义了CameraSelector指定了摄像头。而又找不到指定摄像头,就会出现这个错误了。

上面的代码触发的时候,是在:

cameraProvider.bindToLifecycle(this, cameraSelector, preview, imageAnalysis);

这一行代码中触发的。而这个配置是在try/cathc包裹中。我们只需要主动捕获一下IllegalArgumentException 异常就可以避免崩溃了。

try {
          ...
cameraProvider.bindToLifecycle(this, cameraSelector, preview, imageAnalysis);
         
 catch (IllegalArgumentException  e) {
e.printStackTrace();
 catch (Exception e) {
e.printStackTrace();
      }

但是,这样不够优美。最好的方法就是在需要启动相机相关界面时,检测一下设备是否存在摄像头。效果会更好一些。

检测方法比较简单

boolean isBack = cameraProvider.hasCamera(CameraSelector.DEFAULT_BACK_CAMERA);  //检测默认后置摄像头
boolean isFront = cameraProvider.hasCamera(CameraSelector.DEFAULT_FRONT_CAMERA); //检测默认前置摄像头

可以通过这两个方法检测设备是否存在默认摄像头,但是如果是通过USB,蓝牙等方式动态添加的摄像头。上面两种方法可不会检测到。

我们可以通过获取CameraInfo列表来判断是否有相机:

List<CameraInfo> camerList = provider.getAvailableCameraInfos();//得到相机列表
       //然后根据设备信息列表,得到硬件等级最高的相机
       if (camerList == null || camerList.size() == 0) {
           return null; //没有摄像头
      }
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.xxx.xxx/com.xxx.xxx.activity.xx.xx}: java.lang.IllegalArgumentException: LayoutManager androidx.recyclerview.widget.LinearLayoutManager@ed46d74 is already attached to a RecyclerView: androidx.recyclerview.widget.RecyclerView{584229d VFED..... ......I. 0,0-0,0 #7f0901a0 app:id/recyclerClass}, adapter:com.xxx.xx.xx.xxx@e3cc312, layout:androidx.recyclerview.widget.LinearLayoutManager@ed46d74, context:com.xxx.xx.xx.xxx.xxx@19aeae4
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3298)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3437)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2041)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7386)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:980)

当我们在同一个界面中多个RecyclerView​ 使用同一个LinearLayoutManager​或者GridLayoutManager的时候就会触发上面的运行时错误了。程序就会崩溃

错误写法:

LinearLayoutManager linearLayoutManager=new LinearLayoutManager(this,RecyclerView.VERTICAL,false);
viewBinding.recyclerClass.setLayoutManager(linearLayoutManager);

viewBinding.recyclerGrop.setLayoutManager(linearLayoutManager);

在上面,两个recyclerView​ 使用了同一个LinearLayoutManager。就会触发崩溃了。

正确写法为:

viewBinding.recyclerClass.setLayoutManager(new LinearLayoutManager(this,RecyclerView.VERTICAL,false));

viewBinding.recyclerGrop.setLayoutManager(new LinearLayoutManager(this,RecyclerView.VERTICAL,false));
责任编辑:武晓燕 来源: zinyan

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK