您好,登錄后才能下訂單哦!
OkHttp是比較火的網絡框架,它支持同步與異步請求,支持緩存,可以攔截,更方便下載大文件與上傳文件的操作。下面我們用OkHttp來下載文件并帶進度條!
相關資料:
官網地址:http://square.github.io/okhttp/
github源碼地址:https://github.com/square/okhttp
一、服務器端簡單搭建
可以參考搭建本地Tomcat服務器及相關配置 這篇文章。
新建項目OkHttpServer,在WebContent目錄下新建downloadfile目錄,將要下載的jpg文件放在項目下。如下圖:
啟動服務器,文件下載地址為http://localhost:8080/OkHttpServer/download/2.jpg 。這樣我們服務器就搭好了。
二、Android端
下面我們進入正題。
1.build.gradle的dependencies配置如下
compile 'com.android.support:appcompat-v7:24.1.1' compile 'com.squareup.okhttp3:okhttp:3.2.0' compile 'com.squareup.okio:okio:1.7.0'
2.activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <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.huang.myokhttp.MainActivity"> <Button android:id="@+id/ok_download" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="下載文件" /> <TextView android:id="@+id/download_text" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center" android:text="0" /> <ProgressBar android:id="@+id/download_progress" android:layout_width="match_parent" android:layout_height="wrap_content" android:max="100" /> </RelativeLayout>
3.編寫OkHttpUtil如下:
private static OkHttpClient okHttpClient = new OkHttpClient.Builder().connectTimeout(10000, TimeUnit.MILLISECONDS) .readTimeout(10000,TimeUnit.MILLISECONDS) .writeTimeout(10000,TimeUnit.MILLISECONDS).build(); //下載文件方法 public static void downloadFile(String url, final ProgressListener listener, Callback callback){ //增加攔截器 OkHttpClient client = okHttpClient.newBuilder().addNetworkInterceptor(new Interceptor() { @Override public Response intercept(Chain chain) throws IOException { Response response = chain.proceed(chain.request()); return response.newBuilder().body(new ProgressResponseBody(response.body(),listener)).build(); } }).build(); Request request = new Request.Builder().url(url).build(); client.newCall(request).enqueue(callback); }
4.上面代碼中的ProgressResponseBody是自己編寫的類,ProgressListener 是監聽的接口:
ProgressListener 接口
public interface ProgressListener { //已完成的 總的文件長度 是否完成 void onProgress(long currentBytes, long contentLength, boolean done); }
ProgressResponseBody繼承ResponseBody ,返回監聽進度
public class ProgressResponseBody extends ResponseBody { public static final int UPDATE = 0x01; public static final String TAG = ProgressResponseBody.class.getName(); private ResponseBody responseBody; private ProgressListener mListener; private BufferedSource bufferedSource; private Handler myHandler; public ProgressResponseBody(ResponseBody body, ProgressListener listener) { responseBody = body; mListener = listener; if (myHandler==null){ myHandler = new MyHandler(); } } /** * 將進度放到主線程中顯示 */ class MyHandler extends Handler { public MyHandler() { super(Looper.getMainLooper()); } @Override public void handleMessage(Message msg) { switch (msg.what){ case UPDATE: ProgressModel progressModel = (ProgressModel) msg.obj; //接口返回 if (mListener!=null)mListener.onProgress(progressModel.getCurrentBytes(),progressModel.getContentLength(),progressModel.isDone()); break; } } } @Override public MediaType contentType() { return responseBody.contentType(); } @Override public long contentLength() { return responseBody.contentLength(); } @Override public BufferedSource source() { if (bufferedSource==null){ bufferedSource = Okio.buffer(mySource(responseBody.source())); } return bufferedSource; } private Source mySource(Source source) { return new ForwardingSource(source) { long totalBytesRead = 0L; @Override public long read(Buffer sink, long byteCount) throws IOException { long bytesRead = super.read(sink, byteCount); totalBytesRead +=bytesRead!=-1?bytesRead:0; //發送消息到主線程,ProgressModel為自定義實體類 Message msg = Message.obtain(); msg.what = UPDATE; msg.obj = new ProgressModel(totalBytesRead,contentLength(),totalBytesRead==contentLength()); myHandler.sendMessage(msg); return bytesRead; } }; } }
5.MainActivity的代碼:
public class MainActivity extends AppCompatActivity implements View.OnClickListener{ public static final String TAG = MainActivity.class.getName(); private ProgressBar download_progress; private TextView download_text; public static String basePath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/okhttp"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); download_progress = (ProgressBar) findViewById(R.id.download_progress); download_text = (TextView) findViewById(R.id.download_text); findViewById(R.id.ok_download).setOnClickListener(this); } @Override public void onClick(View view) { switch (view.getId()){ case R.id.ok_download: String url = "http://192.168.0.104:8080/OkHttpServer/download/2.jpg"; final String fileName = url.split("/")[url.split("/").length - 1]; Log.i(TAG, "fileName==" + fileName); OkHttpUtil.downloadFile(url, new ProgressListener() { @Override public void onProgress(long currentBytes, long contentLength, boolean done) { Log.i(TAG, "currentBytes==" + currentBytes + "==contentLength==" + contentLength + "==done==" + done); int progress = (int) (currentBytes * 100 / contentLength); download_progress.setProgress(progress); download_text.setText(progress + "%"); } }, new Callback() { @Override public void onFailure(Call call, IOException e) { } @Override public void onResponse(Call call, Response response) throws IOException { if (response != null) { InputStream is = response.body().byteStream(); FileOutputStream fos = new FileOutputStream(new File(basePath + "/" + fileName)); int len = 0; byte[] buffer = new byte[2048]; while (-1 != (len = is.read(buffer))) { fos.write(buffer, 0, len); } fos.flush(); fos.close(); is.close(); } } }); break; } } }
6.最后不要忘了添加權限:
<uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
源碼下載
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持億速云。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。