Loop to upload images one at a time

I want to upload several images one at a time , for example, as soon as the user clicks the "Download all" button, he should start with the first image visible in the list, as soon as the first image is uploaded to the server, then the second starts automatically, but after one or two second intervals and the same for all available images in the list.

This is my code that allows you to upload a single image: -

Single Image Download Code

// btnUpload holder.uploadImageButton.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { // Upload startUpload(position); } }); 

I use the code below , but upload / sync all images at the same time, I mean together, for example, I have 500 images in the list, so it loads all 500 together , and as a result I get an error when connecting to the Internet and many times without getting the exact status of the downloaded images!

  private SparseBooleanArray flags = new SparseBooleanArray(); // At onClick, set all the flags to indicate that some data needs to be synced ImageButton buttonUploadAll = (ImageButton) findViewById(R.id.sync_btn); buttonUploadAll.setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { for(int position=0; position<listView.getAdapter().getCount(); position++) { flags.put(position, true); } // Calling this would ensure a call to getView() on every // visible child of the listview. That is where we will check if // the data is to be synced and displayed or not ((BaseAdapter) listView.getAdapter()).notifyDataSetChanged(); } }); @Override // In getView of the listview adapter public View getView(int position, View convertView, ViewGroup parent) { // If this item is to be synced if(flags.get(position)) { startUpload(); // Mark as synced flags.put(position, false); } // Rest of the method that draws the view.... } 

why I want to upload multiple images one at a time (in order of priority)

+7
android android-listview
source share
8 answers

I tried to write a service that will load an image from a common prefix one by one: Note: I hv hard-coded some things here, like an image, from sdcard, so the path is hard-coded, image names are hard-coded, so plz will change it accordingly and try below code, I checked and worked for me

Below is the code Service , Activity [download button, list], xmlLayout , php service that will upload the image to ftp.

Activity :

  public class MainActivity extends Activity { SharedPreferences sharedPref; SharedPreferences.Editor editor; ListView listview; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); sharedPref = getSharedPreferences("myfiles", MODE_PRIVATE); editor = sharedPref.edit(); editor.putString("0", "monika_pin.png"); editor.putString("1", "monika_pin1.png"); editor.putString("2", "monika_pin2.png"); editor.commit(); String[] arr = new String[] { "/mnt/sdcard/monika_pin.png", "/mnt/sdcard/monika_pin1.png", "/mnt/sdcard/monika_pin2.png" }; List<String> list = Arrays.asList(arr); MyAdapter adapter = new MyAdapter(this, R.layout.listitem_imv, list); listview = (ListView) findViewById(R.id.listView1); listview.setAdapter(adapter); } class MyAdapter extends ArrayAdapter<String> { List<String> mList; LayoutInflater mInflater; int mResource; public MyAdapter(Context context, int resource, List<String> objects) { super(context, resource, objects); mResource = resource; mInflater = getLayoutInflater(); mList = objects; } @Override public View getView(int position, View convertView, ViewGroup parent) { View view; if (convertView == null) { view = mInflater.inflate(mResource, null); } else { view = convertView; } ImageView imageView = (ImageView) view .findViewById(R.id.imageView1); TextView textView = (TextView) view.findViewById(R.id.textView1); imageView.setTag(mList.get(position));// tag of imageView == path to // image new LoadImage(imageView).execute(); textView.setText(mList.get(position).toString()); return view; } } class LoadImage extends AsyncTask<Object, Void, Bitmap> { private ImageView imv; private String path; public LoadImage(ImageView imv) { this.imv = imv; this.path = imv.getTag().toString(); } @Override protected Bitmap doInBackground(Object... params) { Bitmap bitmap = null; // File file = new File( // Environment.getExternalStorageDirectory().getAbsolutePath() + // path); File file = new File(path); if (file.exists()) { bitmap = BitmapFactory.decodeFile(file.getAbsolutePath()); } return bitmap; } @Override protected void onPostExecute(Bitmap result) { if (!imv.getTag().toString().equals(path)) { /* * The path is not same. This means that this image view is * handled by some other async task. We don't do anything and * return. */ return; } if (result != null && imv != null) { imv.setVisibility(View.VISIBLE); imv.setImageBitmap(result); } else { imv.setVisibility(View.GONE); } } } public void buttonClick(View view) { Intent intent = new Intent(this, MyService.class); startService(intent); } } 

Service :

 public class MyService extends Service { SharedPreferences sharedPref; SharedPreferences.Editor editor; int serverResponseCode = 0; String upLoadServerUri = null; private static final String TAG = "com.example.ServiceExample"; @Override public void onCreate() { Log.i(TAG, "Service onCreate"); sharedPref = getSharedPreferences("myfiles", MODE_PRIVATE); /************* PHP  path ****************/ upLoadServerUri = "http://myserver/uploadimage.php"; } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.i(TAG, "Service onStartCommand " + startId); final int currentId = startId; Runnable r = new Runnable() { public void run() { for (int i = 0; i < 3; i++) { // long endTime = System.currentTimeMillis() + 10*1000; // while (System.currentTimeMillis() < endTime) { synchronized (this) { try { uploadFile(sharedPref.getString(i + "", "")); } catch (Exception e) { } } // } Log.i(TAG, "Service running " + currentId); } stopSelf(); } }; Thread t = new Thread(r); t.start(); return Service.START_STICKY; } @Override public IBinder onBind(Intent arg0) { // TODO Auto-generated method stub Log.i(TAG, "Service onBind"); return null; } @Override public void onDestroy() { Log.i(TAG, "Service onDestroy"); } public int uploadFile(String sourceFileUri) { String fileName = sourceFileUri; HttpURLConnection conn = null; DataOutputStream dos = null; String lineEnd = "\r\n"; String twoHyphens = "--"; String boundary = "*****"; int bytesRead, bytesAvailable, bufferSize; byte[] buffer; int maxBufferSize = 1 * 1024 * 1024; // File sourceFile = new // File(Environment.getExternalStorageDirectory(),sourceFileUri); File sourceFile = new File(Environment.getExternalStorageDirectory() .getAbsolutePath() + "/" + fileName); if (!sourceFile.isFile()) { return 0; } else { try { // open a URL connection to the Servlet FileInputStream fileInputStream = new FileInputStream( sourceFile); URL url = new URL(upLoadServerUri); // Open a HTTP connection to the URL conn = (HttpURLConnection) url.openConnection(); conn.setDoInput(true); // Allow Inputs conn.setDoOutput(true); // Allow Outputs conn.setUseCaches(false); // Don't use a Cached Copy conn.setRequestMethod("POST"); conn.setRequestProperty("Connection", "Keep-Alive"); conn.setRequestProperty("ENCTYPE", "multipart/form-data"); conn.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary); conn.setRequestProperty("uploaded_file", fileName); dos = new DataOutputStream(conn.getOutputStream()); dos.writeBytes(twoHyphens + boundary + lineEnd); // dos.writeBytes("Content-Disposition: form-data; name="uploaded_file";filename=""+ fileName + """ // + lineEnd); dos.writeBytes("Content-Disposition: form-data; name=\"uploaded_file\";filename=\"" + fileName + "\"" + lineEnd); dos.writeBytes(lineEnd); // create a buffer of maximum size bytesAvailable = fileInputStream.available(); bufferSize = Math.min(bytesAvailable, maxBufferSize); buffer = new byte[bufferSize]; // read file and write it into form... bytesRead = fileInputStream.read(buffer, 0, bufferSize); while (bytesRead > 0) { dos.write(buffer, 0, bufferSize); bytesAvailable = fileInputStream.available(); bufferSize = Math.min(bytesAvailable, maxBufferSize); bytesRead = fileInputStream.read(buffer, 0, bufferSize); } // send multipart form data necesssary after file data... dos.writeBytes(lineEnd); dos.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd); // Responses from the server (code and message) serverResponseCode = conn.getResponseCode(); String serverResponseMessage = conn.getResponseMessage(); Log.i("uploadFile", "HTTP Response is : " + serverResponseMessage + ": " + serverResponseCode); if (serverResponseCode == 200) { } // close the streams // fileInputStream.close(); dos.flush(); dos.close(); } catch (MalformedURLException ex) { ex.printStackTrace(); Log.e("Upload file to server", "error: " + ex.getMessage(), ex); } catch (Exception e) { e.printStackTrace(); Log.e("Upload file to server Exception", "Exception : " + e.getMessage(), e); } return serverResponseCode; } // End else block } } 

XmlLayout :

 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="com.example.service.MainActivity" > <Button android:id="@+id/button1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:layout_centerHorizontal="true" android:onClick="buttonClick" android:text="Button" /> <ListView android:id="@+id/listView1" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@+id/button1" android:layout_centerHorizontal="true" > </ListView> </RelativeLayout> 

AndroidManifest

 <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.service" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="21" /> <uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" > <activity android:name=".MainActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <service android:name=".MyService" /> </application> </manifest> 

PhP Script :

 <?php $file_path = "uploads/"; $file_path = $file_path . basename( $_FILES['uploaded_file']['name']); if(move_uploaded_file($_FILES['uploaded_file']['tmp_name'], $file_path)) { echo "success"; } else{ echo "fail"; } ?> 

Note. At the top where you create this php file on ftp, create a folder, also called upload, where all files will be downloaded

If you want to download the full source code -> Source code

+5
source share
  • don't forget to close the connection after you finish writing bytes conn.close()
  • you do not need to use Runnables / Threads

1) add the following interface to your AsyncTask :

  public interface onImageUploadListener{ void onImageUploaded(String status); } 

2) Declare your instance as a class field in AsyncTask (I called it a listener) and add the following constructor:

  public UploadFileAsync(onImageUploadListener listener){ this.listener = listener; } 

3) Use AsyncTask.THREAD_POOL_EXECUTOR if you are using API> 11 so that your download task does not block other tasks you run.

4) Let your Adapter class (for God's sake, first remove the Runnable part), implement the interface:

 public class ImageAdapter extends BaseAdapter implements UploadFileAsync.onImageUploadListener 

you will need to implement the onImageUploaded(String status) method:

  @Override public void onImageUploaded(String status){ //here you are getting your server response) //I use a bit of pseudo-code to describe this condition if(position < lastPosition){ new UploadFileAsync(this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, String.valueOf(nextPosition)); }else{ //we are done }} 

5) In your AsyncTask, assign the server response value to some String and do the following in your onPostExecute() method:

  listener.onImageUploaded(yourResponseCode); 

6) To force a 1 second delay, just call Thread.sleep(1000); inside your doInBackground() method immediately before the return statement .

The onImageUploaded() will be onImageUploaded() every time AsyncTask ends, and you can repeat it again and again from this method until you finish loading. You can also add additional checks to this method, for example, check error codes, but it is up to you.

Hope this helps. Greetings

+3
source share

I would simply queue AsyncTask until more photos are uploaded. Something like

 if (++position < flags.size()) { new UploadFileAsync().execute(String.valueOf(position)); } 

You can do this either in onPostExecute() AsyncTask, or in the statusWhenFinished() method. I'm not sure you even need Runnable ...

NTN

+1
source share

First create a class of type ImageSyncService , located here. Many components of this class are missing as I extracted it from my current project, but you get an overview. If something is not clear, you can ask me.

 public class ImageSyncService extends IntentService { private static final String TAG = "ImageSyncService"; private Image image; private ImageOpenHelper imageOpenHelper; private SharedPreferences preferences; public ImageSyncService() { super(TAG); } @Override protected void onHandleIntent(Intent intent) { Logger.d(TAG, "onHandleIntent"); imageOpenHelper = new ImageOpenHelper(getApplicationContext()); preferences = PreferenceManager.getDefaultSharedPreferences(getApplicationContext()); image = (Image) intent.getSerializableExtra(Config.REQUEST_EXTRA_OBJECT); if(image == null) return; if(image.getResourceURI() == null) { image.setSyncStatus(SyncStatus.SYNCING); imageOpenHelper.updateImage(image, false); Response response = MultiPartDataServer.postData(Config.URL_IMAGE_UPLOAD, nameValuePairs, null); /* on success: * * image.setSyncStatus(SyncStatus.SYNCED); * imageOpenHelper.updateImage(image, false); * * */ } } 

On uploadAll click the button:

  ArrayList<Image> images = imageOpenHelper.getUnsyncedImages(SyncStatus.TO_BE_UPLOADED); Intent imageSyncService = null; for(Image i: images) { imageSyncService = new Intent(getApplicationContext(), ImageSyncService.class); imageSyncService.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); imageSyncService.putExtra(Config.REQUEST_EXTRA_OBJECT, i); startService(imageSyncService); } 

Hope this helps :)

+1
source share

==== The class of action from which the image will be loaded ====

 import android.app.Activity; import android.view.View; import android.view.View.OnClickListener; public class MActivity extends Activity implements OnClickListener, ImageStatusUpdater{ String img_url[] = new String[3]; @Override public void onImageUpload(boolean status, String img_url) { //here you will get the status update with corresponding //image url or say image name what ever } @Override public void onClick(View v) { img_url[0] = "img1_url"; img_url[1] = "img2_url"; img_url[2] = "img3_url"; new ImageUploader(this).execute(img_url); } } 

=== The interface class will be used to update the flag for each image after loading from the AsyncTask class ===

 public interface ImageStatusUpdater { public void onImageUpload(boolean status, String img_url); } 

=== AsyncTask class from which the actual load will be executed ===

 import android.os.AsyncTask; public class ImageUploader extends AsyncTask<String, String, Void>{ ImageStatusUpdater isu; public ImageUploader(ImageStatusUpdater isu) { this.isu = isu; } @Override protected Void doInBackground(String... params) { for (String img_name: params){ //Here you have to write your uploading code String[] result; result = new String[1]; result[0] = img_name; result[1] = "true"; onProgressUpdate(result); } return null; } @Override protected void onProgressUpdate(String... values) { super.onProgressUpdate(values); this.isu.onImageUpload(Boolean.getBoolean(values[1]), values[0]); } } 

This is just some kind of demo code explaining the stream to you, you need to write real code when it will ever be suitable.

+1
source share

An easier way to load one at a time is to simply add a synchronised(mLock){ } block to the doinBackground function. Which keeps that part of the code mutually exclusive, and only one image is loaded at a time. And its QuickFix or workaround , I do not prefer this method for this purpose.

  // Async Upload private static final Object mLock = new Object();//have an object to lock, and define out side the async task class public class UploadFileAsync extends AsyncTask<String, Void, Void> { String resServer; protected void onPreExecute() { super.onPreExecute(); } @Override protected Void doInBackground(String... params) { // TODO Auto-generated method stub synchronized(mLock){ //sync block starts position = Integer.parseInt(params[0]); int bytesRead, bytesAvailable, bufferSize; byte[] buffer; int maxBufferSize = 1 * 1024 * 1024; int resCode = 0; String resMessage = ""; String lineEnd = "\r\n"; String twoHyphens = "--"; String boundary = "*****"; // File Path String strSDPath = ImageList.get(position).toString(); // Upload to PHP  String strUrlServer = ""; try { /** Check file on SD Card ***/ File file = new File(strSDPath); if(!file.exists()) { resServer = "{\"StatusID\":\"0\",\"Error\":\"Please check path on SD Card\"}"; return null; } FileInputStream fileInputStream = new FileInputStream(new File(strSDPath)); URL url = new URL(strUrlServer); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setDoInput(true); conn.setDoOutput(true); conn.setUseCaches(false); conn.setRequestMethod("POST"); conn.setRequestProperty("Connection", "Keep-Alive"); conn.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary); DataOutputStream outputStream = new DataOutputStream(conn .getOutputStream()); outputStream.writeBytes(twoHyphens + boundary + lineEnd); outputStream .writeBytes("Content-Disposition: form-data; name=\"filUpload\";filename=\"" + strSDPath + "\"" + lineEnd); outputStream.writeBytes(lineEnd); bytesAvailable = fileInputStream.available(); bufferSize = Math.min(bytesAvailable, maxBufferSize); buffer = new byte[bufferSize]; // Read file bytesRead = fileInputStream.read(buffer, 0, bufferSize); while (bytesRead > 0) { outputStream.write(buffer, 0, bufferSize); bytesAvailable = fileInputStream.available(); bufferSize = Math.min(bytesAvailable, maxBufferSize); bytesRead = fileInputStream.read(buffer, 0, bufferSize); } outputStream.writeBytes(lineEnd); outputStream.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd); // Response Code and Message resCode = conn.getResponseCode(); if(resCode == HttpURLConnection.HTTP_OK) { InputStream is = conn.getInputStream(); ByteArrayOutputStream bos = new ByteArrayOutputStream(); int read = 0; while ((read = is.read()) != -1) { bos.write(read); } byte[] result = bos.toByteArray(); bos.close(); resMessage = new String(result); } Log.d("resCode=",Integer.toString(resCode)); Log.d("resMessage=",resMessage.toString()); fileInputStream.close(); outputStream.flush(); outputStream.close(); resServer = resMessage.toString(); } catch (Exception ex) { ex.printStackTrace(); } }//Sync block ends return null; } protected void onPostExecute(Void unused) { statusWhenFinish(position,resServer); } } 
+1
source share

Looper at WorkerThread best suited to your requirement. Try this as follows:

 public class MyActivity extends Activity{ public static final int LOAD_IMAGE = 1; public static final MAX_IMAGE_INDEX = 500; public static final DELAY_TIME = 1*1000; // 1 second private WorkerThread mWorkerThread; onCreate(Bundle bundle){ mWorkerThread = new WorkerThread(); mWorkerThread.start(); } public void onCLick(View pView){ Message message = Message.obtain(); message.what = LOAD_IMAGE; message.arg1 = 0; // Start from Image index zero; mWorkerThread.queJob(message, 0); } private class WorkerThread{ Looper looper; Handler handler; private void init(){ if(!isAlive()){ start(); } } public void queJob(Message msg, int delay){ init(); if(handler!=null){ handler.sendMessageDelayed(msg, delay); } } public void run(){ Looper.prepare(); looper = Looper.MyLoop(); handler = new Handler(){ public void handleMessage(Message msg){ if(msg.what==LOAD_IMAGE){ if(msg.agr1<0||msg.arg1>=MAX_IMAGE_INDEX) return; inr imageIndex = msg.arg1; // Create connection here and load image Message message = Message.obtain(); message.what = LOAD_IMAGE; if(loadingSuccess){ // Load next image message.agr1 = msg.arg1 + 1; // increase index to next }else{ // en que the same failed job message.arg1 = msg.arg1; } queJob(message, DELAY_TIME); } } }; Looper.loop(); } } } 
0
source share
  BitmapFactory.Options options = new BitmapFactory.Options(); // down sizing image as it throws OutOfMemory Exception for larger // images options.inSampleSize = 8; Bitmap bitmap = BitmapFactory.decodeFile(filePath, options); imgView.setImageBitmap(bitmap); 
0
source share

All Articles