0

我有这个活动,用户可以从图库中选择一张图片,也可以只拍照并(连同其他数据)将其上传到网站。

到目前为止,我遇到了 2 个不同的问题:

1)如果我用图库中的图片尝试它,我会得到一个带有消息的 IOException /external/images/media/2305: open failed: ENOENT (No such file or directory) 打开文件流时会发生这种情况。

2)如果我通过拍照来尝试,它可以,但是编码的数据字符串由“AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA”(真的更长,但只有A)组成,我想这不是一个好兆头。这只是一个猜测,因为我仍然无法将其正确上传到网站,但显示相同数据字符串的不同图片闻起来很有趣。

这里的代码

@Override

public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    switch (requestCode) {
    case TAKE_PICTURE:
        if (resultCode == Activity.RESULT_OK) {
            //Uri selectedImage = imageUri;
            loadImage(imageUri);

    }
    break;
case SELECT_PHOTO:
    if(resultCode == Activity.RESULT_OK){  
        imageUri = data.getData();
        loadImage(imageUri);
    }
}
}

这就是我将图像(拍摄的图片或从图库中获取的图片)加载到 ImageView 上的方式。它工作正常。

public void loadImage(Uri selectedImage){
    mActivity.getContentResolver().notifyChange(selectedImage, null);

    ContentResolver cr = mActivity.getContentResolver();
    Bitmap bitmap;
    try {
        bitmap = android.provider.MediaStore.Images.Media
                .getBitmap(cr, selectedImage);

        ivPicture.setImageBitmap(bitmap);
        ivPicture.setVisibility(View.VISIBLE);
        mActivity.croutonInfo(selectedImage.toString());

    } catch (Exception e) {
        mActivity.croutonAlert("Failed to load");
        e("Camera " + e.toString());
    }
}

这是我用来模拟数据上传的方法。当我得到 API 时,它将有一个异步任务来处理 http 传输,到目前为止它只将数据放入一个无逻辑的传输对象中

public void uploadTapa() throws IOException{
    mActivity.croutonInfo("subiendo tapa ");
    d("uploadTapa new ");
    TapaUploadParametros tup = new TapaUploadParametros();
    d("uploadTapa bar: " + nombreBar);
    tup.setBarNombre(etBarName.getText().toString());
    d("uploadTapa tapa: " + nombreTapa);
    tup.setNombre(etTapaName.getText().toString());
    d("uploadTapa municipio: " + municipio);
    tup.setLocalidad(municipio);
    d("uploadTapa provincia: " + provincia);
    tup.setProvincia(provincia);
    d("uploadTapa tipologiaId: " + tipologiaId);
    tup.setTipo(tipologiaId);
    d("uploadTapa precioId: " + precioId);
    tup.setPrecio(precioId);

    String encodedImage = encodeImgForHTTP(imageUri);
    d("uploadTapa encoded image: " + encodedImage);
    tup.setPic(encodedImage);
    d("uploadTapa direccionBar: " + direccionBar);
    tup.setBarDireccion(direccionBar);
}

这是对图像进行编码以进行 http 传输的方法。画廊中的图像在“打开流之前”之后失败

   private String encodeImgForHTTP (Uri imageUri) throws IOException{
        ContentResolver cr = mActivity.getContentResolver();
        d("encodeImgForHTTP before opening stream ");
        FileInputStream fis = new FileInputStream(imageUri.getPath());
        d("encodeImgForHTTP after opening stream ");
        // Get binary bytes for encode
        byte[] imageBytes = new byte[fis.available()];
        d("encodeImgForHTTP after getting byte array ");
        // base 64 encode for text transmission (HTTP)
        d("encodeImgForHTTP pre 64: " + imageBytes);
        String data_string = Base64.encodeToString(imageBytes, Base64.URL_SAFE); 
        d("encodeImgForHTTP before returning the encoded data string " + data_string);
        return data_string;
    }

我对画廊图像做错了什么?为什么不同图片的编码看起来一样?

4

2 回答 2

1

我认为您应该将输入流缓冲到较小的字节数组中,并且不要使用该available函数,因为它是您的编码函数中的估计值。

为了拍照,您必须确定要保存图像的路径,并将其作为额外的 Intent 传递,例如:

private void capture(){
    String directoryPath = Environment.getExternalStorageDirectory() + "/" + IMAGE_DIRECTORY + "/";
    String filePath = directoryPath+Long.toHexString(System.currentTimeMillis())+".jpg";
    File directory = new File(directoryPath);
    if (!directory.exists()) {
        directory.mkdirs();
    }
    this.capturePath = filePath; // you will process the image from this path if the capture goes well
    Intent intent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
    intent.putExtra( MediaStore.EXTRA_OUTPUT, Uri.fromFile( new File(filePath) ) );
    startActivityForResult(intent, REQUEST_CAPTURE);                

}
于 2013-03-15T12:09:33.937 回答
0

我想我终于让它工作了。首先,我使用了 Emil 的建议并保存了图像。DCIM_PATH 是 DCIM 文件夹的路径。

public void takePhoto() {
    String directoryPath = DCIM_PATH;
    d("takePhoto directoryPath: " + directoryPath);
    this.pictureFileName = Long.toHexString(System.currentTimeMillis())+".jpg";
    String filePath = directoryPath + pictureFileName ;
    File directory = new File(directoryPath);
    if (!directory.exists()) { // in case there's no DCIM folder
        directory.mkdirs(); // just create it
    }
    d("takePhoto filePath: " + filePath);
    this.imageUri = Uri.parse(filePath);
    d("takePhoto imageUri: " + filePath);
    Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
            // here's where I tell the intent where to save the file
    intent.putExtra( 
            MediaStore.EXTRA_OUTPUT,Uri.fromFile( new File(filePath) )
            );

    startActivityForResult(intent, TAKE_PICTURE);

}

我不得不使用两种不同的方法将图片加载到 imageview。如果是刚拍的照片,我用这个:

public void loadImageJustTaken(Uri selectedImage) {
    mActivity.getContentResolver().notifyChange(selectedImage, null);

    Bitmap bitmap = 
            BitmapFactory.decodeFile(imageUri.getPath());

    ivPicture.setImageBitmap(bitmap);
    ivPicture.setVisibility(View.VISIBLE);
}

但是要使用画廊中的一个,我必须使用 contentResolver

public void loadImage(Uri selectedImage){

    imageUri = selectedImage;
    mActivity.getContentResolver().notifyChange(selectedImage, null);

    ContentResolver cr = mActivity.getContentResolver();
    Bitmap bitmap;
    try {
        bitmap = android.provider.MediaStore.Images.Media
                .getBitmap(cr, imageUri);

        ivPicture.setImageBitmap(bitmap);
        ivPicture.setVisibility(View.VISIBLE);

        mActivity.croutonInfo(imageUri.getPath());

    } catch (Exception e) {
        e("Camera " + e.toString());
    }
}

当我想上传图像时,我必须对其进行编码。只要您提供正确的文件路径,此方法就可以工作

  private String encodeImgForHTTP (Uri imageUri) throws IOException{
    String realPicPath = getPath(imageUri);
    d("encodeImgForHTTP before opening stream " + realPicPath);
    FileInputStream fis = new FileInputStream(realPicPath);
    d("encodeImgForHTTP after opening stream ");
    // Get binary bytes for encode
    byte[] imageBytes = IOUtils.toByteArray(fis);
    d("encodeImgForHTTP after getting byte array ");

    // base 64 encode for text transmission (HTTP)
    //String data_string = Base64.encodeToString(data, Base64.URL_SAFE);
    d("encodeImgForHTTP pre 64: " + imageBytes);
    String data_string = Base64.encodeToString(imageBytes, Base64.URL_SAFE); 
    d("encodeImgForHTTP before returning the encoded data string " + data_string);
    return data_string;
}

这就是我如何获得图片的“真实路径”:

public String getPath(Uri uri) throws IOException {
    String[] projection = { MediaStore.Images.Media.DATA };
    Cursor cursor = mActivity.
            managedQuery(uri, projection, null, null, null);
    if (cursor == null){ // with pictures just taken, the uri returned by the onActivityResult makes cursor to be null. Following method takes care of that
        uri = saveMediaEntry(imageUri.getPath(), pictureFileName, "");
        d("cursor nulo, segundo cursor con uri " + uri.getPath());
        cursor = mActivity.
                managedQuery(uri, projection, null, null, null);
    }
    int column_index = cursor
            .getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
    cursor.moveToFirst();
    return cursor.getString(column_index);
}

方法 saveMediaEntry 为设备的媒体数据库创建一个条目,返回其 Uri。使用那个 Uri,光标现在将指向我们想要的图片文件

  private Uri saveMediaEntry(
        String imagePath,String title,String description) throws IOException {

    ExifInterface exif = new ExifInterface(imagePath);

    ContentValues v = new ContentValues();
    v.put(Images.Media.TITLE, title);
    v.put(Images.Media.DISPLAY_NAME, title);
    v.put(Images.Media.DESCRIPTION, description);
    v.put(Images.Media.DATE_ADDED, System.currentTimeMillis());
    v.put(Images.Media.DATE_TAKEN, exif.getAttribute(ExifInterface.TAG_DATETIME));
    //v.put(Images.Media.DATE_MODIFIED, dateTaken) ;
    v.put(Images.Media.MIME_TYPE, "image/jpeg");
    v.put(Images.Media.ORIENTATION, exif.getAttribute(ExifInterface.TAG_ORIENTATION));
    File f = new File(imagePath) ;
    File parent = f.getParentFile() ;
    String path = parent.toString().toLowerCase() ;
    String name = parent.getName().toLowerCase() ;
    v.put(Images.ImageColumns.BUCKET_ID, path.hashCode());
    v.put(Images.ImageColumns.BUCKET_DISPLAY_NAME, name);
    v.put(Images.Media.SIZE,f.length()) ;
    f = null ;

    v.put(Images.Media.LATITUDE, exif.getAttribute(ExifInterface.TAG_GPS_LATITUDE));
    v.put(Images.Media.LONGITUDE, exif.getAttribute(ExifInterface.TAG_GPS_LONGITUDE));

    v.put("_data",imagePath) ;
    ContentResolver c = mActivity.getContentResolver() ;
    return c.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, v);
}

毕竟,图片可以正常加载,并且 Base64.encodeToString 对于不同的图片返回是不同的:)

希望它可以帮助某人:)

于 2013-03-19T07:54:46.200 回答