Bonjour,
Je travaille sur un projet d'application android. L'utilisateur doit avoir la possibilité de sélectionner et d'envoyer plusieurs photos à la fois depuis sa galerie vers mon serveur.
J'arrive à sélectionner et envoyer une seule photo à la fois. Mais, l'option de choisir plusieurs photos et de les envoyer ensemble me cause beaucoup de soucis.
J'ai trouvé le code suivant qui me permet de faire exactement ce que je veux, mais, le problème est que, je ne reçois rien du côté serveur.
Voici le code que j'utilise :
implementation 'com.squareup.retrofit2:retrofit:2.4.0'
implementation 'com.squareup.retrofit2:converter-gson:2.3.0'
implementation 'com.google.code.gson:gson:2.8.5'
implementation 'com.asksira.android:bsimagepicker:1.2.2'
implementation 'com.github.bumptech.glide:glide:4.8.0'
implementation 'com.github.bumptech.glide:annotations:4.8.0'
implementation('com.github.bumptech.glide:okhttp3-integration:4.0.0') {
exclude group: 'glide-parent'
}
annotationProcessor 'com.github.bumptech.glide:compiler:4.7.1'
implementation "com.karumi:dexter:5.0.0"
import android.annotation.SuppressLint;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.Manifest;
import android.app.ProgressDialog;
import android.content.Intent;
import android.graphics.Bitmap;
import android.net.Uri;
import android.provider.MediaStore;
import android.provider.Settings;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Base64;
import android.util.Log;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.Toast;
import com.android.volley.AuthFailureError;
import com.android.volley.NetworkError;
import com.android.volley.NoConnectionError;
import com.android.volley.ParseError;
import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.ServerError;
import com.android.volley.TimeoutError;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.JsonObjectRequest;
import com.android.volley.toolbox.Volley;
import com.asksira.bsimagepicker.BSImagePicker;
import com.bumptech.glide.Glide;
import com.bumptech.glide.RequestManager;
import com.karumi.dexter.Dexter;
import com.karumi.dexter.MultiplePermissionsReport;
import com.karumi.dexter.PermissionToken;
import com.karumi.dexter.listener.PermissionRequest;
import com.karumi.dexter.listener.multi.MultiplePermissionsListener;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import static android.content.ContentValues.TAG;
public class AjouterPhoto extends AppCompatActivity implements BSImagePicker.OnSingleImageSelectedListener,
BSImagePicker.OnMultiImageSelectedListener, BSImagePicker.ImageLoaderDelegate{
SharedPreferences shared;
private Button choosePhotos;
private RequestManager mGlideRequestManager;
private ViewGroup mSelectedImagesContainer;
private String YOURURL ="http://***************";
String codeCmd;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_ajouter_photo);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
shared = getApplicationContext().getSharedPreferences("maSession", Context.MODE_PRIVATE);
String Telephone = shared.getString("Telephone", null);
String Pass = shared.getString("Pass", null);
String Nom = shared.getString("Nom", null);
String Identifiant = shared.getString("Identifiant", null);
mGlideRequestManager = Glide.with(this);
inIt();
permission();
Random random = new Random();
int code = random.nextInt(1000000000);
codeCmd = String.valueOf(code);
final SharedPreferences.Editor editor = shared.edit();
editor.putString("Commande", codeCmd);
editor.apply();
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}
private void inIt() {
mSelectedImagesContainer = (ViewGroup) findViewById(R.id.selected_photos_container);
choosePhotos = findViewById(R.id.choose_photos);
}
private void permission() {
choosePhotos.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Dexter.withActivity(AjouterPhoto.this)
.withPermissions(Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE)
.withListener(new MultiplePermissionsListener() {
@Override
public void onPermissionsChecked(MultiplePermissionsReport report) {
if (report.areAllPermissionsGranted()) {
BSImagePicker multiSelectionPicker = new BSImagePicker.Builder("com.mon.domaine.app")
.isMultiSelect() //Set this if you want to use multi selection mode.
.setMinimumMultiSelectCount(1) //Default: 1.
.setMaximumMultiSelectCount(10) //Default: Integer.MAX_VALUE (i.e. User can select as many images as he/she wants)
.setMultiSelectBarBgColor(android.R.color.white) //Default: #FFFFFF. You can also set it to a translucent color.
.setMultiSelectTextColor(R.color.primary_text) //Default: #212121(Dark grey). This is the message in the multi-select bottom bar.
.setMultiSelectDoneTextColor(R.color.colorAccent) //Default: #388e3c(Green). This is the color of the "Done" TextView.
.setOverSelectTextColor(R.color.error_text) //Default: #b71c1c. This is the color of the message shown when user tries to select more than maximum select count.
.disableOverSelectionMessage() //You can also decide not to show this over select message.
.build();
multiSelectionPicker.show(getSupportFragmentManager(), "picker");
}
if (report.isAnyPermissionPermanentlyDenied()) {
showSettingsDialog();
}
}
@Override
public void onPermissionRationaleShouldBeShown(List<PermissionRequest> permissions, PermissionToken token) {
token.continuePermissionRequest();
}
}).check();
}
});
}
/**
* Showing Alert Dialog with Settings option
* Navigates user to app settings
* NOTE: Keep proper title and message depending on your app
*/
private void showSettingsDialog() {
AlertDialog.Builder builder = new AlertDialog.Builder(AjouterPhoto.this);
//builder.setTitle(getString(R.string.dialog_permission_title));
//builder.setMessage(getString(R.string.dialog_permission_message));
// Set language level to 8 if error shows.
/*builder.setPositiveButton(getString(R.string.go_to_settings), (dialog, which) -> {
dialog.cancel();
openSettings();
});
builder.setNegativeButton(getString(android.R.string.cancel), (dialog, which) -> dialog.cancel());
builder.show();*/
}
// navigating user to app settings
private void openSettings() {
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
Uri uri = Uri.fromParts("package", getPackageName(), null);
intent.setData(uri);
startActivityForResult(intent, 101);
}
//You can use below function also for byteArray generation.
public byte[] getBytes(InputStream inputStream) {
ByteArrayOutputStream byteBuffer = new ByteArrayOutputStream();
try {
int bufferSize = 1024;
byte[] buffer = new byte[bufferSize];
int len;
while ((len = inputStream.read(buffer)) != -1) {
byteBuffer.write(buffer, 0, len);
}
} catch (Exception e) {
Toast.makeText(this, e.getMessage(), Toast.LENGTH_SHORT).show();
}
return byteBuffer.toByteArray();
}
@Override
public void loadImage(File imageFile, ImageView ivImage) {
Glide.with(AjouterPhoto.this).load(imageFile).into(ivImage);
}
@Override
public void onMultiImageSelected(List<Uri> uriList, String tag) {
mSelectedImagesContainer.removeAllViews();
mSelectedImagesContainer.setVisibility(View.VISIBLE);
int wdpx = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 100, getResources().getDisplayMetrics());
int htpx = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 100, getResources().getDisplayMetrics());
for (Uri uri : uriList) {
View imageHolder = LayoutInflater.from(this).inflate(R.layout.image_item, null);
ImageView thumbnail = (ImageView) imageHolder.findViewById(R.id.media_image);
Glide.with(this)
.load(uri.toString())
.into(thumbnail);
try {
// You can update this bitmap to your server
Bitmap bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), uri);
//((BitmapDrawable) profilePicImage.getDrawable()).getBitmap();
counter++;
savePhoto(bitmap,uri,uriList.size());
// loading profile image from local cache
} catch (IOException e) {
e.printStackTrace();
}
mSelectedImagesContainer.addView(imageHolder);
thumbnail.setLayoutParams(new FrameLayout.LayoutParams(wdpx, htpx));
}
}
@Override
public void onSingleImageSelected(Uri uri, String tag) {
}
int counter=0;
private void savePhoto(Bitmap bitmap,Uri imageUri,int file_count) {
final ProgressDialog pd = new ProgressDialog(AjouterPhoto.this);
pd.setMessage("Envoi de photos est encours..."+counter);
pd.show();
//converting image to base64 string
//bitmap = BitmapFactory.decodeResource(getResources(), R.id.shop_licence_image_1);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);
byte[] imageBytes = baos.toByteArray();
final String imageString = Base64.encodeToString(imageBytes, Base64.DEFAULT);
String Telephone2 = shared.getString("Telephone", null);
String Pass2 = shared.getString("Pass", null);
String Nom2 = shared.getString("Nom", null);
String Identifiant2 = shared.getString("Identifiant", null);
RequestQueue requestQueue = Volley.newRequestQueue(AjouterPhoto.this);
Map<String, String> params = new HashMap<String, String>();
// Those are my required variables for server
params.put("file_name", imageUri.getPath());
params.put("image", imageString);
params.put("file_count",String.valueOf(file_count));
params.put("Telephone",Telephone2);
params.put("Pass",Pass2);
params.put("Nom",Nom2);
params.put("Identifiant",Identifiant2);
params.put("Commande",codeCmd);
JsonObjectRequest objectRequest = new JsonObjectRequest(Request.Method.POST, YOURURL,
new JSONObject(params), new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) {
if(pd!=null)
pd.dismiss();
try {
// Handling Errors After Api call.
if (response.getString("is_error").equals("1")) {
} else {
if (response.getInt("is_error") == 0) {
Toast.makeText(AjouterPhoto.this, "Success", Toast.LENGTH_SHORT).show();
Intent intent_accueil = new Intent(AjouterPhoto.this, MonPanier.class);
startActivity(intent_accueil);
}
}
} catch (JSONException e) {
Toast.makeText(AjouterPhoto.this, e.getMessage(), Toast.LENGTH_SHORT).show();
}
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
if(pd!=null)
pd.dismiss();
//Handling Different types of volley error .
if (error instanceof NoConnectionError)
{
Toast.makeText(AjouterPhoto.this, "Erreur de connexion internet", Toast.LENGTH_SHORT).show();
} else if (error instanceof TimeoutError) {
Toast.makeText(AjouterPhoto.this, "Connexion internet très lente", Toast.LENGTH_SHORT).show();
} else if (error instanceof AuthFailureError) {
} else if (error instanceof ServerError) {
Toast.makeText(AjouterPhoto.this, "Une erreur est survenue au niveau du serveur", Toast.LENGTH_SHORT).show();
} else if (error instanceof NetworkError) {
Toast.makeText(AjouterPhoto.this, "Un problème est survenue sur votre connexion internet", Toast.LENGTH_SHORT).show();
} else if (error instanceof ParseError) {
}
}
}) {
@Override
protected VolleyError parseNetworkError(VolleyError volleyError) {
Log.d(TAG, "Une erreur est venue. Contactez FotoPrints" + volleyError.getMessage());
return super.parseNetworkError(volleyError);
}
//Required for Basic authentication if you are using .Otherwise remove this overridden method.
@Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> headers = new HashMap<>();
// add headers <key,value>
String credentials = "user_name"+ ":" + "password";
String auth = "Basic "
+ Base64.encodeToString(credentials.getBytes(),
Base64.DEFAULT);
headers.put("Authorization", auth);
return headers;
}
@Override
public String getBodyContentType() {
return "application/json; charset=utf-8";
}
};
requestQueue.add(objectRequest);
}
}
<ScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="@dimen/fab_margin">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="@dimen/fab_margin"
android:background="#FFEEEE">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/comment_valider"
android:textSize="@dimen/fab_margin"
/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="1dp"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#000"
android:text="Upload your Images"
android:layout_gravity="center_horizontal"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="It will directly upload your images when you press DONE Button."
android:textSize="12sp"
android:layout_gravity="center_horizontal"
android:gravity="center_horizontal"
android:layout_marginLeft="35dp"
android:layout_marginRight="35dp"/>
</LinearLayout>
<HorizontalScrollView
android:id="@+id/hori_scroll_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fillViewport="false"
android:scrollbars="none"
android:layout_marginTop="20dp"
android:scrollIndicators="none"
android:foregroundGravity="left">
<LinearLayout
android:id="@+id/selected_photos_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:animateLayoutChanges="true"
android:gravity="center"
android:orientation="horizontal"
android:visibility="visible">
</LinearLayout>
</HorizontalScrollView>
</LinearLayout>
</LinearLayout>
</ScrollView>
<Button
android:id="@+id/choose_photos"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Sélectionnez vos photos"
android:textAllCaps="false"
android:capitalize="sentences"
android:background="@drawable/bordure3"
android:textColor="#fff"
android:layout_alignParentBottom="true"
android:padding="@dimen/fab_margin"
android:layout_gravity="bottom|end"
android:gravity="bottom|end"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintRight_toRightOf="parent"
android:layout_margin="@dimen/fab_margin"/>
Merci de m'aider à résoudre ce problème. Le code marche parfaitement bien sauf que je reçois rien du côté serveur.
Afficher la suite