Why is my progress listener update callback not getting called in the OKHttp interceptor?












0















I've built a stripped down Android app to upload files to Amazon S3 using signed URLs. These URLs require a PUT call, which is slightly different than most file uploads which happen over POST.



I just paste in the S3 URL into the textview. I've verified the S3 URL works with this cURL command, so all is well with it.



curl -X PUT 'https://mybucket.s3.us-west-2.amazonaws.com/uploads/android/somevideo.mp4?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credentia...0&X-Amz-Signature=213123123&X-Amz-SignedHeaders=host' --upload-file ~/Downloads/video.mp4



The file upload completes correctly inside the Android app, but I never get into my update callback, so I cannot update the progress bar in the dialog.



Is there something different happening because I am doing a PUT request, and this is not a multipart form upload (I'm just sending the file as the body as an octet stream)?



My Activity code and the inner Progress class are all in one file below. When I set a breakpoint on line 126 (the update function), I never enter it. I used the sample Progress listener linked here, but for some reason my code never is called.



package com.example.putuploadwithprogress;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;

import java.io.File;
import java.io.IOException;

import okhttp3.Interceptor;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.ResponseBody;
import okio.Buffer;
import okio.BufferedSource;
import okio.ForwardingSource;
import okio.Okio;
import okio.Source;

public class MainActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

final TextView uploadUrl = findViewById(R.id.uploadUrl);
Button uploadButton = findViewById(R.id.uploadButton);

uploadButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {

AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
View layout = getLayoutInflater().inflate(R.layout.upload_progress, null);
final ProgressBar progress = layout.findViewById(R.id.uploadProgressBar);
builder.setView(layout);
builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
dialogInterface.dismiss();
}
});
final AlertDialog dialog = builder.show();

final String url = uploadUrl.getText().toString().trim();

try {
new Thread(new Runnable() {
@Override
public void run() {
String mimeType = "video/mp4";
String filename = Environment
.getExternalStoragePublicDirectory(Environment
.DIRECTORY_DOWNLOADS).toString() + "/video.mp4";
File file = new File(filename);
try {

new Progress(url, file, mimeType, MainActivity.this, progress, dialog).run();
MainActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
dialog.hide();
}
});

} catch (Exception e) {
System.out.println( "Got an error: " + e.getMessage());
MainActivity.this.runOnUiThread(new Runnable() { @Override public void run() { dialog.hide(); } });
}
}
}).start();
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
}

class Progress {

private String mime;
ProgressBar progressBar;
AlertDialog dialog;
Activity activity;
private String url;
private File file;

Progress(String _url,
File _file,
String _mime,
Activity _activity,
ProgressBar _progressBar,
AlertDialog _dialog) {
url = _url;
file = _file;
mime = _mime;
dialog = _dialog;
progressBar = _progressBar;
activity = _activity;
}

public void run() {

final Request request = new Request.Builder()
.header("Content-Type", mime)
.url(url)
.put(RequestBody.create(MediaType.parse(mime), file))
.build();

final ProgressListener progressListener = new ProgressListener() {
@Override
public void update(long bytesRead, long contentLength, boolean done) {
if (done) {
if (dialog != null)
activity.runOnUiThread(new Runnable() {
public void run() {
dialog.hide();
}
});
} else {
if (contentLength > 0) {
final int progress = (int) (((double) bytesRead / contentLength) * 100);
if (progressBar != null)
activity.runOnUiThread(new Runnable() {
public void run() {
progressBar.setProgress(progress);
}
});
}
}
}
};

OkHttpClient client = new OkHttpClient.Builder()
.addNetworkInterceptor(new Interceptor() {
@Override public Response intercept(Chain chain) throws IOException {
Response originalResponse = chain.proceed(chain.request());
return originalResponse.newBuilder()
.body(new ProgressResponseBody(originalResponse.body(), progressListener))
.build();
}
})
.build();

try (Response response = client.newCall(request).execute()) {
activity.runOnUiThread(
new Runnable() {
@Override
public void run() {
if (!response.isSuccessful()) {
String message = response.message();
Toast.makeText(activity, "Unable to upload file: " + message, Toast.LENGTH_LONG).show();
} else {
Toast.makeText(activity, "Uploaded file successfully", Toast.LENGTH_LONG).show();
}
dialog.hide();
}
});
} catch (IOException e) {
e.printStackTrace();
}
}

interface ProgressListener {
void update(long bytesRead, long contentLength, boolean done);
}

private static class ProgressResponseBody extends ResponseBody {

private final ResponseBody responseBody;
private final ProgressListener progressListener;
private BufferedSource bufferedSource;

ProgressResponseBody(ResponseBody responseBody, ProgressListener progressListener) {
this.responseBody = responseBody;
this.progressListener = progressListener;
}

@Override
public MediaType contentType() {
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;
}
};
}
}

}


I've got two views. First, the main_activity.xml:



<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">

<Button
android:id="@+id/uploadButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Upload File"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />

<EditText
android:id="@+id/uploadUrl"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="8dp"
android:ems="10"
android:hint="S3 URL, paste in here"
android:inputType="textMultiLine|textNoSuggestions"
app:layout_constraintBottom_toTopOf="@+id/uploadButton"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

</android.support.constraint.ConstraintLayout>


upload_progress.xml:



<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="20dp">

<ProgressBar
android:id="@+id/uploadProgressBar"
style="@style/Widget.AppCompat.ProgressBar.Horizontal"
android:layout_width="0dp"
android:layout_height="30dp"
android:layout_marginStart="8dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="8dp"
android:max="100"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView"
tools:progress="45" />

<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="10dp"
android:text="Uploading file..."
android:textAppearance="@style/TextAppearance.AppCompat.Headline"
app:layout_constraintBottom_toTopOf="@+id/uploadProgressBar"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_chainStyle="spread_inside" />

<TextView
android:id="@+id/uploadStatusMessage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="8dp"
android:text="..."
android:textAppearance="@style/TextAppearance.AppCompat.Light.SearchResult.Title"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/uploadProgressBar" />
</android.support.constraint.ConstraintLayout>


The Android manifest has the correct permissions for internet and I've enabled read permissions in the app permissions.



<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.putuploadwithprogress">

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

<application

android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>

</manifest>









share|improve this question























  • Is function read(Buffer sink, long byteCount) being called for each byte read?

    – NIKHIL MAURYA
    Nov 21 '18 at 9:11













  • @NIKHILMAURYA no, I'm not seeing that hit either

    – xrd
    Nov 21 '18 at 15:36











  • I think you are tracking progress of the response body not the request body. try to use BufferedSink method try this gist.github.com/kyawkyaw/54d9e2feb1c969c90673

    – NIKHIL MAURYA
    Nov 21 '18 at 16:17


















0















I've built a stripped down Android app to upload files to Amazon S3 using signed URLs. These URLs require a PUT call, which is slightly different than most file uploads which happen over POST.



I just paste in the S3 URL into the textview. I've verified the S3 URL works with this cURL command, so all is well with it.



curl -X PUT 'https://mybucket.s3.us-west-2.amazonaws.com/uploads/android/somevideo.mp4?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credentia...0&X-Amz-Signature=213123123&X-Amz-SignedHeaders=host' --upload-file ~/Downloads/video.mp4



The file upload completes correctly inside the Android app, but I never get into my update callback, so I cannot update the progress bar in the dialog.



Is there something different happening because I am doing a PUT request, and this is not a multipart form upload (I'm just sending the file as the body as an octet stream)?



My Activity code and the inner Progress class are all in one file below. When I set a breakpoint on line 126 (the update function), I never enter it. I used the sample Progress listener linked here, but for some reason my code never is called.



package com.example.putuploadwithprogress;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;

import java.io.File;
import java.io.IOException;

import okhttp3.Interceptor;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.ResponseBody;
import okio.Buffer;
import okio.BufferedSource;
import okio.ForwardingSource;
import okio.Okio;
import okio.Source;

public class MainActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

final TextView uploadUrl = findViewById(R.id.uploadUrl);
Button uploadButton = findViewById(R.id.uploadButton);

uploadButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {

AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
View layout = getLayoutInflater().inflate(R.layout.upload_progress, null);
final ProgressBar progress = layout.findViewById(R.id.uploadProgressBar);
builder.setView(layout);
builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
dialogInterface.dismiss();
}
});
final AlertDialog dialog = builder.show();

final String url = uploadUrl.getText().toString().trim();

try {
new Thread(new Runnable() {
@Override
public void run() {
String mimeType = "video/mp4";
String filename = Environment
.getExternalStoragePublicDirectory(Environment
.DIRECTORY_DOWNLOADS).toString() + "/video.mp4";
File file = new File(filename);
try {

new Progress(url, file, mimeType, MainActivity.this, progress, dialog).run();
MainActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
dialog.hide();
}
});

} catch (Exception e) {
System.out.println( "Got an error: " + e.getMessage());
MainActivity.this.runOnUiThread(new Runnable() { @Override public void run() { dialog.hide(); } });
}
}
}).start();
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
}

class Progress {

private String mime;
ProgressBar progressBar;
AlertDialog dialog;
Activity activity;
private String url;
private File file;

Progress(String _url,
File _file,
String _mime,
Activity _activity,
ProgressBar _progressBar,
AlertDialog _dialog) {
url = _url;
file = _file;
mime = _mime;
dialog = _dialog;
progressBar = _progressBar;
activity = _activity;
}

public void run() {

final Request request = new Request.Builder()
.header("Content-Type", mime)
.url(url)
.put(RequestBody.create(MediaType.parse(mime), file))
.build();

final ProgressListener progressListener = new ProgressListener() {
@Override
public void update(long bytesRead, long contentLength, boolean done) {
if (done) {
if (dialog != null)
activity.runOnUiThread(new Runnable() {
public void run() {
dialog.hide();
}
});
} else {
if (contentLength > 0) {
final int progress = (int) (((double) bytesRead / contentLength) * 100);
if (progressBar != null)
activity.runOnUiThread(new Runnable() {
public void run() {
progressBar.setProgress(progress);
}
});
}
}
}
};

OkHttpClient client = new OkHttpClient.Builder()
.addNetworkInterceptor(new Interceptor() {
@Override public Response intercept(Chain chain) throws IOException {
Response originalResponse = chain.proceed(chain.request());
return originalResponse.newBuilder()
.body(new ProgressResponseBody(originalResponse.body(), progressListener))
.build();
}
})
.build();

try (Response response = client.newCall(request).execute()) {
activity.runOnUiThread(
new Runnable() {
@Override
public void run() {
if (!response.isSuccessful()) {
String message = response.message();
Toast.makeText(activity, "Unable to upload file: " + message, Toast.LENGTH_LONG).show();
} else {
Toast.makeText(activity, "Uploaded file successfully", Toast.LENGTH_LONG).show();
}
dialog.hide();
}
});
} catch (IOException e) {
e.printStackTrace();
}
}

interface ProgressListener {
void update(long bytesRead, long contentLength, boolean done);
}

private static class ProgressResponseBody extends ResponseBody {

private final ResponseBody responseBody;
private final ProgressListener progressListener;
private BufferedSource bufferedSource;

ProgressResponseBody(ResponseBody responseBody, ProgressListener progressListener) {
this.responseBody = responseBody;
this.progressListener = progressListener;
}

@Override
public MediaType contentType() {
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;
}
};
}
}

}


I've got two views. First, the main_activity.xml:



<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">

<Button
android:id="@+id/uploadButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Upload File"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />

<EditText
android:id="@+id/uploadUrl"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="8dp"
android:ems="10"
android:hint="S3 URL, paste in here"
android:inputType="textMultiLine|textNoSuggestions"
app:layout_constraintBottom_toTopOf="@+id/uploadButton"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

</android.support.constraint.ConstraintLayout>


upload_progress.xml:



<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="20dp">

<ProgressBar
android:id="@+id/uploadProgressBar"
style="@style/Widget.AppCompat.ProgressBar.Horizontal"
android:layout_width="0dp"
android:layout_height="30dp"
android:layout_marginStart="8dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="8dp"
android:max="100"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView"
tools:progress="45" />

<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="10dp"
android:text="Uploading file..."
android:textAppearance="@style/TextAppearance.AppCompat.Headline"
app:layout_constraintBottom_toTopOf="@+id/uploadProgressBar"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_chainStyle="spread_inside" />

<TextView
android:id="@+id/uploadStatusMessage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="8dp"
android:text="..."
android:textAppearance="@style/TextAppearance.AppCompat.Light.SearchResult.Title"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/uploadProgressBar" />
</android.support.constraint.ConstraintLayout>


The Android manifest has the correct permissions for internet and I've enabled read permissions in the app permissions.



<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.putuploadwithprogress">

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

<application

android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>

</manifest>









share|improve this question























  • Is function read(Buffer sink, long byteCount) being called for each byte read?

    – NIKHIL MAURYA
    Nov 21 '18 at 9:11













  • @NIKHILMAURYA no, I'm not seeing that hit either

    – xrd
    Nov 21 '18 at 15:36











  • I think you are tracking progress of the response body not the request body. try to use BufferedSink method try this gist.github.com/kyawkyaw/54d9e2feb1c969c90673

    – NIKHIL MAURYA
    Nov 21 '18 at 16:17
















0












0








0








I've built a stripped down Android app to upload files to Amazon S3 using signed URLs. These URLs require a PUT call, which is slightly different than most file uploads which happen over POST.



I just paste in the S3 URL into the textview. I've verified the S3 URL works with this cURL command, so all is well with it.



curl -X PUT 'https://mybucket.s3.us-west-2.amazonaws.com/uploads/android/somevideo.mp4?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credentia...0&X-Amz-Signature=213123123&X-Amz-SignedHeaders=host' --upload-file ~/Downloads/video.mp4



The file upload completes correctly inside the Android app, but I never get into my update callback, so I cannot update the progress bar in the dialog.



Is there something different happening because I am doing a PUT request, and this is not a multipart form upload (I'm just sending the file as the body as an octet stream)?



My Activity code and the inner Progress class are all in one file below. When I set a breakpoint on line 126 (the update function), I never enter it. I used the sample Progress listener linked here, but for some reason my code never is called.



package com.example.putuploadwithprogress;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;

import java.io.File;
import java.io.IOException;

import okhttp3.Interceptor;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.ResponseBody;
import okio.Buffer;
import okio.BufferedSource;
import okio.ForwardingSource;
import okio.Okio;
import okio.Source;

public class MainActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

final TextView uploadUrl = findViewById(R.id.uploadUrl);
Button uploadButton = findViewById(R.id.uploadButton);

uploadButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {

AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
View layout = getLayoutInflater().inflate(R.layout.upload_progress, null);
final ProgressBar progress = layout.findViewById(R.id.uploadProgressBar);
builder.setView(layout);
builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
dialogInterface.dismiss();
}
});
final AlertDialog dialog = builder.show();

final String url = uploadUrl.getText().toString().trim();

try {
new Thread(new Runnable() {
@Override
public void run() {
String mimeType = "video/mp4";
String filename = Environment
.getExternalStoragePublicDirectory(Environment
.DIRECTORY_DOWNLOADS).toString() + "/video.mp4";
File file = new File(filename);
try {

new Progress(url, file, mimeType, MainActivity.this, progress, dialog).run();
MainActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
dialog.hide();
}
});

} catch (Exception e) {
System.out.println( "Got an error: " + e.getMessage());
MainActivity.this.runOnUiThread(new Runnable() { @Override public void run() { dialog.hide(); } });
}
}
}).start();
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
}

class Progress {

private String mime;
ProgressBar progressBar;
AlertDialog dialog;
Activity activity;
private String url;
private File file;

Progress(String _url,
File _file,
String _mime,
Activity _activity,
ProgressBar _progressBar,
AlertDialog _dialog) {
url = _url;
file = _file;
mime = _mime;
dialog = _dialog;
progressBar = _progressBar;
activity = _activity;
}

public void run() {

final Request request = new Request.Builder()
.header("Content-Type", mime)
.url(url)
.put(RequestBody.create(MediaType.parse(mime), file))
.build();

final ProgressListener progressListener = new ProgressListener() {
@Override
public void update(long bytesRead, long contentLength, boolean done) {
if (done) {
if (dialog != null)
activity.runOnUiThread(new Runnable() {
public void run() {
dialog.hide();
}
});
} else {
if (contentLength > 0) {
final int progress = (int) (((double) bytesRead / contentLength) * 100);
if (progressBar != null)
activity.runOnUiThread(new Runnable() {
public void run() {
progressBar.setProgress(progress);
}
});
}
}
}
};

OkHttpClient client = new OkHttpClient.Builder()
.addNetworkInterceptor(new Interceptor() {
@Override public Response intercept(Chain chain) throws IOException {
Response originalResponse = chain.proceed(chain.request());
return originalResponse.newBuilder()
.body(new ProgressResponseBody(originalResponse.body(), progressListener))
.build();
}
})
.build();

try (Response response = client.newCall(request).execute()) {
activity.runOnUiThread(
new Runnable() {
@Override
public void run() {
if (!response.isSuccessful()) {
String message = response.message();
Toast.makeText(activity, "Unable to upload file: " + message, Toast.LENGTH_LONG).show();
} else {
Toast.makeText(activity, "Uploaded file successfully", Toast.LENGTH_LONG).show();
}
dialog.hide();
}
});
} catch (IOException e) {
e.printStackTrace();
}
}

interface ProgressListener {
void update(long bytesRead, long contentLength, boolean done);
}

private static class ProgressResponseBody extends ResponseBody {

private final ResponseBody responseBody;
private final ProgressListener progressListener;
private BufferedSource bufferedSource;

ProgressResponseBody(ResponseBody responseBody, ProgressListener progressListener) {
this.responseBody = responseBody;
this.progressListener = progressListener;
}

@Override
public MediaType contentType() {
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;
}
};
}
}

}


I've got two views. First, the main_activity.xml:



<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">

<Button
android:id="@+id/uploadButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Upload File"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />

<EditText
android:id="@+id/uploadUrl"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="8dp"
android:ems="10"
android:hint="S3 URL, paste in here"
android:inputType="textMultiLine|textNoSuggestions"
app:layout_constraintBottom_toTopOf="@+id/uploadButton"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

</android.support.constraint.ConstraintLayout>


upload_progress.xml:



<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="20dp">

<ProgressBar
android:id="@+id/uploadProgressBar"
style="@style/Widget.AppCompat.ProgressBar.Horizontal"
android:layout_width="0dp"
android:layout_height="30dp"
android:layout_marginStart="8dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="8dp"
android:max="100"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView"
tools:progress="45" />

<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="10dp"
android:text="Uploading file..."
android:textAppearance="@style/TextAppearance.AppCompat.Headline"
app:layout_constraintBottom_toTopOf="@+id/uploadProgressBar"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_chainStyle="spread_inside" />

<TextView
android:id="@+id/uploadStatusMessage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="8dp"
android:text="..."
android:textAppearance="@style/TextAppearance.AppCompat.Light.SearchResult.Title"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/uploadProgressBar" />
</android.support.constraint.ConstraintLayout>


The Android manifest has the correct permissions for internet and I've enabled read permissions in the app permissions.



<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.putuploadwithprogress">

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

<application

android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>

</manifest>









share|improve this question














I've built a stripped down Android app to upload files to Amazon S3 using signed URLs. These URLs require a PUT call, which is slightly different than most file uploads which happen over POST.



I just paste in the S3 URL into the textview. I've verified the S3 URL works with this cURL command, so all is well with it.



curl -X PUT 'https://mybucket.s3.us-west-2.amazonaws.com/uploads/android/somevideo.mp4?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credentia...0&X-Amz-Signature=213123123&X-Amz-SignedHeaders=host' --upload-file ~/Downloads/video.mp4



The file upload completes correctly inside the Android app, but I never get into my update callback, so I cannot update the progress bar in the dialog.



Is there something different happening because I am doing a PUT request, and this is not a multipart form upload (I'm just sending the file as the body as an octet stream)?



My Activity code and the inner Progress class are all in one file below. When I set a breakpoint on line 126 (the update function), I never enter it. I used the sample Progress listener linked here, but for some reason my code never is called.



package com.example.putuploadwithprogress;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;

import java.io.File;
import java.io.IOException;

import okhttp3.Interceptor;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.ResponseBody;
import okio.Buffer;
import okio.BufferedSource;
import okio.ForwardingSource;
import okio.Okio;
import okio.Source;

public class MainActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

final TextView uploadUrl = findViewById(R.id.uploadUrl);
Button uploadButton = findViewById(R.id.uploadButton);

uploadButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {

AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
View layout = getLayoutInflater().inflate(R.layout.upload_progress, null);
final ProgressBar progress = layout.findViewById(R.id.uploadProgressBar);
builder.setView(layout);
builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
dialogInterface.dismiss();
}
});
final AlertDialog dialog = builder.show();

final String url = uploadUrl.getText().toString().trim();

try {
new Thread(new Runnable() {
@Override
public void run() {
String mimeType = "video/mp4";
String filename = Environment
.getExternalStoragePublicDirectory(Environment
.DIRECTORY_DOWNLOADS).toString() + "/video.mp4";
File file = new File(filename);
try {

new Progress(url, file, mimeType, MainActivity.this, progress, dialog).run();
MainActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
dialog.hide();
}
});

} catch (Exception e) {
System.out.println( "Got an error: " + e.getMessage());
MainActivity.this.runOnUiThread(new Runnable() { @Override public void run() { dialog.hide(); } });
}
}
}).start();
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
}

class Progress {

private String mime;
ProgressBar progressBar;
AlertDialog dialog;
Activity activity;
private String url;
private File file;

Progress(String _url,
File _file,
String _mime,
Activity _activity,
ProgressBar _progressBar,
AlertDialog _dialog) {
url = _url;
file = _file;
mime = _mime;
dialog = _dialog;
progressBar = _progressBar;
activity = _activity;
}

public void run() {

final Request request = new Request.Builder()
.header("Content-Type", mime)
.url(url)
.put(RequestBody.create(MediaType.parse(mime), file))
.build();

final ProgressListener progressListener = new ProgressListener() {
@Override
public void update(long bytesRead, long contentLength, boolean done) {
if (done) {
if (dialog != null)
activity.runOnUiThread(new Runnable() {
public void run() {
dialog.hide();
}
});
} else {
if (contentLength > 0) {
final int progress = (int) (((double) bytesRead / contentLength) * 100);
if (progressBar != null)
activity.runOnUiThread(new Runnable() {
public void run() {
progressBar.setProgress(progress);
}
});
}
}
}
};

OkHttpClient client = new OkHttpClient.Builder()
.addNetworkInterceptor(new Interceptor() {
@Override public Response intercept(Chain chain) throws IOException {
Response originalResponse = chain.proceed(chain.request());
return originalResponse.newBuilder()
.body(new ProgressResponseBody(originalResponse.body(), progressListener))
.build();
}
})
.build();

try (Response response = client.newCall(request).execute()) {
activity.runOnUiThread(
new Runnable() {
@Override
public void run() {
if (!response.isSuccessful()) {
String message = response.message();
Toast.makeText(activity, "Unable to upload file: " + message, Toast.LENGTH_LONG).show();
} else {
Toast.makeText(activity, "Uploaded file successfully", Toast.LENGTH_LONG).show();
}
dialog.hide();
}
});
} catch (IOException e) {
e.printStackTrace();
}
}

interface ProgressListener {
void update(long bytesRead, long contentLength, boolean done);
}

private static class ProgressResponseBody extends ResponseBody {

private final ResponseBody responseBody;
private final ProgressListener progressListener;
private BufferedSource bufferedSource;

ProgressResponseBody(ResponseBody responseBody, ProgressListener progressListener) {
this.responseBody = responseBody;
this.progressListener = progressListener;
}

@Override
public MediaType contentType() {
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;
}
};
}
}

}


I've got two views. First, the main_activity.xml:



<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">

<Button
android:id="@+id/uploadButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Upload File"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />

<EditText
android:id="@+id/uploadUrl"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="8dp"
android:ems="10"
android:hint="S3 URL, paste in here"
android:inputType="textMultiLine|textNoSuggestions"
app:layout_constraintBottom_toTopOf="@+id/uploadButton"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

</android.support.constraint.ConstraintLayout>


upload_progress.xml:



<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="20dp">

<ProgressBar
android:id="@+id/uploadProgressBar"
style="@style/Widget.AppCompat.ProgressBar.Horizontal"
android:layout_width="0dp"
android:layout_height="30dp"
android:layout_marginStart="8dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="8dp"
android:max="100"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView"
tools:progress="45" />

<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="10dp"
android:text="Uploading file..."
android:textAppearance="@style/TextAppearance.AppCompat.Headline"
app:layout_constraintBottom_toTopOf="@+id/uploadProgressBar"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_chainStyle="spread_inside" />

<TextView
android:id="@+id/uploadStatusMessage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="8dp"
android:text="..."
android:textAppearance="@style/TextAppearance.AppCompat.Light.SearchResult.Title"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/uploadProgressBar" />
</android.support.constraint.ConstraintLayout>


The Android manifest has the correct permissions for internet and I've enabled read permissions in the app permissions.



<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.putuploadwithprogress">

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

<application

android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>

</manifest>






android amazon-s3 okhttp okhttp3






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Nov 21 '18 at 8:55









xrdxrd

1,97641825




1,97641825













  • Is function read(Buffer sink, long byteCount) being called for each byte read?

    – NIKHIL MAURYA
    Nov 21 '18 at 9:11













  • @NIKHILMAURYA no, I'm not seeing that hit either

    – xrd
    Nov 21 '18 at 15:36











  • I think you are tracking progress of the response body not the request body. try to use BufferedSink method try this gist.github.com/kyawkyaw/54d9e2feb1c969c90673

    – NIKHIL MAURYA
    Nov 21 '18 at 16:17





















  • Is function read(Buffer sink, long byteCount) being called for each byte read?

    – NIKHIL MAURYA
    Nov 21 '18 at 9:11













  • @NIKHILMAURYA no, I'm not seeing that hit either

    – xrd
    Nov 21 '18 at 15:36











  • I think you are tracking progress of the response body not the request body. try to use BufferedSink method try this gist.github.com/kyawkyaw/54d9e2feb1c969c90673

    – NIKHIL MAURYA
    Nov 21 '18 at 16:17



















Is function read(Buffer sink, long byteCount) being called for each byte read?

– NIKHIL MAURYA
Nov 21 '18 at 9:11







Is function read(Buffer sink, long byteCount) being called for each byte read?

– NIKHIL MAURYA
Nov 21 '18 at 9:11















@NIKHILMAURYA no, I'm not seeing that hit either

– xrd
Nov 21 '18 at 15:36





@NIKHILMAURYA no, I'm not seeing that hit either

– xrd
Nov 21 '18 at 15:36













I think you are tracking progress of the response body not the request body. try to use BufferedSink method try this gist.github.com/kyawkyaw/54d9e2feb1c969c90673

– NIKHIL MAURYA
Nov 21 '18 at 16:17







I think you are tracking progress of the response body not the request body. try to use BufferedSink method try this gist.github.com/kyawkyaw/54d9e2feb1c969c90673

– NIKHIL MAURYA
Nov 21 '18 at 16:17














1 Answer
1






active

oldest

votes


















0














The issue was, as nikhil mentioned, that this was intercepting the response and not the request.



The interceptor needed to be changed this like:



.addNetworkInterceptor(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Request originalRequest = chain.request();

if (originalRequest.body() == null) {
return chain.proceed(originalRequest);
}
Request progressRequest = originalRequest.newBuilder()
.method(originalRequest.method(),
new CountingRequestBody(originalRequest.body(), progressListener))
.build();

return chain.proceed(progressRequest);

}


This below full code works.



package com.example.putuploadwithprogress;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;

import java.io.File;
import java.io.IOException;

import okhttp3.Interceptor;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okio.Buffer;
import okio.BufferedSink;
import okio.ForwardingSink;
import okio.Okio;
import okio.Sink;

public class MainActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

final TextView uploadUrl = findViewById(R.id.uploadUrl);
Button uploadButton = findViewById(R.id.uploadButton);

uploadButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {

AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
View layout = getLayoutInflater().inflate(R.layout.upload_progress, null);
final ProgressBar progress = layout.findViewById(R.id.uploadProgressBar);
builder.setView(layout);
builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
dialogInterface.dismiss();
}
});
final AlertDialog dialog = builder.show();

final String url = uploadUrl.getText().toString().trim();

try {
new Thread(new Runnable() {
@Override
public void run() {
String mimeType = "video/mp4";
String filename = Environment
.getExternalStoragePublicDirectory(Environment
.DIRECTORY_DOWNLOADS).toString() + "/video.mp4";
File file = new File(filename);
try {

new Progress(url, file, mimeType, MainActivity.this, progress, dialog).run();
MainActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
dialog.hide();
}
});

} catch (Exception e) {
System.out.println( "Got an error: " + e.getMessage());
MainActivity.this.runOnUiThread(new Runnable() { @Override public void run() { dialog.hide(); } });
}
}
}).start();
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
}

class Progress {

private String mime;
ProgressBar progressBar;
AlertDialog dialog;
Activity activity;
private String url;
private File file;

Progress(String _url,
File _file,
String _mime,
Activity _activity,
ProgressBar _progressBar,
AlertDialog _dialog) {
url = _url;
file = _file;
mime = _mime;
dialog = _dialog;
progressBar = _progressBar;
activity = _activity;
}

public void run() {

final Request request = new Request.Builder()
.header("Content-Type", mime)
.url(url)
.put(RequestBody.create(MediaType.parse(mime), file))
.build();

final CountingRequestBody.Listener progressListener = new CountingRequestBody.Listener() {
@Override
public void onRequestProgress(long bytesRead, long contentLength) {
if (bytesRead >= contentLength) {
if (dialog != null)
activity.runOnUiThread(new Runnable() {
public void run() {
dialog.hide();
}
});
} else {
if (contentLength > 0) {
final int progress = (int) (((double) bytesRead / contentLength) * 100);
if (progressBar != null)
activity.runOnUiThread(new Runnable() {
public void run() {
progressBar.setProgress(progress);
}
});
}
}
}
};

OkHttpClient client = new OkHttpClient.Builder()
.addNetworkInterceptor(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Request originalRequest = chain.request();

if (originalRequest.body() == null) {
return chain.proceed(originalRequest);
}
Request progressRequest = originalRequest.newBuilder()
.method(originalRequest.method(),
new CountingRequestBody(originalRequest.body(), progressListener))
.build();

return chain.proceed(progressRequest);

}
})
.build();

try (Response response = client.newCall(request).execute()) {
activity.runOnUiThread(
new Runnable() {
@Override
public void run() {
if (!response.isSuccessful()) {
String message = response.message();
Toast.makeText(activity, "Unable to upload file: " + message, Toast.LENGTH_LONG).show();
} else {
Toast.makeText(activity, "Uploaded file successfully", Toast.LENGTH_LONG).show();
}
dialog.hide();
}
});
} catch (IOException e) {
e.printStackTrace();
}
}
}


class CountingRequestBody extends RequestBody {

protected RequestBody delegate;
protected Listener listener;

protected CountingSink countingSink;

public CountingRequestBody(RequestBody delegate, Listener listener) {
this.delegate = delegate;
this.listener = listener;
}

@Override public MediaType contentType() {
return delegate.contentType();
}

@Override public long contentLength() {
try {
return delegate.contentLength();
} catch (IOException e) {
e.printStackTrace();
}
return -1;
}

@Override public void writeTo(BufferedSink sink) throws IOException {
BufferedSink bufferedSink;

countingSink = new CountingSink(sink);
bufferedSink = Okio.buffer(countingSink);

delegate.writeTo(bufferedSink);

bufferedSink.flush();
}

protected final class CountingSink extends ForwardingSink {

private long bytesWritten = 0;

public CountingSink(Sink delegate) {
super(delegate);
}

@Override public void write(Buffer source, long byteCount) throws IOException {
super.write(source, byteCount);

bytesWritten += byteCount;
listener.onRequestProgress(bytesWritten, contentLength());
}
}

public static interface Listener {

public void onRequestProgress(long bytesWritten, long contentLength);
}
}





share|improve this answer























    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53408345%2fwhy-is-my-progress-listener-update-callback-not-getting-called-in-the-okhttp-int%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    1 Answer
    1






    active

    oldest

    votes








    1 Answer
    1






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    0














    The issue was, as nikhil mentioned, that this was intercepting the response and not the request.



    The interceptor needed to be changed this like:



    .addNetworkInterceptor(new Interceptor() {
    @Override
    public Response intercept(Chain chain) throws IOException {
    Request originalRequest = chain.request();

    if (originalRequest.body() == null) {
    return chain.proceed(originalRequest);
    }
    Request progressRequest = originalRequest.newBuilder()
    .method(originalRequest.method(),
    new CountingRequestBody(originalRequest.body(), progressListener))
    .build();

    return chain.proceed(progressRequest);

    }


    This below full code works.



    package com.example.putuploadwithprogress;

    import android.app.Activity;
    import android.app.AlertDialog;
    import android.content.DialogInterface;
    import android.os.Bundle;
    import android.os.Environment;
    import android.support.v7.app.AppCompatActivity;
    import android.view.View;
    import android.widget.Button;
    import android.widget.ProgressBar;
    import android.widget.TextView;
    import android.widget.Toast;

    import java.io.File;
    import java.io.IOException;

    import okhttp3.Interceptor;
    import okhttp3.MediaType;
    import okhttp3.OkHttpClient;
    import okhttp3.Request;
    import okhttp3.RequestBody;
    import okhttp3.Response;
    import okio.Buffer;
    import okio.BufferedSink;
    import okio.ForwardingSink;
    import okio.Okio;
    import okio.Sink;

    public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    final TextView uploadUrl = findViewById(R.id.uploadUrl);
    Button uploadButton = findViewById(R.id.uploadButton);

    uploadButton.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {

    AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
    View layout = getLayoutInflater().inflate(R.layout.upload_progress, null);
    final ProgressBar progress = layout.findViewById(R.id.uploadProgressBar);
    builder.setView(layout);
    builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
    @Override
    public void onClick(DialogInterface dialogInterface, int i) {
    dialogInterface.dismiss();
    }
    });
    final AlertDialog dialog = builder.show();

    final String url = uploadUrl.getText().toString().trim();

    try {
    new Thread(new Runnable() {
    @Override
    public void run() {
    String mimeType = "video/mp4";
    String filename = Environment
    .getExternalStoragePublicDirectory(Environment
    .DIRECTORY_DOWNLOADS).toString() + "/video.mp4";
    File file = new File(filename);
    try {

    new Progress(url, file, mimeType, MainActivity.this, progress, dialog).run();
    MainActivity.this.runOnUiThread(new Runnable() {
    @Override
    public void run() {
    dialog.hide();
    }
    });

    } catch (Exception e) {
    System.out.println( "Got an error: " + e.getMessage());
    MainActivity.this.runOnUiThread(new Runnable() { @Override public void run() { dialog.hide(); } });
    }
    }
    }).start();
    } catch (Exception e) {
    e.printStackTrace();
    }
    }
    });
    }
    }

    class Progress {

    private String mime;
    ProgressBar progressBar;
    AlertDialog dialog;
    Activity activity;
    private String url;
    private File file;

    Progress(String _url,
    File _file,
    String _mime,
    Activity _activity,
    ProgressBar _progressBar,
    AlertDialog _dialog) {
    url = _url;
    file = _file;
    mime = _mime;
    dialog = _dialog;
    progressBar = _progressBar;
    activity = _activity;
    }

    public void run() {

    final Request request = new Request.Builder()
    .header("Content-Type", mime)
    .url(url)
    .put(RequestBody.create(MediaType.parse(mime), file))
    .build();

    final CountingRequestBody.Listener progressListener = new CountingRequestBody.Listener() {
    @Override
    public void onRequestProgress(long bytesRead, long contentLength) {
    if (bytesRead >= contentLength) {
    if (dialog != null)
    activity.runOnUiThread(new Runnable() {
    public void run() {
    dialog.hide();
    }
    });
    } else {
    if (contentLength > 0) {
    final int progress = (int) (((double) bytesRead / contentLength) * 100);
    if (progressBar != null)
    activity.runOnUiThread(new Runnable() {
    public void run() {
    progressBar.setProgress(progress);
    }
    });
    }
    }
    }
    };

    OkHttpClient client = new OkHttpClient.Builder()
    .addNetworkInterceptor(new Interceptor() {
    @Override
    public Response intercept(Chain chain) throws IOException {
    Request originalRequest = chain.request();

    if (originalRequest.body() == null) {
    return chain.proceed(originalRequest);
    }
    Request progressRequest = originalRequest.newBuilder()
    .method(originalRequest.method(),
    new CountingRequestBody(originalRequest.body(), progressListener))
    .build();

    return chain.proceed(progressRequest);

    }
    })
    .build();

    try (Response response = client.newCall(request).execute()) {
    activity.runOnUiThread(
    new Runnable() {
    @Override
    public void run() {
    if (!response.isSuccessful()) {
    String message = response.message();
    Toast.makeText(activity, "Unable to upload file: " + message, Toast.LENGTH_LONG).show();
    } else {
    Toast.makeText(activity, "Uploaded file successfully", Toast.LENGTH_LONG).show();
    }
    dialog.hide();
    }
    });
    } catch (IOException e) {
    e.printStackTrace();
    }
    }
    }


    class CountingRequestBody extends RequestBody {

    protected RequestBody delegate;
    protected Listener listener;

    protected CountingSink countingSink;

    public CountingRequestBody(RequestBody delegate, Listener listener) {
    this.delegate = delegate;
    this.listener = listener;
    }

    @Override public MediaType contentType() {
    return delegate.contentType();
    }

    @Override public long contentLength() {
    try {
    return delegate.contentLength();
    } catch (IOException e) {
    e.printStackTrace();
    }
    return -1;
    }

    @Override public void writeTo(BufferedSink sink) throws IOException {
    BufferedSink bufferedSink;

    countingSink = new CountingSink(sink);
    bufferedSink = Okio.buffer(countingSink);

    delegate.writeTo(bufferedSink);

    bufferedSink.flush();
    }

    protected final class CountingSink extends ForwardingSink {

    private long bytesWritten = 0;

    public CountingSink(Sink delegate) {
    super(delegate);
    }

    @Override public void write(Buffer source, long byteCount) throws IOException {
    super.write(source, byteCount);

    bytesWritten += byteCount;
    listener.onRequestProgress(bytesWritten, contentLength());
    }
    }

    public static interface Listener {

    public void onRequestProgress(long bytesWritten, long contentLength);
    }
    }





    share|improve this answer




























      0














      The issue was, as nikhil mentioned, that this was intercepting the response and not the request.



      The interceptor needed to be changed this like:



      .addNetworkInterceptor(new Interceptor() {
      @Override
      public Response intercept(Chain chain) throws IOException {
      Request originalRequest = chain.request();

      if (originalRequest.body() == null) {
      return chain.proceed(originalRequest);
      }
      Request progressRequest = originalRequest.newBuilder()
      .method(originalRequest.method(),
      new CountingRequestBody(originalRequest.body(), progressListener))
      .build();

      return chain.proceed(progressRequest);

      }


      This below full code works.



      package com.example.putuploadwithprogress;

      import android.app.Activity;
      import android.app.AlertDialog;
      import android.content.DialogInterface;
      import android.os.Bundle;
      import android.os.Environment;
      import android.support.v7.app.AppCompatActivity;
      import android.view.View;
      import android.widget.Button;
      import android.widget.ProgressBar;
      import android.widget.TextView;
      import android.widget.Toast;

      import java.io.File;
      import java.io.IOException;

      import okhttp3.Interceptor;
      import okhttp3.MediaType;
      import okhttp3.OkHttpClient;
      import okhttp3.Request;
      import okhttp3.RequestBody;
      import okhttp3.Response;
      import okio.Buffer;
      import okio.BufferedSink;
      import okio.ForwardingSink;
      import okio.Okio;
      import okio.Sink;

      public class MainActivity extends AppCompatActivity {

      @Override
      protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);

      final TextView uploadUrl = findViewById(R.id.uploadUrl);
      Button uploadButton = findViewById(R.id.uploadButton);

      uploadButton.setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View view) {

      AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
      View layout = getLayoutInflater().inflate(R.layout.upload_progress, null);
      final ProgressBar progress = layout.findViewById(R.id.uploadProgressBar);
      builder.setView(layout);
      builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
      @Override
      public void onClick(DialogInterface dialogInterface, int i) {
      dialogInterface.dismiss();
      }
      });
      final AlertDialog dialog = builder.show();

      final String url = uploadUrl.getText().toString().trim();

      try {
      new Thread(new Runnable() {
      @Override
      public void run() {
      String mimeType = "video/mp4";
      String filename = Environment
      .getExternalStoragePublicDirectory(Environment
      .DIRECTORY_DOWNLOADS).toString() + "/video.mp4";
      File file = new File(filename);
      try {

      new Progress(url, file, mimeType, MainActivity.this, progress, dialog).run();
      MainActivity.this.runOnUiThread(new Runnable() {
      @Override
      public void run() {
      dialog.hide();
      }
      });

      } catch (Exception e) {
      System.out.println( "Got an error: " + e.getMessage());
      MainActivity.this.runOnUiThread(new Runnable() { @Override public void run() { dialog.hide(); } });
      }
      }
      }).start();
      } catch (Exception e) {
      e.printStackTrace();
      }
      }
      });
      }
      }

      class Progress {

      private String mime;
      ProgressBar progressBar;
      AlertDialog dialog;
      Activity activity;
      private String url;
      private File file;

      Progress(String _url,
      File _file,
      String _mime,
      Activity _activity,
      ProgressBar _progressBar,
      AlertDialog _dialog) {
      url = _url;
      file = _file;
      mime = _mime;
      dialog = _dialog;
      progressBar = _progressBar;
      activity = _activity;
      }

      public void run() {

      final Request request = new Request.Builder()
      .header("Content-Type", mime)
      .url(url)
      .put(RequestBody.create(MediaType.parse(mime), file))
      .build();

      final CountingRequestBody.Listener progressListener = new CountingRequestBody.Listener() {
      @Override
      public void onRequestProgress(long bytesRead, long contentLength) {
      if (bytesRead >= contentLength) {
      if (dialog != null)
      activity.runOnUiThread(new Runnable() {
      public void run() {
      dialog.hide();
      }
      });
      } else {
      if (contentLength > 0) {
      final int progress = (int) (((double) bytesRead / contentLength) * 100);
      if (progressBar != null)
      activity.runOnUiThread(new Runnable() {
      public void run() {
      progressBar.setProgress(progress);
      }
      });
      }
      }
      }
      };

      OkHttpClient client = new OkHttpClient.Builder()
      .addNetworkInterceptor(new Interceptor() {
      @Override
      public Response intercept(Chain chain) throws IOException {
      Request originalRequest = chain.request();

      if (originalRequest.body() == null) {
      return chain.proceed(originalRequest);
      }
      Request progressRequest = originalRequest.newBuilder()
      .method(originalRequest.method(),
      new CountingRequestBody(originalRequest.body(), progressListener))
      .build();

      return chain.proceed(progressRequest);

      }
      })
      .build();

      try (Response response = client.newCall(request).execute()) {
      activity.runOnUiThread(
      new Runnable() {
      @Override
      public void run() {
      if (!response.isSuccessful()) {
      String message = response.message();
      Toast.makeText(activity, "Unable to upload file: " + message, Toast.LENGTH_LONG).show();
      } else {
      Toast.makeText(activity, "Uploaded file successfully", Toast.LENGTH_LONG).show();
      }
      dialog.hide();
      }
      });
      } catch (IOException e) {
      e.printStackTrace();
      }
      }
      }


      class CountingRequestBody extends RequestBody {

      protected RequestBody delegate;
      protected Listener listener;

      protected CountingSink countingSink;

      public CountingRequestBody(RequestBody delegate, Listener listener) {
      this.delegate = delegate;
      this.listener = listener;
      }

      @Override public MediaType contentType() {
      return delegate.contentType();
      }

      @Override public long contentLength() {
      try {
      return delegate.contentLength();
      } catch (IOException e) {
      e.printStackTrace();
      }
      return -1;
      }

      @Override public void writeTo(BufferedSink sink) throws IOException {
      BufferedSink bufferedSink;

      countingSink = new CountingSink(sink);
      bufferedSink = Okio.buffer(countingSink);

      delegate.writeTo(bufferedSink);

      bufferedSink.flush();
      }

      protected final class CountingSink extends ForwardingSink {

      private long bytesWritten = 0;

      public CountingSink(Sink delegate) {
      super(delegate);
      }

      @Override public void write(Buffer source, long byteCount) throws IOException {
      super.write(source, byteCount);

      bytesWritten += byteCount;
      listener.onRequestProgress(bytesWritten, contentLength());
      }
      }

      public static interface Listener {

      public void onRequestProgress(long bytesWritten, long contentLength);
      }
      }





      share|improve this answer


























        0












        0








        0







        The issue was, as nikhil mentioned, that this was intercepting the response and not the request.



        The interceptor needed to be changed this like:



        .addNetworkInterceptor(new Interceptor() {
        @Override
        public Response intercept(Chain chain) throws IOException {
        Request originalRequest = chain.request();

        if (originalRequest.body() == null) {
        return chain.proceed(originalRequest);
        }
        Request progressRequest = originalRequest.newBuilder()
        .method(originalRequest.method(),
        new CountingRequestBody(originalRequest.body(), progressListener))
        .build();

        return chain.proceed(progressRequest);

        }


        This below full code works.



        package com.example.putuploadwithprogress;

        import android.app.Activity;
        import android.app.AlertDialog;
        import android.content.DialogInterface;
        import android.os.Bundle;
        import android.os.Environment;
        import android.support.v7.app.AppCompatActivity;
        import android.view.View;
        import android.widget.Button;
        import android.widget.ProgressBar;
        import android.widget.TextView;
        import android.widget.Toast;

        import java.io.File;
        import java.io.IOException;

        import okhttp3.Interceptor;
        import okhttp3.MediaType;
        import okhttp3.OkHttpClient;
        import okhttp3.Request;
        import okhttp3.RequestBody;
        import okhttp3.Response;
        import okio.Buffer;
        import okio.BufferedSink;
        import okio.ForwardingSink;
        import okio.Okio;
        import okio.Sink;

        public class MainActivity extends AppCompatActivity {

        @Override
        protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        final TextView uploadUrl = findViewById(R.id.uploadUrl);
        Button uploadButton = findViewById(R.id.uploadButton);

        uploadButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {

        AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
        View layout = getLayoutInflater().inflate(R.layout.upload_progress, null);
        final ProgressBar progress = layout.findViewById(R.id.uploadProgressBar);
        builder.setView(layout);
        builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialogInterface, int i) {
        dialogInterface.dismiss();
        }
        });
        final AlertDialog dialog = builder.show();

        final String url = uploadUrl.getText().toString().trim();

        try {
        new Thread(new Runnable() {
        @Override
        public void run() {
        String mimeType = "video/mp4";
        String filename = Environment
        .getExternalStoragePublicDirectory(Environment
        .DIRECTORY_DOWNLOADS).toString() + "/video.mp4";
        File file = new File(filename);
        try {

        new Progress(url, file, mimeType, MainActivity.this, progress, dialog).run();
        MainActivity.this.runOnUiThread(new Runnable() {
        @Override
        public void run() {
        dialog.hide();
        }
        });

        } catch (Exception e) {
        System.out.println( "Got an error: " + e.getMessage());
        MainActivity.this.runOnUiThread(new Runnable() { @Override public void run() { dialog.hide(); } });
        }
        }
        }).start();
        } catch (Exception e) {
        e.printStackTrace();
        }
        }
        });
        }
        }

        class Progress {

        private String mime;
        ProgressBar progressBar;
        AlertDialog dialog;
        Activity activity;
        private String url;
        private File file;

        Progress(String _url,
        File _file,
        String _mime,
        Activity _activity,
        ProgressBar _progressBar,
        AlertDialog _dialog) {
        url = _url;
        file = _file;
        mime = _mime;
        dialog = _dialog;
        progressBar = _progressBar;
        activity = _activity;
        }

        public void run() {

        final Request request = new Request.Builder()
        .header("Content-Type", mime)
        .url(url)
        .put(RequestBody.create(MediaType.parse(mime), file))
        .build();

        final CountingRequestBody.Listener progressListener = new CountingRequestBody.Listener() {
        @Override
        public void onRequestProgress(long bytesRead, long contentLength) {
        if (bytesRead >= contentLength) {
        if (dialog != null)
        activity.runOnUiThread(new Runnable() {
        public void run() {
        dialog.hide();
        }
        });
        } else {
        if (contentLength > 0) {
        final int progress = (int) (((double) bytesRead / contentLength) * 100);
        if (progressBar != null)
        activity.runOnUiThread(new Runnable() {
        public void run() {
        progressBar.setProgress(progress);
        }
        });
        }
        }
        }
        };

        OkHttpClient client = new OkHttpClient.Builder()
        .addNetworkInterceptor(new Interceptor() {
        @Override
        public Response intercept(Chain chain) throws IOException {
        Request originalRequest = chain.request();

        if (originalRequest.body() == null) {
        return chain.proceed(originalRequest);
        }
        Request progressRequest = originalRequest.newBuilder()
        .method(originalRequest.method(),
        new CountingRequestBody(originalRequest.body(), progressListener))
        .build();

        return chain.proceed(progressRequest);

        }
        })
        .build();

        try (Response response = client.newCall(request).execute()) {
        activity.runOnUiThread(
        new Runnable() {
        @Override
        public void run() {
        if (!response.isSuccessful()) {
        String message = response.message();
        Toast.makeText(activity, "Unable to upload file: " + message, Toast.LENGTH_LONG).show();
        } else {
        Toast.makeText(activity, "Uploaded file successfully", Toast.LENGTH_LONG).show();
        }
        dialog.hide();
        }
        });
        } catch (IOException e) {
        e.printStackTrace();
        }
        }
        }


        class CountingRequestBody extends RequestBody {

        protected RequestBody delegate;
        protected Listener listener;

        protected CountingSink countingSink;

        public CountingRequestBody(RequestBody delegate, Listener listener) {
        this.delegate = delegate;
        this.listener = listener;
        }

        @Override public MediaType contentType() {
        return delegate.contentType();
        }

        @Override public long contentLength() {
        try {
        return delegate.contentLength();
        } catch (IOException e) {
        e.printStackTrace();
        }
        return -1;
        }

        @Override public void writeTo(BufferedSink sink) throws IOException {
        BufferedSink bufferedSink;

        countingSink = new CountingSink(sink);
        bufferedSink = Okio.buffer(countingSink);

        delegate.writeTo(bufferedSink);

        bufferedSink.flush();
        }

        protected final class CountingSink extends ForwardingSink {

        private long bytesWritten = 0;

        public CountingSink(Sink delegate) {
        super(delegate);
        }

        @Override public void write(Buffer source, long byteCount) throws IOException {
        super.write(source, byteCount);

        bytesWritten += byteCount;
        listener.onRequestProgress(bytesWritten, contentLength());
        }
        }

        public static interface Listener {

        public void onRequestProgress(long bytesWritten, long contentLength);
        }
        }





        share|improve this answer













        The issue was, as nikhil mentioned, that this was intercepting the response and not the request.



        The interceptor needed to be changed this like:



        .addNetworkInterceptor(new Interceptor() {
        @Override
        public Response intercept(Chain chain) throws IOException {
        Request originalRequest = chain.request();

        if (originalRequest.body() == null) {
        return chain.proceed(originalRequest);
        }
        Request progressRequest = originalRequest.newBuilder()
        .method(originalRequest.method(),
        new CountingRequestBody(originalRequest.body(), progressListener))
        .build();

        return chain.proceed(progressRequest);

        }


        This below full code works.



        package com.example.putuploadwithprogress;

        import android.app.Activity;
        import android.app.AlertDialog;
        import android.content.DialogInterface;
        import android.os.Bundle;
        import android.os.Environment;
        import android.support.v7.app.AppCompatActivity;
        import android.view.View;
        import android.widget.Button;
        import android.widget.ProgressBar;
        import android.widget.TextView;
        import android.widget.Toast;

        import java.io.File;
        import java.io.IOException;

        import okhttp3.Interceptor;
        import okhttp3.MediaType;
        import okhttp3.OkHttpClient;
        import okhttp3.Request;
        import okhttp3.RequestBody;
        import okhttp3.Response;
        import okio.Buffer;
        import okio.BufferedSink;
        import okio.ForwardingSink;
        import okio.Okio;
        import okio.Sink;

        public class MainActivity extends AppCompatActivity {

        @Override
        protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        final TextView uploadUrl = findViewById(R.id.uploadUrl);
        Button uploadButton = findViewById(R.id.uploadButton);

        uploadButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {

        AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
        View layout = getLayoutInflater().inflate(R.layout.upload_progress, null);
        final ProgressBar progress = layout.findViewById(R.id.uploadProgressBar);
        builder.setView(layout);
        builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialogInterface, int i) {
        dialogInterface.dismiss();
        }
        });
        final AlertDialog dialog = builder.show();

        final String url = uploadUrl.getText().toString().trim();

        try {
        new Thread(new Runnable() {
        @Override
        public void run() {
        String mimeType = "video/mp4";
        String filename = Environment
        .getExternalStoragePublicDirectory(Environment
        .DIRECTORY_DOWNLOADS).toString() + "/video.mp4";
        File file = new File(filename);
        try {

        new Progress(url, file, mimeType, MainActivity.this, progress, dialog).run();
        MainActivity.this.runOnUiThread(new Runnable() {
        @Override
        public void run() {
        dialog.hide();
        }
        });

        } catch (Exception e) {
        System.out.println( "Got an error: " + e.getMessage());
        MainActivity.this.runOnUiThread(new Runnable() { @Override public void run() { dialog.hide(); } });
        }
        }
        }).start();
        } catch (Exception e) {
        e.printStackTrace();
        }
        }
        });
        }
        }

        class Progress {

        private String mime;
        ProgressBar progressBar;
        AlertDialog dialog;
        Activity activity;
        private String url;
        private File file;

        Progress(String _url,
        File _file,
        String _mime,
        Activity _activity,
        ProgressBar _progressBar,
        AlertDialog _dialog) {
        url = _url;
        file = _file;
        mime = _mime;
        dialog = _dialog;
        progressBar = _progressBar;
        activity = _activity;
        }

        public void run() {

        final Request request = new Request.Builder()
        .header("Content-Type", mime)
        .url(url)
        .put(RequestBody.create(MediaType.parse(mime), file))
        .build();

        final CountingRequestBody.Listener progressListener = new CountingRequestBody.Listener() {
        @Override
        public void onRequestProgress(long bytesRead, long contentLength) {
        if (bytesRead >= contentLength) {
        if (dialog != null)
        activity.runOnUiThread(new Runnable() {
        public void run() {
        dialog.hide();
        }
        });
        } else {
        if (contentLength > 0) {
        final int progress = (int) (((double) bytesRead / contentLength) * 100);
        if (progressBar != null)
        activity.runOnUiThread(new Runnable() {
        public void run() {
        progressBar.setProgress(progress);
        }
        });
        }
        }
        }
        };

        OkHttpClient client = new OkHttpClient.Builder()
        .addNetworkInterceptor(new Interceptor() {
        @Override
        public Response intercept(Chain chain) throws IOException {
        Request originalRequest = chain.request();

        if (originalRequest.body() == null) {
        return chain.proceed(originalRequest);
        }
        Request progressRequest = originalRequest.newBuilder()
        .method(originalRequest.method(),
        new CountingRequestBody(originalRequest.body(), progressListener))
        .build();

        return chain.proceed(progressRequest);

        }
        })
        .build();

        try (Response response = client.newCall(request).execute()) {
        activity.runOnUiThread(
        new Runnable() {
        @Override
        public void run() {
        if (!response.isSuccessful()) {
        String message = response.message();
        Toast.makeText(activity, "Unable to upload file: " + message, Toast.LENGTH_LONG).show();
        } else {
        Toast.makeText(activity, "Uploaded file successfully", Toast.LENGTH_LONG).show();
        }
        dialog.hide();
        }
        });
        } catch (IOException e) {
        e.printStackTrace();
        }
        }
        }


        class CountingRequestBody extends RequestBody {

        protected RequestBody delegate;
        protected Listener listener;

        protected CountingSink countingSink;

        public CountingRequestBody(RequestBody delegate, Listener listener) {
        this.delegate = delegate;
        this.listener = listener;
        }

        @Override public MediaType contentType() {
        return delegate.contentType();
        }

        @Override public long contentLength() {
        try {
        return delegate.contentLength();
        } catch (IOException e) {
        e.printStackTrace();
        }
        return -1;
        }

        @Override public void writeTo(BufferedSink sink) throws IOException {
        BufferedSink bufferedSink;

        countingSink = new CountingSink(sink);
        bufferedSink = Okio.buffer(countingSink);

        delegate.writeTo(bufferedSink);

        bufferedSink.flush();
        }

        protected final class CountingSink extends ForwardingSink {

        private long bytesWritten = 0;

        public CountingSink(Sink delegate) {
        super(delegate);
        }

        @Override public void write(Buffer source, long byteCount) throws IOException {
        super.write(source, byteCount);

        bytesWritten += byteCount;
        listener.onRequestProgress(bytesWritten, contentLength());
        }
        }

        public static interface Listener {

        public void onRequestProgress(long bytesWritten, long contentLength);
        }
        }






        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Nov 21 '18 at 17:14









        xrdxrd

        1,97641825




        1,97641825






























            draft saved

            draft discarded




















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53408345%2fwhy-is-my-progress-listener-update-callback-not-getting-called-in-the-okhttp-int%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            "Incorrect syntax near the keyword 'ON'. (on update cascade, on delete cascade,)

            Alcedinidae

            Origin of the phrase “under your belt”?