我有一个Android应用程序,需要让用户从图库中选择一些图片,并将这些图片(以及其他一些数据)发送到后端。
要允许用户选择图片,我的片段中应包含以下内容:
private void pickImages() {
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("image/*");
intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
startActivityForResult(intent, PICK_PHOTO_FOR_AVATAR);
}
我在这里得到用户选择的照片的结果:
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == PICK_PHOTO_FOR_AVATAR && resultCode == Activity.RESULT_OK) {
if (data == null) {
//Display an error
Toast.makeText(getActivity(), "There was an error getting the pictures", Toast.LENGTH_LONG).show();
return;
}
ClipData clipData = data.getClipData();
String fileName = null, extension = null;
//if ClipData is null, then we have a regular file
if (clipData == null) {
//get the selected file uri
fileName = FileUtils.getPath(getActivity(), data.getData());
//obtain the extension of the file
int index = fileName.lastIndexOf('.');
if (index > 0) {
extension = fileName.substring(index + 1);
if (extension.equals("jpg") || extension.equals("png") || extension.equals("bmp") || extension.equals("jpeg"))
isAttachedFile = true;
}
}
ArrayList<Uri> photosUris = new ArrayList<>();
//for each image in the list of images, add it to the filesUris
if (clipData != null) for (int i = 0; i < clipData.getItemCount(); i++) {
ClipData.Item item = clipData.getItemAt(i);
Uri uri = item.getUri();
switch (i) {
case 0:
picture1Uri = uri;
break;
case 1:
picture2Uri = uri;
break;
}
photosUris.add(uri);
}
else if (isAttachedFile) {
Uri uri = Uri.parse(fileName);
picture1Uri = uri;
photosUris.add(uri);
}
uris = photosUris;
if (picture1Uri != null) {
image1.setVisibility(View.VISIBLE);
image1.setImageURI(picture1Uri);
}
if (picture2Uri != null) {
image2.setVisibility(View.VISIBLE);
image2.setImageURI(picture2Uri);
}
}
然后,我将URI列表发送给Presenter,在其中执行对后端的MultiPart Retrofit调用:
//obtain the file(s) information of the message, if any
if (uris != null && uris.size() > 0) {
for (int i = 0; i < uris.size(); i++) {
File file = null;
//this is the corect way to encode the pictures
String encodedPath = uris.get(i).getEncodedPath();
file = new File(encodedPath);
builder.addFormDataPart("photos[]", file.getName(), RequestBody.create(MediaType.parse("multipart/form-data"), file));
}
}
MultipartBody requestBody = builder.build();
//send the newly generated ticket
Call<GenerateNewTicketResponse> generateNewTicketCall = OperatorApplication.getApiClient().generateNewTicket(Constants.BEARER + accessToken, requestBody);
问题在于这有时可行,有时却无效。有时我会收到错误“ java.io.FileNotFoundException”,这使我陷入Retrofit调用的onFailure()
回调中。
我发现了以下Reading File from Uri gives java.io.FileNotFoundException: open failed: ENOENT的stackoverflow帖子,但是我不确定如何在针对我的特定情况的响应中实施一般建议。
正确的方法是获取用户选择的图片的正确路径,以便我可以从其中创建文件并将其附加到MultiPart请求中?
建议的公用软件
使用ContentResolver和openInputStream()获取Uri指向的内容上的InputStream。然后,将其传递给您的解码逻辑,例如BitmapFactory及其解码方法。
,但我不确定如何以编程方式进行操作。
任何帮助将不胜感激。
答案 0 :(得分:1)
要允许用户选择图片,我的片段中应包含以下内容:
此代码正在使用ACTION_GET_CONTENT
。特别是在Android 7.0+上,通常会使用Uri
方案返回content
值。您的代码假定您正在通过Uri
方案获取file
值,其中路径实际上具有含义。而且,您的代码假设用户正在选择您可以访问的文件系统上的文件,并且没有任何强迫用户这样做的事情。 ACTION_GET_CONTENT
的内容受以下应用支持:
BLOB
列中的字节流使用this OkHttp issue comment中的RequestBody.create()
来代替InputStreamRequestBody
。您提供了与以前相同的媒体类型,但是提供了File
(来自ContentResolver
上的getContentResolver()
)而不是Context
(错误创建)。 Uri
。