我有这样的活动,用户可以从图库中选择一张图片,或者只是拍照并(和其他数据一起)上传到网站。
到目前为止,我遇到了两个不同的问题:
1)如果我尝试使用图库中的图片,我会收到一条带有消息的IOException / external / images / media / 2305:打开失败:ENOENT(没有这样的文件或目录) 当打开文件流时会发生这种情况。
2)如果我尝试采取图片,它会确定,但编码数据串是由“AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA”(真长,但只有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时,它会有一个asynctask来处理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;
}
我对画廊图片做错了什么?为什么不同图片的编码看起来一样?
答案 0 :(得分:1)
我认为您应该将输入流缓冲到较小的字节数组中,而不是使用available
函数,因为它是编码函数中的估计值。
为了拍摄照片,您必须确定您希望保存图像的路径,并将其作为意图中的额外内容传递,例如:
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);
}
答案 1 :(得分: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);
}
毕竟,图片加载OK,并且不同图片的Base64.encodeToString返回不同:)
希望它可以帮助某人:)