I have implemented an Android plugin for Unity which peform a call to webapi service
ClientPlugin class functionality
1)the api called is unauthorizedDateRequest, it make a request with the date of last update as parameter, the response is a JsonArray that contains object with 2 attributes: ID and Name
2)for each ID i make a second call to unauthorizedImageRequest, which is an ImageRequest of Volley, i've made class MyImageRequest that extends ImageRequest, in order to get the name from header fields
3)I pass response(bitmap) and nameFile to saveImageToGallery, this function symply save the downloaded bitmap
Problems comes randomly cause sometimes all images (for this demo i have 4 images) are saved, and other times only 3 of 4 image are saved and one of the 3 image is saved 2 times in a row, I assume it's a problem of concurrency, although Volley is thread safe
How can i solve this problem?
This is my code of class ClientPlugin
public class ClientPlugin {
private static final ClientPlugin newInstance = new ClientPlugin();
private String url;
private NetworkManager networkManager;
public static Activity mainActivity;
public String imageName;
private static ClientPlugin getInstance() {return newInstance;}
public ClientPlugin() {
String LOGCAT = "--ClientPlugin---";
Log.i(LOGCAT,"Created DownloadPlugin");
}
public void unauthorizedDateRequest(){
String LOGCAT ="-------------unauthorizedDateRequest-------------";
String lastUpdate = getLastUpdateDate();
url = "https://demo.companyName.com/api/ImagesList_na/date/"+lastUpdate;
networkManager = NetworkManager.getInstance(mainActivity);
RequestQueue queue = networkManager.getRequestQueue();
JsonArrayRequest jsonArrayRequest = new JsonArrayRequest
(Request.Method.GET, url, null, new Response.Listener<JSONArray>() {
@Override
public void onResponse(JSONArray response) {
try {
for (int i = 0; i < response.length(); i++) {
JSONObject obj = response.getJSONObject(i);
String name = obj.getString("ID");
unauthorizedImageRequest(name);
}
} catch (JSONException e) {
Log.e(LOGCAT, Log.getStackTraceString(e));
}
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
String LOGCAT = "---DateRequestonErrorRespone---";
Log.e(LOGCAT, Log.getStackTraceString(error));
}
});
queue.add(jsonArrayRequest);
}
public void unauthorizedImageRequest(String id){
networkManager = NetworkManager.getInstance(mainActivity);
RequestQueue queue = networkManager.getRequestQueue();
url = "https://demo.companyName.com/api/Image_na/" + id;
MyImageRequest request = new MyImageRequest(
url, // Image URL
new Response.Listener<Bitmap>() { // Bitmap listener
@Override
public void onResponse(Bitmap responseBitmap) {
String LOGCAT ="----onResponse----";
String nameFile = MyImageRequest.getMyNameFile();
// Save this downloaded bitmap to internal storage
Uri uri = saveImageToGallery(responseBitmap, nameFile)
Log.d(LOGCAT, uri.toString());
}
},
0,
0,
null,
Bitmap.Config.RGB_565, //Image decode configuration
new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
String LOGCAT ="---ErroreOnRespone---";
Log.e(LOGCAT, Log.getStackTraceString(error));
}
}
);
request.setRetryPolicy(new DefaultRetryPolicy(
5000,
5,
DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
queue.add(request);
}
public Uri saveImageToGallery(Bitmap responseBitmap, String nameFile){
String LOGCAT = "------saveImageToGallery-------";
ContextWrapper wrapper = new ContextWrapper(mainActivity.getApplicationContext());
File pathFile = wrapper.getExternalFilesDir(Environment.DIRECTORY_PICTURES);
File file = new File(pathFile,nameFile);
try{
OutputStream stream = null;
stream = new FileOutputStream(file);
responseBitmap.compress(Bitmap.CompressFormat.JPEG,100,stream);
stream.flush();
stream.close();
Log.d(LOGCAT, "Image Saved");
} catch (FileNotFoundException e) {
Log.d(LOGCAT, Log.getStackTraceString(e));
} catch (IOException e) {
Log.d(LOGCAT, Log.getStackTraceString(e));
}
// Parse the gallery image url to uri
Uri savedImageURI = Uri.parse(file.getAbsolutePath());
// Return the saved image Uri
return savedImageURI;
}
}
Code of NetworkManager class, this is a singleton
public class NetworkManager {
private static NetworkManager instance;
private RequestQueue requestQueue;
public synchronized static NetworkManager getInstance(Activity activity) {
if (instance == null) {
instance = new NetworkManager();
instance.requestQueue = Volley.newRequestQueue(activity);
}
return instance;
}
public RequestQueue getRequestQueue() {
return requestQueue;
}
}
And this is code of MyImageRequest, i've implemented this class because i needed to Override parseNetworkResponse in order to retrieve name file from headers fields
public class MyImageRequest extends ImageRequest {
private final String LOGCAT ="-----------parseNetworkResponse-----------";
private static String myNameFile="";
public static String getMyNameFile() {
return myNameFile;
}
public MyImageRequest(String url, Response.Listener<Bitmap> listener, int maxWidth, int maxHeight, ImageView.ScaleType scaleType, Bitmap.Config decodeConfig, @Nullable Response.ErrorListener errorListener) {
super(url, listener, maxWidth, maxHeight, scaleType, decodeConfig, errorListener);
}
@Override
protected Response<Bitmap> parseNetworkResponse(NetworkResponse response) {
String tmpContentDisposition = response.headers.get("Content-Disposition");
tmpContentDisposition = tmpContentDisposition.substring(21);
Log.d(LOGCAT,tmpContentDisposition);
myNameFile = tmpContentDisposition;
return super.parseNetworkResponse(response);
}
}