无法使用照片的URI在Android的默认图像查看器中打开捕获的照片

时间:2018-05-18 09:45:16

标签: android

我的应用程序的一个功能是允许用户分配存储在数据库中的项目的照片。这可以通过使用内置相机拍摄新照片或从库中选择图像来完成。然后,app会调整捕获的图像大小,检索完整大小的图像URI并将其存储在数据库中。如果用户想要使用默认图像查看器加载完整大小的图像,则存储全尺寸图像URI以供稍后使用。一切正常,除了查看器在拍摄照片后无法从捕获的图像URI加载图像,但只有从库中选择时才可以加载相同的图像。 好的是代码:

清单:

    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
 <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

    <provider
        android:name="android.support.v4.content.FileProvider"
        android:authorities="com.packagename.inventoryapp.fileprovider"
        android:exported="false"
        android:grantUriPermissions="true">
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/fileprovider" />
    </provider>

fileprovider.xml

    <external-files-path
    name="images"
    path="Pictures" />

处理相机:

  @NeedsPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)
public void onLaunchCamera(){
    Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    photoFileName = String.valueOf(System.currentTimeMillis()) + ".jpg";
    photoFile = getPhotoFileUri(photoFileName);
    Uri fileProvider = FileProvider.getUriForFile(this,
            ProductContract.CONTENT_AUTHORITY + ".fileprovider", photoFile);
    intent.putExtra(MediaStore.EXTRA_OUTPUT, fileProvider);
    if (intent.resolveActivity(getPackageManager()) != null) {
        startActivityForResult(intent, CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE);
    }
}

public File getPhotoFileUri(String fileName){
    File mediaStorageDir = new File(getExternalFilesDir(Environment.DIRECTORY_PICTURES), APP_TAG);
    if (!mediaStorageDir.exists() && !mediaStorageDir.mkdirs()){
        Log.d(APP_TAG, "failed to create directory");
    }
    return new File(mediaStorageDir.getPath() + File.separator + fileName);
}

onActivtiyResult( takenImage - 全局位图变量; mPicUri - 全局Uri变量):

 @Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    /* User chose to take a new photo */
    if (requestCode == CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE) {
        if (resultCode == RESULT_OK) {
            File takenPhotoUri = getPhotoFileUri(photoFileName);
            mPicUri = FileProvider.getUriForFile
                    (this, ProductContract.CONTENT_AUTHORITY + ".fileprovider", photoFile);
            Bitmap fullSizeImage = BitmapFactory.decodeFile(takenPhotoUri.getAbsolutePath());
            takenImage = BitmapScaler.scaleToFitWidth
                    (fullSizeImage, mProductImageView.getWidth() / 100 * 50);
        } else { // Result was a failure
            Toast.makeText(this, getString(R.string.no_picture_taken),
                    Toast.LENGTH_SHORT).show();
        }
    }

    /* User chose to take an an existing photo from the gallery */
    else if (requestCode == PICK_PHOTO_CODE){
        if (resultCode == RESULT_OK) {
            mPicUri = data.getData();
            try {
                Bitmap fullSizeImage = MediaStore.Images.Media.getBitmap
                        (getContentResolver(), mPicUri);
                takenImage = BitmapScaler.scaleToFitWidth
                        (fullSizeImage, mProductImageView.getWidth() / 100 * 60);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    mProductImageView.setImageBitmap(takenImage);

    /* Save image and it's URi to the database  */
    if (takenImage != null){
            ContentValues values = new ContentValues();
            values.put(ProductEntry.COLUMN_IMAGE, DbBitmapUtility.getBytesArray(takenImage));
            values.put(ProductEntry.COLUMN_IMAGE_URL, mPicUri.toString());
           int rows = getContentResolver().update(mProductUri, values, null, null);
    }
}

打开默认图像图像查看器以从Uri加载完整尺寸的图像:

                Intent intent = new Intent(Intent.ACTION_VIEW);
            intent.setData(mPicUri);
            startActivity(intent);

我意识到问题出在捕获照片的Uri路径上。当我以上述方式检索它时,我会得到类似的结果:

content://com.packagename.inventoryapp.fileprovider/images/InventoryApp/1526632674426.jpg

和图像查看器以空白屏幕启动,表明它正在搜索图像但没有成功。 我尝试使用getAbsolutePath()方法获取mPicUri,导致应用程序在使用该消息启动intent时崩溃:

android.content.ActivityNotFoundException:找不到处理Intent的Activity {act = android.intent.action.VIEW dat = / storage / emulated / 0 / Android / data / com.packagename.inventoryapp / files / Pictures /InventoryApp/1526635391354.jpg}

相反,从现有库中获取图像效果很好,图像Uri看起来像:

content://com.google.android.apps.photos.contentprovider/0/1/content%3A%2F%2Fmedia%2Fexternal%2Fimages%2Fmedia%2F2504/ORIGINAL/NONE/1872082740

所以问题是有可能以某种方式检索捕获的图像Uri,它不是app私有的,可能是图像查看器的红色吗?

1 个答案:

答案 0 :(得分:3)

android.content.ActivityNotFoundException: No Activity found to handle Intent { act=android.intent.action.VIEW dat=/storage/emulated/0/Android/data/com.packagename.inventoryapp/files/Pictures/InventoryApp/1526635391354.jpg }

这不是有效的Uri

Uri有一个方案。你的没有。您的类似于裸文件系统路径。原则上,您可以使用Uri将其转换为Uri.fromFile()。 但是,在Android 7.0及更高版本中,使用此类Uri将失败,并显示FileUriExposedException

相反,请将FileFileProvider.getUriForFile()一起使用,并将Uri提供给ACTION_VIEW Intent。请务必在addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)上致电Intent,以允许第三方应用阅读Uri标识的内容。