我正在使用以下代码使用Retrofit下载文件并显示进度。但是在下载了几个百分比,即20%,50%等之后,它会通过提供以下致命异常来停止。可能是什么问题以及如何解决这个问题?
错误:
E/JavaBinder: !!! FAILED BINDER TRANSACTION !!! (parcel size = 2844)
--------- beginning of crash
E/AndroidRuntime: FATAL EXCEPTION: Timer-363
Process: com.solutionz.mp3.songs.cloud, PID: 9093
DeadSystemException: The system died; earlier logs will point to the root cause
E/JavaBinder: !!! FAILED BINDER TRANSACTION !!! (parcel size = 2844)
E/JavaBinder: !!! FAILED BINDER TRANSACTION !!! (parcel size = 2844)
E/JavaBinder: !!! FAILED BINDER TRANSACTION !!! (parcel size = 2844)
E/JavaBinder: !!! FAILED BINDER TRANSACTION !!! (parcel size = 2844)
E/JavaBinder: !!! FAILED BINDER TRANSACTION !!! (parcel size = 2844)
E/JavaBinder: !!! FAILED BINDER TRANSACTION !!! (parcel size = 2844)
E/JavaBinder: !!! FAILED BINDER TRANSACTION !!! (parcel size = 2844)
E/JavaBinder: !!! FAILED BINDER TRANSACTION !!! (parcel size = 2844)
E/JavaBinder: !!! FAILED BINDER TRANSACTION !!! (parcel size = 2844)
E/JavaBinder: !!! FAILED BINDER TRANSACTION !!! (parcel size = 2844)
E/JavaBinder: !!! FAILED BINDER TRANSACTION !!! (parcel size = 2844)
E/JavaBinder: !!! FAILED BINDER TRANSACTION !!! (parcel size = 2844)
E/JavaBinder: !!! FAILED BINDER TRANSACTION !!! (parcel size = 2844)
E/JavaBinder: !!! FAILED BINDER TRANSACTION !!! (parcel size = 2844)
E/JavaBinder: !!! FAILED BINDER TRANSACTION !!! (parcel size = 2844)
E/JavaBinder: !!! FAILED BINDER TRANSACTION !!! (parcel size = 2844)
W/art: Suspending all threads took: 66.167ms
E/JavaBinder: !!! FAILED BINDER TRANSACTION !!! (parcel size = 2844)
E/JavaBinder: !!! FAILED BINDER TRANSACTION !!! (parcel size = 2844)
D/DownloadFile: Progress: 3710576/5061039 >>>> 0.73316485
D/DownloadFile: Progress: 3712624/5061039 >>>> 0.7335695
D/DownloadFile: Progress: 3714672/5061039 >>>> 0.7339742
代码:
import android.content.Context;
import android.os.AsyncTask;
import android.util.Log;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Response;
import okhttp3.ResponseBody;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
import retrofit2.http.GET;
import retrofit2.http.Streaming;
import retrofit2.http.Url;
public class DownloadFileWithProgress {
private static final String TAG = "DownloadFile";
private String BASE_URL;
private String fileName, fileTitle;
private Context context;
private ProgressNotification mNotification;
private int notificationId;
private ProgressResponseBody.ProgressListener progressListener = new ProgressResponseBody.ProgressListener() {
@Override
public void update(long bytesRead, long contentLength, boolean done) {
System.out.println(bytesRead);
System.out.println(contentLength);
System.out.println(done);
int percentage = (int) ((100 * bytesRead) / contentLength);
System.out.format("%d%% done\n", percentage);
if (!done) {
mNotification.progressUpdate(percentage, contentLength, (int) bytesRead, "");
mNotification.updateNotification(notificationId);
} else {
// mNotification.setCompletion();
mNotification.getTimer().cancel();
mNotification.completed(notificationId);
}
AppGlobal.Log("usm_notificationId", "id= " + notificationId);
}
@Override
public void onError(String error) {
AppGlobal.Log("usm_error", "error= " + error);
mNotification.getTimer().cancel();
mNotification.completed(notificationId);
}
};
public DownloadFileWithProgress(Context context, String title, String fileUrl) {
this.context = context;
String[] fileStr = fileUrl.split("/");
this.BASE_URL = fileUrl.substring(0, fileUrl.lastIndexOf("/")) + "/";
this.fileName = fileStr[fileStr.length - 1];
this.fileTitle = title;
this.mNotification = new ProgressNotification(context);
}
public void run() {
OkHttpClient.Builder httpClient = new OkHttpClient.Builder()
.addNetworkInterceptor(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
try {
Response originalResponse = chain.proceed(chain.request());
return originalResponse.newBuilder()
.body(new ProgressResponseBody(originalResponse.body(), progressListener))
.build();
} catch (Exception e) {
e.printStackTrace();
progressListener.onError(e.getCause() + ": " + e.getMessage());
}
return chain.proceed(chain.request());
}
});
Retrofit.Builder builder = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create());
Retrofit retrofit = builder.client(httpClient.build()).build();
RetrofitInterface downloadService = retrofit.create(RetrofitInterface.class);
Call<ResponseBody> call = downloadService.downloadFileByUrl(fileName);
this.notificationId = this.mNotification.createNotification(fileTitle, "Downloading...");
call.enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(Call<ResponseBody> call, final retrofit2.Response<ResponseBody> response) {
if (response.isSuccessful()) {
Log.d(TAG, "Got the body for the file");
new AsyncTask<Void, Long, Void>() {
@Override
protected Void doInBackground(Void... voids) {
saveToDisk(response.body());
return null;
}
}.execute();
} else {
Log.d(TAG, "Connection failed " + response.errorBody());
}
}
@Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
t.printStackTrace();
Log.e(TAG, t.getMessage());
}
});
}
private void saveToDisk(ResponseBody body) {
try {
File mydir = new File(AppGlobal.DIRECTORY_PATH);
if (!mydir.exists())
mydir.mkdir();
File destinationFile = new File(AppGlobal.DIRECTORY_PATH + "/" + fileName);
InputStream is = null;
OutputStream os = null;
try {
Log.d(TAG, "File Size=" + body.contentLength());
is = body.byteStream();
os = new FileOutputStream(destinationFile);
byte data[] = new byte[4096];
int count;
int progress = 0;
while ((count = is.read(data)) != -1) {
os.write(data, 0, count);
progress += count;
Log.d(TAG, "Progress: " + progress + "/" + body.contentLength() + " >>>> " + (float) progress / body.contentLength());
}
os.flush();
Log.d(TAG, "File saved successfully!");
return;
} catch (IOException e) {
e.printStackTrace();
Log.d(TAG, "Failed to save the file!");
return;
} finally {
if (is != null) is.close();
if (os != null) os.close();
}
} catch (IOException e) {
e.printStackTrace();
Log.d(TAG, "Failed to save the file!");
return;
}
}
public interface RetrofitInterface {
@Streaming
@GET
Call<ResponseBody> downloadFileByUrl(@Url String fileUrl);
}
}
ProgressResponseBody:
import java.io.IOException;
import okhttp3.MediaType;
import okhttp3.ResponseBody;
import okio.Buffer;
import okio.BufferedSource;
import okio.ForwardingSource;
import okio.Okio;
import okio.Source;
public class ProgressResponseBody extends ResponseBody {
private final ResponseBody responseBody;
private final ProgressListener progressListener;
private BufferedSource bufferedSource;
public ProgressResponseBody(ResponseBody responseBody, ProgressListener progressListener) {
this.responseBody = responseBody;
this.progressListener = progressListener;
}
@Override
public MediaType contentType() {
//return MediaType.parse("image/*");
return responseBody.contentType();
}
@Override
public long contentLength() {
return responseBody.contentLength();
}
@Override
public BufferedSource source() {
if (bufferedSource == null) {
bufferedSource = Okio.buffer(source(responseBody.source()));
}
return bufferedSource;
}
private Source source(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);
// read() returns the number of bytes read, or -1 if this source is exhausted.
totalBytesRead += bytesRead != -1 ? bytesRead : 0;
progressListener.update(totalBytesRead, responseBody.contentLength(), bytesRead == -1);
return bytesRead;
}
};
}
public interface ProgressListener {
void update(long bytesRead, long contentLength, boolean done);
void onError(String error);
}
}