Skip to content

Commit

Permalink
Android: Allow to provide a different HttpClient implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
anod committed Feb 1, 2023
1 parent e8eb28f commit b07bfd0
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 18 deletions.
4 changes: 4 additions & 0 deletions lib/android_build/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ android {
version "3.10.2"
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}

dependencies {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,17 +23,20 @@
import android.os.Build;
import android.provider.Settings;
import android.util.Log;

import androidx.annotation.Keep;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;

import java.io.BufferedInputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
Expand Down Expand Up @@ -86,16 +89,15 @@ public final void onCapabilitiesChanged(
private boolean m_metered;
}

class Request implements Runnable {
class Request implements HttpClientRequest {

Request(
HttpClient parent,
String url,
String method,
byte[] body,
String request_id,
int[] header_length,
byte[] header_buffer)
@NonNull HttpClient parent,
String url,
String method,
byte[] body,
String request_id,
@NonNull Map<String, String> headers)
throws java.io.IOException {
m_parent = parent;
m_connection = (HttpURLConnection) parent.newUrl(url).openConnection();
Expand All @@ -106,13 +108,8 @@ class Request implements Runnable {
m_connection.setDoOutput(true);
}
m_request_id = request_id;
int offset = 0;
for (int i = 0; i + 1 < header_length.length; i += 2) {
String k = new String(header_buffer, offset, header_length[i], UTF_8);
offset += header_length[i];
String v = new String(header_buffer, offset, header_length[i + 1], UTF_8);
offset += header_length[i + 1];
m_connection.setRequestProperty(k, v);
for (Map.Entry<String, String> header : headers.entrySet()) {
m_connection.setRequestProperty(header.getKey(), header.getValue());
}
}

Expand Down Expand Up @@ -188,9 +185,25 @@ public class HttpClient {
private static final String ANDROID_DEVICE_CLASS_PC = "Android.PC";
private static final String ANDROID_DEVICE_CLASS_PHONE = "Android.Phone";

static Map<String, String> convertHeaders(
int[] header_length,
byte[] header_buffer
) {
int offset = 0;
Map<String, String> result = new HashMap<>(header_length.length);
for (int i = 0; i + 1 < header_length.length; i += 2) {
String k = new String(header_buffer, offset, header_length[i], UTF_8);
offset += header_length[i];
String v = new String(header_buffer, offset, header_length[i + 1], UTF_8);
offset += header_length[i + 1];
result.put(k, v);
}
return result;
}

/** Shim FutureTask: we would like to @Keep the cancel method for JNI */
static class FutureShim extends FutureTask<Boolean> {
FutureShim(Request inner) {
FutureShim(HttpClientRequest inner) {
super(inner, true);
}

Expand All @@ -202,7 +215,12 @@ public boolean cancel(boolean mayInterruptIfRunning) {
}

public HttpClient(Context context) {
this(context, new HttpClientRequest.Factory.AndroidUrlConnection());
}

public HttpClient(Context context, HttpClientRequest.Factory requestFactory) {
m_context = context;
m_requestFactory = requestFactory;
String path = System.getProperty("java.io.tmpdir");
setCacheFilePath(path);
setDeviceInfo(calculateID(context), Build.MANUFACTURER, Build.MODEL);
Expand Down Expand Up @@ -376,7 +394,8 @@ public FutureTask<Boolean> createTask(
int[] header_index,
byte[] header_buffer) {
try {
Request r = new Request(this, url, method, body, request_id, header_index, header_buffer);
Map<String, String> headers = HttpClient.convertHeaders(header_index, header_buffer);
HttpClientRequest r = m_requestFactory.create(this, url, method, body, request_id, headers);
return new FutureShim(r);
} catch (Exception e) {
return null;
Expand All @@ -393,4 +412,5 @@ public void executeTask(FutureTask<Boolean> t) {
private android.net.ConnectivityManager m_connectivityManager;
private PowerInfoReceiver m_power_receiver;
private final Context m_context;
}
private final HttpClientRequest.Factory m_requestFactory;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
//
// Copyright (c) Microsoft Corporation. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
//
package com.microsoft.applications.events;

import androidx.annotation.NonNull;

import java.io.IOException;
import java.util.Map;

public interface HttpClientRequest extends Runnable {

interface Factory {
HttpClientRequest create(
@NonNull HttpClient parent,
String url,
String method,
byte[] body,
String request_id,
@NonNull Map<String, String> headers
) throws IOException;

class AndroidUrlConnection implements HttpClientRequest.Factory {
@Override
public HttpClientRequest create(@NonNull HttpClient parent, String url, String method, byte[] body, String request_id, @NonNull Map<String, String> headers) throws IOException {
return new Request(parent, url, method, body, request_id, headers);
}
}
}
}

0 comments on commit b07bfd0

Please sign in to comment.