"Volley is not suitable for large download or streaming operations, since Volley holds all responses in memory during parsing. For large download operations, consider using an alternative like DownloadManager."
這是真的,特別是內存小的手機,使用Volley下載很多文件或者單個大文件就不是很恰當了。這裡的large是相對手機內存大小而定。
首先準備一個帶Progress Bar的layout
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/download"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<LinearLayout
android:id="@+id/download"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="32dp"
android:layout_marginEnd="32dp"
android:background="@drawable/rounded_edge"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintCircleRadius="5dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<ProgressBar
android:id="@+id/progressBar"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="80dp"
android:layout_height="80dp"
android:layout_gravity="center"
android:layout_marginTop="16dp"
android:background="@drawable/ic_download"
android:progressDrawable="@drawable/circular_progress_bar" />
<TextView
android:id="@+id/textView3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="16dp"
android:gravity="center"
android:text="@string/download_desc"
android:textColor="#fff" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="4dp"
android:orientation="horizontal">
<Button
android:id="@+id/dialog_button_agree"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_weight="1"
android:background="@android:color/transparent"
android:drawableStart="@drawable/ic_agree"
android:text="@string/agree"
android:textAlignment="viewStart"
android:textColor="#F4E829" />
<View
android:layout_width="1px"
android:layout_height="match_parent"
android:layout_marginHorizontal="16dp"
android:background="@android:color/darker_gray" />
<Button
android:id="@+id/dialog_button_back"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
android:layout_weight="1"
android:background="@android:color/transparent"
android:drawableStart="@drawable/ic_disagress"
android:text="@string/back"
android:textAlignment="viewStart"
android:textColor="#F4E829" />
</LinearLayout>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
準備一下進度條。
<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:fromDegrees="270"
android:toDegrees="270">
<shape
android:innerRadiusRatio="2.44"
android:shape="ring"
android:thickness="2dp"
android:useLevel="true">
<gradient
android:angle="0"
android:endColor="#FFF000"
android:startColor="#FFF000"
android:type="sweep"
android:useLevel="false" />
</shape>
</rotate>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="80dp"
android:height="80dp"
android:viewportWidth="80"
android:viewportHeight="80">
<path
android:fillColor="#686868"
android:pathData="M40,7.5163C48.6699,7.5163 56.8366,10.902 62.9673,17.0327C69.098,23.1634 72.4837,31.3301 72.4837,40C72.4837,48.6699 69.098,56.8366 62.9673,62.9673C56.8366,69.098 48.6699,72.4837 40,72.4837C31.3301,72.4837 23.1634,69.098 17.0327,62.9673C10.902,56.8366 7.5163,48.6699 7.5163,40C7.5163,31.3301 10.902,23.1634 17.0327,17.0327C23.1634,10.902 31.3301,7.5163 40,7.5163ZM40,5C20.6699,5 5,20.6699 5,40C5,59.3301 20.6699,75 40,75C59.3301,75 75,59.3301 75,40C75,20.6699 59.3301,5 40,5Z" />
<path
android:fillColor="#FFF000"
android:pathData="M41.0378,49.9393L56.2402,34.4966L54.0244,32.3541L41.5146,45.0422V20H38.4293V45.0422L25.9195,32.3541L23.7037,34.4966L38.9061,49.9393H17V53H63V49.9393H41.0378ZM40.0281,46.6003H39.9719H40.0281Z" />
</vector>
封裝一下 Volley。
package com.szeching.volleyexample;
import androidx.annotation.Nullable;
import com.android.volley.NetworkResponse;
import com.android.volley.Request;
import com.android.volley.Response;
import com.android.volley.toolbox.HttpHeaderParser;
import java.util.Map;
public class DownloadRequest extends Request<byte[]> {
private final Response.Listener<byte[]> mListener;
public Map<String, String> responseHeaders;
public DownloadRequest(int method, String url, Response.Listener<byte[]> listener, @Nullable Response.ErrorListener errorListener) {
super(method, url, errorListener);
setShouldCache(false);
this.mListener = listener;
}
@Override
protected Response<byte[]> parseNetworkResponse(NetworkResponse response) {
responseHeaders = response.headers;
return Response.success(response.data, HttpHeaderParser.parseCacheHeaders(response));
}
@Override
protected void deliverResponse(byte[] response) {
mListener.onResponse(response);
}
}
在Activity中發起請求並設置進度條進度。
package com.szeching.volleyexample;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.widget.ProgressBar;
import androidx.appcompat.app.AppCompatActivity;
import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.HurlStack;
import com.android.volley.toolbox.Volley;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.download);
}
private void requestSource() {
request = new DownloadRequest(Request.Method.GET, "https://example.com/example.mp4", new Response.Listener<byte[]>() {
@Override
public void onResponse(byte[] response) {
HashMap<String, Object> map = new HashMap<String, Object>();
try {
if (response != null) {
long file_length = response.length;
InputStream input = new ByteArrayInputStream(response);
File path = getApplicationContext().getExternalFilesDir(Environment.DIRECTORY_MOVIES);
File file = new File(path, "filename.mp4");
map.put("resume_path", file.toString());
BufferedOutputStream output = new BufferedOutputStream(new FileOutputStream(file));
byte[] data = new byte[1024];
long total = 0;
while ((count = input.read(data)) != -1) {
total += count;
output.write(data, 0, count);
int progress = (int) ((int) total * 100 / file_length);
Log.d("onProgress",""+progress);
progressBar.setProgress(progress);
}
output.flush();
output.close();
input.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
error.printStackTrace();
}
});
RequestQueue mRequestQueue = Volley.newRequestQueue(getApplicationContext(), new HurlStack());
mRequestQueue.add(request);
}
}