Nice programing

Android로 파일을 다운로드하고 ProgressDialog에 진행률 표시

nicepro 2020. 9. 27. 13:57
반응형

Android로 파일을 다운로드하고 ProgressDialog에 진행률 표시


업데이트되는 간단한 응용 프로그램을 작성하려고합니다. 이를 위해 파일을 다운로드 하고 현재 진행 상황ProgressDialog. 을 수행하는 방법을 알고 ProgressDialog있지만 현재 진행 상황을 표시하는 방법과 처음에 파일을 다운로드하는 방법을 잘 모르겠습니다.


파일을 다운로드하는 방법은 여러 가지가 있습니다. 다음으로 가장 일반적인 방법을 게시하겠습니다. 앱에 더 나은 방법을 결정하는 것은 사용자에게 달려 있습니다.

1. AsyncTask대화 상자에서 다운로드 진행률 사용 및 표시

이 메서드를 사용하면 일부 백그라운드 프로세스를 실행하고 동시에 UI를 업데이트 할 수 있습니다 (이 경우 진행률 표시 줄을 업데이트합니다).

다음은 예제 코드입니다.

// declare the dialog as a member field of your activity
ProgressDialog mProgressDialog;

// instantiate it within the onCreate method
mProgressDialog = new ProgressDialog(YourActivity.this);
mProgressDialog.setMessage("A message");
mProgressDialog.setIndeterminate(true);
mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
mProgressDialog.setCancelable(true);

// execute this when the downloader must be fired
final DownloadTask downloadTask = new DownloadTask(YourActivity.this);
downloadTask.execute("the url to the file you want to download");

mProgressDialog.setOnCancelListener(new DialogInterface.OnCancelListener() {

    @Override
    public void onCancel(DialogInterface dialog) {
        downloadTask.cancel(true); //cancel the task
    }
});

AsyncTask다음과 같이 표시됩니다

// usually, subclasses of AsyncTask are declared inside the activity class.
// that way, you can easily modify the UI thread from here
private class DownloadTask extends AsyncTask<String, Integer, String> {

    private Context context;
    private PowerManager.WakeLock mWakeLock;

    public DownloadTask(Context context) {
        this.context = context;
    }

    @Override
    protected String doInBackground(String... sUrl) {
        InputStream input = null;
        OutputStream output = null;
        HttpURLConnection connection = null;
        try {
            URL url = new URL(sUrl[0]);
            connection = (HttpURLConnection) url.openConnection();
            connection.connect();

            // expect HTTP 200 OK, so we don't mistakenly save error report
            // instead of the file
            if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) {
                return "Server returned HTTP " + connection.getResponseCode()
                        + " " + connection.getResponseMessage();
            }

            // this will be useful to display download percentage
            // might be -1: server did not report the length
            int fileLength = connection.getContentLength();

            // download the file
            input = connection.getInputStream();
            output = new FileOutputStream("/sdcard/file_name.extension");

            byte data[] = new byte[4096];
            long total = 0;
            int count;
            while ((count = input.read(data)) != -1) {
                // allow canceling with back button
                if (isCancelled()) {
                    input.close();
                    return null;
                }
                total += count;
                // publishing the progress....
                if (fileLength > 0) // only if total length is known
                    publishProgress((int) (total * 100 / fileLength));
                output.write(data, 0, count);
            }
        } catch (Exception e) {
            return e.toString();
        } finally {
            try {
                if (output != null)
                    output.close();
                if (input != null)
                    input.close();
            } catch (IOException ignored) {
            }

            if (connection != null)
                connection.disconnect();
        }
        return null;
    }

위의 메서드 ( doInBackground)는 항상 백그라운드 스레드에서 실행됩니다. 거기에서 UI 작업을 수행해서는 안됩니다. 반면에, onProgressUpdate그리고 onPreExecute당신이 진행 표시 줄을 변경할 수 있으므로이, UI 스레드에서 실행 :

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        // take CPU lock to prevent CPU from going off if the user 
        // presses the power button during download
        PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
        mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
             getClass().getName());
        mWakeLock.acquire();
        mProgressDialog.show();
    }

    @Override
    protected void onProgressUpdate(Integer... progress) {
        super.onProgressUpdate(progress);
        // if we get here, length is known, now set indeterminate to false
        mProgressDialog.setIndeterminate(false);
        mProgressDialog.setMax(100);
        mProgressDialog.setProgress(progress[0]);
    }

    @Override
    protected void onPostExecute(String result) {
        mWakeLock.release();
        mProgressDialog.dismiss();
        if (result != null)
            Toast.makeText(context,"Download error: "+result, Toast.LENGTH_LONG).show();
        else
            Toast.makeText(context,"File downloaded", Toast.LENGTH_SHORT).show();
    }

이를 실행하려면 WAKE_LOCK 권한이 필요합니다.

<uses-permission android:name="android.permission.WAKE_LOCK" />

2. 서비스에서 다운로드

여기서 큰 질문 은 서비스에서 내 활동을 어떻게 업데이트합니까? . 다음 예제에서는 여러분이 알지 못하는 두 개의 클래스를 사용할 것입니다 : ResultReceiverIntentService. ResultReceiver서비스에서 스레드를 업데이트 할 수있게 해주는 것입니다. 백그라운드 작업을 수행하기 위해 스레드를 생성 IntentService하는 하위 클래스입니다 Service(이 Service실제로 앱의 동일한 스레드에서 실행 됨을 알아야합니다 .를 확장 할 때 ServiceCPU 차단 작업을 실행하려면 새 스레드를 수동으로 생성해야합니다).

다운로드 서비스는 다음과 같습니다.

public class DownloadService extends IntentService {
    public static final int UPDATE_PROGRESS = 8344;

    public DownloadService() {
        super("DownloadService");
    }
    @Override
    protected void onHandleIntent(Intent intent) {

        String urlToDownload = intent.getStringExtra("url");
        ResultReceiver receiver = (ResultReceiver) intent.getParcelableExtra("receiver");
        try {

            //create url and connect
            URL url = new URL(urlToDownload);
            URLConnection connection = url.openConnection();
            connection.connect();

            // this will be useful so that you can show a typical 0-100% progress bar
            int fileLength = connection.getContentLength();

            // download the file
            InputStream input = new BufferedInputStream(connection.getInputStream());

            String path = "/sdcard/BarcodeScanner-debug.apk" ;
            OutputStream output = new FileOutputStream(path);

            byte data[] = new byte[1024];
            long total = 0;
            int count;
            while ((count = input.read(data)) != -1) {
                total += count;

                // publishing the progress....
                Bundle resultData = new Bundle();
                resultData.putInt("progress" ,(int) (total * 100 / fileLength));
                receiver.send(UPDATE_PROGRESS, resultData);
                output.write(data, 0, count);
            }

            // close streams 
            output.flush();
            output.close();
            input.close();

        } catch (IOException e) {
            e.printStackTrace();
        }

        Bundle resultData = new Bundle();
        resultData.putInt("progress" ,100);

        receiver.send(UPDATE_PROGRESS, resultData);
    }
}

매니페스트에 서비스를 추가합니다.

<service android:name=".DownloadService"/>

그리고 활동은 다음과 같습니다.

// initialize the progress dialog like in the first example

// this is how you fire the downloader
mProgressDialog.show();
Intent intent = new Intent(this, DownloadService.class);
intent.putExtra("url", "url of the file to download");
intent.putExtra("receiver", new DownloadReceiver(new Handler()));
startService(intent);

여기 ResultReceiver에 놀러 왔습니다.

private class DownloadReceiver extends ResultReceiver{

    public DownloadReceiver(Handler handler) {
        super(handler);
    }

    @Override
    protected void onReceiveResult(int resultCode, Bundle resultData) {

        super.onReceiveResult(resultCode, resultData);

        if (resultCode == DownloadService.UPDATE_PROGRESS) {

            int progress = resultData.getInt("progress"); //get the progress
            dialog.setProgress(progress);

            if (progress == 100) {
                dialog.dismiss();
            }
        }
    }
}

2.1 Groundy 라이브러리 사용

Groundy 는 기본적으로 백그라운드 서비스에서 코드 조각을 실행하는 데 도움이되는 라이브러리이며ResultReceiver위에 표시된 개념을기반으로합니다. 이 라이브러리는 현재 사용되지 않습니다 . 이것은 어떻게 전체 코드는 같을 것이다 :

대화를 표시하는 활동 ...

public class MainActivity extends Activity {

    private ProgressDialog mProgressDialog;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        findViewById(R.id.btn_download).setOnClickListener(new View.OnClickListener() {
            public void onClick(View view) {
                String url = ((EditText) findViewById(R.id.edit_url)).getText().toString().trim();
                Bundle extras = new Bundler().add(DownloadTask.PARAM_URL, url).build();
                Groundy.create(DownloadExample.this, DownloadTask.class)
                        .receiver(mReceiver)
                        .params(extras)
                        .queue();

                mProgressDialog = new ProgressDialog(MainActivity.this);
                mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
                mProgressDialog.setCancelable(false);
                mProgressDialog.show();
            }
        });
    }

    private ResultReceiver mReceiver = new ResultReceiver(new Handler()) {
        @Override
        protected void onReceiveResult(int resultCode, Bundle resultData) {
            super.onReceiveResult(resultCode, resultData);
            switch (resultCode) {
                case Groundy.STATUS_PROGRESS:
                    mProgressDialog.setProgress(resultData.getInt(Groundy.KEY_PROGRESS));
                    break;
                case Groundy.STATUS_FINISHED:
                    Toast.makeText(DownloadExample.this, R.string.file_downloaded, Toast.LENGTH_LONG);
                    mProgressDialog.dismiss();
                    break;
                case Groundy.STATUS_ERROR:
                    Toast.makeText(DownloadExample.this, resultData.getString(Groundy.KEY_ERROR), Toast.LENGTH_LONG).show();
                    mProgressDialog.dismiss();
                    break;
            }
        }
    };
}

Groundy 에서 파일을 다운로드하고 진행 상황을 표시하는 GroundyTask데 사용 하는 구현 :

public class DownloadTask extends GroundyTask {    
    public static final String PARAM_URL = "com.groundy.sample.param.url";

    @Override
    protected boolean doInBackground() {
        try {
            String url = getParameters().getString(PARAM_URL);
            File dest = new File(getContext().getFilesDir(), new File(url).getName());
            DownloadUtils.downloadFile(getContext(), url, dest, DownloadUtils.getDownloadListenerForTask(this));
            return true;
        } catch (Exception pokemon) {
            return false;
        }
    }
}

그리고 이것을 매니페스트에 추가하십시오.

<service android:name="com.codeslap.groundy.GroundyService"/>

이보다 쉬울 수 없다고 생각합니다. Github 에서 최신 병 가져 오면 바로 사용할 수 있습니다. 있다는 사실을 숙지 Groundy 의 주요 목적은 쉽게와 UI에 배경 서비스의 외부 REST API에 대한 호출 및 사후 결과를 확인하는 것입니다. 앱에서 이와 같은 작업을한다면 정말 유용 할 것입니다.

2.2 https://github.com/koush/ion 사용

3. DownloadManager수업 사용 ( GingerBread이상 만 해당)

GingerBread는 DownloadManager파일을 쉽게 다운로드하고 스레드, 스트림 등을 처리하는 힘든 작업을 시스템에 위임 할 수 있는 새로운 기능을 가져 왔습니다 .

먼저 유틸리티 메서드를 살펴 보겠습니다.

/**
 * @param context used to check the device version and DownloadManager information
 * @return true if the download manager is available
 */
public static boolean isDownloadManagerAvailable(Context context) {

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
        return true;
    }
    return false;
}

방법의 이름이 모든 것을 설명합니다. DownloadManager사용 가능 여부 가 확인되면 다음과 같이 할 수 있습니다.

String url = "url you want to download";
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));
request.setDescription("Some descrition");
request.setTitle("Some title");
// in order for this if to run, you must use the android 3.2 to compile your app
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
    request.allowScanningByMediaScanner();
    request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
}
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, "name-of-the-file.ext");

// get download service and enqueue file
DownloadManager manager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
manager.enqueue(request);

알림 표시 줄에 다운로드 진행률이 표시됩니다.

마지막 생각들

첫 번째와 두 번째 방법은 빙산의 일각에 불과합니다. 앱을 강력하게 만들려면 염두에 두어야 할 사항이 많이 있습니다. 다음은 간단한 목록입니다.

  • 사용자가 인터넷에 연결되어 있는지 확인해야합니다.
  • 올바른 권한 ( INTERNETWRITE_EXTERNAL_STORAGE) 이 있는지 확인하십시오 . ACCESS_NETWORK_STATE인터넷 가용성을 확인하려는 경우 에도 마찬가지 입니다.
  • 파일을 다운로드하려는 디렉토리가 존재하고 쓰기 권한이 있는지 확인하십시오.
  • 다운로드가 너무 크면 이전 시도가 실패한 경우 다운로드를 재개하는 방법을 구현할 수 있습니다.
  • 사용자가 다운로드를 중단하도록 허용하면 감사 할 것입니다.

다운로드 프로세스에 대한 자세한 제어가 필요하지 않은 경우 DownloadManager위에 나열된 대부분의 항목을 이미 처리하므로 (3) 사용을 고려 하십시오.

그러나 또한 귀하의 요구 사항이 변경 될 수 있음을 고려하십시오. 예를 들어, DownloadManager 응답 캐싱이 없습니다 . 맹목적으로 동일한 큰 파일을 여러 번 다운로드합니다. 사실 후에는 쉽게 고칠 수있는 방법이 없습니다. 기본 HttpURLConnection(1, 2)으로 시작하는 경우 필요한 것은 HttpResponseCache. 따라서 기본 표준 도구를 배우는 초기 노력은 좋은 투자가 될 수 있습니다.

이 클래스는 API 레벨 26에서 더 이상 사용되지 않습니다. ProgressDialog는 사용자가 앱과 상호 작용하지 못하도록하는 모달 대화 상자입니다. 이 클래스를 사용하는 대신 앱의 UI에 포함 할 수있는 ProgressBar와 같은 진행률 표시기를 사용해야합니다. 또는 알림을 사용하여 작업 진행 상황을 사용자에게 알릴 수 있습니다. 자세한 내용은 링크


인터넷에서 항목을 다운로드하려면 매니페스트 파일에 권한을 추가하는 것을 잊지 마십시오!

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.helloandroid"
    android:versionCode="1"
    android:versionName="1.0">

        <uses-sdk android:minSdkVersion="10" />

        <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
        <uses-permission android:name="android.permission.INTERNET"></uses-permission>
        <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"></uses-permission>
        <uses-permission android:name="android.permission.READ_PHONE_STATE"></uses-permission>

        <application 
            android:icon="@drawable/icon" 
            android:label="@string/app_name" 
            android:debuggable="true">

        </application>

</manifest>

예, 위의 코드는 작동합니다. 그러나 progressbarin onProgressUpdate업데이트 Asynctask하고 뒤로 버튼을 누르거나 활동을 완료 AsyncTask하면 UI로 트랙이 느슨해집니다. 그리고 활동으로 돌아 가면 다운로드가 백그라운드에서 실행 중이더라도 다음이 표시됩니다. 진행률 표시 줄에 업데이트가 없습니다. 따라서 실행중인 백그라운드 에서 업데이트 된 값으로 ur를 업데이트하는 타이머 작업 OnResume()과 같은 스레드를 실행 해보십시오 .runOnUIThreadprogressbarAsyncTask

private void updateProgressBar(){
    Runnable runnable = new updateProgress();
    background = new Thread(runnable);
    background.start();
}

public class updateProgress implements Runnable {
    public void run() {
        while(Thread.currentThread()==background)
            //while (!Thread.currentThread().isInterrupted()) {
            try {
                Thread.sleep(1000); 
                Message msg = new Message();
                progress = getProgressPercentage();        
                handler.sendMessage(msg);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            } catch (Exception e) {
        }
    }
}

private Handler handler = new Handler(){
    @Override
    public void handleMessage(Message msg) {
        progress.setProgress(msg.what);
    }
};

ur 활동이 보이지 않을 때 스레드 삭제 하는 것을 잊지 마십시오 .

private void destroyRunningThreads() {
    if (background != null) {
        background.interrupt();
        background=null;
    }
}

내 Project Netroid 를 사용하는 것이 좋습니다 . Volley 기반입니다 . 다중 이벤트 콜백, 파일 다운로드 관리와 같은 몇 가지 기능을 추가했습니다. 이것은 도움이 될 수 있습니다.


동일한 컨텍스트에서 AsyncTask생성을 처리 하도록 클래스를 수정했습니다 progressDialog. 다음 코드가 더 재사용 가능할 것이라고 생각합니다. (모든 활동에서 호출 할 수 있습니다. 컨텍스트, 대상 파일, 대화 상자 메시지를 전달하면됩니다.)

public static class DownloadTask extends AsyncTask<String, Integer, String> {
    private ProgressDialog mPDialog;
    private Context mContext;
    private PowerManager.WakeLock mWakeLock;
    private File mTargetFile;
    //Constructor parameters :
    // @context (current Activity)
    // @targetFile (File object to write,it will be overwritten if exist)
    // @dialogMessage (message of the ProgresDialog)
    public DownloadTask(Context context,File targetFile,String dialogMessage) {
        this.mContext = context;
        this.mTargetFile = targetFile;
        mPDialog = new ProgressDialog(context);

        mPDialog.setMessage(dialogMessage);
        mPDialog.setIndeterminate(true);
        mPDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
        mPDialog.setCancelable(true);
        // reference to instance to use inside listener
        final DownloadTask me = this;
        mPDialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
            @Override
            public void onCancel(DialogInterface dialog) {
                me.cancel(true);
            }
        });
        Log.i("DownloadTask","Constructor done");
    }

    @Override
    protected String doInBackground(String... sUrl) {
        InputStream input = null;
        OutputStream output = null;
        HttpURLConnection connection = null;
        try {
            URL url = new URL(sUrl[0]);
            connection = (HttpURLConnection) url.openConnection();
            connection.connect();

            // expect HTTP 200 OK, so we don't mistakenly save error report
            // instead of the file
            if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) {
                return "Server returned HTTP " + connection.getResponseCode()
                        + " " + connection.getResponseMessage();
            }
            Log.i("DownloadTask","Response " + connection.getResponseCode());

            // this will be useful to display download percentage
            // might be -1: server did not report the length
            int fileLength = connection.getContentLength();

            // download the file
            input = connection.getInputStream();
            output = new FileOutputStream(mTargetFile,false);

            byte data[] = new byte[4096];
            long total = 0;
            int count;
            while ((count = input.read(data)) != -1) {
                // allow canceling with back button
                if (isCancelled()) {
                    Log.i("DownloadTask","Cancelled");
                    input.close();
                    return null;
                }
                total += count;
                // publishing the progress....
                if (fileLength > 0) // only if total length is known
                    publishProgress((int) (total * 100 / fileLength));
                output.write(data, 0, count);
            }
        } catch (Exception e) {
            return e.toString();
        } finally {
            try {
                if (output != null)
                    output.close();
                if (input != null)
                    input.close();
            } catch (IOException ignored) {
            }

            if (connection != null)
                connection.disconnect();
        }
        return null;
    }
    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        // take CPU lock to prevent CPU from going off if the user
        // presses the power button during download
        PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
        mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
                getClass().getName());
        mWakeLock.acquire();

        mPDialog.show();

    }

    @Override
    protected void onProgressUpdate(Integer... progress) {
        super.onProgressUpdate(progress);
        // if we get here, length is known, now set indeterminate to false
        mPDialog.setIndeterminate(false);
        mPDialog.setMax(100);
        mPDialog.setProgress(progress[0]);

    }

    @Override
    protected void onPostExecute(String result) {
        Log.i("DownloadTask", "Work Done! PostExecute");
        mWakeLock.release();
        mPDialog.dismiss();
        if (result != null)
            Toast.makeText(mContext,"Download error: "+result, Toast.LENGTH_LONG).show();
        else
            Toast.makeText(mContext,"File Downloaded", Toast.LENGTH_SHORT).show();
    }
}

"/ sdcard ..."를 새 파일 ( "/ mnt / sdcard / ...") 로 바꾸는 것을 잊지 마십시오. 그렇지 않으면 FileNotFoundException이 발생합니다.


내가 찾은 블로그 게시물은 매우 유용, 다운로드 파일에 그것의 사용 loopJ, 그것은 단지 하나의 간단한 기능을 가지고, 새로운 안드로이드 사람에게 도움이 될 것입니다.


안드로이드 개발을 배우기 시작하면서 그것이 ProgressDialog가는 길임을 배웠습니다 . setProgress의 방법 ProgressDialog파일이 다운로드됩니다으로 진행 수준을 업데이트하기 위해 호출 할 수있는가.

많은 앱에서 내가 본 가장 좋은 점은이 진행률 대화 상자의 속성을 사용자 지정하여 기본 버전보다 진행률 대화 상자에 더 나은 모양과 느낌을 제공한다는 것입니다. 사용자가 개구리, 코끼리 또는 귀여운 고양이 / 강아지와 같은 애니메이션에 계속 참여하도록하는 데 좋습니다. 진행률 대화 상자에있는 모든 애니메이션은 사용자를 끌어 들이고 오래 기다리지 않는 것 같습니다.


내 개인적인 조언은 진행률 대화 상자 를 사용 하고 실행하기 전에 빌드하거나 OnPreExecute()진행률 대화 상자의 수평 스타일 진행률 표시 줄을 사용하는 경우 진행률을 자주 게시하는 것입니다. 나머지 부분은의 알고리즘을 최적화하는 것입니다 doInBackground.


Android Query 라이브러리를 사용하면 매우 멋집니다 ProgressDialog. 다른 예제에서 볼 수 있듯이 사용하도록 변경할 수 있습니다.이 라이브러리 는 레이아웃에서 진행률보기를 표시하고 완료 후에는 숨 깁니다.

File target = new File(new File(Environment.getExternalStorageDirectory(), "ApplicationName"), "tmp.pdf");
new AQuery(this).progress(R.id.progress_view).download(_competition.qualificationScoreCardsPdf(), target, new AjaxCallback<File>() {
    public void callback(String url, File file, AjaxStatus status) {
        if (file != null) {
            // do something with file  
        } 
    }
});

권한

  <uses-permission android:name="android.permission.INTERNET" />
  <uses-permission 
   android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

HttpURLConnection 사용

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;

import android.app.Activity;
import android.app.Dialog;
import android.os.Bundle;
import android.os.Environment;
import android.view.View;
import android.view.Window;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;

public class DownloadFileUseHttpURLConnection extends Activity {

ProgressBar pb;
Dialog dialog;
int downloadedSize = 0;
int totalSize = 0;
TextView cur_val;
String dwnload_file_path =  
"http://coderzheaven.com/sample_folder/sample_file.png";
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    Button b = (Button) findViewById(R.id.b1);
    b.setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View v) {
             showProgress(dwnload_file_path);

                new Thread(new Runnable() {
                    public void run() {
                         downloadFile();
                    }
                  }).start();
        }
    });
}

void downloadFile(){

    try {
        URL url = new URL(dwnload_file_path);
        HttpURLConnection urlConnection = (HttpURLConnection)   
 url.openConnection();

        urlConnection.setRequestMethod("GET");
        urlConnection.setDoOutput(true);

        //connect
        urlConnection.connect();

        //set the path where we want to save the file           
        File SDCardRoot = Environment.getExternalStorageDirectory(); 
        //create a new file, to save the downloaded file 
        File file = new File(SDCardRoot,"downloaded_file.png");

        FileOutputStream fileOutput = new FileOutputStream(file);

        //Stream used for reading the data from the internet
        InputStream inputStream = urlConnection.getInputStream();

        //this is the total size of the file which we are downloading
        totalSize = urlConnection.getContentLength();

        runOnUiThread(new Runnable() {
            public void run() {
                pb.setMax(totalSize);
            }               
        });

        //create a buffer...
        byte[] buffer = new byte[1024];
        int bufferLength = 0;

        while ( (bufferLength = inputStream.read(buffer)) > 0 ) {
            fileOutput.write(buffer, 0, bufferLength);
            downloadedSize += bufferLength;
            // update the progressbar //
            runOnUiThread(new Runnable() {
                public void run() {
                    pb.setProgress(downloadedSize);
                    float per = ((float)downloadedSize/totalSize) *     
                    100;
                    cur_val.setText("Downloaded " + downloadedSize +  

                    "KB / " + totalSize + "KB (" + (int)per + "%)" );
                }
            });
        }
        //close the output stream when complete //
        fileOutput.close();
        runOnUiThread(new Runnable() {
            public void run() {
                // pb.dismiss(); // if you want close it..
            }
        });         

    } catch (final MalformedURLException e) {
        showError("Error : MalformedURLException " + e);        
        e.printStackTrace();
    } catch (final IOException e) {
        showError("Error : IOException " + e);          
        e.printStackTrace();
    }
    catch (final Exception e) {
        showError("Error : Please check your internet connection " +  
e);
    }       
}

void showError(final String err){
    runOnUiThread(new Runnable() {
        public void run() {
            Toast.makeText(DownloadFileDemo1.this, err,  
      Toast.LENGTH_LONG).show();
        }
    });
}

void showProgress(String file_path){
    dialog = new Dialog(DownloadFileDemo1.this);
    dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
    dialog.setContentView(R.layout.myprogressdialog);
    dialog.setTitle("Download Progress");

    TextView text = (TextView) dialog.findViewById(R.id.tv1);
    text.setText("Downloading file from ... " + file_path);
    cur_val = (TextView) dialog.findViewById(R.id.cur_pg_tv);
    cur_val.setText("Starting download...");
    dialog.show();

     pb = (ProgressBar)dialog.findViewById(R.id.progress_bar);
     pb.setProgress(0);
            pb.setProgressDrawable(
      getResources().getDrawable(R.drawable.green_progress));  
  }
}

Android 쿼리가 너무 커서 건강을 유지하기 위해 유지 관리되지 않기 때문에 현재 사용중인 다른 솔루션에 대한 또 다른 답변을 추가하고 있습니다. 그래서 나는 https://github.com/amitshekhariitbhu/Fast-Android-Networking 으로 옮겼습니다 .

    AndroidNetworking.download(url,dirPath,fileName).build()
      .setDownloadProgressListener(new DownloadProgressListener() {
        public void onProgress(long bytesDownloaded, long totalBytes) {
            bar.setMax((int) totalBytes);
            bar.setProgress((int) bytesDownloaded);
        }
    }).startDownload(new DownloadListener() {
        public void onDownloadComplete() {
            ...
        }

        public void onError(ANError error) {
            ...
        }
    });

참고 URL : https://stackoverflow.com/questions/3028306/download-a-file-with-android-and-showing-the-progress-in-a-progressdialog

반응형