Added TLS 1.1/2 support for Android 4
parent
edc440afa9
commit
c6cc56602c
|
@ -37,7 +37,7 @@
|
||||||
<ConfirmationsSetting value="0" id="Add" />
|
<ConfirmationsSetting value="0" id="Add" />
|
||||||
<ConfirmationsSetting value="0" id="Remove" />
|
<ConfirmationsSetting value="0" id="Remove" />
|
||||||
</component>
|
</component>
|
||||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" assert-keyword="true" jdk-15="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
|
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" default="true" assert-keyword="true" jdk-15="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
|
||||||
<output url="file://$PROJECT_DIR$/build/classes" />
|
<output url="file://$PROJECT_DIR$/build/classes" />
|
||||||
</component>
|
</component>
|
||||||
<component name="ProjectType">
|
<component name="ProjectType">
|
||||||
|
|
|
@ -16,7 +16,7 @@ android {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
compileSdkVersion 23
|
compileSdkVersion 23
|
||||||
buildToolsVersion "23.0.3"
|
buildToolsVersion '25.0.0'
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId "us.keithirwin.tracman"
|
applicationId "us.keithirwin.tracman"
|
||||||
minSdkVersion 14
|
minSdkVersion 14
|
||||||
|
@ -45,8 +45,10 @@ dependencies {
|
||||||
compile ('com.github.nkzawa:socket.io-client:0.4.1'){
|
compile ('com.github.nkzawa:socket.io-client:0.4.1'){
|
||||||
exclude group: 'org.json', module: 'json'
|
exclude group: 'org.json', module: 'json'
|
||||||
}
|
}
|
||||||
compile 'com.squareup.retrofit2:retrofit:2.0.0-beta3'
|
compile 'com.squareup.retrofit2:retrofit:2.2.0'
|
||||||
compile 'com.squareup.retrofit2:converter-gson:2.0.0-beta3'
|
// compile 'com.squareup.retrofit2:converter-gson:2.2.0'
|
||||||
|
// compile 'com.squareup.retrofit2:retrofit:2.0.0-beta3'
|
||||||
|
// compile 'com.squareup.retrofit2:converter-gson:2.0.0-beta3'
|
||||||
}
|
}
|
||||||
|
|
||||||
apply plugin: 'com.google.gms.google-services'
|
apply plugin: 'com.google.gms.google-services'
|
|
@ -13,7 +13,7 @@ public class BootReceiver extends BroadcastReceiver {
|
||||||
public void onReceive(Context context, Intent intent) {
|
public void onReceive(Context context, Intent intent) {
|
||||||
// Starts location service on boot
|
// Starts location service on boot
|
||||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||||
if (prefs.getBoolean("pref_start_boot", true)) {
|
if (prefs.getBoolean("pref_start_boot", false)) {
|
||||||
context.startService(new Intent(context, LocationService.class));
|
context.startService(new Intent(context, LocationService.class));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,7 +42,8 @@ import java.net.URISyntaxException;
|
||||||
public class LocationService extends Service implements GoogleApiClient.ConnectionCallbacks,
|
public class LocationService extends Service implements GoogleApiClient.ConnectionCallbacks,
|
||||||
GoogleApiClient.OnConnectionFailedListener, LocationListener {
|
GoogleApiClient.OnConnectionFailedListener, LocationListener {
|
||||||
public LocationService() {}
|
public LocationService() {}
|
||||||
private String TAG = "LocationService";
|
// private String TAG = "LocationService";
|
||||||
|
final String SERVER_ADDRESS = "https://dev.tracman.org/";
|
||||||
|
|
||||||
private Socket mSocket;
|
private Socket mSocket;
|
||||||
private String mUserID;
|
private String mUserID;
|
||||||
|
@ -128,7 +129,6 @@ public class LocationService extends Service implements GoogleApiClient.Connecti
|
||||||
|
|
||||||
mUserID = sharedPref.getString("loggedInUserId", null);
|
mUserID = sharedPref.getString("loggedInUserId", null);
|
||||||
mUserSK = sharedPref.getString("loggedInUserSk", null);
|
mUserSK = sharedPref.getString("loggedInUserSk", null);
|
||||||
final String SERVER_ADDRESS = "https://tracman.org/";
|
|
||||||
|
|
||||||
// Connect to socket
|
// Connect to socket
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -25,18 +25,31 @@ import org.json.JSONException;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.security.KeyStore;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
|
||||||
|
import javax.net.ssl.SSLContext;
|
||||||
|
import javax.net.ssl.SSLSocketFactory;
|
||||||
|
import javax.net.ssl.TrustManager;
|
||||||
|
import javax.net.ssl.TrustManagerFactory;
|
||||||
|
import javax.net.ssl.X509TrustManager;
|
||||||
|
|
||||||
|
import okhttp3.Call;
|
||||||
|
import okhttp3.CipherSuite;
|
||||||
|
import okhttp3.ConnectionSpec;
|
||||||
import okhttp3.OkHttpClient;
|
import okhttp3.OkHttpClient;
|
||||||
import okhttp3.Request;
|
import okhttp3.Request;
|
||||||
import okhttp3.Callback;
|
import okhttp3.Callback;
|
||||||
import okhttp3.Response;
|
import okhttp3.Response;
|
||||||
|
import okhttp3.TlsVersion;
|
||||||
|
|
||||||
public class LoginActivity extends AppCompatActivity implements
|
public class LoginActivity extends AppCompatActivity implements
|
||||||
GoogleApiClient.OnConnectionFailedListener,
|
GoogleApiClient.OnConnectionFailedListener,
|
||||||
View.OnClickListener {
|
View.OnClickListener {
|
||||||
private static final String TAG = "LoginActivity";
|
private static final String TAG = "LoginActivity";
|
||||||
private static final int RC_SIGN_IN = 9001;
|
private static final int RC_SIGN_IN = 9001;
|
||||||
private final String SERVER_ADDRESS = "https://tracman.org/";
|
private final String SERVER_ADDRESS = "https://dev.tracman.org/";
|
||||||
private static final String GOOGLE_WEB_CLIENT_ID = "483494341936-hrn0ms1tebgdtfs5f4i6ebmkt3qmo16o.apps.googleusercontent.com";
|
private static final String GOOGLE_WEB_CLIENT_ID = "483494341936-hrn0ms1tebgdtfs5f4i6ebmkt3qmo16o.apps.googleusercontent.com";
|
||||||
|
|
||||||
private GoogleApiClient mGoogleApiClient;
|
private GoogleApiClient mGoogleApiClient;
|
||||||
|
@ -122,23 +135,36 @@ public class LoginActivity extends AppCompatActivity implements
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AuthenticateGoogle(final String token) throws Exception {
|
private void AuthenticateGoogle(final String token) throws Exception {
|
||||||
final OkHttpClient client = new OkHttpClient();
|
|
||||||
|
// Needed to support TLS 1.1 and 1.2
|
||||||
|
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(
|
||||||
|
TrustManagerFactory.getDefaultAlgorithm());
|
||||||
|
trustManagerFactory.init((KeyStore) null);
|
||||||
|
TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
|
||||||
|
if (trustManagers.length != 1 || !(trustManagers[0] instanceof X509TrustManager)) {
|
||||||
|
throw new IllegalStateException("Unexpected default trust managers:"
|
||||||
|
+ Arrays.toString(trustManagers));
|
||||||
|
}
|
||||||
|
X509TrustManager trustManager = (X509TrustManager) trustManagers[0];
|
||||||
|
|
||||||
|
OkHttpClient client = new OkHttpClient.Builder()
|
||||||
|
.sslSocketFactory(new TLSSocketFactory(), trustManager)
|
||||||
|
.build();
|
||||||
|
|
||||||
Request request = new Request.Builder()
|
Request request = new Request.Builder()
|
||||||
.url(SERVER_ADDRESS+"auth/google/idtoken?id_token="+token)
|
.url(SERVER_ADDRESS+"auth/google/idtoken?id_token="+token)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
// Log.d(TAG, "Attempting Tracman signin with token: " + token);
|
|
||||||
client.newCall(request).enqueue(new Callback() {
|
client.newCall(request).enqueue(new Callback() {
|
||||||
@Override
|
@Override
|
||||||
public void onFailure(Request request, IOException throwable) {
|
public void onFailure(Call call, IOException e) {
|
||||||
// Log.e(TAG, "Failed to connect to server: " + SERVER_ADDRESS + "auth/google/idtoken?id_token=" + token);
|
Log.e(TAG, "Failed to connect to server: " + SERVER_ADDRESS + "auth/google/idtoken?id_token=" + token);
|
||||||
showError(R.string.server_connection_error);
|
showError(R.string.server_connection_error);
|
||||||
throwable.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onResponse(Response res) throws IOException {
|
public void onResponse(Call call, Response res) throws IOException {
|
||||||
if (!res.isSuccessful()) {
|
if (!res.isSuccessful()) {
|
||||||
showError(R.string.login_no_user_error);
|
showError(R.string.login_no_user_error);
|
||||||
res.body().close();
|
res.body().close();
|
||||||
|
@ -173,9 +199,11 @@ public class LoginActivity extends AppCompatActivity implements
|
||||||
editor.commit();
|
editor.commit();
|
||||||
|
|
||||||
startActivity(new Intent(getBaseContext(), SettingsActivity.class));
|
startActivity(new Intent(getBaseContext(), SettingsActivity.class));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleSignInResult(GoogleSignInResult result) {
|
private void handleSignInResult(GoogleSignInResult result) {
|
||||||
|
|
|
@ -6,7 +6,6 @@ import android.annotation.TargetApi;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.content.pm.PackageManager;
|
|
||||||
import android.content.res.Configuration;
|
import android.content.res.Configuration;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
@ -14,7 +13,6 @@ import android.preference.ListPreference;
|
||||||
import android.preference.Preference;
|
import android.preference.Preference;
|
||||||
import android.preference.PreferenceActivity;
|
import android.preference.PreferenceActivity;
|
||||||
import android.support.v4.app.ActivityCompat;
|
import android.support.v4.app.ActivityCompat;
|
||||||
import android.support.v4.content.ContextCompat;
|
|
||||||
import android.support.v7.app.ActionBar;
|
import android.support.v7.app.ActionBar;
|
||||||
import android.preference.PreferenceFragment;
|
import android.preference.PreferenceFragment;
|
||||||
import android.preference.PreferenceManager;
|
import android.preference.PreferenceManager;
|
||||||
|
@ -68,6 +66,37 @@ public class SettingsActivity extends AppCompatPreferenceActivity {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A preference value change listener that restarts the location service
|
||||||
|
* after something relevant is changed.
|
||||||
|
*/
|
||||||
|
private Preference.OnPreferenceChangeListener sRestartLocationServiceOnChangeListener = new Preference.OnPreferenceChangeListener() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onPreferenceChange(Preference preference, Object obj) {
|
||||||
|
SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(SettingsActivity.this);
|
||||||
|
|
||||||
|
stopService(new Intent(SettingsActivity.this, LocationService.class));
|
||||||
|
|
||||||
|
if (sharedPref.getBoolean("gps_switch", false)) {
|
||||||
|
|
||||||
|
// Ask for location permissions (can't be done in service, only activity)
|
||||||
|
if (!LocationService.checkLocationPermission(SettingsActivity.this)) {
|
||||||
|
ActivityCompat.requestPermissions(
|
||||||
|
SettingsActivity.this,
|
||||||
|
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
|
||||||
|
MY_FINE_LOCATION_PERMISSION);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Log.d(TAG, "Starting LocationService");
|
||||||
|
startService(new Intent(SettingsActivity.this, LocationService.class));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper method to determine if the device has an extra-large screen. For
|
* Helper method to determine if the device has an extra-large screen. For
|
||||||
* example, 10" tablets are extra-large.
|
* example, 10" tablets are extra-large.
|
||||||
|
@ -103,6 +132,9 @@ public class SettingsActivity extends AppCompatPreferenceActivity {
|
||||||
setupActionBar();
|
setupActionBar();
|
||||||
// Log.d(TAG, "activity onCreate called");
|
// Log.d(TAG, "activity onCreate called");
|
||||||
|
|
||||||
|
// Restart LocationService when any related preference is changed
|
||||||
|
// findPreference("gps_switch").setOnPreferenceChangeListener(sRestartLocationServiceOnChangeListener);
|
||||||
|
|
||||||
// Get User ID
|
// Get User ID
|
||||||
SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
|
SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
|
||||||
String mUserID = sharedPref.getString("loggedInUserId", null);
|
String mUserID = sharedPref.getString("loggedInUserId", null);
|
||||||
|
@ -111,34 +143,10 @@ public class SettingsActivity extends AppCompatPreferenceActivity {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void showLocationPermissionDialog() {
|
|
||||||
if (!LocationService.checkLocationPermission(this)) {
|
|
||||||
ActivityCompat.requestPermissions(
|
|
||||||
this,
|
|
||||||
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
|
|
||||||
MY_FINE_LOCATION_PERMISSION);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onStop() {
|
protected void onStop() {
|
||||||
|
|
||||||
// Log.d(TAG, "onStop called");
|
// Log.d(TAG, "onStop called");
|
||||||
super.onStop();
|
super.onStop();
|
||||||
|
|
||||||
// Restart service so settings can take effect
|
|
||||||
stopService(new Intent(this, LocationService.class));
|
|
||||||
SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
|
|
||||||
if (sharedPref.getBoolean("gps_switch", false)) {
|
|
||||||
|
|
||||||
// Ask for location permissions (can't be done in service, only activity)
|
|
||||||
showLocationPermissionDialog();
|
|
||||||
|
|
||||||
// Start location tracking service
|
|
||||||
// Log.d(TAG, "Starting LocationService");
|
|
||||||
startService(new Intent(this, LocationService.class));
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -207,6 +215,9 @@ public class SettingsActivity extends AppCompatPreferenceActivity {
|
||||||
addPreferencesFromResource(R.xml.pref_general);
|
addPreferencesFromResource(R.xml.pref_general);
|
||||||
setHasOptionsMenu(true);
|
setHasOptionsMenu(true);
|
||||||
|
|
||||||
|
// // Restart LocationService when any related preference is changed
|
||||||
|
// findPreference("gps_switch").setOnPreferenceChangeListener(sRestartLocationServiceOnChangeListener);
|
||||||
|
|
||||||
// Bind the summary of preferences to their value
|
// Bind the summary of preferences to their value
|
||||||
bindPreferenceSummaryToValue(findPreference("broadcast_frequency"));
|
bindPreferenceSummaryToValue(findPreference("broadcast_frequency"));
|
||||||
bindPreferenceSummaryToValue(findPreference("broadcast_priority"));
|
bindPreferenceSummaryToValue(findPreference("broadcast_priority"));
|
||||||
|
|
|
@ -0,0 +1,75 @@
|
||||||
|
package us.keithirwin.tracman;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.net.Socket;
|
||||||
|
import java.net.UnknownHostException;
|
||||||
|
import java.security.KeyManagementException;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
|
||||||
|
import javax.net.ssl.SSLContext;
|
||||||
|
import javax.net.ssl.SSLSocket;
|
||||||
|
import javax.net.ssl.SSLSocketFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author fkrauthan
|
||||||
|
* From: https://blog.dev-area.net/2015/08/13/android-4-1-enable-tls-1-1-and-tls-1-2/
|
||||||
|
*/
|
||||||
|
public class TLSSocketFactory extends SSLSocketFactory {
|
||||||
|
|
||||||
|
private SSLSocketFactory internalSSLSocketFactory;
|
||||||
|
|
||||||
|
public TLSSocketFactory() throws KeyManagementException, NoSuchAlgorithmException {
|
||||||
|
SSLContext context = SSLContext.getInstance("TLS");
|
||||||
|
context.init(null, null, null);
|
||||||
|
internalSSLSocketFactory = context.getSocketFactory();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String[] getDefaultCipherSuites() {
|
||||||
|
return internalSSLSocketFactory.getDefaultCipherSuites();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String[] getSupportedCipherSuites() {
|
||||||
|
return internalSSLSocketFactory.getSupportedCipherSuites();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Socket createSocket() throws IOException {
|
||||||
|
return enableTLSOnSocket(internalSSLSocketFactory.createSocket());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException {
|
||||||
|
return enableTLSOnSocket(internalSSLSocketFactory.createSocket(s, host, port, autoClose));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Socket createSocket(String host, int port) throws IOException, UnknownHostException {
|
||||||
|
return enableTLSOnSocket(internalSSLSocketFactory.createSocket(host, port));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException, UnknownHostException {
|
||||||
|
return enableTLSOnSocket(internalSSLSocketFactory.createSocket(host, port, localHost, localPort));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Socket createSocket(InetAddress host, int port) throws IOException {
|
||||||
|
return enableTLSOnSocket(internalSSLSocketFactory.createSocket(host, port));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException {
|
||||||
|
return enableTLSOnSocket(internalSSLSocketFactory.createSocket(address, port, localAddress, localPort));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Socket enableTLSOnSocket(Socket socket) {
|
||||||
|
if(socket != null && (socket instanceof SSLSocket)) {
|
||||||
|
((SSLSocket)socket).setEnabledProtocols(new String[] {"TLSv1.1", "TLSv1.2"});
|
||||||
|
}
|
||||||
|
return socket;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -5,7 +5,7 @@ buildscript {
|
||||||
jcenter()
|
jcenter()
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.android.tools.build:gradle:2.2.3'
|
classpath 'com.android.tools.build:gradle:2.3.0'
|
||||||
classpath 'com.google.gms:google-services:3.0.0'
|
classpath 'com.google.gms:google-services:3.0.0'
|
||||||
|
|
||||||
// NOTE: Do not place your application dependencies here; they belong
|
// NOTE: Do not place your application dependencies here; they belong
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
#Tue Sep 27 15:34:22 EDT 2016
|
#Fri Mar 03 16:00:54 EST 2017
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip
|
||||||
|
|
Loading…
Reference in New Issue