小米手机Attempt to invoke interface method 'boolean android.database.Cursor.moveToFirst()'

针对小米手机在选择图片后可能出现的崩溃问题,介绍了一种解决方案,通过使用MiPictureHelper工具类来获取图片的绝对路径。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

原文:http://blog.youkuaiyun.com/iamwutianbao/article/details/52459509

小米手机选择了图片之后,小米机会崩掉(别的机子,啥版本都没问题)。看异常信息,指示cursor.moveToFirst(),空指针异常。也就是说,cursor为空。是uri的问题,4.4之前,返回的是包含图片绝对路劲的,4.4之后,返回的不再是绝对路劲了,而是一个图片的编码。小米不论版本高低,小米机会崩掉,得到的只是一个图片编码。这时需要去转换为绝对路径,才能方便使用。下面方法是可以得到绝对路径的方法,是大神封装好了,封装成了一个pictureHelper工具类。


吐槽一下,除了小米,用ACTION_PICK,都能得到一个图片的绝对路径。如果是小米,用ACTION_PICK,就需要去转化了。但是,小米用ACTION_GET_CONTENT或者ACTION_OPEN_DOCUMENT,低版本,也能得到绝对路径。。最后统一的处理方法就是,用ACTION_GET_CONTENT,然后分版本处理,低版本还是旧的方法,高版本,用pictureHelper工具类处理得到绝对路径。

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. package com.xxxe.utils;  
  2.   
  3. import android.annotation.SuppressLint;  
  4. import android.content.ContentUris;  
  5. import android.content.Context;  
  6. import android.database.Cursor;  
  7. import android.net.Uri;  
  8. import android.os.Build;  
  9. import android.os.Environment;  
  10. import android.provider.DocumentsContract;  
  11. import android.provider.MediaStore;  
  12.       
  13. /** 
  14.  *  小米手机获取本地相册图片出现空指针异常处理类 
  15.  * @author dec 
  16.  * 
  17.  */  
  18.   
  19. public class MiPictureHelper {  
  20.       
  21.       
  22.   
  23.     @SuppressLint("NewApi")  
  24.     public static String getPath(final Context context, final Uri uri) {  
  25.         final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;  
  26.         // DocumentProvider  
  27.         if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {  
  28.             // ExternalStorageProvider  
  29.             if (isExternalStorageDocument(uri)) {  
  30.                 final String docId = DocumentsContract.getDocumentId(uri);  
  31.                 final String[] split = docId.split(":");  
  32.                 final String type = split[0];  
  33.                 if ("primary".equalsIgnoreCase(type)) {  
  34.                     return Environment.getExternalStorageDirectory() + "/" + split[1];  
  35.                 }  
  36.             }  
  37.             // DownloadsProvider  
  38.             else if (isDownloadsDocument(uri)) {  
  39.                 final String id = DocumentsContract.getDocumentId(uri);  
  40.                 final Uri contentUri = ContentUris.withAppendedId(  
  41.                 Uri.parse("content://downloads/public_downloads"),  
  42.                 Long.valueOf(id));  
  43.                 return getDataColumn(context, contentUri, nullnull);  
  44.             }  
  45.             // MediaProvider  
  46.             else if (isMediaDocument(uri)) {  
  47.                 final String docId = DocumentsContract.getDocumentId(uri);  
  48.                 final String[] split = docId.split(":");  
  49.                 final String type = split[0];  
  50.                 Uri contentUri = null;  
  51.                 if ("image".equals(type)) {  
  52.                     contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;  
  53.                 } else if ("video".equals(type)) {  
  54.                     contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;  
  55.                 } else if ("audio".equals(type)) {  
  56.                     contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;  
  57.                 }  
  58.                 final String selection = "_id=?";  
  59.                 final String[] selectionArgs = new String[] { split[1] };  
  60.                 return getDataColumn(context, contentUri, selection,  
  61.                 selectionArgs);  
  62.             }  
  63.         }  
  64.         // MediaStore (and general)  
  65.         else if ("content".equalsIgnoreCase(uri.getScheme())) {  
  66.             // Return the remote address  
  67.             if (isGooglePhotosUri(uri))  
  68.                 return uri.getLastPathSegment();  
  69.             return getDataColumn(context, uri, nullnull);  
  70.         }  
  71.         // File  
  72.         else if ("file".equalsIgnoreCase(uri.getScheme())) {  
  73.             return uri.getPath();  
  74.         }  
  75.         return null;  
  76.   
  77.     }  
  78.   
  79.     public static String getDataColumn(Context context, Uri uri, String selection, String[] selectionArgs) {  
  80.         Cursor cursor = null;  
  81.         final String column = "_data";  
  82.         final String[] projection = { column };  
  83.         try {  
  84.             cursor = context.getContentResolver().query(uri, projection,  
  85.             selection, selectionArgs, null);  
  86.             if (cursor != null && cursor.moveToFirst()) {  
  87.                 final int index = cursor.getColumnIndexOrThrow(column);  
  88.                 return cursor.getString(index);  
  89.             }  
  90.         } finally {  
  91.             if (cursor != null)  
  92.                 cursor.close();  
  93.         }  
  94.         return null;  
  95.   
  96.     }  
  97.   
  98.     public static boolean isExternalStorageDocument(Uri uri) {  
  99.         return "com.android.externalstorage.documents".equals(uri.getAuthority());  
  100.     }  
  101.   
  102.     public static boolean isDownloadsDocument(Uri uri) {  
  103.         return "com.android.providers.downloads.documents".equals(uri.getAuthority());  
  104.     }  
  105.   
  106.     public static boolean isMediaDocument(Uri uri) {  
  107.         return "com.android.providers.media.documents".equals(uri.getAuthority());  
  108.     }  
  109.   
  110.     private static boolean isGooglePhotosUri(Uri uri) {  
  111.         return "com.google.android.apps.photos.content".equals(uri.getAuthority());  
  112.     }  
  113.   
  114. }  

如果是想要获取相册中图片的路径,直接这样调用:

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. protected void onActivityResult(int requestCode, int resultCode, Intent data) {  
  2.     switch (requestCode) {  
  3.         case PICK_PICTURE:  
  4.         // 选取照片  
  5.         if(data!=null){  
  6.             try {  
  7.                 Uri uri = data.getData();  
  8.                 String pickPath = MiPictureHelper.getPath(mContext, uri);  // 获取图片路径的方法调用  
  9.                 System.out.println("图片路径 -->> " + pickPath);  
  10.                 }  
  11.             }  
  12.         }  
  13.     }  
  14. }  

====================== 我是一条分割线 ==========================


下面是其他开发者的处理方法

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. * 解决小米手机上获取图片路径为null的情况    
  2. @param intent    
  3. @return    
  4. */    
  5. public Uri getPictureUri(android.content.Intent intent) {      
  6.        Uri uri = intent.getData();      
  7.        String type = intent.getType();      
  8.        if (uri.getScheme().equals("file") && (type.contains("image/"))) {      
  9.            String path = uri.getEncodedPath();      
  10.            if (path != null) {      
  11.                path = Uri.decode(path);      
  12.                ContentResolver cr = this.getContentResolver();      
  13.                StringBuffer buff = new StringBuffer();      
  14.                buff.append("(").append(Images.ImageColumns.DATA).append("=")      
  15.                        .append("'" + path + "'").append(")");      
  16.                Cursor cur = cr.query(Images.Media.EXTERNAL_CONTENT_URI,      
  17.                        new String[] { Images.ImageColumns._ID },      
  18.                        buff.toString(), nullnull);      
  19.                int index = 0;      
  20.                for (cur.moveToFirst(); !cur.isAfterLast(); cur.moveToNext()) {      
  21.                    index = cur.getColumnIndex(Images.ImageColumns._ID);      
  22.                    // set _id value      
  23.                    index = cur.getInt(index);      
  24.                }      
  25.                if (index == 0) {      
  26.                    // do nothing      
  27.                } else {      
  28.                    Uri uri_temp = Uri      
  29.                            .parse("content://media/external/images/media/"      
  30.                                    + index);      
  31.                    if (uri_temp != null) {      
  32.                        uri = uri_temp;      
  33.                    }      
  34.                }      
  35.            }      
  36.        }      
  37.        return uri;      
  38.    }   

他们这样调用方法:

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. <span style="white-space:pre">    </span>if (data == null) {    
  2.         return;    
  3.     }    
  4.     uri = data.getData();    
  5.     uri = getPictureUri(data); // 方法调用  
  6.         String[] proj = { MediaStore.Images.Media.DATA };    
  7.         Cursor cursor = managedQuery(uri, proj, nullnullnull);    
  8.         if(cursor!=null) {    
  9.         int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);    
  10.                 cursor.moveToFirst();    
  11.                 String path = cursor.getString(column_index);// 图片在的路径    
  12.                 Intent intent3 = new Intent(this, SYClipActivity.class);    
  13.                 intent3.putExtra("path", path);    
  14.                 startActivityForResult(intent3, IMAGE_COMPLETE);    
  15.     }    

<think>嗯,用户遇到了一个Java的空指针异常,具体是试图调用一个接口方法'android.hardware.CameraStatus[]',但对象为null。我需要先理解这个错误发生的上下文。首先,空指针异常通常是因为尝试访问或调用一个未初始化的对象的方法或属性。这里的错误信息显示是在调用CameraStatus数组的方法时出现的,可能是在Android的Camera HAL层或者相关服务中。 用户可能是在开发Android系统或与硬件相关的应用时遇到了这个问题。可能的情况包括Camera服务没有正确初始化,或者某个接口没有正确绑定,导致在调用时引用了null对象。需要检查Camera服务是否正常启动,以及相关的绑定是否正确。 接下来,我应该考虑常见的导致这个问题的原因。例如,Camera服务可能没有正确加载,或者在获取Camera状态时,返回的数组为null。另外,可能是由于权限问题导致无法访问Camera服务,或者硬件抽象层(HAL)的实现有问题。 用户可能需要知道如何排查这个问题。可能的步骤包括检查Camera服务的状态,查看系统日志中是否有相关的错误信息,验证接口是否正确绑定,以及检查权限配置。此外,如果是自定义ROM或修改过HAL层,可能需要检查代码中相关部分的实现是否正确。 另外,用户可能需要具体的解决方案,比如如何检查服务是否运行,如何重新启动服务,或者如何修改代码以避免空指针。可能需要提供一些调试命令,如使用adb命令检查服务状态,或者查看logcat日志。 还需要考虑用户的技术水平。如果用户是开发者,可能需要更深入的技术细节,比如如何检查Binder接口,或者如何使用调试工具。如果用户是普通用户遇到这个问题,可能需要指导如何重启设备或恢复出厂设置,但根据错误信息来看,用户更可能是开发者。 最后,确保回答清晰,分步骤说明可能的原因和解决方法,并提供相关的命令或代码示例。同时,按照用户的要求,生成相关的问题建议,帮助用户进一步扩展思路。</think>在Android系统中遇到 `java.lang.NullPointerException: Attempt to invoke interface method 'android.hardware.CameraStatus[]'` 异常,通常表示调用了空对象的接口方法。以下是排查和解决此问题的步骤: --- ### **常见原因及解决方案** 1. **Camera服务未正确初始化** - **原因**:`CameraService` 或相关 HAL(硬件抽象层)未启动或初始化失败。 - **解决**: - 检查系统日志(如 `logcat` 或 `dmesg`)是否有 Camera 服务启动失败的记录。 - 确认设备的 Camera HAL 实现(如 `/vendor/lib/hw/camera.*.so`)是否正常加载。 - 重启 Camera 服务: ```bash adb shell stop adb shell start ``` 2. **接口绑定失败** - **原因**:调用 `ICameraService` 或 `ICameraDevice` 接口时,Binder 通信未正确建立。 - **解决**: - 检查 `CameraService` 是否成功注册到 ServiceManager: ```bash adb shell service list | grep camera ``` 正常输出应包含 `media.camera` 或类似条目。 - 若接口未注册,尝试重启设备或修复系统服务。 3. **权限或 SELinux 限制** - **原因**:调用方无权限访问 Camera 服务,或 SELinux 策略阻止了访问。 - **解决**: - 检查调用方的权限声明(如 `AndroidManifest.xml` 中是否声明了 `CAMERA` 权限)。 - 查看 SELinux 日志(`dmesg | grep avc`)是否有拒绝访问的记录,并调整策略。 4. **HAL 层实现问题** - **原因**:Camera HAL 接口(如 `camera3_device_ops`)未正确实现或返回空指针。 - **解决**: - 检查 HAL 层代码中是否未正确初始化 `CameraStatus` 数组。 - 在 HAL 层添加空值检查逻辑,避免返回空对象。 --- ### **调试命令与工具** 1. **查看 Camera 服务状态**: ```bash adb shell dumpsys media.camera ``` 若输出为空或报错,说明 Camera 服务未正常运行。 2. **分析系统日志**: ```bash adb logcat -s CameraService ``` 搜索 `FATAL` 或 `ERROR` 级别日志,定位初始化失败的具体原因。 3. **验证 HAL 加载**: ```bash adb shell lshal list --print ``` 确认 `android.hardware.camera.provider` 是否列出有效的 HAL 实现。 --- ### **代码修复示例** 在调用 `CameraStatus` 数组前添加空值检查: ```java ICameraService cameraService = ICameraService.Stub.asInterface( ServiceManager.getService("camera")); if (cameraService != null) { CameraStatus[] statuses = cameraService.getCameraDeviceStatus(); if (statuses != null) { // 正常处理 } else { Log.e("CameraError", "CameraStatus array is null"); } } else { Log.e("CameraError", "CameraService is not available"); } ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值