Ich habe eine Android-App, mit der der Benutzer einige Bilder aus der Galerie auswählen und diese Bilder (zusammen mit einigen anderen Daten) an das Backend senden kann.
Damit der Benutzer die Bilder auswählen kann, habe ich Folgendes in meinem Fragment:
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);
}
Ich bekomme das Ergebnis der ausgewählten Fotos vom Benutzer hier herein:
@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);
}
}
Ich sende dann die Liste der URIs an den Presenter, wo ich meinen MultiPart Retrofit-Aufruf an das Backend ausführe:
//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);
Das Problem ist, dass dies manchmal funktioniert, manchmal nicht. Manchmal bekomme ich den Fehler “java.io.FileNotFoundException”, der mich in die onFailure()
Rückruf des Retrofit-Aufrufs.
Ich habe den folgenden Stackoverflow-Beitrag gefunden. Lesen der Datei von Uri gibt java.io.FileNotFoundException: Öffnen fehlgeschlagen: ENOENT, aber ich bin mir nicht genau sicher, wie ich den allgemeinen Vorschlag in dieser Antwort auf meine spezielle Situation implementieren soll.
Was wäre der richtige Weg, um den richtigen Weg zu den vom Benutzer ausgewählten Bildern zu finden, damit ich daraus Dateien erstellen und sie in meine MultiPart-Anfrage einfügen kann?
Commonsware vorgeschlagen
Verwenden Sie einen ContentResolver und openInputStream(), um einen InputStream für den Inhalt zu erhalten, auf den der Uri zeigt. Übergeben Sie das dann an Ihre Decodierungslogik, z. B. BitmapFactory und seine Methode decodeStream().
aber ich bin mir nicht sicher, wie ich das programmgesteuert machen soll.
Jede Hilfe wäre willkommen.