Загрузка нескольких изображений на сервер в очереди

Случай использования: Загружать изображения в очередь в фоновом режиме на сервер, изображения могут быть веб-адресами или файлами изображений, хранящимися в памяти телефона.

То, что я хочу. Ограничьте количество элементов в очереди до 3 и покажите размытые изображения в качестве заполнителей для фактических изображений, загружаемых в recyclerview, в действие с индикатором выполнения на каждом заполнителе, указывающем, сколько он был загружен. В верхней части каждого заполнителя находятся три кнопки для приостановки, отмены или возобновления загрузки изображения.

Текущая ситуация: Сейчас я использовал Multipart в Retrofit 1.9.0 для загрузки изображений, и этот служебный вызов выполнялся внутри действия.

Я не могу понять, как отменить, приостановить или возобновить запрос multipart-POST с помощью Retrofit или любой другой библиотеки в целом и как связать событие пользовательского интерфейса с потоком сервиса api. Я могу обновить пользовательский интерфейс от службы, но как мне что-то обновить в службе от события в пользовательском интерфейсе (пауза/возобновление/отмена)?

Как мне следует использовать этот прецедент? Нужно ли использовать сервис? Могу ли я показывать индикаторы прогресса в другом действии на основе запросов, выполняемых в службе? Какая должна быть архитектура для этого процесса? Мне не нужен код для этого, но если есть некоторые полезные ссылки, связанные с этим, я бы хотел прочитать и проверить его, чтобы наконец получить мой подход.

Ответ 1

Вот как вы можете это сделать: это пример кода для загрузки изображения с устройства путем передачи пути изображения. Аналогично, вы можете сделать это для URL-адреса изображения, Шаги: 1) Создайте поток, который будет запускаться для каждого изображения. 2) после этого каждая загрузка изображения даст вам ответ. 3) теперь для каждого изображения вы можете обновить свой интерфейс.

//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);
    }
};

Надеюсь, это поможет вам.

Ответ 2

Я настоятельно рекомендую вам использовать Square Tape, когда вы одновременно загружаете несколько файлов/изображений, просто глядя на простоту использования, эффективность, обработку ошибок, систему очередей. Если вы используете только один файл во время, попробуйте использовать любую загрузку файлов из нескольких частей в любых клиентах Http для Android.

Это то, что Квадратная лента:

Tape - это коллекция классов, связанных с очередями для Android и Java, Square, Inc.

QueueFile - это быстрый, транзакционный, основанный на файлах FIFO. Добавление и удаление из экземпляра является операцией O (1) и является атомарной. Записи синхронны; данные будут записаны на диск перед возвратом операции. Основной файл структурирован, чтобы выдержать процесс и даже системные сбои, и если исключение ввода-вывода выбрано во время мутирующего изменения, изменение отменяется.

ObjectQueue представляет собой упорядочение произвольных объектов, которые могут поддерживаться либо файловой системой (через QueueFile), либо только в памяти.

TaskQueue - это специальная очередь объектов, которая содержит задачи, объекты, которые имеют представление о выполнении. Экземпляры управляются внешним исполнителем, который подготавливает и выполняет заданные задачи.

Ответ 3

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 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();
    }
}