Skip to content

Commit ac7ba18

Browse files
author
Noor Dawod
committed
Add sample showing use of Range response handler.
1 parent bc7b165 commit ac7ba18

File tree

4 files changed

+180
-1
lines changed

4 files changed

+180
-1
lines changed

sample/src/main/AndroidManifest.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
<activity android:name=".FilesSample"/>
3535
<activity android:name=".CustomCASample"/>
3636
<activity android:name=".RetryRequestSample"/>
37+
<activity android:name=".RangeResponseSample"/>
3738

3839
<service android:name=".services.ExampleIntentService"/>
3940
</application>
Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
/*
2+
Android Asynchronous Http Client Sample
3+
Copyright (c) 2014 Marek Sebera <[email protected]>
4+
http://loopj.com
5+
6+
Licensed under the Apache License, Version 2.0 (the "License");
7+
you may not use this file except in compliance with the License.
8+
You may obtain a copy of the License at
9+
10+
http://www.apache.org/licenses/LICENSE-2.0
11+
12+
Unless required by applicable law or agreed to in writing, software
13+
distributed under the License is distributed on an "AS IS" BASIS,
14+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
See the License for the specific language governing permissions and
16+
limitations under the License.
17+
*/
18+
19+
package com.loopj.android.http.sample;
20+
21+
import android.os.Bundle;
22+
import android.util.Log;
23+
import android.widget.Toast;
24+
import com.loopj.android.http.AsyncHttpClient;
25+
import com.loopj.android.http.RangeFileAsyncHttpResponseHandler;
26+
import com.loopj.android.http.RequestHandle;
27+
import com.loopj.android.http.ResponseHandlerInterface;
28+
import java.io.File;
29+
import java.io.IOException;
30+
import org.apache.http.Header;
31+
import org.apache.http.HttpEntity;
32+
import org.apache.http.client.methods.HttpUriRequest;
33+
34+
/**
35+
* This sample demonstrates use of {@link RangeFileAsyncHttpResponseHandler} to
36+
* download a remote file in multiple requests. While this response handler
37+
* class handles file storage, it's up to the app itself to request all chunks
38+
* of the file.
39+
*
40+
* Also demonstrated a method to query the remote file's size prior to sending
41+
* the actual GET requests. This ensures that the remote server is actually
42+
* capable of supporting the "Range" header, necessary to make this sample work.
43+
*
44+
* @author Noor Dawod <[email protected]>
45+
*/
46+
public class RangeResponseSample extends GetSample {
47+
48+
public static final String LOG_TAG = "RangeResponseSample";
49+
50+
private static final String CONTENT_LENGTH = "Content-Length";
51+
private static final String ACCEPT_RANGES = "Accept-Ranges";
52+
private static final int CHUNK_SIZE = 10240;
53+
54+
private File file;
55+
private long fileSize = -1;
56+
57+
@Override
58+
protected void onCreate(Bundle savedInstanceState) {
59+
super.onCreate(savedInstanceState);
60+
try {
61+
// Temporary file to host the URL's downloaded contents.
62+
file = File.createTempFile("temp_", "_handled", getCacheDir());
63+
} catch (IOException e) {
64+
Log.e(LOG_TAG, "Cannot create temporary file", e);
65+
}
66+
}
67+
68+
@Override
69+
protected void onDestroy() {
70+
super.onDestroy();
71+
72+
// Remove temporary file.
73+
if (file != null) {
74+
file.delete();
75+
file = null;
76+
}
77+
}
78+
79+
@Override
80+
public boolean isRequestHeadersAllowed() {
81+
return false;
82+
}
83+
84+
@Override
85+
public String getDefaultURL() {
86+
return "http://upload.wikimedia.org/wikipedia/commons/f/fa/Geysers_on_Mars.jpg";
87+
}
88+
89+
@Override
90+
public int getSampleTitle() {
91+
return R.string.title_range_sample;
92+
}
93+
94+
@Override
95+
public RequestHandle executeSample(AsyncHttpClient client, String URL, Header[] headers, HttpEntity entity, ResponseHandlerInterface responseHandler) {
96+
if (fileSize > 0) {
97+
// Send a GET query when we know the size of the remote file.
98+
return client.get(this, URL, headers, null, responseHandler);
99+
} else {
100+
// Send a HEAD query to know the size of the remote file.
101+
return client.head(this, URL, headers, null, responseHandler);
102+
}
103+
}
104+
105+
public void sendNextRangeRequest() {
106+
if (file.length() < fileSize) {
107+
// File is still smaller than remote file; send a new request.
108+
onRunButtonPressed();
109+
}
110+
}
111+
112+
@Override
113+
public ResponseHandlerInterface getResponseHandler() {
114+
return new RangeFileAsyncHttpResponseHandler(file) {
115+
116+
@Override
117+
public void onSuccess(int statusCode, Header[] headers, File file) {
118+
debugHeaders(LOG_TAG, headers);
119+
debugStatusCode(LOG_TAG, statusCode);
120+
121+
if (fileSize < 1) {
122+
boolean supportsRange = false;
123+
// Cycle through the headers and look for the Content-Length header.
124+
for (Header header : headers) {
125+
String headerName = header.getName();
126+
if (CONTENT_LENGTH.equals(headerName)) {
127+
fileSize = Long.parseLong(header.getValue());
128+
} else if (ACCEPT_RANGES.equals(headerName)) {
129+
supportsRange = true;
130+
}
131+
}
132+
133+
// Is the content length known?
134+
if (!supportsRange || fileSize < 1) {
135+
Toast.makeText(
136+
RangeResponseSample.this,
137+
"Unable to determine remote file's size, or\nremote server doesn't support ranges",
138+
Toast.LENGTH_LONG
139+
).show();
140+
}
141+
}
142+
143+
// If remote file size is known, request next portion.
144+
if (fileSize > 0) {
145+
debugFileResponse(file);
146+
// Send a new request for the same resource.
147+
sendNextRangeRequest();
148+
}
149+
}
150+
151+
@Override
152+
public void onFailure(int statusCode, Header[] headers, Throwable e, File file) {
153+
debugHeaders(LOG_TAG, headers);
154+
debugStatusCode(LOG_TAG, statusCode);
155+
debugThrowable(LOG_TAG, e);
156+
debugFileResponse(file);
157+
}
158+
159+
@Override
160+
public void updateRequestHeaders(HttpUriRequest uriRequest) {
161+
// Call super so appending could work.
162+
super.updateRequestHeaders(uriRequest);
163+
164+
// Length of the downloaded content thus far.
165+
long length = file.length();
166+
167+
// Request the next portion of the file to be downloaded.
168+
uriRequest.setHeader("Range", "bytes=" + length + "-" + (length + CHUNK_SIZE - 1));
169+
}
170+
171+
void debugFileResponse(File file) {
172+
debugResponse(LOG_TAG, "File size thus far: " + file.length() + " bytes");
173+
}
174+
};
175+
}
176+
}

sample/src/main/java/com/loopj/android/http/sample/WaypointsActivity.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,8 @@ public class WaypointsActivity extends ListActivity {
4949
new SampleConfig(R.string.title_post_files, FilesSample.class),
5050
new SampleConfig(R.string.title_persistent_cookies, PersistentCookiesSample.class),
5151
new SampleConfig(R.string.title_custom_ca, CustomCASample.class),
52-
new SampleConfig(R.string.title_retry_handler, RetryRequestSample.class)
52+
new SampleConfig(R.string.title_retry_handler, RetryRequestSample.class),
53+
new SampleConfig(R.string.title_range_sample, RangeResponseSample.class)
5354
};
5455

5556
@Override

sample/src/main/res/values/strings.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,5 @@
2727
<string name="title_persistent_cookies">Handling persistent cookies</string>
2828
<string name="title_custom_ca">Custom CA Example</string>
2929
<string name="title_retry_handler">Retrying requests by Exception</string>
30+
<string name="title_range_sample">Range response handling</string>
3031
</resources>

0 commit comments

Comments
 (0)