如何分别显示多个上传的上传进度 - Android

时间:2017-07-03 06:39:16

标签: android file-upload progress-bar image-uploading

如何使用上传按钮显示我在Android上传的每个文件的进度条,如下所示: Uploading Screenshot

我尝试过使用服务和通知,但我希望在UI中显示进度。

任何代码示例都会有所帮助。

我正在使用以下类进行分段上传:

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

2 个答案:

答案 0 :(得分:1)

为此创建单例设计,并为每个下载文件在带有键值的HashMap条目中创建一个条目。例如,对于file1,应该有一个键,值应该是其更新的进度。并根据文件上传进度(当进度更新的回调接收时)对密钥更新该条目。并且还根据键更新该哈希映射的进度条。因为您的哈希映射将始终具有更新的值。希望有所帮助。 在我的一个项目中,我实现了同样的事情。我现在正在分享

创建下载服务

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

}

以下是进度接收器

public class ProgressReceiver extends BroadcastReceiver实现了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);
}

}

以下是跟踪下载状态的主要代码。

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

}

希望有所帮助。

答案 1 :(得分:0)

我就是这样做的:

  1. 创建RecyclerView以保存每个上传进度行
  2. 开始新上传时 - 将新项目(行)添加到RecyclerView
  3. 您需要在RecyclerView行位置和它代表的上传任务之间保留某种映射(HashMap是一个不错的选择)
  4. 收听任务的上传进度(我看到你已经实现了一个监听器),当更新到达时 - 从步骤3查询HashMap以检查你需要更新的RecyclerView行。
  5. 使用步骤4中的位置更新RecyclerView行。
  6. 一些可以帮助您入门的资源:

    Working with Recycler View

    How to add new item to RecyclerView

    How to update/refresh specific item in RecyclerView

    Java HashMap class