1
+ /*
2
+ Android Asynchronous Http Client
3
+ Copyright (c) 2011 James Smith <[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 ;
20
+
21
+ import java .io .IOException ;
22
+
23
+ import org .apache .http .Header ;
24
+ import org .apache .http .HttpEntity ;
25
+ import org .apache .http .HttpResponse ;
26
+ import org .apache .http .StatusLine ;
27
+ import org .apache .http .client .HttpResponseException ;
28
+ import org .apache .http .entity .BufferedHttpEntity ;
29
+ import org .apache .http .util .EntityUtils ;
30
+
31
+ import android .os .Handler ;
32
+ import android .os .Message ;
33
+ import android .os .Looper ;
34
+
35
+ /**
36
+ * Used to intercept and handle the responses from requests made using
37
+ * {@link AsyncHttpClient}, with automatic handling of png/jpg image data
38
+ * (e.g. checks Content-Type against allowed list, Content-length). Receives response body as
39
+ * byte array.
40
+ * <p>
41
+ * Additionally, you can override the {@link #onFailure(Throwable, String)},
42
+ * {@link #onStart()}, and {@link #onFinish()} methods as required.
43
+ * <p>
44
+ * For example:
45
+ * <p>
46
+ * <pre>
47
+ * AsyncHttpClient client = new AsyncHttpClient();
48
+ * client.get("http://www.google.com", new AsyncHttpResponseHandler() {
49
+ * @Override
50
+ * public void onStart() {
51
+ * // Initiated the request
52
+ * }
53
+ *
54
+ * @Override
55
+ * public void onSuccess(String response) {
56
+ * // Successfully got a response
57
+ * }
58
+ *
59
+ * @Override
60
+ * public void onFailure(Throwable e, String response) {
61
+ * // Response failed :(
62
+ * }
63
+ *
64
+ * @Override
65
+ * public void onFinish() {
66
+ * // Completed the request (either success or failure)
67
+ * }
68
+ * });
69
+ * </pre>
70
+ */
71
+ public class ImageHttpResponseHandler extends AsyncHttpResponseHandler {
72
+ private static final int SUCCESS_MESSAGE = 0 ;
73
+ private static final int FAILURE_MESSAGE = 1 ;
74
+ private static final int START_MESSAGE = 2 ;
75
+ private static final int FINISH_MESSAGE = 3 ;
76
+
77
+ private static String [] mAllowedContentTypes = new String [] { "image/jpeg" ,
78
+ "image/png" };
79
+
80
+ private Handler handler ;
81
+
82
+ /**
83
+ * Creates a new AsyncHttpResponseHandler
84
+ */
85
+ public ImageHttpResponseHandler () {
86
+ super ();
87
+ }
88
+
89
+ /**
90
+ * Creates a new AsyncHttpResponseHandler, and overrides the default allowed image
91
+ * content types with passed String array (hopefully) of image content types.
92
+ */
93
+ public ImageHttpResponseHandler (String [] allowedContentTypes ) {
94
+ this ();
95
+ mAllowedContentTypes = allowedContentTypes ;
96
+ }
97
+
98
+
99
+ //
100
+ // Callbacks to be overridden, typically anonymously
101
+ //
102
+
103
+ /**
104
+ * Fired when a request returns successfully, override to handle in your own code
105
+ * @param content the body of the HTTP response from the server
106
+ */
107
+ public void onSuccess (byte [] imageData ) {}
108
+
109
+ /**
110
+ * Fired when a request fails to complete, override to handle in your own code
111
+ * @param error the underlying cause of the failure
112
+ * @deprecated use {@link #onFailure(Throwable, String)}
113
+ */
114
+ public void onFailure (Throwable error ) {}
115
+
116
+ /**
117
+ * Fired when a request fails to complete, override to handle in your own code
118
+ * @param error the underlying cause of the failure
119
+ * @param content the response body, if any
120
+ */
121
+ public void onFailure (Throwable error , byte [] imageData ) {
122
+ // By default, call the deprecated onFailure(Throwable) for compatibility
123
+ onFailure (error );
124
+ }
125
+
126
+
127
+ //
128
+ // Pre-processing of messages (executes in background threadpool thread)
129
+ //
130
+
131
+ protected void sendSuccessMessage (byte [] responseBody ) {
132
+ sendMessage (obtainMessage (SUCCESS_MESSAGE , responseBody ));
133
+ }
134
+
135
+ protected void sendFailureMessage (Throwable e , byte [] responseBody ) {
136
+ sendMessage (obtainMessage (FAILURE_MESSAGE , new Object []{e , responseBody }));
137
+ }
138
+
139
+ //
140
+ // Pre-processing of messages (in original calling thread, typically the UI thread)
141
+ //
142
+
143
+ protected void handleSuccessMessage (byte [] responseBody ) {
144
+ onSuccess (responseBody );
145
+ }
146
+
147
+ protected void handleFailureMessage (Throwable e , byte [] responseBody ) {
148
+ onFailure (e , responseBody );
149
+ }
150
+
151
+
152
+
153
+ // Methods which emulate android's Handler and Message methods
154
+ protected void handleMessage (Message msg ) {
155
+ switch (msg .what ) {
156
+ case SUCCESS_MESSAGE :
157
+ handleSuccessMessage ((byte [])msg .obj );
158
+ break ;
159
+ case FAILURE_MESSAGE :
160
+ Object [] response = (Object [])msg .obj ;
161
+ handleFailureMessage ((Throwable )response [0 ], (byte [])response [1 ]);
162
+ break ;
163
+ case START_MESSAGE :
164
+ onStart ();
165
+ break ;
166
+ case FINISH_MESSAGE :
167
+ onFinish ();
168
+ break ;
169
+ }
170
+ }
171
+
172
+ // Interface to AsyncHttpRequest
173
+ void sendResponseMessage (HttpResponse response ) {
174
+ StatusLine status = response .getStatusLine ();
175
+ Header [] contentTypeHeaders = response .getHeaders ("Content-Type" );
176
+ byte [] responseBody = null ;
177
+ if (contentTypeHeaders .length != 1 ) {
178
+ //malformed/ambiguous HTTP Header, ABORT!
179
+ sendFailureMessage (new HttpResponseException (status .getStatusCode (), "None, or more than one, Content-Type Header found!" ), responseBody );
180
+ return ;
181
+ }
182
+ Header contentTypeHeader = contentTypeHeaders [0 ];
183
+ boolean foundAllowedContentType = false ;
184
+ for (String anAllowedContentType : mAllowedContentTypes ) {
185
+ if (anAllowedContentType .equals (contentTypeHeader .getValue ())) {
186
+ foundAllowedContentType = true ;
187
+ }
188
+ }
189
+ if (!foundAllowedContentType ) {
190
+ //Content-Type not in allowed list, ABORT!
191
+ sendFailureMessage (new HttpResponseException (status .getStatusCode (), "Content-Type not allowed!" ), responseBody );
192
+ return ;
193
+ }
194
+ try {
195
+ HttpEntity entity = null ;
196
+ HttpEntity temp = response .getEntity ();
197
+ if (temp != null ) {
198
+ entity = new BufferedHttpEntity (temp );
199
+ }
200
+ responseBody = EntityUtils .toByteArray (entity );
201
+ } catch (IOException e ) {
202
+ sendFailureMessage (e , (byte []) null );
203
+ }
204
+
205
+ if (status .getStatusCode () >= 300 ) {
206
+ sendFailureMessage (new HttpResponseException (status .getStatusCode (), status .getReasonPhrase ()), responseBody );
207
+ } else {
208
+ sendSuccessMessage (responseBody );
209
+ }
210
+ }
211
+ }
0 commit comments