【问题标题】:BitmapFactory.decodeFile is null unless I WAIT to accept photoBitmapFactory.decodeFile 为空,除非我等待接受照片
【发布时间】:2016-12-13 02:23:12
【问题描述】:

我遇到了这个奇怪的问题,它似乎只发生在我的一台运行 android 6 的平板电脑上。

我有这段代码可以将相机拍摄的照片添加到recycler view

1) 我在设备上创建了一个文件对象(这是照片)

2) 我从那个文件中得到了uri

3) 我创建了一个意图传递 uri 本身

Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (intent.resolveActivity(getActivity().getPackageManager()) != null)
// this is done in a fragment, everything else below is in the if statement

intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
startActivityForResult(take_photo_intent, option_int);

我知道MediaStore.EXTRA_OUTPUT 不会向onActivityResult 返回任何内容,而是写入您传入的uri。

现在在onActivityResult里面我有

Log.i("PHOTO", "path--->" + uri.getPath());

所以我想提一下,当程序工作或 不工作 工作时,uri ALWAYS 有一个路径,其中一个路径的示例是

/storage/emulated/0/data/20161212_175150797715155.jpg

所以继续onActivityResult

5) 根据uri 路径创建位图以供以后使用

BitmapFactory.Options bitmap_options = new BitmapFactory.Options();
bitmap_options.inPreferredConfig = Bitmap.Config.ARGB_8888;
*************** problem here ****************         
Bitmap temp = BitmapFactory.decodeFile(uri.getPath()); 

临时位图返回 null 有些的时间,让我解释一下

当我拍照时,华硕 android 6 平板电脑在你拍照时显示两个按钮,一个按钮丢弃照片,另一个按钮保留照片.. 这是奇怪的部分,在那个屏幕上,如果我等待就像在按下按钮保留照片前 5-15 秒,bitmap 不会为空,但如果我拍照并立即接受它,则位图为空。

现在如前所述,不管我怎么做,如果bitmap 为空,或者它不为空,它总是有一个路径,然后将它传递给bitmapdecode 函数(即奇怪)

我不知道是不是相机软件,物理相机硬件,android 6 bug....

我还想说,我不确定这是否是最好的代码,但它已在其他 4 台 Android 设备(手机、平板电脑)上运行,只是这台平板电脑是华硕的,只有一台支持 android 6,它适用于其他一切

编辑:

我按照建议尝试了这个

  Bitmap TEMP = null;
  try {
      TEMP = BitmapFactory.decodeStream(getContext().getContentResolver().openInputStream(uri));
  } 
  catch (FileNotFoundException e) 
  {
      e.printStackTrace();
  }

没有运气

编辑 2:

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    if (requestCode == 1 && resultCode == Activity.RESULT_OK) {
        BitmapFactory.Options bitmap_options = new BitmapFactory.Options();
        bitmap_options.inPreferredConfig = Bitmap.Config.ARGB_8888;
        Bitmap TEMP = BitmapFactory.decodeFile(uri.getPath());
        Bitmap bitmap_image = ThumbnailUtils.extractThumbnail(TEMP, THUMBNAIL_SIZE, THUMBNAIL_SIZE);

        if (bitmap_image == null)
            Log.i("PHOTO", "BITMAP THUMBNAIL NULL");

        setAdapterBitmap(bitmap_image, uri.getPath(), 1);
    }
}

解决方案:

我有这个方法来创建一个File 对象并将它变成一个URI 对象

private File createFileForImage() throws IOException {
        String file_creation_time = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(new Date());
        String image_file_name = DIR_NAME + "_" +  file_creation_time;
        File storage_dir = new File(String.valueOf(Environment.getExternalStorageDirectory()), DIR_NAME);
        if (!storage_dir.exists())
        {
            if(!storage_dir.mkdir())
            {
                return null;
            }
        }
        return File.createTempFile(image_file_name, ".jpg", storage_dir);
    }

然后我在它返回后使用了这个

uri = Uri.fromFile(image_file);

但由于某种原因,这是有效的,但它有轻微的延迟,导致原始帖子中所述的奇怪行为

Jan Kaufmann 的建议似乎可行,我做了一些小的修改

private Uri getOutputMediaUriFromFile()
{
    File photo_storage_dir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), DIR_NAME);
if (!photo_storage_dir.exists())
{
    if (!photo_storage_dir.mkdirs())
    {
        return null;
    }
}

String file_creation_time = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(new Date());
String image_file_name = "ipr" + "_" +  file_creation_time;
File photo = new File(photo_storage_dir.getPath() + File.separator + image_file_name + ".jpg");
return Uri.fromFile(photo);
}

它基本上做同样的事情,但由于某种原因,这不会导致我遇到的问题,至少在我的测试中不会。

我很高兴这现在有效,但谁能解释为什么有效?

【问题讨论】:

  • 试过ContentResolver#openInputStream?
  • @pskink 你能解释一下吗?
  • 试试BitmapFactory#decodeStream 和ContentResolver#openInputStream 看看有什么不同
  • 没有区别 :( @pskink
  • hmm,尝试在该文件上使用 FileObserver 进行测试,你得到什么事件?

标签: java android android-studio bitmap android-bitmap


【解决方案1】:
  • 确保图片尺寸不要太大。如果需要,对原始图像进行二次采样以节省内存

         BitmapFactory.Options opt = new BitmapFactory.Options();
         opt.inSampleSize = 8;
    
  • 确保您有权限

       <uses-permission  android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    
  • 或者尝试将您的 URI 构造成这样的:

Uri uri = getOutputMediaFileUri(MEDIA_TYPE_IMAGE, "myimage"); 其中 getOutputMediaFileUri 是:

 private File getOutputMediaFile(int type, String imgname) {
          // External sdcard location
          //public static String DIRECTORY_PICTURES = "Pictures";
          File mediaStorageDir = new File(
          Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), IMAGE_DIRECTORY_NAME);

      // Create the storage directory if it does not exist
      if (!mediaStorageDir.exists()) {
         if (!mediaStorageDir.mkdirs()) {
            Log.d(IMAGE_DIRECTORY_NAME, "Oops! Failed create "
                + IMAGE_DIRECTORY_NAME + " directory");
            return null;
         }
      }


      File mediaFile;
      if (type == MEDIA_TYPE_IMAGE) {
         mediaFile = new File(mediaStorageDir.getPath() + File.separator + "IMG_" + imgname + ".jpg");
      }  else {
         return null;
      }
      return mediaFile;
   }

【讨论】:

  • 函数头与函数(名称和返回类型)不匹配是否缺少信息?
  • 实际上,从头开始,我用这个修改了一些东西,我认为它有效!生病测试更多并回复你
  • 我相信这解决了它,不知道如何但它不再搞砸了,谢谢!
  • 很好用,非常感谢,你知道为什么会这样吗?
  • 有道理,再次感谢,你是救命稻草
【解决方案2】:

试试这个家伙:

TEMP = MediaStore.Images.Media.getBitmap(context.getContentResolver(), YOUR_URL);

如果这不起作用,我猜你没有创建临时文件来保存图像。

new Handler().postDelayed(new Runnable() {
        @Override
        public void run() {
            try{
                GEY_FILE;
            }catch (Exception ex){
                Log.i(TAG, "run: " + ex);
            }
        }
    }, 15000);

【讨论】:

  • 不走运,我仍然需要等待大约 5-15 秒,然后文件才会出现,除此之外它是空的。当我在获取它的 uri 之前创建文件时,我会进行原始帖子中未显示的空值检查,所以不确定出了什么问题 =[
  • 我认为您不需要等待文件。
  • 如果是这样,您可以尝试使用处理程序。比如:new Handler().postDelayed(new Runnable() { @Override public void run() { try{ GEY_FILE; }catch (Exception ex){ Log.i(TAG, "run: " + ex); } } } , 15000);
  • 运气不好=[
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-16
  • 2020-04-27
  • 1970-01-01
  • 2015-11-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多