13

Use case: Upload images in a queue in background to the server, images can be web urls or image file stored on the phone's memory.

What I want Limit the number of items in queue to 3 and show blurred images as placeholders for the actual images being uploaded in a recyclerview in an activity with a progress bar on each placeholder indicating how much of it has been uploaded. On top of every placeholder are three buttons to either pause, cancel or resume the upload of the image.

Current Situation: Right now, I was using Multipart in Retrofit 1.9.0 to upload images and this service call was being done inside the activity.

I am not able to figure out how to cancel, pause or resume a multipart-POST request using Retrofit or any other library in general and how to tie a UI event with an api service thread. I can update the UI from service, but how do I update something in the service from an event in UI (pause/resume/cancel)?

How should I proceed with this use case? Do I need to use service? Can I show progress indicators in another activity based on the requests being executed in the service? What should be the architecture for this process? I don't need the code for it, but if there are some useful references related to this, I would like to read and test it out to finally derive my approach.

Amit Tiwari
  • 3,684
  • 6
  • 33
  • 75
  • `A user can upload an image to server either through existing urls(facebook or instagram) or through a local image file.` ??? An image can be uploaded to a server. The server has an url. One cannot upload images through local image files. Please rephrase as now it makes no sense. – greenapps Aug 08 '16 at 07:28
  • @greenapps ok, I will fix that. Actually, the thing is, the app is an image sharing platform where you can either share fb or instagram images or you can directly upload from your phone album. – Amit Tiwari Aug 08 '16 at 07:31

2 Answers2

1

This is how you can do: this is the sample code to upload the Image from device by passing the path of the image..similarly you can do it for Image url, Steps:1) Create a thread which will run for each image. 2) after that each image upload will give you the response. 3) now for each image you can update your UI.

//TODO: Multiple file upload
public class FileUpload implements Runnable {
    Context context;
    String uploadApiUrl, uploadFilePath, fileType;
    int uploadId;
    LocalQueenDataBase localQueenDataBase;
    Activity activity;

    public FileUpload(Context context, ,String uploadApiUrl, String uploadFilePath, String fileType, int uploadId) {
        this.context = context;
        this.uploadApiUrl = uploadApiUrl;
        this.uploadFilePath = uploadFilePath;
        this.fileType = fileType;
        this.uploadId = uploadId;
        localQueenDataBase = new LocalQueenDataBase(context);
        Thread uploader = new Thread(this);
        uploader.start();
    }

    @Override
    public void run() {
        try {
            executeMultipartPost();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void executeMultipartPost() throws Exception {
        try {
            String originalPath = uploadFilePath;
            if (uploadFilePath == null) {
                uploadFilePath = originalPath;
            }
            HttpClient httpclient = new DefaultHttpClient();
            HttpPost httppost = new HttpPost("your api url");
            httppost.addHeader("put your header if required")
            FileBody bin = new FileBody(new File(uploadFilePath));
            StringBody fileTypeBody = new StringBody(fileType);
            StringBody uploadIdBody = new StringBody(uploadId + "");

            MultipartEntity reqEntity = new MultipartEntity();
            reqEntity.addPart("file", bin);
            reqEntity.addPart("fileType", fileTypeBody);
            reqEntity.addPart("uploadId", uploadIdBody);
            httppost.setEntity(reqEntity);

            HttpResponse response = httpclient.execute(httppost);
            HttpEntity resEntity = response.getEntity();
            String retSrc = EntityUtils.toString(resEntity);//Render your response
            //TODO: update your UI for each uploaded image by creating the Handler
             Message msg = handler.obtainMessage();
             handler.sendMessage(msg);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

final Handler handler = new Handler() {
    @Override
    public void handleMessage(Message msg) {
        try {
            uploadGalleryRecyclerAdapter = new UploadGalleryRecyclerAdapter(getApplicationContext(), PostUpdateActivity.this, localQueenDataBase.getGallery());
            postUpdateRV.setAdapter(uploadGalleryRecyclerAdapter);
            if (localQueenDataBase.getGallery().size() > 3)
                gallerylayoutManager.scrollToPosition(localQueenDataBase.getGallery().size() - 2);
        } catch (Exception e) {
            e.printStackTrace();
        }
        super.handleMessage(msg);
    }
};

Hope this will help you.

1
enter codepackage com.mohit.mom.multipleimage;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.StrictMode;
import android.util.Log;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.mime.MultipartEntity;
import org.apache.http.entity.mime.content.ByteArrayBody;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.protocol.HttpContext;
import org.apache.http.util.EntityUtils;
import java.io.ByteArrayOutputStream;
import java.util.ArrayList;

@SuppressLint("NewApi")
public class MainActivity extends Activity {
    private Button upload, pick;
    private ProgressDialog dialog;
    MultipartEntity entity;
    GridView gv;
    int count = 0;
    public ArrayList<String> map = new ArrayList<String>();
    Bundle b;
    TextView noImage;
    HttpEntity resEntity;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder()
                .permitAll().build();
        StrictMode.setThreadPolicy(policy);
        b = getIntent().getExtras();

        noImage = (TextView) findViewById(R.id.noImage);
        upload = (Button) findViewById(R.id.btnUpload);
        pick = (Button) findViewById(R.id.btnPicture);
        gv = (GridView) findViewById(R.id.gridview);
        gv.setAdapter(new ImageAdapter(this));

        if (b != null)
        {
            ArrayList<String> ImgData = b.getStringArrayList("IMAGE");
            for (int i = 0; i < ImgData.size(); i++)
            {
                map.add(ImgData.get(i).toString());
            }
        } else
        {
            noImage.setVisibility(View.VISIBLE);
        }

        upload.setOnClickListener(new View.OnClickListener() {

            public void onClick(View v)
            {
                new ImageUploadTask().execute(count + "", "pk" + count + ".jpg");
            }
        });

        pick.setOnClickListener(new View.OnClickListener() {

            public void onClick(View v) {
                Intent i3 = new Intent(MainActivity.this, UploadActivity.class);
                startActivity(i3);
            }
        });

    }

    class ImageUploadTask extends AsyncTask<String, Void, String> {

        String sResponse = null;

        @Override
        protected void onPreExecute() {
            // TODO Auto-generated method stub
            super.onPreExecute();
            dialog = ProgressDialog.show(MainActivity.this, "Uploading",
                    "Please wait...", true);
            dialog.show();
        }

        @Override
        protected String doInBackground(String... params) {
            try {

                String url = "yours url";
                int i = Integer.parseInt(params[0]);
                Bitmap bitmap = decodeFile(map.get(i));
                HttpClient httpClient = new DefaultHttpClient();
                HttpContext localContext = new BasicHttpContext();
                HttpPost httpPost = new HttpPost(url);
                entity = new MultipartEntity();

                ByteArrayOutputStream bos = new ByteArrayOutputStream();
                bitmap.compress(CompressFormat.JPEG, 50, bos);
                byte[] data = bos.toByteArray();

                entity.addPart("user_id", new StringBody("199"));
                entity.addPart("club_id", new StringBody("10"));
                entity.addPart("club_image", new ByteArrayBody(data,
                        "image/jpeg", params[1]));

                httpPost.setEntity(entity);
                HttpResponse response = httpClient.execute(httpPost);
                resEntity = response.getEntity();
                sResponse = EntityUtils.toString(resEntity);
                //HttpResponse response = httpClient.execute(httpPost,localContext);
                //sResponse = EntityUtils.getContentCharSet(response.getEntity());

                System.out.println("sResponse : " + sResponse);
            } catch (Exception e) {
                if (dialog.isShowing())
                    dialog.dismiss();
                Log.e(e.getClass().getName(), e.getMessage(), e);

            }
            return sResponse;
        }

        @Override
        protected void onPostExecute(String sResponse) {
            try {
                if (dialog.isShowing())
                    dialog.dismiss();

                if (sResponse != null) {
                    Toast.makeText(getApplicationContext(),
                            sResponse + " Photo uploaded successfully",
                            Toast.LENGTH_SHORT).show();
                    count++;
                    if (count < map.size()) {
                        new ImageUploadTask().execute(count + "", "hm" + count
                                + ".jpg");
                    }
                }

            } catch (Exception e) {
                Toast.makeText(getApplicationContext(), e.getMessage(),
                        Toast.LENGTH_LONG).show();
                Log.e(e.getClass().getName(), e.getMessage(), e);
            }

        }
    }

    public Bitmap decodeFile(String filePath) {
// Decode image size
        BitmapFactory.Options o = new BitmapFactory.Options();
        o.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(filePath, o);
// The new size we want to scale to
        final int REQUIRED_SIZE = 1024;
// Find the correct scale value. It should be the power of 2.
        int width_tmp = o.outWidth, height_tmp = o.outHeight;
        int scale = 1;
        while (true) {
            if (width_tmp < REQUIRED_SIZE && height_tmp < REQUIRED_SIZE)
                break;
            width_tmp /= 2;
            height_tmp /= 2;
            scale *= 2;
        }
        BitmapFactory.Options o2 = new BitmapFactory.Options();
        o2.inSampleSize = scale;
        Bitmap bitmap = BitmapFactory.decodeFile(filePath, o2);
        return bitmap;
    }

    private class ImageAdapter extends BaseAdapter
    {
        private Context mContext;

        public ImageAdapter(Context c)
        {
            mContext = c;
        }

        public int getCount()
        {
            return map.size();
        }

        public Object getItem(int position)
        {
            return null;
        }

        // create a new ImageView for each item referenced by the Adapter
        public View getView(int position, View convertView, ViewGroup parent) {
            ImageView imageView;
            if (convertView == null)
            { // if it's not recycled, initialize some
                // attributes
                imageView = new ImageView(mContext);
                imageView.setLayoutParams(new GridView.LayoutParams(85, 85,
                        Gravity.CENTER));
                imageView.setScaleType(ImageView.ScaleType.FIT_XY);
                imageView.setPadding(1, 1, 1, 1);

            }
            else
            {
                imageView = (ImageView) convertView;
            }
            //Bitmap bm=BitmapFactory.decodeFile(map.get(position));
            final BitmapFactory.Options options = new BitmapFactory.Options();
            options.inSampleSize = 8;
            Bitmap bmp = BitmapFactory.decodeFile(map.get(position),options);
            imageView.setImageBitmap(bmp);
            return imageView;
        }

        @Override
        public long getItemId(int position) {
            // TODO Auto-generated method stub
            return 0;
        }
    }

    @Override
    public void onBackPressed() {
// TODO Auto-generated method stub
        super.onBackPressed();
        MainActivity.this.finish();
    }
}
WrightsCS
  • 50,551
  • 22
  • 134
  • 186