Glide POST request for image - android

I'm trying to download image from server with POST (json body). To accomplish that I created okhttp interceptor:
private static class PostThumbnailRequestInterceptor implements Interceptor {
private static final String DEVICE_GUID = "device_guid";
private static final String RESOURCE_GUIDS = "resource_guids";
private static final String UTC_TIMESTAMP = "utc_timestamp";
private String mChannelGuid;
private String mResourceGuid;
public PostThumbnailRequestInterceptor(String channelGuid, String resourceGuid) {
mChannelGuid = channelGuid;
mResourceGuid = resourceGuid;
}
#Override
public Response intercept(Chain chain) throws IOException {
final MediaType JSON
= MediaType.parse("application/json; charset=utf-8");
JSONArray resources = new JSONArray();
resources.put(mResourceGuid);
JSONObject requestedThumbnail = new JSONObject();
JSONObject payload = new JSONObject();
try {
requestedThumbnail.put(UTC_TIMESTAMP, System.currentTimeMillis() * 1000);
requestedThumbnail.put(DEVICE_GUID, mChannelGuid);
requestedThumbnail.put(RESOURCE_GUIDS, resources);
payload.put("thumbnails", new JSONArray() {{put(requestedThumbnail);}});
} catch (JSONException e) {
throw new IOException("Failed to create payload");
}
RequestBody body = RequestBody.create(JSON, payload.toString());
final Request original = chain.request();
final Request.Builder requestBuilder = original.newBuilder()
.url(original.url())
.post(body);
//return chain.proceed(requestBuilder.build());
Response response = chain.proceed(requestBuilder.build());
try {
MediaType contentType = MediaType.parse("data:image/jpeg;base64");// response.body().contentType();
JSONObject object = new JSONObject(response.body().string());
String base64String = object.optJSONArray("thumbnails").getJSONObject(0).optString("content");
base64String = base64String.replace("data:image/jpeg;base64,", "");
byte[] rawImage = Base64.decode(base64String , Base64.DEFAULT);
ResponseBody realResponseBody = ResponseBody.create(contentType, rawImage);
response = response.newBuilder().body(realResponseBody).build();
} catch (JSONException e) {
e.printStackTrace();
}
return response;
}
}
And using it like this
OkHttpClient mOkHttpClient = new OkHttpClient.Builder()
.addInterceptor(new PostThumbnailRequestInterceptor(channel.id.getServerId(), channel.id.getChannelId()))
.build();
GlideApp.get(getContext())
.getRegistry().replace(GlideUrl.class, InputStream.class, new OkHttpUrlLoader.Factory(mOkHttpClient));
It is works well with 1 request per time, but if I bind it with recycler view, replacing classes in Glide with dynamic interceptor produce a lot of errors (failed to load resource).
Am I on right way to request post or it is only 1 way - firstly request as usual and then pass decoded bytes to Glide?

Related

OkHttp image type

When I upload an image okHttp only accepts PNG? When I try jpg it denies.
This is my code:
public static Boolean uploadFile(final File file, final Context context) {
AsyncTask.THREAD_POOL_EXECUTOR.execute(new Runnable() {
#Override
public void run() {
try {
final MediaType MEDIA_TYPE_JPG = MediaType.parse("image");
//employee verkrijgen
DataLayer dataLayer = new DataLayer(context);
Employee employee = dataLayer.getEmployee();
dataLayer.close();
//request body aanmaken
RequestBody formBody = new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("ProfilePicture", file.getName(),
RequestBody.create(MEDIA_TYPE_JPG,file))
.addFormDataPart("api_token", employee.getApiToken())
.build();
Request request = new Request.Builder().url(static_urls.Employee.uploadProfilePicture(employee.getEmployeeId())).post(formBody).build();
OkHttpClient client = new OkHttpClient();
Response response = client.newCall(request).execute();
String responseString = response.body().string().substring(5000, response.body().string().length());
}
catch(Exception ex)
{
Log.e("upload",Log.getStackTraceString(ex));
}
}
});
return false;
}
What am I doing wrong?
use
MediaType.parse("image/jpeg");
Here is full list of mime types

Using Okhttp to get a json file but need to add a username and password

I am trying to log into server to receive a json file back. But the server needs a username and pass word. I don't know how to add that into my build. I looked at a lot of sources but I cannot figure it out what to add to my builder. Thank you very much for any help
Here is my OkhttpHandeler code
public class OkHttpHandler extends AsyncTask<String, Void, String> {
OkHttpClient client = new OkHttpClient();
Response response;
Request request;
private final String apUrl = "http://xxxxxxxx.xxxxxx.com/api/1.0/promotions";
String output;
String picture;
//JSon Data
String jsonData;
JSONObject jsonObject;
JSONArray jsonArray;
#Override
protected String doInBackground(String... params) {
RequestBody formbody = new FormBody.Builder()
.add("username", "admin")
.add("password", "admin")
.build();
//Request.Builder builder = new Request.Builder();
//builder.url(params[0]);
request = new Request.Builder()
.url(apUrl)
.post(formbody)
.build();
//request = builder.build();
try {
response = client.newCall(request).execute();
Log.d("Respones:", response.body().string());
output = response.body().string();
jsonData = output;
try {
jsonObject = new JSONObject(jsonData);
jsonArray = jsonObject.getJSONArray("");
} catch (JSONException e) {
e.printStackTrace();
}
try {
JSONObject object = jsonArray.getJSONObject(0);
picture = object.getString("picture");
} catch (JSONException e) {
e.printStackTrace();
}
//return response.body().bytes();
return picture;
}catch (Exception e){
e.printStackTrace();
}
return null;
}
}

OKHTTP is secure?

I am building an android app that needs to log the user to our server and the connection needs to be secure (HTTPs). My question is, should I use OKHTTP library for this purpose?
I use the library to log a user as follows:
public class MainActivity extends AppCompatActivity {
public static final MediaType JSON
= MediaType.parse("application/json; charset=utf-8");
private static final String TAG = MainActivity.class.getSimpleName();
private JSONObject responseJson;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
final JSONObject myJson = new JSONObject();
try {
myJson.put("udid","c376e418-da42-39fb-0000-d821f1fd2804");
myJson.put("email","email
myJson.put("password","password");
} catch (JSONException e) {
e.printStackTrace();
}
Thread thread = new Thread(new Runnable(){
#Override
public void run() {
try {
//Your code goes here
String response = post("https://ADDRESS/v1/auth", myJson.toString());
responseJson = new JSONObject(response);
String message = responseJson.getString("message");
String token = responseJson.getString("token");
Log.d(TAG,"Response message: " + message);
Log.d(TAG,"Response token: " + token);
Log.d("MainActivity",response);
} catch (Exception e) {
e.printStackTrace();
}
}
});
thread.start();
}
String post(String url, String json) throws IOException {
OkHttpClient client = new OkHttpClient();
RequestBody body = RequestBody.create(JSON, json);
Request request = new Request.Builder()
.url(url)
.post(body)
.build();
Response response = client.newCall(request).execute();
return response.body().string();
}
}
should I use OKHTTP library for this purpose?
OkHttp supports https URLs, as do most HTTP client libraries for Android.

Retrofit2: Modifying request body in OkHttp Interceptor

I am using Retrofit 2 (2.0.0-beta3) with OkHttp client in Android application and so far everything going great. But currently I am facing issue with OkHttp Interceptor. The server I am communicating with is taking access token in body of request, so when I intercept the request to add auth token or in authenticate method of Authenticator when I need to add updated auth token, I need to modify body of request for this purpose. But it looks like I can only add data in headers but not in the body of ongoing request. The code I have written so far is as follows:
client.interceptors().add(new Interceptor() {
#Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
if (UserPreferences.ACCESS_TOKEN != null) {
// need to add this access token in request body as encoded form field instead of header
request = request.newBuilder()
.header("access_token", UserPreferences.ACCESS_TOKEN))
.method(request.method(), request.body())
.build();
}
Response response = chain.proceed(request);
return response;
}
});
Can anyone point me to the right direction as how to modify request body to add my access token (first time or updated after token refresh)? Any pointer to right direction would be appreciated.
I using this to add post parameter to the existing ones.
OkHttpClient client = new OkHttpClient.Builder()
.protocols(protocols)
.addInterceptor(new Interceptor() {
#Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
Request.Builder requestBuilder = request.newBuilder();
RequestBody formBody = new FormEncodingBuilder()
.add("email", "Jurassic#Park.com")
.add("tel", "90301171XX")
.build();
String postBodyString = Utils.bodyToString(request.body());
postBodyString += ((postBodyString.length() > 0) ? "&" : "") + Utils.bodyToString(formBody);
request = requestBuilder
.post(RequestBody.create(MediaType.parse("application/x-www-form-urlencoded;charset=UTF-8"), postBodyString))
.build();
return chain.proceed(request);
}
})
.build();
public static String bodyToString(final RequestBody request){
try {
final RequestBody copy = request;
final Buffer buffer = new Buffer();
if(copy != null)
copy.writeTo(buffer);
else
return "";
return buffer.readUtf8();
}
catch (final IOException e) {
return "did not work";
}
}
OkHttp3:
RequestBody formBody = new FormBody.Builder()
.add("email", "Jurassic#Park.com")
.add("tel", "90301171XX")
.build();
I'll share my Kotlin implementation of #Fabian's answer using Dagger. I wanted origin=app added to the request url for GET requests, and added to the body for form-encoded POST requests
#Provides
#Singleton
fun providesRequestInterceptor() =
Interceptor {
val request = it.request()
it.proceed(when (request.method()) {
"GET" -> {
val url = request.url()
request.newBuilder()
.url(url.newBuilder()
.addQueryParameter("origin", "app")
.build())
.build()
}
"POST" -> {
val body = request.body()
request.newBuilder()
.post(RequestBody.create(body?.contentType(),
body.bodyToString() + "&origin=app"))
.build()
}
else -> request
})
}
fun RequestBody?.bodyToString(): String {
if (this == null) return ""
val buffer = okio.Buffer()
writeTo(buffer)
return buffer.readUtf8()
}
Since this cannot be written in the comments of the previous answer by #Fabian, I am posting this one as separate answer. This answer deals with both "application/json" as well as form data.
import android.content.Context;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.IOException;
import okhttp3.FormBody;
import okhttp3.Interceptor;
import okhttp3.MediaType;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okio.Buffer;
/**
* Created by debanjan on 16/4/17.
*/
public class TokenInterceptor implements Interceptor {
private Context context; //This is here because I needed it for some other cause
//private static final String TOKEN_IDENTIFIER = "token_id";
public TokenInterceptor(Context context) {
this.context = context;
}
#Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
RequestBody requestBody = request.body();
String token = "toku";//whatever or however you get it.
String subtype = requestBody.contentType().subtype();
if(subtype.contains("json")){
requestBody = processApplicationJsonRequestBody(requestBody, token);
}
else if(subtype.contains("form")){
requestBody = processFormDataRequestBody(requestBody, token);
}
if(requestBody != null) {
Request.Builder requestBuilder = request.newBuilder();
request = requestBuilder
.post(requestBody)
.build();
}
return chain.proceed(request);
}
private String bodyToString(final RequestBody request){
try {
final RequestBody copy = request;
final Buffer buffer = new Buffer();
if(copy != null)
copy.writeTo(buffer);
else
return "";
return buffer.readUtf8();
}
catch (final IOException e) {
return "did not work";
}
}
private RequestBody processApplicationJsonRequestBody(RequestBody requestBody,String token){
String customReq = bodyToString(requestBody);
try {
JSONObject obj = new JSONObject(customReq);
obj.put("token", token);
return RequestBody.create(requestBody.contentType(), obj.toString());
} catch (JSONException e) {
e.printStackTrace();
}
return null;
}
private RequestBody processFormDataRequestBody(RequestBody requestBody, String token){
RequestBody formBody = new FormBody.Builder()
.add("token", token)
.build();
String postBodyString = bodyToString(requestBody);
postBodyString += ((postBodyString.length() > 0) ? "&" : "") + bodyToString(formBody);
return RequestBody.create(requestBody.contentType(), postBodyString);
}
}
You can edit the request body by below method, Pass the request and the parameter to edit.
private fun editBody(request: Request, parameter: String): RequestBody {
val oldBody = request.body //retrieve the current request body
val buffer = Buffer()
oldBody?.writeTo(buffer)
val strOldBody = buffer.readUtf8() // String representation of the current request body
buffer.clear()
buffer.close()
val strNewBody = JSONObject(strOldBody).put("parameter", parameter).toString()
return strNewBody.toRequestBody(request.body?.contentType()) // New request body with the encrypted/modified string of the current request body
}
Now you can request again with updated request body
override fun intercept(chain: Interceptor.Chain): Response {
val request: Request = chain.request()
return chain.proceed(requestWithUpdatedParameter(request, "parameter"))
}
private fun requestWithUpdatedParameter(req: Request, parameter: String): Request {
val newRequest: Request
val body = editBody(req, parameter)
newRequest = req.newBuilder().method(req.method, body).build()
return newRequest
}
private static class NetworkInterceptor implements Interceptor {
#Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
RequestBody oldBody = request.body(); //retrieve the current request body
Buffer buffer = new Buffer();
oldBody.writeTo(buffer);
String strOldBody = buffer.readUtf8(); // String representation of the current request body
buffer.clear();
buffer.close();
MediaType mediaType = MediaType.parse("application/json; charset=UTF-8");
String strNewBody = enDecService.encryptBody(strOldBody); // Your encryption/ modification logic
RequestBody body = RequestBody.create(mediaType, strNewBody); // New request body with the encrypted/modified string of the current request body
request = request.newBuilder()
.header("Content-Type", "application/json")
.header("Content-Length", String.valueOf(body.contentLength()))
.header("Authorization", "Bearer " + "your token")
.method(request.method(), body).build();
long t1 = System.nanoTime();
Log.d(TAG, String.format("Sending request %s on %s", request.url(), request.headers()));
Response response = chain.proceed(request); // sending req. to server. current req. body is a encrypted string.
int maxAge = 6000; // read from cache for 6000 seconds even if there is internet connection
response.header("Cache-Control", "public, max-age=" + maxAge);
response = response.newBuilder().removeHeader("Pragma").build();
long t2 = System.nanoTime();
Log.d(TAG, String.format("Received response for %s in %.1fms %s", response.request().url(), (t2 - t1) / 1e6d, response.toString()));
try {
String s = response.body().string(); // retrieve string representation of encrypted response assuming your response is encrypted.
ResponseBody responseBody = ResponseBody.create(mediaType, enDecService.decryptBody(s)); // decrypt the encrypted response or make other modifications.yor decryption/modifications logic goes here.
response = response.newBuilder().body(responseBody).build(); // build a new response with the decrypted response body.
} catch (JOSEException e) {
} catch (ParseException e) {
}
return response;
}
}
I'm using this way to verify my token
final OkHttpClient okHttpClient = new OkHttpClient.Builder()
.connectTimeout(30, TimeUnit.SECONDS) //retrofit default 10 seconds
.writeTimeout(30, TimeUnit.SECONDS) //retrofit default 10 seconds
.readTimeout(30, TimeUnit.SECONDS) //retrofit default 10 seconds
.addInterceptor(logging.setLevel(HttpLoggingInterceptor.Level.BODY))
.addInterceptor(new BasicAuthInterceptor())
.build();
Here i'm sending token through BasicAuthInterceptor
public class MyServiceInterceptor implements Interceptor {
private String HEADER_NAME="Authorization";
private String OBJECT_NAME="Bearer";
private String SPACE=" ";
#Override public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
Request.Builder requestBuilder = request.newBuilder();
String token= PreferenceManager.getInstance().getString(PreferenceManager.TOKEN);
if (token != null) { {
requestBuilder.addHeader(HEADER_NAME, OBJECT_NAME+SPACE+ token);
}
}
return chain.proceed(requestBuilder.build());
}
}

Android OkHttpClient POST\PUT requests received as GET

I'm trying to send post/put request to my service using OkHttp library.
private static final String SERVICE = "service_url";
private static final MediaType JSON = MediaType.parse("text/json");
private OkHttpClient mClient = new OkHttpClient();
//---------------------------------------------------------------
Request req = new Request.Builder()
.url(SERVICE)
.put(RequestBody.create(JSON, body))
.build();
try {
Response httpResp = mClient.newCall(req).execute();
resp = httpResp.body().string();
} catch (IOException ex) {
ex.printStackTrace();
}
But this code sends GET request, not PUT. The same situation will be if I use .post.
I was trying to use HttpURLConnection and I've got the same result.
What am I doing wrong?

Categories

Resources