Android在ImageView上从URI设置图像

Android在ImageView上从URI设置图像,android,Android,更新了更多代码 我正在尝试抓取刚拍摄的照片,并以编程方式将其设置为ImageView 按下图片按钮 picture_button.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { takePhoto(mTextureView); } }); 它运行takePhoto方法: public void takePhoto(View view) { try

更新了更多代码

我正在尝试抓取刚拍摄的照片,并以编程方式将其设置为
ImageView

按下图片按钮

picture_button.setOnClickListener(new View.OnClickListener() {
    public void onClick(View v) {
        takePhoto(mTextureView);
    }
});
它运行takePhoto方法:

public void takePhoto(View view) {
    try {
        mImageFile = createImageFile();
        final ImageView latest_picture = (ImageView) findViewById(R.id.latest_picture);
        final RelativeLayout latest_picture_container = (RelativeLayout) findViewById(R.id.latest_picture_container);
        final String mImageFileLocationNew = mImageFileLocation.replaceFirst("^/", "");
        Toast.makeText(getApplicationContext(), "" + mImageFile, Toast.LENGTH_SHORT).show();
        Uri uri = Uri.fromFile(mImageFile);
        Toast.makeText(getApplicationContext(), ""+uri, Toast.LENGTH_LONG).show();
        latest_picture.setImageURI(uri);
        latest_picture_container.setVisibility(View.VISIBLE);
    } catch (IOException e){
        e.printStackTrace();
    }
    lockFocus();
    captureStillImage();
}
它运行
createImageFile()
captureStillImage()

图像保存在此处:

private static class ImageSaver implements Runnable {
    private final Image mImage;
    private ImageSaver(Image image) {
        mImage = image;
    }
    @Override
    public void run() {
        ByteBuffer byteBuffer = mImage.getPlanes()[0].getBuffer();
        byte[] bytes = new byte[byteBuffer.remaining()];
        byteBuffer.get(bytes);

        FileOutputStream fileOutputStream = null;

        try {
            fileOutputStream = new FileOutputStream(mImageFile);
            fileOutputStream.write(bytes);

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            mImage.close();
            if(fileOutputStream != null){
                try {
                    fileOutputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }

            }
        }
createImageFile()
之后,我获得了图像的正确路径,并对其进行烘烤,以显示每次都是什么。但即使是
最新图片\u容器
上的
设置可见性
也无法正常工作。。。如果我注释掉
InputStream
Bitmap
setImageBitmap
,则
最新图片\u容器将正常显示。不知道为什么这是错误的

出于某种原因,URI在文件后面加了三个斜杠

file:///storage/0/...
AssetManager#open()
方法仅适用于应用程序的资产;i、 例如,项目的
/assets
文件夹中的文件。由于您试图打开一个外部文件,因此应该在从路径创建的
文件
对象上使用
文件输入流
。此外,
takePhoto()
方法是在将任何内容写入文件之前在
ImageView
上设置图像,这将导致一个空的
ImageView

public interface OnImageDecodedListener {
    public void onImageDecoded(Bitmap b);
}
由于您的应用程序直接使用摄像头,因此我们可以对写入图像文件的同一字节数组中的图像进行解码,并节省不必要的存储读取。此外,在下面的代码示例中,文件写入是在一个单独的线程上进行的,因此我们不妨在执行图像解码时利用这一点,因为它将最小化对UI线程的影响

首先,我们将创建一个界面,
ImageSaver
可以通过该界面将图像传递回
活动
,以显示在
ImageView

public interface OnImageDecodedListener {
    public void onImageDecoded(Bitmap b);
}
然后我们需要稍微修改
ImageSaver
类,以在构造函数中获取
Activity
参数。我还添加了一个
文件
参数,因此
活动
的相应字段不必是
静态

private static class ImageSaver implements Runnable {
    private final Activity mActivity;
    private final Image mImage;
    private final File mImageFile;

    public ImageSaver(Activity activity, Image image, File imageFile) {
        mActivity = activity;
        mImage = image;
        mImageFile = imageFile;
    }

    @Override
    public void run() {
        ByteBuffer byteBuffer = mImage.getPlanes()[0].getBuffer();
        byte[] bytes = new byte[byteBuffer.remaining()];
        byteBuffer.get(bytes);

        final Bitmap b = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
        mActivity.runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    ((OnImageDecodedListener) mActivity).onImageDecoded(b);
                }
            }
        );

        FileOutputStream fileOutputStream = null;
        ...
    }
}
一旦我们获得字节数组中的图像数据,我们就对其进行解码并将其传递回
活动
,这样它就不必等待文件写入,而文件写入可以在后台安静地进行。我们需要在UI线程上调用接口方法,因为我们正在“触摸”视图

活动
需要实现接口,我们可以将
视图
相关内容从
takePhoto()
移动到
onImageDecoded()
方法

public class MainActivity extends Activity
    implements ImageSaver.OnImageDecodedListener {
    ...

    @Override
    public void onImageDecoded(Bitmap b) {
        final ImageView latest_picture =
            (ImageView) findViewById(R.id.latest_picture);
        final RelativeLayout latest_picture_container =
            (RelativeLayout) findViewById(R.id.latest_picture_container);

        latest_picture.setImageBitmap(b);
        latest_picture_container.setVisibility(View.VISIBLE);
    }

    public void takePhoto(View view) {
        try {
            mImageFile = createImageFile();
            captureStillImage();
            lockFocus();
        }
        catch (IOException e) {
            e.printStackTrace();
        }
    }
    ...
}
最后,我们需要实际执行
ImageReader
onImageAvailable()
方法中的
ImageSaver
。同样按照这个例子,它是这样的

private final ImageReader.OnImageAvailableListener mOnImageAvailableListener = 
    new ImageReader.OnImageAvailableListener() {
    @Override
    public void onImageAvailable(ImageReader reader) {
        mBackgroundHandler.post(new ImageSaver(MainActivity.this,
                                               reader.acquireNextImage(),
                                               mImageFile)
        );
    }
};

我通常使用毕加索图书馆

将依赖项添加到build.gradle

compile 'com.squareup.picasso:picasso:2.5.2'
由于您要获取文件路径,请将路径设置为文件对象,然后让毕加索从手机中抓取图像,并将其设置为所需的ImageView

我确实建议在你的应用程序上使用毕加索进行任何类型的图像活动,无论是在线还是离线。毕加索由Square制作,在图像加载、缓存

public static String getEDirectory(String folderName,Activity activity) {
    if(Environment.MEDIA_MOUNTED.equalsIgnoreCase(Environment.getExternalStorageState())){
        LogUtils.e( activity.getExternalFilesDir(folderName).getAbsolutePath());
        return activity.getExternalFilesDir(folderName).getAbsolutePath();
    }else{
        return activity.getFilesDir().getAbsolutePath() +File.separator+folderName;
    }
}    
public static Uri getImageUri(String shortname,Activity activity) {

    if (shortname == null) {
        shortname = "www.jpg";
    }
    String path = DataStore.getEDirectory("pure",activity);
    File files = new File(path);
    files.mkdirs();

    File file = new File(path, shortname);
    return Uri.fromFile(file);

}
    public static Uri attemptStartCamera(Activity ctx){
        Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        String latestfilename = System.currentTimeMillis() + ".jpg";
        Uri imageUri = getImageUri(latestfilename,ctx);
        intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
        ctx.startActivityForResult(intent, MsgCodes.PICK_CAMERA);
        return imageUri;
    }
在活动中:

mUri = attemptStartCamera(Activity.this);
这样,您就得到了Uri

您可以在onActivityResult中加载图像:

public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if(requestCode==MsgCodes.PICK_CAMERA && resultCode == RESULT_OK){
        mImageView.setImageUri(mUri);
    }
}
试试这个简单的代码

ImageView imgView = view.findViewById(R.id.lw_foto);

imgView.setImageURI(mListaContactos.get(i).foto);

您确定获得了正确的图像路径吗?你试过打印路径了吗?@4k3R我刚刚发现路径在
文件://
之后放了一个额外的
/
,所以我想知道它是从哪里来的,以及如何摆脱它it@4k3R,如果有帮助的话,我已经添加了创建图像的方法。您的图像存储在哪里?@tinysunlight,它存储在我刚才添加的最后一种方法的末尾,非常令人惊讶,迈克,谢谢你的辛勤工作和帮助
ImageView imgView = view.findViewById(R.id.lw_foto);

imgView.setImageURI(mListaContactos.get(i).foto);