Загрузка нескольких изображений на сервер в очереди
Случай использования: Загружать изображения в очередь в фоновом режиме на сервер, изображения могут быть веб-адресами или файлами изображений, хранящимися в памяти телефона.
То, что я хочу. Ограничьте количество элементов в очереди до 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();
}
}