2016-08-08 46 views
12

Anwendungsfall: Bilder in eine Warteschlange im Hintergrund auf den Server hochladen, können Bilder Web-URLs oder Bilddatei im Speicher des Telefons gespeichert werden.Laden Sie mehrere Bilder auf den Server in einer Warteschlange

Was ich will Begrenzen Sie die Anzahl der Elemente in der Warteschlange bis 3 und zeigen unscharfe Bilder als Platzhalter für die tatsächlichen Bilder in einem recyclerview in einer Aktivität mit einem Fortschrittsbalken auf jeden Platzhalter hochgeladen werden angibt, wie viel davon hat hochgeladen. Über jedem Platzhalter befinden sich drei Schaltflächen, um den Upload des Bildes entweder anzuhalten, abzubrechen oder fortzusetzen.

Aktuelle Situation: Gerade jetzt, war ich Multipart in Retrofit 1.9.0 mit Bildern hochladen und dieser Service-Aufruf in der Aktivität getan wurde.

Ich bin nicht in der Lage herauszufinden, wie eine Multipart-POST-Anfrage mit Retrofit oder einer anderen Bibliothek im Allgemeinen zu stornieren, zu pausieren oder fortzusetzen und ein UI-Ereignis mit einem API-Dienst-Thread zu verknüpfen. Ich kann die Benutzeroberfläche vom Dienst aus aktualisieren, aber wie aktualisiere ich etwas im Service von einem Ereignis in der Benutzeroberfläche (Pause/Fortsetzen/Abbrechen)?

Wie soll ich mit diesem Anwendungsfall fortfahren? Muss ich den Service nutzen? Kann ich Fortschrittsindikatoren in einer anderen Aktivität basierend auf den Anforderungen anzeigen, die im Service ausgeführt werden? Was sollte die Architektur für diesen Prozess sein? Ich brauche den Code dafür nicht, aber wenn es einige nützliche Referenzen dazu gibt, würde ich gerne lesen und testen, um meinen Ansatz schließlich abzuleiten.

+0

'Ein Benutzer kann ein Bild entweder über vorhandene URLs (Facebook oder Instagram) oder über eine lokale Bilddatei auf den Server hochladen. Ein Bild kann auf einen Server hochgeladen werden. Der Server hat eine URL. Bilder können nicht über lokale Bilddateien hochgeladen werden. Bitte umformuliere, wie es jetzt keinen Sinn macht. – greenapps

+0

@greenapps ok, ich werde das beheben. Eigentlich ist die App eine Bild-Sharing-Plattform, auf der Sie entweder fb- oder Instagram-Bilder teilen oder direkt von Ihrem Telefonalbum hochladen können. –

Antwort

1

Dies ist, wie Sie tun können: dies ist der Beispielcode das Bild von Gerät, indem Sie den Pfad des image..similarly laden Sie es für Bild-URL tun, Schritte: 1) einen Thread erzeugen, wird für jedes Bild ausführen. 2) Danach gibt jedes Bild Upload die Antwort. 3) Jetzt können Sie für jedes Bild Ihre Benutzeroberfläche aktualisieren.

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

Hoffe, das wird Ihnen helfen.

1

Ich empfehle Ihnen Square Tape zu verwenden, während Sie mehrere Dateien/Bilder auf einmal hochladen, um die Benutzerfreundlichkeit, Effizienz, Fehlerbehandlung, Warteschlangensystem zu prüfen. Wenn Sie nur eine Datei zur Zeit mit versuchen, den beliebigen mehrteiligen Datei-Upload in jedem Android Http Clients zu verwenden

Dies ist, was Square's Tape:

Band ist eine Sammlung von Queue-bezogenen Klassen für Android und Java durch Square

QueueFile ist ein blitzschneller, transaktionaler, dateibasierter FIFO. Hinzufügen und Entfernen von einer Instanz ist eine O (1) -Operation und ist atomar. Schriftsätze sind synchron; Daten werden auf den Datenträger geschrieben, bevor eine Operation zurückgegeben wird. Die zugrunde liegende Datei ist so strukturiert, dass sie Prozess- und sogar Systemabstürzen standhält. Wenn während einer mutierenden Änderung eine E/A-Ausnahme ausgelöst wird, wird die Änderung abgebrochen.

Eine ObjectQueue repräsentiert eine Reihenfolge beliebiger Objekte, die entweder vom Dateisystem (über QueueFile) oder nur im Speicher gesichert werden können.

TaskQueue ist eine spezielle Objektwarteschlange, die Tasks enthält, Objekte, die ausgeführt werden sollen. Instanzen werden von einem externen Executor verwaltet, der in Warteschlange eingereihte Tasks vorbereitet und ausführt.

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

dieser code ist vollkommen in Ordnung ... implementiere das ... danach poste ich auch den serverseitigen code .. –