2

How should can I show progress bar for each file I upload in android using an upload button, something like this: Uploading Screenshot

I have tried doing so using services and notification but I would like to show progress in the UI itself.

Any Code Sample will help.

I am using the following Class for multipart upload:

public class MultipartUtility
{
    FileUploadListener listener;
    private static final int BUFFER_SIZE = 1024;
    private static final int TIME_OUT = 3 * 60 * 1000;
    private final String boundary;
    private static final String LINE_FEED = "\r\n";
    private HttpURLConnection httpConn;
    private String charset;
    private OutputStream outputStream;
    private PrintWriter writer;
    public int statusCode;
    public String mURL;

    public interface FileUploadListener {
        void onUpdateProgress(int percentage, long kb);
        boolean isCanceled();
    }

    /**
     * This constructor initializes a new HTTP POST request with content type
     * is set to multipart/form-data
     *
     * @param requestURL
     * @param charset
     * @throws IOException
     */
    public MultipartUtility(Context context, String requestURL, String charset, FileUploadListener listener)
            throws IOException {
        this.charset = charset;
        this.listener = listener;
        mURL = requestURL;
        // creates a unique boundary based on time stamp
        boundary = "" + System.currentTimeMillis() + "";

        URL url = new URL(requestURL);
        httpConn = null;
        if (url.getProtocol().toLowerCase().equals("https")) {
            trustAllHosts();
            HttpsURLConnection https = (HttpsURLConnection) url.openConnection();
            https.setHostnameVerifier(new HostnameVerifier() {
                @Override
                public boolean verify(String hostname, SSLSession session) {
                    return true;
                }
            });
            httpConn = https;
        } else {
            httpConn = (HttpURLConnection) url.openConnection();
        }

        // httpConn.setConnectTimeout(TIME_OUT);
        //httpConn.setReadTimeout(TIME_OUT);
        httpConn.setUseCaches(false);
        httpConn.setDoOutput(true); // indicates POST method
        httpConn.setDoInput(true);
        httpConn.setChunkedStreamingMode(BUFFER_SIZE);
        httpConn.setRequestMethod("POST");
        Storage storage = new Storage(context);
        httpConn.setRequestProperty("x-auth", storage.readString("user_token"));
        httpConn.setRequestProperty("Content-Type",
                "multipart/form-data; boundary=" + boundary);
        httpConn.setRequestProperty("Connection", "Keep-Alive");
        outputStream = httpConn.getOutputStream();
        writer = new PrintWriter(new OutputStreamWriter(outputStream, charset),
                true);
    }

    private static void trustAllHosts() {
        // Create a trust manager that does not validate certificate chains
        TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() {
            public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                return new java.security.cert.X509Certificate[]{};
            }

            public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
            }

            public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
            }
        }};

        // Install the all-trusting trust manager
        try {
            SSLContext sc = SSLContext.getInstance("TLS");
            sc.init(null, trustAllCerts, new java.security.SecureRandom());
            HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    /**
     * Adds a form field to the request
     *
     * @param name  field name
     * @param value field value
     */
    public void addFormField(String name, String value) {
        writer.append("--" + boundary).append(LINE_FEED);
        writer.append("Content-Disposition: form-data; name=\"" + name + "\"")
                .append(LINE_FEED);
        writer.append("Content-Type: text/plain; charset=" + charset).append(
                LINE_FEED);
        writer.append(LINE_FEED);
        writer.append(value).append(LINE_FEED);
        writer.flush();
    }

    /**
     * Adds a upload file section to the request
     *
     * @param fieldName name attribute in <input type="file" name="..." />
     * @param uploadFile a File to be uploaded
     * @throws IOException
     */
    private long lastProgressUpdateTime = 0;

    public void addFilePart(String fieldName, File uploadFile)
            throws IOException {
        String fileName = uploadFile.getName();
        writer.append("--" + boundary).append(LINE_FEED);
        writer.append(
                "Content-Disposition: form-data; name=\"" + fieldName
                        + "\"; filename=\"" + fileName + "\"")
                .append(LINE_FEED);
        writer.append(
                "Content-Type: "
                        + URLConnection.guessContentTypeFromName(fileName))
                .append(LINE_FEED);
        writer.append("charset=" + charset).append(
                LINE_FEED);
        writer.append(LINE_FEED);
        writer.flush();

        outputStream.flush();
        byte[] buffer = new byte[BUFFER_SIZE];

        try {
            final FileInputStream inputStream = new FileInputStream(uploadFile);
            long totalRead = 0;
            long totalSize = uploadFile.length();

            int read;
            while ((read = inputStream.read(buffer)) > 0) {
                totalRead += read;
                int percentage = (int) ((totalRead / (float) totalSize) * 100);
                outputStream.write(buffer, 0, read);

                long now = System.currentTimeMillis();
                if (lastProgressUpdateTime == 0 || lastProgressUpdateTime < now - 100) {
                    lastProgressUpdateTime = now;

                    Log.e("", totalRead + " " + " " + percentage);

                    if (listener != null)
                        this.listener.onUpdateProgress(percentage, totalRead);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            outputStream.flush();
        }

        writer.append(LINE_FEED);
        writer.flush();
    }


    /**
     * Adds a header field to the request.
     *
     * @param name  - name of the header field
     * @param value - value of the header field
     */
    public void addHeaderField(String name, String value) {
        writer.append(name + ": " + value).append(LINE_FEED);
        writer.flush();
    }

    /**
     * Completes the request and receives response from the server.
     *
     * @return a list of Strings as response in case the server returned
     * status OK, otherwise an exception is thrown.
     * @throws IOException
     */
    public String Execute() throws IOException {
        String responses = "";

        writer.append(LINE_FEED).flush();
        writer.append("--" + boundary + "--").append(LINE_FEED);
        writer.close();
        StringBuilder sb = new StringBuilder();
        try {
            // checks server's status code first
            statusCode = httpConn.getResponseCode();
            //responses = ;

            sb.append("" + Helpers.convertStreamToString(httpConn.getInputStream()) + "\n");

            if (statusCode == HttpURLConnection.HTTP_OK) {
                httpConn.disconnect();
            }
            responses = sb.toString();
            return responses;
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            sb = new StringBuilder();

            sb.append("" + Helpers.convertStreamToString(httpConn.getErrorStream()) + "\n");

            responses = sb.toString();
        }
        return responses;
    }
}
Shakti Phartiyal
  • 5,370
  • 2
  • 19
  • 42

2 Answers2

2

Create a singleton design for this and for every downloading file create an entry in HashMap entry with key value. For example for file1 there should be a key and value should be its updated progress. And update that entry according to file upload progress(when the call back of on progress update receive) against the key. And also update the progress bar from that hash map according to key.Because your hash map will always have updated values. Hope that helps. In one of my project I implemented the same thing. I am sharing that now

Create download service

public class DownloadService extends IntentService {

public DownloadService() {
    super("DownloadService");
}

@Override
protected void onHandleIntent(Intent intent) {
    String rhymeName = intent.getStringExtra(Constants.RHYME_NAME);
    String URL = intent.getStringExtra(Constants.URL);
    downloadRhyme(rhymeName, URL);
}

private void sendMyBroadCast(long currentProgress, long totalVideoSize, String rhymeName) {
    Intent intentUpdate = new Intent();
    intentUpdate.setAction(Constants.ACTION_MYUPDATE);
    intentUpdate.addCategory(Intent.CATEGORY_DEFAULT);
    intentUpdate.putExtra(Constants.UPDATED_VALUES, currentProgress);
    intentUpdate.putExtra(Constants.TOTAL_VIDEO_SIZE, totalVideoSize);
    intentUpdate.putExtra(Constants.RHYME_NAME, rhymeName);
    sendBroadcast(intentUpdate);
}

private void registerMyTaskCompletedListener(ITaskCompletedListener taskCompletedListener, boolean successful, String rhymeName) {
    if (successful)
        taskCompletedListener.taskCompleted(rhymeName);
    else
        taskCompletedListener.taskFailed(rhymeName);
}


private final void downloadRhyme(String rhymeName, String URL) {

    boolean successful = false;
    URL downloadURL = null;
    HttpURLConnection httpURLConnection = null;
    InputStream inputStream = null;
    FileOutputStream fileOutputStream = null;
    File file = null;
    try {
        downloadURL = new URL(URL);
        httpURLConnection = (HttpURLConnection) downloadURL.openConnection();
        int responseCode = httpURLConnection.getResponseCode();
        if (responseCode != HttpURLConnection.HTTP_OK)
            return;
        inputStream = httpURLConnection.getInputStream();
        file = AppUtility.getInternalDirectoryForRhymes(this, rhymeName);
        fileOutputStream = new FileOutputStream(file);
        int read = -1;
        long totalRead =0 ;
        int totalLength = httpURLConnection.getContentLength();
        byte [] buffer = new byte[1024];
        while ((read = inputStream.read(buffer)) != -1) {
            totalRead += read;
            fileOutputStream.write(buffer, 0, read);
            sendMyBroadCast(totalRead, totalLength, rhymeName);
        }
        successful = true;
        UrduRhymesActivity.getInstance().unregisterMyReceiver();
        callListener(successful, rhymeName);

    }  catch (Exception e) {
        if (e instanceof SocketTimeoutException) {
            ProgressReceiver.showSocketConnectionDialogue();
        }
        callListener(successful, rhymeName);
    } finally {
        if (httpURLConnection != null) {
            httpURLConnection.disconnect();
        }
        if (inputStream != null) {
            try {
                inputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        if (fileOutputStream != null) {
            try {
                fileOutputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

private void callListener(boolean successful, String rhymeName) {
    ITaskCompletedListener taskCompletedListener = new ProgressReceiver();
    registerMyTaskCompletedListener(taskCompletedListener, successful, rhymeName);
}

}

Below is the progress receiver

public class ProgressReceiver extends BroadcastReceiver implements ITaskCompletedListener {

@Override
public void onReceive(Context context, Intent intent) {
    long currentProgress = intent.getLongExtra(Constants.UPDATED_VALUES, 0);
    long totalSize = intent.getLongExtra(Constants.TOTAL_VIDEO_SIZE, 0);
    String rhymeName = intent.getStringExtra(Constants.RHYME_NAME);
    ProgressbarDetails progressbarDetails = ProgressbarDetails.getProgressDetail(rhymeName);
    if (progressbarDetails != null) {
        int updates = ((int) ((currentProgress / (float) totalSize) * 100));
        progressbarDetails.prgProgressBar.setVisibility(View.VISIBLE);
        progressbarDetails.prgProgressBar.setProgress(updates);
        LogUtility.infoLog("current downloaded file size is " + currentProgress);
        LogUtility.infoLog("total file size " + totalSize);
        LogUtility.infoLog("After conversion " + updates);
    }
}

@Override
public void taskCompleted(String rhymeName) {
    runThread(rhymeName);

}

private void runThread(final String rhymeName) {
    UrduRhymesActivity.getInstance().runOnUiThread(new Runnable() {
        @Override
        public void run() {
            ProgressbarDetails progressbarDetails = ProgressbarDetails.getProgressDetail(rhymeName);
            progressbarDetails.download_btn_settings.setBackgroundResource(R.mipmap.btn_play);
            progressbarDetails.prgProgressBar.setVisibility(View.GONE);
            ProgressbarDetails.deleteUpdateProgressDetail(rhymeName);

        }
    });
}

public static void showSocketConnectionDialogue() {
    UrduRhymesActivity.getInstance().runOnUiThread(new Runnable() {
        @Override
        public void run() {
            //[Case:When server is down]
            AppUtility.showConnectionDialoge(UrduRhymesActivity.sUrduRhymesActivity);

        }
    });
}

@Override
public void taskFailed(String rhymeName) {
    boolean deleteStatus = false;
     if (rhymeName != null)
        deleteStatus = AppUtility.deleteFileFromInternalDirectory(MyApplication.getAppContext(), rhymeName);
    if (deleteStatus)
        LogUtility.infoLog("file deleted Successfully");
    else LogUtility.infoLog("File not deleted");

    ProgressbarDetails.deleteUpdateProgressDetail(rhymeName);
}

}

Here is the main code that keeps track of downloading status.

public class ProgressbarDetails  {

public ProgressBar prgProgressBar;
public int progress;
public LinearLayout download_btn_settings;

private static HashMap<String, ProgressbarDetails> progressMapper = null;

public static HashMap<String, ProgressbarDetails> getProgressMapper() {
    if(progressMapper == null)
        progressMapper  = new HashMap<>();
    return progressMapper;
}

public static ProgressbarDetails getProgressDetail(String rhymeName) {
    Object obj = getProgressMapper().get(rhymeName);
    ProgressbarDetails ProgressbarDetails = null;
    if (obj != null)
        ProgressbarDetails = (ProgressbarDetails) obj;

    return ProgressbarDetails;
}

public static void addUpdateProgressDetail(String rhymeName, ProgressbarDetails prgBarDetail) {
    progressMapper = getProgressMapper();
    progressMapper.put(rhymeName, prgBarDetail);
}

public static void deleteUpdateProgressDetail(String rhymeName) {
    progressMapper  = getProgressMapper();
    if(progressMapper.containsKey(rhymeName))
        progressMapper.remove(rhymeName);
}

}

Hope that helps.

Abdul Waheed
  • 3,994
  • 4
  • 30
  • 49
0

This is how I would do it:

  1. Create a RecyclerView to hold each upload progress row
  2. Upon starting a new upload - add new item (row) to the RecyclerView
  3. You need to keep some kind of mapping between the RecyclerView row position and the upload task it represents (HashMap is a good option)
  4. Listen to the upload progress of your task (I see you have a listener already implemented) and when an update arrives - query to HashMap from step 3 to check which RecyclerView row you need to update.
  5. Update the RecyclerView row with the position from step 4.

Some resources to get you started:

Working with Recycler View

How to add new item to RecyclerView

How to update/refresh specific item in RecyclerView

Java HashMap class

Yossi Segev
  • 587
  • 4
  • 12
  • It's not the full code - the whole mechanism with the UI update is pretty complex to write in a single answer. But it should point you in right directions to achieve the screenshot you provided and the functionality. Best of luck :) – Yossi Segev Jul 03 '17 at 07:28