Add proxy settings
This commit is contained in:
parent
bb45d82b08
commit
19e1e4afdb
323
app/src/main/java/de/danoeh/antennapod/dialog/ProxyDialog.java
Normal file
323
app/src/main/java/de/danoeh/antennapod/dialog/ProxyDialog.java
Normal file
@ -0,0 +1,323 @@
|
||||
package de.danoeh.antennapod.dialog;
|
||||
|
||||
import android.app.Dialog;
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.text.Editable;
|
||||
import android.text.TextUtils;
|
||||
import android.text.TextWatcher;
|
||||
import android.util.Patterns;
|
||||
import android.view.View;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.EditText;
|
||||
import android.widget.Spinner;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.afollestad.materialdialogs.DialogAction;
|
||||
import com.afollestad.materialdialogs.MaterialDialog;
|
||||
import com.afollestad.materialdialogs.internal.MDButton;
|
||||
import com.squareup.okhttp.Credentials;
|
||||
import com.squareup.okhttp.OkHttpClient;
|
||||
import com.squareup.okhttp.Request;
|
||||
import com.squareup.okhttp.Response;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.Proxy;
|
||||
import java.net.SocketAddress;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import de.danoeh.antennapod.R;
|
||||
import de.danoeh.antennapod.core.preferences.UserPreferences;
|
||||
import de.danoeh.antennapod.core.service.download.AntennapodHttpClient;
|
||||
import de.danoeh.antennapod.core.service.download.ProxyConfig;
|
||||
import rx.Observable;
|
||||
import rx.Subscriber;
|
||||
import rx.Subscription;
|
||||
import rx.android.schedulers.AndroidSchedulers;
|
||||
import rx.schedulers.Schedulers;
|
||||
|
||||
public class ProxyDialog {
|
||||
|
||||
private static final String TAG = "ProxyDialog";
|
||||
|
||||
private Context context;
|
||||
|
||||
private MaterialDialog dialog;
|
||||
|
||||
private Spinner spType;
|
||||
private EditText etHost;
|
||||
private EditText etPort;
|
||||
private EditText etUsername;
|
||||
private EditText etPassword;
|
||||
|
||||
private boolean testSuccessful = false;
|
||||
private TextView txtvMessage;
|
||||
private Subscription subscription;
|
||||
|
||||
public ProxyDialog(Context context) {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
public Dialog createDialog() {
|
||||
dialog = new MaterialDialog.Builder(context)
|
||||
.title(R.string.pref_proxy_title)
|
||||
.customView(R.layout.proxy_settings, true)
|
||||
.positiveText(R.string.proxy_test_label)
|
||||
.negativeText(R.string.cancel_label)
|
||||
.onPositive((dialog1, which) -> {
|
||||
if(!testSuccessful) {
|
||||
dialog.getActionButton(DialogAction.POSITIVE).setEnabled(false);
|
||||
test();
|
||||
return;
|
||||
}
|
||||
String type = (String) ((Spinner) dialog1.findViewById(R.id.spType)).getSelectedItem();
|
||||
ProxyConfig proxy;
|
||||
if(Proxy.Type.valueOf(type) == Proxy.Type.DIRECT) {
|
||||
proxy = ProxyConfig.direct();
|
||||
} else {
|
||||
String host = etHost.getText().toString();
|
||||
String port = etPort.getText().toString();
|
||||
String username = etUsername.getText().toString();
|
||||
if(TextUtils.isEmpty(username)) {
|
||||
username = null;
|
||||
}
|
||||
String password = etPassword.getText().toString();
|
||||
if(TextUtils.isEmpty(password)) {
|
||||
password = null;
|
||||
}
|
||||
int portValue = 0;
|
||||
if(!TextUtils.isEmpty(port)) {
|
||||
portValue = Integer.valueOf(port);
|
||||
}
|
||||
proxy = ProxyConfig.http(host, portValue, username, password);
|
||||
}
|
||||
UserPreferences.setProxyConfig(proxy);
|
||||
AntennapodHttpClient.reinit();
|
||||
dialog.dismiss();
|
||||
})
|
||||
.onNegative((dialog1, which) -> {
|
||||
dialog1.dismiss();
|
||||
})
|
||||
.autoDismiss(false)
|
||||
.build();
|
||||
View view = dialog.getCustomView();
|
||||
spType = (Spinner) view.findViewById(R.id.spType);
|
||||
String[] types = { Proxy.Type.DIRECT.name(), Proxy.Type.HTTP.name() };
|
||||
ArrayAdapter<String> adapter = new ArrayAdapter<>(context,
|
||||
android.R.layout.simple_spinner_item, types);
|
||||
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
||||
spType.setAdapter(adapter);
|
||||
ProxyConfig proxyConfig = UserPreferences.getProxyConfig();
|
||||
spType.setSelection(adapter.getPosition(proxyConfig.type.name()));
|
||||
etHost = (EditText) view.findViewById(R.id.etHost);
|
||||
if(!TextUtils.isEmpty(proxyConfig.host)) {
|
||||
etHost.setText(proxyConfig.host);
|
||||
}
|
||||
etHost.addTextChangedListener(requireTestOnChange);
|
||||
etPort = (EditText) view.findViewById(R.id.etPort);
|
||||
if(proxyConfig.port > 0) {
|
||||
etPort.setText(String.valueOf(proxyConfig.port));
|
||||
}
|
||||
etPort.addTextChangedListener(requireTestOnChange);
|
||||
etUsername = (EditText) view.findViewById(R.id.etUsername);
|
||||
if(!TextUtils.isEmpty(proxyConfig.username)) {
|
||||
etUsername.setText(proxyConfig.username);
|
||||
}
|
||||
etUsername.addTextChangedListener(requireTestOnChange);
|
||||
etPassword = (EditText) view.findViewById(R.id.etPassword);
|
||||
if(!TextUtils.isEmpty(proxyConfig.password)) {
|
||||
etPassword.setText(proxyConfig.username);
|
||||
}
|
||||
etPassword.addTextChangedListener(requireTestOnChange);
|
||||
if(proxyConfig.type == Proxy.Type.DIRECT) {
|
||||
enableSettings(false);
|
||||
setTestRequired(false);
|
||||
}
|
||||
spType.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
|
||||
@Override
|
||||
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
|
||||
enableSettings(position > 0);
|
||||
setTestRequired(position > 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNothingSelected(AdapterView<?> parent) {
|
||||
enableSettings(false);
|
||||
}
|
||||
});
|
||||
txtvMessage = (TextView) view.findViewById(R.id.txtvMessage);
|
||||
checkValidity();
|
||||
return dialog;
|
||||
}
|
||||
|
||||
private final TextWatcher requireTestOnChange = new TextWatcher() {
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
|
||||
|
||||
@Override
|
||||
public void onTextChanged(CharSequence s, int start, int before, int count) {}
|
||||
|
||||
@Override
|
||||
public void afterTextChanged(Editable s) {
|
||||
setTestRequired(true);
|
||||
}
|
||||
};
|
||||
|
||||
private void enableSettings(boolean enable) {
|
||||
etHost.setEnabled(enable);
|
||||
etPort.setEnabled(enable);
|
||||
etUsername.setEnabled(enable);
|
||||
etPassword.setEnabled(enable);
|
||||
}
|
||||
|
||||
private boolean checkValidity() {
|
||||
boolean valid = true;
|
||||
if(spType.getSelectedItemPosition() > 0) {
|
||||
valid &= checkHost();
|
||||
}
|
||||
valid &= checkPort();
|
||||
return valid;
|
||||
}
|
||||
|
||||
private boolean checkHost() {
|
||||
String host = etHost.getText().toString();
|
||||
if(host.length() == 0) {
|
||||
etHost.setError(context.getString(R.string.proxy_host_empty_error));
|
||||
return false;
|
||||
}
|
||||
if(!"localhost".equals(host) && !Patterns.DOMAIN_NAME.matcher(host).matches()) {
|
||||
etHost.setError(context.getString(R.string.proxy_host_invalid_error));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean checkPort() {
|
||||
int port = getPort();
|
||||
if(port < 0 && port > 65535) {
|
||||
etPort.setError(context.getString(R.string.proxy_port_invalid_error));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private int getPort() {
|
||||
String port = etPort.getText().toString();
|
||||
if(port.length() > 0) {
|
||||
try {
|
||||
int portValue = Integer.parseInt(port);
|
||||
return portValue;
|
||||
} catch(NumberFormatException e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
private void setTestRequired(boolean required) {
|
||||
if(required) {
|
||||
testSuccessful = false;
|
||||
MDButton button = dialog.getActionButton(DialogAction.POSITIVE);
|
||||
button.setText(context.getText(R.string.proxy_test_label));
|
||||
button.setEnabled(true);
|
||||
} else {
|
||||
testSuccessful = true;
|
||||
MDButton button = dialog.getActionButton(DialogAction.POSITIVE);
|
||||
button.setText(context.getText(android.R.string.ok));
|
||||
button.setEnabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
private void test() {
|
||||
if(subscription != null) {
|
||||
subscription.unsubscribe();
|
||||
}
|
||||
if(!checkValidity()) {
|
||||
setTestRequired(true);
|
||||
return;
|
||||
}
|
||||
TypedArray res = context.getTheme().obtainStyledAttributes(new int[] { android.R.attr.textColorPrimary });
|
||||
int textColorPrimary = res.getColor(0, 0);
|
||||
res.recycle();
|
||||
String checking = context.getString(R.string.proxy_checking);
|
||||
txtvMessage.setTextColor(textColorPrimary);
|
||||
txtvMessage.setText("{fa-circle-o-notch spin} " + checking);
|
||||
txtvMessage.setVisibility(View.VISIBLE);
|
||||
subscription = Observable.create(new Observable.OnSubscribe<Response>() {
|
||||
@Override
|
||||
public void call(Subscriber<? super Response> subscriber) {
|
||||
String type = (String) spType.getSelectedItem();
|
||||
String host = etHost.getText().toString();
|
||||
String port = etPort.getText().toString();
|
||||
String username = etUsername.getText().toString();
|
||||
String password = etPassword.getText().toString();
|
||||
int portValue = 8080;
|
||||
if(!TextUtils.isEmpty(port)) {
|
||||
portValue = Integer.valueOf(port);
|
||||
}
|
||||
SocketAddress address = InetSocketAddress.createUnresolved(host, portValue);
|
||||
Proxy.Type proxyType = Proxy.Type.valueOf(type.toUpperCase());
|
||||
Proxy proxy = new Proxy(proxyType, address);
|
||||
OkHttpClient client = AntennapodHttpClient.newHttpClient();
|
||||
client.setConnectTimeout(10, TimeUnit.SECONDS);
|
||||
client.setProxy(proxy);
|
||||
client.interceptors().clear();
|
||||
if(!TextUtils.isEmpty(username)) {
|
||||
String credentials = Credentials.basic(username, password);
|
||||
client.interceptors().add(chain -> {
|
||||
Request request = chain.request().newBuilder()
|
||||
.header("Proxy-Authorization", credentials).build();
|
||||
return chain.proceed(request);
|
||||
});
|
||||
}
|
||||
Request request = new Request.Builder()
|
||||
.url("http://www.google.com")
|
||||
.head()
|
||||
.build();
|
||||
try {
|
||||
Response response = client.newCall(request).execute();
|
||||
subscriber.onNext(response);
|
||||
} catch(IOException e) {
|
||||
subscriber.onError(e);
|
||||
}
|
||||
subscriber.onCompleted();
|
||||
}
|
||||
})
|
||||
.subscribeOn(Schedulers.newThread())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(
|
||||
response -> {
|
||||
int colorId;
|
||||
String icon;
|
||||
String result;
|
||||
if(response.isSuccessful()) {
|
||||
colorId = R.color.download_success_green;
|
||||
icon = "{fa-check}";
|
||||
result = context.getString(R.string.proxy_test_successful);
|
||||
} else {
|
||||
colorId = R.color.download_failed_red;
|
||||
icon = "{fa-close}";
|
||||
result = context.getString(R.string.proxy_test_failed);
|
||||
}
|
||||
int color = ContextCompat.getColor(context, colorId);
|
||||
txtvMessage.setTextColor(color);
|
||||
String message = String.format("%s %s: %s", icon, result, response.message());
|
||||
txtvMessage.setText(message);
|
||||
setTestRequired(!response.isSuccessful());
|
||||
},
|
||||
error -> {
|
||||
String icon = "{fa-close}";
|
||||
String result = context.getString(R.string.proxy_test_failed);
|
||||
int color = ContextCompat.getColor(context, R.color.download_failed_red);
|
||||
txtvMessage.setTextColor(color);
|
||||
String message = String.format("%s %s: %s", icon, result, error.getMessage());
|
||||
txtvMessage.setText(message);
|
||||
setTestRequired(true);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
}
|
@ -58,6 +58,7 @@ import de.danoeh.antennapod.core.util.flattr.FlattrUtils;
|
||||
import de.danoeh.antennapod.dialog.AuthenticationDialog;
|
||||
import de.danoeh.antennapod.dialog.AutoFlattrPreferenceDialog;
|
||||
import de.danoeh.antennapod.dialog.GpodnetSetHostnameDialog;
|
||||
import de.danoeh.antennapod.dialog.ProxyDialog;
|
||||
import de.danoeh.antennapod.dialog.VariableSpeedDialog;
|
||||
|
||||
/**
|
||||
@ -82,6 +83,7 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc
|
||||
public static final String PREF_GPODNET_LOGOUT = "pref_gpodnet_logout";
|
||||
public static final String PREF_GPODNET_HOSTNAME = "pref_gpodnet_hostname";
|
||||
public static final String PREF_EXPANDED_NOTIFICATION = "prefExpandNotify";
|
||||
public static final String PREF_PROXY = "prefProxy";
|
||||
|
||||
private final PreferenceUI ui;
|
||||
|
||||
@ -356,6 +358,11 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc
|
||||
return false;
|
||||
}
|
||||
);
|
||||
ui.findPreference(PREF_PROXY).setOnPreferenceClickListener(preference -> {
|
||||
ProxyDialog dialog = new ProxyDialog(ui.getActivity());
|
||||
dialog.createDialog().show();
|
||||
return true;
|
||||
});
|
||||
ui.findPreference("prefSendCrashReport").setOnPreferenceClickListener(preference -> {
|
||||
Intent emailIntent = new Intent(Intent.ACTION_SEND);
|
||||
emailIntent.setType("text/plain");
|
||||
|
90
app/src/main/res/layout/proxy_settings.xml
Normal file
90
app/src/main/res/layout/proxy_settings.xml
Normal file
@ -0,0 +1,90 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txtvType"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/proxy_type_label"
|
||||
android:textColor="?android:attr/textColorSecondary" />
|
||||
|
||||
<Spinner
|
||||
android:id="@+id/spType"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txtvHost"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:text="@string/host_label"
|
||||
android:textColor="?android:attr/textColorSecondary" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/etHost"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:singleLine="true"
|
||||
android:inputType="textUri"
|
||||
android:hint="www.example.com" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txtvPort"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:text="@string/port_label"
|
||||
android:textColor="?android:attr/textColorSecondary" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/etPort"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="8080"
|
||||
android:inputType="number" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txtvUsername"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:singleLine="true"
|
||||
android:text="@string/username_label"
|
||||
android:textColor="?android:attr/textColorSecondary" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/etUsername"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/optional_hint" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txtvPassword"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:text="@string/password_label"
|
||||
android:textColor="?android:attr/textColorSecondary" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/etPassword"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/optional_hint"
|
||||
android:inputType="textPassword" />
|
||||
|
||||
<com.joanzapata.iconify.widget.IconTextView
|
||||
android:id="@+id/txtvMessage"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:visibility="invisible"
|
||||
android:gravity="center"/>
|
||||
|
||||
</LinearLayout>
|
@ -200,8 +200,11 @@
|
||||
android:key="prefEnableAutoDownloadWifiFilter"
|
||||
android:title="@string/pref_autodl_wifi_filter_title"
|
||||
android:summary="@string/pref_autodl_wifi_filter_sum"/>
|
||||
|
||||
</PreferenceScreen>
|
||||
<Preference
|
||||
android:key="prefProxy"
|
||||
android:summary="@string/pref_proxy_sum"
|
||||
android:title="@string/pref_proxy_title" />
|
||||
|
||||
</PreferenceCategory>
|
||||
|
||||
|
@ -17,6 +17,7 @@ import org.json.JSONException;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.Proxy;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Calendar;
|
||||
@ -25,6 +26,7 @@ import java.util.concurrent.TimeUnit;
|
||||
|
||||
import de.danoeh.antennapod.core.R;
|
||||
import de.danoeh.antennapod.core.receiver.FeedUpdateReceiver;
|
||||
import de.danoeh.antennapod.core.service.download.ProxyConfig;
|
||||
import de.danoeh.antennapod.core.storage.APCleanupAlgorithm;
|
||||
import de.danoeh.antennapod.core.storage.APNullCleanupAlgorithm;
|
||||
import de.danoeh.antennapod.core.storage.APQueueCleanupAlgorithm;
|
||||
@ -78,6 +80,11 @@ public class UserPreferences {
|
||||
public static final String PREF_ENABLE_AUTODL_ON_BATTERY = "prefEnableAutoDownloadOnBattery";
|
||||
public static final String PREF_ENABLE_AUTODL_WIFI_FILTER = "prefEnableAutoDownloadWifiFilter";
|
||||
public static final String PREF_AUTODL_SELECTED_NETWORKS = "prefAutodownloadSelectedNetworks";
|
||||
public static final String PREF_PROXY_TYPE = "prefProxyType";
|
||||
public static final String PREF_PROXY_HOST = "prefProxyHost";
|
||||
public static final String PREF_PROXY_PORT = "prefProxyPort";
|
||||
public static final String PREF_PROXY_USER = "prefProxyUser";
|
||||
public static final String PREF_PROXY_PASSWORD = "prefProxyPassword";
|
||||
|
||||
// Services
|
||||
public static final String PREF_AUTO_FLATTR = "pref_auto_flattr";
|
||||
@ -371,6 +378,42 @@ public class UserPreferences {
|
||||
return TextUtils.split(selectedNetWorks, ",");
|
||||
}
|
||||
|
||||
public static void setProxyConfig(ProxyConfig config) {
|
||||
SharedPreferences.Editor editor = prefs.edit();
|
||||
editor.putString(PREF_PROXY_TYPE, config.type.name());
|
||||
if(TextUtils.isEmpty(config.host)) {
|
||||
editor.remove(PREF_PROXY_HOST);
|
||||
} else {
|
||||
editor.putString(PREF_PROXY_HOST, config.host);
|
||||
}
|
||||
if(config.port <= 0 || config.port > 65535) {
|
||||
editor.remove(PREF_PROXY_PORT);
|
||||
} else {
|
||||
editor.putInt(PREF_PROXY_PORT, config.port);
|
||||
}
|
||||
if(TextUtils.isEmpty(config.username)) {
|
||||
editor.remove(PREF_PROXY_USER);
|
||||
} else {
|
||||
editor.putString(PREF_PROXY_USER, config.username);
|
||||
}
|
||||
if(TextUtils.isEmpty(config.password)) {
|
||||
editor.remove(PREF_PROXY_PASSWORD);
|
||||
} else {
|
||||
editor.putString(PREF_PROXY_PASSWORD, config.password);
|
||||
}
|
||||
editor.apply();
|
||||
}
|
||||
|
||||
public static ProxyConfig getProxyConfig() {
|
||||
Proxy.Type type = Proxy.Type.valueOf(prefs.getString(PREF_PROXY_TYPE, Proxy.Type.DIRECT.name()));
|
||||
String host = prefs.getString(PREF_PROXY_HOST, null);
|
||||
int port = prefs.getInt(PREF_PROXY_PORT, 0);
|
||||
String username = prefs.getString(PREF_PROXY_USER, null);
|
||||
String password = prefs.getString(PREF_PROXY_PASSWORD, null);
|
||||
ProxyConfig config = new ProxyConfig(type, host, port, username, password);
|
||||
return config;
|
||||
}
|
||||
|
||||
public static boolean shouldResumeAfterCall() {
|
||||
return prefs.getBoolean(PREF_RESUME_AFTER_CALL, true);
|
||||
}
|
||||
|
@ -2,8 +2,10 @@ package de.danoeh.antennapod.core.service.download;
|
||||
|
||||
import android.os.Build;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import com.squareup.okhttp.Credentials;
|
||||
import com.squareup.okhttp.OkHttpClient;
|
||||
import com.squareup.okhttp.Request;
|
||||
import com.squareup.okhttp.Response;
|
||||
@ -14,7 +16,10 @@ import java.net.CookieManager;
|
||||
import java.net.CookiePolicy;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.Proxy;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketAddress;
|
||||
import java.net.URL;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
@ -23,6 +28,7 @@ import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.SSLSocket;
|
||||
import javax.net.ssl.SSLSocketFactory;
|
||||
|
||||
import de.danoeh.antennapod.core.preferences.UserPreferences;
|
||||
import de.danoeh.antennapod.core.storage.DBWriter;
|
||||
|
||||
/**
|
||||
@ -44,12 +50,15 @@ public class AntennapodHttpClient {
|
||||
*/
|
||||
public static synchronized OkHttpClient getHttpClient() {
|
||||
if (httpClient == null) {
|
||||
|
||||
httpClient = newHttpClient();
|
||||
}
|
||||
return httpClient;
|
||||
}
|
||||
|
||||
public static synchronized void reinit() {
|
||||
httpClient = newHttpClient();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new HTTP client. Most users should just use
|
||||
* getHttpClient() to get the standard AntennaPod client,
|
||||
@ -69,13 +78,13 @@ public class AntennapodHttpClient {
|
||||
client.networkInterceptors().add(chain -> {
|
||||
Request request = chain.request();
|
||||
Response response = chain.proceed(request);
|
||||
if(response.code() == HttpURLConnection.HTTP_MOVED_PERM ||
|
||||
if (response.code() == HttpURLConnection.HTTP_MOVED_PERM ||
|
||||
response.code() == StatusLine.HTTP_PERM_REDIRECT) {
|
||||
String location = response.header("Location");
|
||||
if(location.startsWith("/")) { // URL is not absolute, but relative
|
||||
if (location.startsWith("/")) { // URL is not absolute, but relative
|
||||
URL url = request.url();
|
||||
location = url.getProtocol() + "://" + url.getHost() + location;
|
||||
} else if(!location.toLowerCase().startsWith("http://") &&
|
||||
} else if (!location.toLowerCase().startsWith("http://") &&
|
||||
!location.toLowerCase().startsWith("https://")) {
|
||||
// Reference is relative to current path
|
||||
URL url = request.url();
|
||||
@ -106,6 +115,21 @@ public class AntennapodHttpClient {
|
||||
client.setFollowRedirects(true);
|
||||
client.setFollowSslRedirects(true);
|
||||
|
||||
ProxyConfig config = UserPreferences.getProxyConfig();
|
||||
if (config.type != Proxy.Type.DIRECT) {
|
||||
int port = config.port > 0 ? config.port : ProxyConfig.DEFAULT_PORT;
|
||||
SocketAddress address = InetSocketAddress.createUnresolved(config.host, port);
|
||||
Proxy proxy = new Proxy(config.type, address);
|
||||
client.setProxy(proxy);
|
||||
if (!TextUtils.isEmpty(config.username)) {
|
||||
String credentials = Credentials.basic(config.username, config.password);
|
||||
client.interceptors().add(chain -> {
|
||||
Request request = chain.request().newBuilder()
|
||||
.header("Proxy-Authorization", credentials).build();
|
||||
return chain.proceed(request);
|
||||
});
|
||||
}
|
||||
}
|
||||
if(16 <= Build.VERSION.SDK_INT && Build.VERSION.SDK_INT < 21) {
|
||||
client.setSslSocketFactory(new CustomSslSocketFactory());
|
||||
}
|
||||
|
@ -0,0 +1,32 @@
|
||||
package de.danoeh.antennapod.core.service.download;
|
||||
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
import java.net.Proxy;
|
||||
|
||||
public class ProxyConfig {
|
||||
|
||||
public final Proxy.Type type;
|
||||
@Nullable public final String host;
|
||||
@Nullable public final int port;
|
||||
@Nullable public final String username;
|
||||
@Nullable public final String password;
|
||||
|
||||
public final static int DEFAULT_PORT = 8080;
|
||||
|
||||
public static ProxyConfig direct() {
|
||||
return new ProxyConfig(Proxy.Type.DIRECT, null, 0, null, null);
|
||||
}
|
||||
|
||||
public static ProxyConfig http(String host, int port, String username, String password) {
|
||||
return new ProxyConfig(Proxy.Type.HTTP, host, port, username, password);
|
||||
}
|
||||
|
||||
public ProxyConfig(Proxy.Type type, String host, int port, String username, String password) {
|
||||
this.type = type;
|
||||
this.host = host;
|
||||
this.port = port;
|
||||
this.username = username;
|
||||
this.password = password;
|
||||
}
|
||||
}
|
@ -387,6 +387,8 @@
|
||||
<string name="pref_sonic_title">Sonic media player</string>
|
||||
<string name="pref_sonic_message">Use built-in sonic media player as a replacement for Android\'s native mediaplayer and Prestissimo</string>
|
||||
<string name="pref_current_value">Current value: %1$s</string>
|
||||
<string name="pref_proxy_title">Proxy</string>
|
||||
<string name="pref_proxy_sum">Set a network proxy</string>
|
||||
|
||||
<!-- Auto-Flattr dialog -->
|
||||
<string name="auto_flattr_enable">Enable automatic flattring</string>
|
||||
@ -593,4 +595,17 @@
|
||||
<string name="stereo_to_mono">Downmix: Stereo to mono</string>
|
||||
<string name="sonic_only">Sonic only</string>
|
||||
|
||||
<!-- proxy settings -->
|
||||
<string name="proxy_type_label">Type</string>
|
||||
<string name="host_label">Host</string>
|
||||
<string name="port_label">Port</string>
|
||||
<string name="optional_hint">(Optional)</string>
|
||||
<string name="proxy_test_label">Test</string>
|
||||
<string name="proxy_checking">Checking…</string>
|
||||
<string name="proxy_test_successful">Test successful</string>
|
||||
<string name="proxy_test_failed">Test failed</string>
|
||||
<string name="proxy_host_empty_error">Host must not be empty</string>
|
||||
<string name="proxy_host_invalid_error">Host not valid UP or domain</string>
|
||||
<string name="proxy_port_invalid_error">Port not valid</string>
|
||||
|
||||
</resources>
|
||||
|
Loading…
x
Reference in New Issue
Block a user