diff --git a/src/frontends/android/.gitignore b/src/frontends/android/.gitignore
index 7e4bcfd4e..aeb7cd7ab 100644
--- a/src/frontends/android/.gitignore
+++ b/src/frontends/android/.gitignore
@@ -1,5 +1,6 @@
.gradle/
.idea/
+build/
app/build/
app/src/main/libs
app/src/main/obj
diff --git a/src/frontends/android/app/build.gradle b/src/frontends/android/app/build.gradle
index 46927ea27..9ef7d171c 100644
--- a/src/frontends/android/app/build.gradle
+++ b/src/frontends/android/app/build.gradle
@@ -1,8 +1,8 @@
apply plugin: 'com.android.application'
android {
- compileSdkVersion 21
- buildToolsVersion "22.0.1"
+ compileSdkVersion 23
+ buildToolsVersion "23.0.3"
defaultConfig {
applicationId "org.strongswan.android"
@@ -29,6 +29,7 @@ android {
tasks.withType(JavaCompile) {
compileTask -> compileTask.dependsOn buildNative
+ options.compilerArgs << "-Xlint:unchecked" << "-Xlint:deprecation"
}
clean.dependsOn 'cleanNative'
@@ -42,5 +43,7 @@ android {
}
dependencies {
+ compile 'com.android.support:appcompat-v7:23.3.0'
+ compile 'com.android.support:design:23.3.0'
testCompile 'junit:junit:4.12'
}
diff --git a/src/frontends/android/app/src/main/AndroidManifest.xml b/src/frontends/android/app/src/main/AndroidManifest.xml
index 2ab833cdb..da465ba74 100644
--- a/src/frontends/android/app/src/main/AndroidManifest.xml
+++ b/src/frontends/android/app/src/main/AndroidManifest.xml
@@ -66,7 +66,7 @@
+ android:theme="@style/AlertDialogTheme" >
diff --git a/src/frontends/android/app/src/main/java/org/strongswan/android/logic/TrustedCertificateManager.java b/src/frontends/android/app/src/main/java/org/strongswan/android/logic/TrustedCertificateManager.java
index 82a7cbe4e..843dfaff4 100644
--- a/src/frontends/android/app/src/main/java/org/strongswan/android/logic/TrustedCertificateManager.java
+++ b/src/frontends/android/app/src/main/java/org/strongswan/android/logic/TrustedCertificateManager.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012-2014 Tobias Brunner
+ * Copyright (C) 2012-2015 Tobias Brunner
* Copyright (C) 2012 Giuliano Grassi
* Copyright (C) 2012 Ralf Sager
* Hochschule fuer Technik Rapperswil
@@ -17,6 +17,8 @@
package org.strongswan.android.logic;
+import android.util.Log;
+
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.cert.Certificate;
@@ -24,11 +26,10 @@ import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Hashtable;
+import java.util.Observable;
import java.util.concurrent.locks.ReentrantReadWriteLock;
-import android.util.Log;
-
-public class TrustedCertificateManager
+public class TrustedCertificateManager extends Observable
{
private static final String TAG = TrustedCertificateManager.class.getSimpleName();
private final ReentrantReadWriteLock mLock = new ReentrantReadWriteLock();
@@ -61,13 +62,13 @@ public class TrustedCertificateManager
*/
private TrustedCertificateManager()
{
- for (String name : new String[] { "LocalCertificateStore", "AndroidCAStore" })
+ for (String name : new String[]{"LocalCertificateStore", "AndroidCAStore"})
{
KeyStore store;
try
{
store = KeyStore.getInstance(name);
- store.load(null,null);
+ store.load(null, null);
mKeyStores.add(store);
}
catch (Exception e)
@@ -81,12 +82,14 @@ public class TrustedCertificateManager
/**
* This is not instantiated until the first call to getInstance()
*/
- private static class Singleton {
+ private static class Singleton
+ {
public static final TrustedCertificateManager mInstance = new TrustedCertificateManager();
}
/**
* Get the single instance of the CA certificate manager.
+ *
* @return CA certificate manager
*/
public static TrustedCertificateManager getInstance()
@@ -97,12 +100,17 @@ public class TrustedCertificateManager
/**
* Invalidates the current load state so that the next call to load()
* will force a reload of the cached CA certificates.
+ *
+ * Observers are notified when this method is called.
+ *
* @return reference to itself
*/
public TrustedCertificateManager reset()
{
Log.d(TAG, "Force reload of cached CA certificates on next load");
this.mReload = true;
+ this.setChanged();
+ this.notifyObservers();
return this;
}
@@ -110,6 +118,9 @@ public class TrustedCertificateManager
* Ensures that the certificates are loaded but does not force a reload.
* As this takes a while if the certificates are not loaded yet it should
* be called asynchronously.
+ *
+ * Observers are only notified when the certificates are initially loaded, not when reloaded.
+ *
* @return reference to itself
*/
public TrustedCertificateManager load()
@@ -138,12 +149,18 @@ public class TrustedCertificateManager
fetchCertificates(certs, store);
}
this.mCACerts = certs;
- this.mLoaded = true;
+ if (!this.mLoaded)
+ {
+ this.setChanged();
+ this.notifyObservers();
+ this.mLoaded = true;
+ }
Log.d(TAG, "Cached CA certificates loaded");
}
/**
* Load all X.509 certificates from the given KeyStore.
+ *
* @param certs Hashtable to store certificates in
* @param store KeyStore to load certificates from
*/
@@ -171,6 +188,7 @@ public class TrustedCertificateManager
/**
* Retrieve the CA certificate with the given alias.
+ *
* @param alias alias of the certificate to get
* @return the certificate, null if not found
*/
@@ -208,6 +226,7 @@ public class TrustedCertificateManager
/**
* Get all CA certificates (from all keystores).
+ *
* @return Hashtable mapping aliases to certificates
*/
@SuppressWarnings("unchecked")
@@ -222,6 +241,7 @@ public class TrustedCertificateManager
/**
* Get all certificates from the given source.
+ *
* @param source type to filter certificates
* @return Hashtable mapping aliases to certificates
*/
diff --git a/src/frontends/android/app/src/main/java/org/strongswan/android/ui/CertificateDeleteConfirmationDialog.java b/src/frontends/android/app/src/main/java/org/strongswan/android/ui/CertificateDeleteConfirmationDialog.java
index c381900c6..e8d12fd7e 100644
--- a/src/frontends/android/app/src/main/java/org/strongswan/android/ui/CertificateDeleteConfirmationDialog.java
+++ b/src/frontends/android/app/src/main/java/org/strongswan/android/ui/CertificateDeleteConfirmationDialog.java
@@ -15,20 +15,20 @@
package org.strongswan.android.ui;
-import org.strongswan.android.R;
-
import android.app.Activity;
-import android.app.AlertDialog;
import android.app.Dialog;
-import android.app.DialogFragment;
import android.content.DialogInterface;
import android.os.Bundle;
+import android.support.v7.app.AlertDialog;
+import android.support.v7.app.AppCompatDialogFragment;
+
+import org.strongswan.android.R;
/**
* Class that displays a confirmation dialog to delete a selected local
* certificate.
*/
-public class CertificateDeleteConfirmationDialog extends DialogFragment
+public class CertificateDeleteConfirmationDialog extends AppCompatDialogFragment
{
public static final String ALIAS = "alias";
OnCertificateDeleteListener mListener;
diff --git a/src/frontends/android/app/src/main/java/org/strongswan/android/ui/ImcStateFragment.java b/src/frontends/android/app/src/main/java/org/strongswan/android/ui/ImcStateFragment.java
index 5b1799744..7328693f1 100644
--- a/src/frontends/android/app/src/main/java/org/strongswan/android/ui/ImcStateFragment.java
+++ b/src/frontends/android/app/src/main/java/org/strongswan/android/ui/ImcStateFragment.java
@@ -15,14 +15,6 @@
package org.strongswan.android.ui;
-import java.util.ArrayList;
-
-import org.strongswan.android.R;
-import org.strongswan.android.logic.VpnStateService;
-import org.strongswan.android.logic.VpnStateService.VpnStateListener;
-import org.strongswan.android.logic.imc.ImcState;
-import org.strongswan.android.logic.imc.RemediationInstruction;
-
import android.app.Fragment;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
@@ -33,6 +25,7 @@ import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
+import android.support.v4.content.ContextCompat;
import android.view.GestureDetector;
import android.view.LayoutInflater;
import android.view.MotionEvent;
@@ -44,13 +37,24 @@ import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.TextView;
+import org.strongswan.android.R;
+import org.strongswan.android.logic.VpnStateService;
+import org.strongswan.android.logic.VpnStateService.VpnStateListener;
+import org.strongswan.android.logic.imc.ImcState;
+import org.strongswan.android.logic.imc.RemediationInstruction;
+
+import java.util.ArrayList;
+
public class ImcStateFragment extends Fragment implements VpnStateListener
{
+ private int mColorIsolate;
+ private int mColorBlock;
private TextView mStateView;
private TextView mAction;
private LinearLayout mButton;
private VpnStateService mService;
- private final ServiceConnection mServiceConnection = new ServiceConnection() {
+ private final ServiceConnection mServiceConnection = new ServiceConnection()
+ {
@Override
public void onServiceDisconnected(ComponentName name)
{
@@ -71,6 +75,9 @@ public class ImcStateFragment extends Fragment implements VpnStateListener
{
super.onCreate(savedInstanceState);
+ mColorIsolate = ContextCompat.getColor(getActivity(), R.color.warning_text);
+ mColorBlock = ContextCompat.getColor(getActivity(), R.color.error_text);
+
/* bind to the service only seems to work from the ApplicationContext */
Context context = getActivity().getApplicationContext();
context.bindService(new Intent(context, VpnStateService.class),
@@ -86,7 +93,8 @@ public class ImcStateFragment extends Fragment implements VpnStateListener
View view = inflater.inflate(R.layout.imc_state_fragment, container, false);
mButton = (LinearLayout)view.findViewById(R.id.imc_state_button);
- mButton.setOnClickListener(new OnClickListener() {
+ mButton.setOnClickListener(new OnClickListener()
+ {
@Override
public void onClick(View v)
{
@@ -104,7 +112,8 @@ public class ImcStateFragment extends Fragment implements VpnStateListener
startActivity(intent);
}
});
- final GestureDetector gestures = new GestureDetector(getActivity(), new GestureDetector.SimpleOnGestureListener() {
+ final GestureDetector gestures = new GestureDetector(getActivity(), new GestureDetector.SimpleOnGestureListener()
+ {
/* a better value would be getScaledTouchExplorationTapSlop() but that is hidden */
private final int mMinDistance = ViewConfiguration.get(getActivity()).getScaledTouchSlop() * 4;
@@ -122,7 +131,8 @@ public class ImcStateFragment extends Fragment implements VpnStateListener
return false;
}
});
- mButton.setOnTouchListener(new OnTouchListener() {
+ mButton.setOnTouchListener(new OnTouchListener()
+ {
@Override
public boolean onTouch(View v, MotionEvent event)
{
@@ -190,12 +200,12 @@ public class ImcStateFragment extends Fragment implements VpnStateListener
break;
case ISOLATE:
mStateView.setText(R.string.imc_state_isolate);
- mStateView.setTextColor(getResources().getColor(R.color.warning_text));
+ mStateView.setTextColor(mColorIsolate);
ft.show(this);
break;
case BLOCK:
mStateView.setText(R.string.imc_state_block);
- mStateView.setTextColor(getResources().getColor(R.color.error_text));
+ mStateView.setTextColor(mColorBlock);
ft.show(this);
break;
}
diff --git a/src/frontends/android/app/src/main/java/org/strongswan/android/ui/LogActivity.java b/src/frontends/android/app/src/main/java/org/strongswan/android/ui/LogActivity.java
index a5efecc09..4ad2ebb57 100644
--- a/src/frontends/android/app/src/main/java/org/strongswan/android/ui/LogActivity.java
+++ b/src/frontends/android/app/src/main/java/org/strongswan/android/ui/LogActivity.java
@@ -15,21 +15,21 @@
package org.strongswan.android.ui;
-import java.io.File;
+import android.content.Intent;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.os.Bundle;
+import android.support.v7.app.AppCompatActivity;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.widget.Toast;
import org.strongswan.android.R;
import org.strongswan.android.data.LogContentProvider;
import org.strongswan.android.logic.CharonVpnService;
-import android.app.Activity;
-import android.content.Intent;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.os.Bundle;
-import android.view.Menu;
-import android.view.MenuItem;
-import android.widget.Toast;
+import java.io.File;
-public class LogActivity extends Activity
+public class LogActivity extends AppCompatActivity
{
@Override
public void onCreate(Bundle savedInstanceState)
@@ -37,7 +37,7 @@ public class LogActivity extends Activity
super.onCreate(savedInstanceState);
setContentView(R.layout.log_activity);
- getActionBar().setDisplayHomeAsUpEnabled(true);
+ getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}
@Override
@@ -74,7 +74,7 @@ public class LogActivity extends Activity
}
Intent intent = new Intent(Intent.ACTION_SEND);
- intent.putExtra(Intent.EXTRA_EMAIL, new String[] { MainActivity.CONTACT_EMAIL });
+ intent.putExtra(Intent.EXTRA_EMAIL, new String[]{MainActivity.CONTACT_EMAIL});
intent.putExtra(Intent.EXTRA_SUBJECT, String.format(getString(R.string.log_mail_subject), version));
intent.setType("text/plain");
intent.putExtra(Intent.EXTRA_STREAM, LogContentProvider.createContentUri());
diff --git a/src/frontends/android/app/src/main/java/org/strongswan/android/ui/MainActivity.java b/src/frontends/android/app/src/main/java/org/strongswan/android/ui/MainActivity.java
index e1b3e0783..3d5324056 100644
--- a/src/frontends/android/app/src/main/java/org/strongswan/android/ui/MainActivity.java
+++ b/src/frontends/android/app/src/main/java/org/strongswan/android/ui/MainActivity.java
@@ -17,22 +17,7 @@
package org.strongswan.android.ui;
-import org.strongswan.android.R;
-import org.strongswan.android.data.VpnProfile;
-import org.strongswan.android.data.VpnProfileDataSource;
-import org.strongswan.android.data.VpnType.VpnTypeFeature;
-import org.strongswan.android.logic.CharonVpnService;
-import org.strongswan.android.logic.TrustedCertificateManager;
-import org.strongswan.android.logic.VpnStateService;
-import org.strongswan.android.logic.VpnStateService.State;
-import org.strongswan.android.ui.VpnProfileListFragment.OnVpnProfileSelectedListener;
-
-import android.app.ActionBar;
-import android.app.Activity;
-import android.app.AlertDialog;
-import android.app.AlertDialog.Builder;
import android.app.Dialog;
-import android.app.DialogFragment;
import android.app.Fragment;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
@@ -46,6 +31,10 @@ import android.net.VpnService;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.IBinder;
+import android.support.v7.app.ActionBar;
+import android.support.v7.app.AlertDialog;
+import android.support.v7.app.AppCompatActivity;
+import android.support.v7.app.AppCompatDialogFragment;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
@@ -54,12 +43,24 @@ import android.view.Window;
import android.widget.EditText;
import android.widget.Toast;
-public class MainActivity extends Activity implements OnVpnProfileSelectedListener
+import org.strongswan.android.R;
+import org.strongswan.android.data.VpnProfile;
+import org.strongswan.android.data.VpnProfileDataSource;
+import org.strongswan.android.data.VpnType.VpnTypeFeature;
+import org.strongswan.android.logic.CharonVpnService;
+import org.strongswan.android.logic.TrustedCertificateManager;
+import org.strongswan.android.logic.VpnStateService;
+import org.strongswan.android.logic.VpnStateService.State;
+import org.strongswan.android.ui.VpnProfileListFragment.OnVpnProfileSelectedListener;
+
+public class MainActivity extends AppCompatActivity implements OnVpnProfileSelectedListener
{
public static final String CONTACT_EMAIL = "android@strongswan.org";
public static final String START_PROFILE = "org.strongswan.android.action.START_PROFILE";
public static final String EXTRA_VPN_PROFILE_ID = "org.strongswan.android.VPN_PROFILE_ID";
- /** Use "bring your own device" (BYOD) features */
+ /**
+ * Use "bring your own device" (BYOD) features
+ */
public static final boolean USE_BYOD = true;
private static final int PREPARE_VPN_SERVICE = 0;
private static final String PROFILE_NAME = "org.strongswan.android.MainActivity.PROFILE_NAME";
@@ -69,7 +70,8 @@ public class MainActivity extends Activity implements OnVpnProfileSelectedListen
private Bundle mProfileInfo;
private VpnStateService mService;
- private final ServiceConnection mServiceConnection = new ServiceConnection() {
+ private final ServiceConnection mServiceConnection = new ServiceConnection()
+ {
@Override
public void onServiceDisconnected(ComponentName name)
{
@@ -91,16 +93,18 @@ public class MainActivity extends Activity implements OnVpnProfileSelectedListen
@Override
public void onCreate(Bundle savedInstanceState)
{
- super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
+ super.onCreate(savedInstanceState);
setContentView(R.layout.main);
+ ActionBar bar = getSupportActionBar();
+ bar.setDisplayShowHomeEnabled(true);
+ bar.setDisplayShowTitleEnabled(false);
+ bar.setIcon(R.drawable.ic_launcher);
+
this.bindService(new Intent(this, VpnStateService.class),
mServiceConnection, Service.BIND_AUTO_CREATE);
- ActionBar bar = getActionBar();
- bar.setDisplayShowTitleEnabled(false);
-
/* load CA certificates in a background task */
new LoadCertificatesTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
@@ -157,6 +161,7 @@ public class MainActivity extends Activity implements OnVpnProfileSelectedListen
/**
* Prepare the VpnService. If this succeeds the current VPN profile is
* started.
+ *
* @param profileInfo a bundle containing the information about the profile to be started
*/
protected void prepareVpnService(Bundle profileInfo)
@@ -231,7 +236,7 @@ public class MainActivity extends Activity implements OnVpnProfileSelectedListen
ConfirmationDialog dialog = new ConfirmationDialog();
dialog.setArguments(profileInfo);
- dialog.show(this.getFragmentManager(), DIALOG_TAG);
+ dialog.show(this.getSupportFragmentManager(), DIALOG_TAG);
return;
}
startVpnProfile(profileInfo);
@@ -239,6 +244,7 @@ public class MainActivity extends Activity implements OnVpnProfileSelectedListen
/**
* Start the given VPN profile asking the user for a password if required.
+ *
* @param profileInfo data about the profile
*/
private void startVpnProfile(Bundle profileInfo)
@@ -248,7 +254,7 @@ public class MainActivity extends Activity implements OnVpnProfileSelectedListen
{
LoginDialog login = new LoginDialog();
login.setArguments(profileInfo);
- login.show(getFragmentManager(), DIALOG_TAG);
+ login.show(getSupportFragmentManager(), DIALOG_TAG);
return;
}
prepareVpnService(profileInfo);
@@ -257,6 +263,7 @@ public class MainActivity extends Activity implements OnVpnProfileSelectedListen
/**
* Start the VPN profile referred to by the given intent. Displays an error
* if the profile doesn't exist.
+ *
* @param intent Intent that caused us to start this
*/
private void startVpnProfile(Intent intent)
@@ -291,11 +298,13 @@ public class MainActivity extends Activity implements OnVpnProfileSelectedListen
{
setProgressBarIndeterminateVisibility(true);
}
+
@Override
protected TrustedCertificateManager doInBackground(Void... params)
{
return TrustedCertificateManager.getInstance().load();
}
+
@Override
protected void onPostExecute(TrustedCertificateManager result)
{
@@ -322,7 +331,7 @@ public class MainActivity extends Activity implements OnVpnProfileSelectedListen
* Class that displays a confirmation dialog if a VPN profile is already connected
* and then initiates the selected VPN profile if the user confirms the dialog.
*/
- public static class ConfirmationDialog extends DialogFragment
+ public static class ConfirmationDialog extends AppCompatDialogFragment
{
@Override
public Dialog onCreateDialog(Bundle savedInstanceState)
@@ -345,7 +354,8 @@ public class MainActivity extends Activity implements OnVpnProfileSelectedListen
.setIcon(icon)
.setTitle(String.format(getString(title), profileInfo.getString(PROFILE_NAME)))
.setMessage(message)
- .setPositiveButton(button, new DialogInterface.OnClickListener() {
+ .setPositiveButton(button, new DialogInterface.OnClickListener()
+ {
@Override
public void onClick(DialogInterface dialog, int whichButton)
{
@@ -353,7 +363,8 @@ public class MainActivity extends Activity implements OnVpnProfileSelectedListen
activity.startVpnProfile(profileInfo);
}
})
- .setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
+ .setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener()
+ {
@Override
public void onClick(DialogInterface dialog, int which)
{
@@ -367,7 +378,7 @@ public class MainActivity extends Activity implements OnVpnProfileSelectedListen
* Class that displays a login dialog and initiates the selected VPN
* profile if the user confirms the dialog.
*/
- public static class LoginDialog extends DialogFragment
+ public static class LoginDialog extends AppCompatDialogFragment
{
@Override
public Dialog onCreateDialog(Bundle savedInstanceState)
@@ -379,10 +390,11 @@ public class MainActivity extends Activity implements OnVpnProfileSelectedListen
username.setText(profileInfo.getString(VpnProfileDataSource.KEY_USERNAME));
final EditText password = (EditText)view.findViewById(R.id.password);
- Builder adb = new AlertDialog.Builder(getActivity());
+ AlertDialog.Builder adb = new AlertDialog.Builder(getActivity());
adb.setView(view);
adb.setTitle(getString(R.string.login_title));
- adb.setPositiveButton(R.string.login_confirm, new DialogInterface.OnClickListener() {
+ adb.setPositiveButton(R.string.login_confirm, new DialogInterface.OnClickListener()
+ {
@Override
public void onClick(DialogInterface dialog, int whichButton)
{
@@ -391,7 +403,8 @@ public class MainActivity extends Activity implements OnVpnProfileSelectedListen
activity.prepareVpnService(profileInfo);
}
});
- adb.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
+ adb.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener()
+ {
@Override
public void onClick(DialogInterface dialog, int which)
{
@@ -406,17 +419,17 @@ public class MainActivity extends Activity implements OnVpnProfileSelectedListen
* Class representing an error message which is displayed if VpnService is
* not supported on the current device.
*/
- public static class VpnNotSupportedError extends DialogFragment
+ public static class VpnNotSupportedError extends AppCompatDialogFragment
{
static final String ERROR_MESSAGE_ID = "org.strongswan.android.VpnNotSupportedError.MessageId";
- public static void showWithMessage(Activity activity, int messageId)
+ public static void showWithMessage(AppCompatActivity activity, int messageId)
{
Bundle bundle = new Bundle();
bundle.putInt(ERROR_MESSAGE_ID, messageId);
VpnNotSupportedError dialog = new VpnNotSupportedError();
dialog.setArguments(bundle);
- dialog.show(activity.getFragmentManager(), DIALOG_TAG);
+ dialog.show(activity.getSupportFragmentManager(), DIALOG_TAG);
}
@Override
@@ -428,7 +441,8 @@ public class MainActivity extends Activity implements OnVpnProfileSelectedListen
.setTitle(R.string.vpn_not_supported_title)
.setMessage(messageId)
.setCancelable(false)
- .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
+ .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener()
+ {
@Override
public void onClick(DialogInterface dialog, int id)
{
diff --git a/src/frontends/android/app/src/main/java/org/strongswan/android/ui/RemediationInstructionsActivity.java b/src/frontends/android/app/src/main/java/org/strongswan/android/ui/RemediationInstructionsActivity.java
index 66d0de261..7e7e870be 100644
--- a/src/frontends/android/app/src/main/java/org/strongswan/android/ui/RemediationInstructionsActivity.java
+++ b/src/frontends/android/app/src/main/java/org/strongswan/android/ui/RemediationInstructionsActivity.java
@@ -15,24 +15,24 @@
package org.strongswan.android.ui;
-import java.util.ArrayList;
+import android.os.Bundle;
+import android.support.v7.app.AppCompatActivity;
+import android.view.MenuItem;
import org.strongswan.android.R;
import org.strongswan.android.logic.imc.RemediationInstruction;
import org.strongswan.android.ui.RemediationInstructionsFragment.OnRemediationInstructionSelectedListener;
-import android.app.Activity;
-import android.os.Bundle;
-import android.view.MenuItem;
+import java.util.ArrayList;
-public class RemediationInstructionsActivity extends Activity implements OnRemediationInstructionSelectedListener
+public class RemediationInstructionsActivity extends AppCompatActivity implements OnRemediationInstructionSelectedListener
{
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.remediation_instructions);
- getActionBar().setDisplayHomeAsUpEnabled(true);
+ getSupportActionBar().setDisplayHomeAsUpEnabled(true);
if (savedInstanceState != null)
{ /* only update if we're not restoring */
@@ -64,7 +64,7 @@ public class RemediationInstructionsActivity extends Activity implements OnRemed
{
finish();
}
- getActionBar().setTitle(getTitle());
+ getSupportActionBar().setTitle(getTitle());
return true;
default:
return super.onOptionsItemSelected(item);
@@ -88,7 +88,7 @@ public class RemediationInstructionsActivity extends Activity implements OnRemed
frag.setArguments(args);
getFragmentManager().beginTransaction().replace(R.id.fragment_container, frag).addToBackStack(null).commit();
- getActionBar().setTitle(instruction.getTitle());
+ getSupportActionBar().setTitle(instruction.getTitle());
}
}
}
diff --git a/src/frontends/android/app/src/main/java/org/strongswan/android/ui/TrustedCertificateImportActivity.java b/src/frontends/android/app/src/main/java/org/strongswan/android/ui/TrustedCertificateImportActivity.java
index 61bd2c9a2..6b8eb2ee8 100644
--- a/src/frontends/android/app/src/main/java/org/strongswan/android/ui/TrustedCertificateImportActivity.java
+++ b/src/frontends/android/app/src/main/java/org/strongswan/android/ui/TrustedCertificateImportActivity.java
@@ -15,6 +15,24 @@
package org.strongswan.android.ui;
+import android.annotation.TargetApi;
+import android.app.Activity;
+import android.app.Dialog;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Build;
+import android.os.Bundle;
+import android.support.v4.app.FragmentTransaction;
+import android.support.v7.app.AlertDialog;
+import android.support.v7.app.AppCompatActivity;
+import android.support.v7.app.AppCompatDialogFragment;
+import android.widget.Toast;
+
+import org.strongswan.android.R;
+import org.strongswan.android.data.VpnProfileDataSource;
+import org.strongswan.android.logic.TrustedCertificateManager;
+
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.security.KeyStore;
@@ -22,34 +40,17 @@ import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
-import org.strongswan.android.R;
-import org.strongswan.android.data.VpnProfileDataSource;
-import org.strongswan.android.logic.TrustedCertificateManager;
-
-import android.annotation.TargetApi;
-import android.app.Activity;
-import android.app.AlertDialog;
-import android.app.Dialog;
-import android.app.DialogFragment;
-import android.app.FragmentTransaction;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.net.Uri;
-import android.os.Build;
-import android.os.Bundle;
-import android.widget.Toast;
-
-public class TrustedCertificateImportActivity extends Activity
+public class TrustedCertificateImportActivity extends AppCompatActivity
{
private static final int OPEN_DOCUMENT = 0;
private static final String DIALOG_TAG = "Dialog";
/* same as those listed in the manifest */
private static final String[] ACCEPTED_MIME_TYPES = {
- "application/x-x509-ca-cert",
- "application/x-x509-server-cert",
- "application/x-pem-file",
- "application/pkix-cert"
+ "application/x-x509-ca-cert",
+ "application/x-x509-server-cert",
+ "application/x-pem-file",
+ "application/pkix-cert"
};
@TargetApi(Build.VERSION_CODES.KITKAT)
@@ -97,6 +98,7 @@ public class TrustedCertificateImportActivity extends Activity
/**
* Import the file pointed to by the given URI as a certificate.
+ *
* @param uri
*/
private void importCertificate(Uri uri)
@@ -117,13 +119,14 @@ public class TrustedCertificateImportActivity extends Activity
Bundle args = new Bundle();
args.putSerializable(VpnProfileDataSource.KEY_CERTIFICATE, certificate);
dialog.setArguments(args);
- FragmentTransaction ft = getFragmentManager().beginTransaction();
+ FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.add(dialog, DIALOG_TAG);
ft.commit();
}
/**
* Load the file from the given URI and try to parse it as X.509 certificate.
+ *
* @param uri
* @return certificate or null
*/
@@ -151,6 +154,7 @@ public class TrustedCertificateImportActivity extends Activity
/**
* Try to store the given certificate in the KeyStore.
+ *
* @param certificate
* @return whether it was successfully stored
*/
@@ -175,7 +179,7 @@ public class TrustedCertificateImportActivity extends Activity
* Class that displays a confirmation dialog when a certificate should get
* imported. If the user confirms the import we try to store it.
*/
- public static class ConfirmImportDialog extends DialogFragment
+ public static class ConfirmImportDialog extends AppCompatDialogFragment
{
@Override
public Dialog onCreateDialog(Bundle savedInstanceState)
@@ -188,7 +192,8 @@ public class TrustedCertificateImportActivity extends Activity
.setIcon(R.drawable.ic_launcher)
.setTitle(R.string.import_certificate)
.setMessage(certificate.getSubjectDN().toString())
- .setPositiveButton(R.string.import_certificate, new DialogInterface.OnClickListener() {
+ .setPositiveButton(R.string.import_certificate, new DialogInterface.OnClickListener()
+ {
@Override
public void onClick(DialogInterface dialog, int whichButton)
{
@@ -205,7 +210,8 @@ public class TrustedCertificateImportActivity extends Activity
getActivity().finish();
}
})
- .setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
+ .setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener()
+ {
@Override
public void onClick(DialogInterface dialog, int which)
{
diff --git a/src/frontends/android/app/src/main/java/org/strongswan/android/ui/TrustedCertificateListFragment.java b/src/frontends/android/app/src/main/java/org/strongswan/android/ui/TrustedCertificateListFragment.java
index 8bd39c435..9782a30db 100644
--- a/src/frontends/android/app/src/main/java/org/strongswan/android/ui/TrustedCertificateListFragment.java
+++ b/src/frontends/android/app/src/main/java/org/strongswan/android/ui/TrustedCertificateListFragment.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012-2014 Tobias Brunner
+ * Copyright (C) 2012-2015 Tobias Brunner
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -15,26 +15,12 @@
package org.strongswan.android.ui;
-import java.security.cert.X509Certificate;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Hashtable;
-import java.util.List;
-import java.util.Map.Entry;
-
-import org.strongswan.android.R;
-import org.strongswan.android.logic.TrustedCertificateManager;
-import org.strongswan.android.logic.TrustedCertificateManager.TrustedCertificateSource;
-import org.strongswan.android.security.TrustedCertificateEntry;
-import org.strongswan.android.ui.adapter.TrustedCertificateAdapter;
-
-import android.app.Activity;
-import android.app.ListFragment;
-import android.app.LoaderManager.LoaderCallbacks;
-import android.content.AsyncTaskLoader;
import android.content.Context;
-import android.content.Loader;
import android.os.Bundle;
+import android.support.v4.app.ListFragment;
+import android.support.v4.app.LoaderManager.LoaderCallbacks;
+import android.support.v4.content.AsyncTaskLoader;
+import android.support.v4.content.Loader;
import android.text.TextUtils;
import android.view.Menu;
import android.view.MenuInflater;
@@ -44,6 +30,21 @@ import android.widget.ListView;
import android.widget.SearchView;
import android.widget.SearchView.OnQueryTextListener;
+import org.strongswan.android.R;
+import org.strongswan.android.logic.TrustedCertificateManager;
+import org.strongswan.android.logic.TrustedCertificateManager.TrustedCertificateSource;
+import org.strongswan.android.security.TrustedCertificateEntry;
+import org.strongswan.android.ui.adapter.TrustedCertificateAdapter;
+
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Map.Entry;
+import java.util.Observable;
+import java.util.Observer;
+
public class TrustedCertificateListFragment extends ListFragment implements LoaderCallbacks>, OnQueryTextListener
{
public static final String EXTRA_CERTIFICATE_SOURCE = "certificate_source";
@@ -54,7 +55,8 @@ public class TrustedCertificateListFragment extends ListFragment implements Load
/**
* The activity containing this fragment should implement this interface
*/
- public interface OnTrustedCertificateSelectedListener {
+ public interface OnTrustedCertificateSelectedListener
+ {
public void onTrustedCertificateSelected(TrustedCertificateEntry selected);
}
@@ -87,13 +89,13 @@ public class TrustedCertificateListFragment extends ListFragment implements Load
}
@Override
- public void onAttach(Activity activity)
+ public void onAttach(Context context)
{
- super.onAttach(activity);
+ super.onAttach(context);
- if (activity instanceof OnTrustedCertificateSelectedListener)
+ if (context instanceof OnTrustedCertificateSelectedListener)
{
- mListener = (OnTrustedCertificateSelectedListener)activity;
+ mListener = (OnTrustedCertificateSelectedListener)context;
}
}
@@ -123,18 +125,6 @@ public class TrustedCertificateListFragment extends ListFragment implements Load
return true;
}
- /**
- * Reset the loader of this list fragment
- */
- public void reset()
- {
- if (isResumed())
- {
- setListShown(false);
- }
- getLoaderManager().restartLoader(0, null, this);
- }
-
@Override
public Loader> onCreateLoader(int id, Bundle args)
{ /* we don't need the id as we have only one loader */
@@ -175,6 +165,7 @@ public class TrustedCertificateListFragment extends ListFragment implements Load
{
private List mData;
private final TrustedCertificateSource mSource;
+ private TrustedCertificateManagerObserver mObserver;
public CertificateListLoader(Context context, TrustedCertificateSource source)
{
@@ -186,7 +177,7 @@ public class TrustedCertificateListFragment extends ListFragment implements Load
public List loadInBackground()
{
TrustedCertificateManager certman = TrustedCertificateManager.getInstance().load();
- Hashtable certificates = certman.getCACertificates(mSource);
+ Hashtable certificates = certman.getCACertificates(mSource);
List selected;
selected = new ArrayList();
@@ -204,9 +195,11 @@ public class TrustedCertificateListFragment extends ListFragment implements Load
if (mData != null)
{ /* if we have data ready, deliver it directly */
deliverResult(mData);
- return;
}
- forceLoad();
+ if (takeContentChanged() || mData == null)
+ {
+ forceLoad();
+ }
}
@Override
@@ -220,6 +213,11 @@ public class TrustedCertificateListFragment extends ListFragment implements Load
if (isStarted())
{ /* if it is started we deliver the data directly,
* otherwise this is handled in onStartLoading */
+ if (mObserver == null)
+ {
+ mObserver = new TrustedCertificateManagerObserver();
+ TrustedCertificateManager.getInstance().addObserver(mObserver);
+ }
super.deliverResult(data);
}
}
@@ -227,7 +225,34 @@ public class TrustedCertificateListFragment extends ListFragment implements Load
@Override
protected void onReset()
{
+ if (mObserver != null)
+ {
+ TrustedCertificateManager.getInstance().deleteObserver(mObserver);
+ mObserver = null;
+ }
mData = null;
+ super.onReset();
+ }
+
+ @Override
+ protected void onAbandon()
+ {
+ if (mObserver != null)
+ {
+ TrustedCertificateManager.getInstance().deleteObserver(mObserver);
+ mObserver = null;
+ }
+ }
+
+ private class TrustedCertificateManagerObserver implements Observer
+ {
+ private ForceLoadContentObserver mContentObserver = new ForceLoadContentObserver();
+
+ @Override
+ public void update(Observable observable, Object data)
+ {
+ mContentObserver.onChange(false);
+ }
}
}
}
diff --git a/src/frontends/android/app/src/main/java/org/strongswan/android/ui/TrustedCertificatesActivity.java b/src/frontends/android/app/src/main/java/org/strongswan/android/ui/TrustedCertificatesActivity.java
index 663950c16..fd8a51944 100644
--- a/src/frontends/android/app/src/main/java/org/strongswan/android/ui/TrustedCertificatesActivity.java
+++ b/src/frontends/android/app/src/main/java/org/strongswan/android/ui/TrustedCertificatesActivity.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012-2014 Tobias Brunner
+ * Copyright (C) 2012-2015 Tobias Brunner
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -15,7 +15,20 @@
package org.strongswan.android.ui;
-import java.security.KeyStore;
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Build;
+import android.os.Bundle;
+import android.support.design.widget.TabLayout;
+import android.support.v4.app.Fragment;
+import android.support.v4.app.FragmentManager;
+import android.support.v4.app.FragmentPagerAdapter;
+import android.support.v4.view.ViewPager;
+import android.support.v7.app.ActionBar;
+import android.support.v7.app.AppCompatActivity;
+import android.view.Menu;
+import android.view.MenuItem;
import org.strongswan.android.R;
import org.strongswan.android.data.VpnProfileDataSource;
@@ -24,22 +37,15 @@ import org.strongswan.android.logic.TrustedCertificateManager.TrustedCertificate
import org.strongswan.android.security.TrustedCertificateEntry;
import org.strongswan.android.ui.CertificateDeleteConfirmationDialog.OnCertificateDeleteListener;
-import android.app.ActionBar;
-import android.app.ActionBar.Tab;
-import android.app.Activity;
-import android.app.Fragment;
-import android.app.FragmentTransaction;
-import android.content.Intent;
-import android.os.Build;
-import android.os.Bundle;
-import android.view.Menu;
-import android.view.MenuItem;
+import java.security.KeyStore;
-public class TrustedCertificatesActivity extends Activity implements TrustedCertificateListFragment.OnTrustedCertificateSelectedListener, OnCertificateDeleteListener
+public class TrustedCertificatesActivity extends AppCompatActivity implements TrustedCertificateListFragment.OnTrustedCertificateSelectedListener, OnCertificateDeleteListener
{
public static final String SELECT_CERTIFICATE = "org.strongswan.android.action.SELECT_CERTIFICATE";
private static final String DIALOG_TAG = "Dialog";
private static final int IMPORT_CERTIFICATE = 0;
+ private TrustedCertificatesPagerAdapter mAdapter;
+ private ViewPager mPager;
private boolean mSelect;
@Override
@@ -48,44 +54,20 @@ public class TrustedCertificatesActivity extends Activity implements TrustedCert
super.onCreate(savedInstanceState);
setContentView(R.layout.trusted_certificates_activity);
- ActionBar actionBar = getActionBar();
+ ActionBar actionBar = getSupportActionBar();
actionBar.setDisplayHomeAsUpEnabled(true);
- actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
- TrustedCertificatesTabListener listener;
- listener = new TrustedCertificatesTabListener(this, "system", TrustedCertificateSource.SYSTEM);
- actionBar.addTab(actionBar
- .newTab()
- .setText(R.string.system_tab)
- .setTag(listener)
- .setTabListener(listener));
- listener = new TrustedCertificatesTabListener(this, "user", TrustedCertificateSource.USER);
- actionBar.addTab(actionBar
- .newTab()
- .setText(R.string.user_tab)
- .setTag(listener)
- .setTabListener(listener));
- listener = new TrustedCertificatesTabListener(this, "local", TrustedCertificateSource.LOCAL);
- actionBar.addTab(actionBar
- .newTab()
- .setText(R.string.local_tab)
- .setTag(listener)
- .setTabListener(listener));
+ mAdapter = new TrustedCertificatesPagerAdapter(getSupportFragmentManager(), this);
+
+ mPager = (ViewPager)findViewById(R.id.viewpager);
+ mPager.setAdapter(mAdapter);
+
+ TabLayout tabs = (TabLayout)findViewById(R.id.tabs);
+ tabs.setupWithViewPager(mPager);
- if (savedInstanceState != null)
- {
- actionBar.setSelectedNavigationItem(savedInstanceState.getInt("tab", 0));
- }
mSelect = SELECT_CERTIFICATE.equals(getIntent().getAction());
}
- @Override
- protected void onSaveInstanceState(Bundle outState)
- {
- super.onSaveInstanceState(outState);
- outState.putInt("tab", getActionBar().getSelectedNavigationIndex());
- }
-
@Override
public boolean onCreateOptionsMenu(Menu menu)
{
@@ -148,18 +130,13 @@ public class TrustedCertificatesActivity extends Activity implements TrustedCert
setResult(Activity.RESULT_OK, intent);
finish();
}
- else
+ else if (mAdapter.getSource(mPager.getCurrentItem()) == TrustedCertificateSource.LOCAL)
{
- TrustedCertificatesTabListener listener;
- listener = (TrustedCertificatesTabListener)getActionBar().getSelectedTab().getTag();
- if (listener.mTag == "local")
- {
- Bundle args = new Bundle();
- args.putString(CertificateDeleteConfirmationDialog.ALIAS, selected.getAlias());
- CertificateDeleteConfirmationDialog dialog = new CertificateDeleteConfirmationDialog();
- dialog.setArguments(args);
- dialog.show(this.getFragmentManager(), DIALOG_TAG);
- }
+ Bundle args = new Bundle();
+ args.putString(CertificateDeleteConfirmationDialog.ALIAS, selected.getAlias());
+ CertificateDeleteConfirmationDialog dialog = new CertificateDeleteConfirmationDialog();
+ dialog.setArguments(args);
+ dialog.show(getSupportFragmentManager(), DIALOG_TAG);
}
}
@@ -182,74 +159,69 @@ public class TrustedCertificatesActivity extends Activity implements TrustedCert
private void reloadCertificates()
{
TrustedCertificateManager.getInstance().reset();
- for (int i = 0; i < getActionBar().getTabCount(); i++)
+ }
+
+ public static class TrustedCertificatesPagerAdapter extends FragmentPagerAdapter
+ {
+ private TrustedCertificatesTab mTabs[];
+
+ public TrustedCertificatesPagerAdapter(FragmentManager fm, Context context)
{
- Tab tab = getActionBar().getTabAt(i);
- TrustedCertificatesTabListener listener = (TrustedCertificatesTabListener)tab.getTag();
- listener.reset();
+ super(fm);
+ mTabs = new TrustedCertificatesTab[]{
+ new TrustedCertificatesTab(context.getString(R.string.system_tab), TrustedCertificateSource.SYSTEM),
+ new TrustedCertificatesTab(context.getString(R.string.user_tab), TrustedCertificateSource.USER),
+ new TrustedCertificatesTab(context.getString(R.string.local_tab), TrustedCertificateSource.LOCAL),
+ };
+ }
+
+ @Override
+ public int getCount()
+ {
+ return mTabs.length;
+ }
+
+ @Override
+ public CharSequence getPageTitle(int position)
+ {
+ return mTabs[position].getTitle();
+ }
+
+ public TrustedCertificateSource getSource(int position)
+ {
+ return mTabs[position].getSource();
+ }
+
+ @Override
+ public Fragment getItem(int position)
+ {
+ TrustedCertificateListFragment fragment = new TrustedCertificateListFragment();
+ Bundle args = new Bundle();
+ args.putSerializable(TrustedCertificateListFragment.EXTRA_CERTIFICATE_SOURCE, mTabs[position].getSource());
+ fragment.setArguments(args);
+ return fragment;
}
}
- public static class TrustedCertificatesTabListener implements ActionBar.TabListener
+ public static class TrustedCertificatesTab
{
- private final String mTag;
+ private final String mTitle;
private final TrustedCertificateSource mSource;
- private Fragment mFragment;
- public TrustedCertificatesTabListener(Activity activity, String tag, TrustedCertificateSource source)
+ public TrustedCertificatesTab(String title, TrustedCertificateSource source)
{
- mTag = tag;
+ mTitle = title;
mSource = source;
- /* check to see if we already have a fragment for this tab, probably
- * from a previously saved state. if so, deactivate it, because the
- * initial state is that no tab is shown */
- mFragment = activity.getFragmentManager().findFragmentByTag(mTag);
- if (mFragment != null && !mFragment.isDetached())
- {
- FragmentTransaction ft = activity.getFragmentManager().beginTransaction();
- ft.detach(mFragment);
- ft.commit();
- }
}
- @Override
- public void onTabSelected(Tab tab, FragmentTransaction ft)
+ public String getTitle()
{
- if (mFragment == null)
- {
- mFragment = new TrustedCertificateListFragment();
- Bundle args = new Bundle();
- args.putSerializable(TrustedCertificateListFragment.EXTRA_CERTIFICATE_SOURCE, mSource);
- mFragment.setArguments(args);
- ft.add(android.R.id.content, mFragment, mTag);
- }
- else
- {
- ft.attach(mFragment);
- }
+ return mTitle;
}
- @Override
- public void onTabUnselected(Tab tab, FragmentTransaction ft)
+ public TrustedCertificateSource getSource()
{
- if (mFragment != null)
- {
- ft.detach(mFragment);
- }
- }
-
- @Override
- public void onTabReselected(Tab tab, FragmentTransaction ft)
- {
- /* nothing to be done */
- }
-
- public void reset()
- {
- if (mFragment != null)
- {
- ((TrustedCertificateListFragment)mFragment).reset();
- }
+ return mSource;
}
}
}
diff --git a/src/frontends/android/app/src/main/java/org/strongswan/android/ui/VpnProfileDetailActivity.java b/src/frontends/android/app/src/main/java/org/strongswan/android/ui/VpnProfileDetailActivity.java
index a8b3daa06..bcc226b1f 100644
--- a/src/frontends/android/app/src/main/java/org/strongswan/android/ui/VpnProfileDetailActivity.java
+++ b/src/frontends/android/app/src/main/java/org/strongswan/android/ui/VpnProfileDetailActivity.java
@@ -17,20 +17,7 @@
package org.strongswan.android.ui;
-import java.security.cert.X509Certificate;
-
-import org.strongswan.android.R;
-import org.strongswan.android.data.VpnProfile;
-import org.strongswan.android.data.VpnProfileDataSource;
-import org.strongswan.android.data.VpnType;
-import org.strongswan.android.data.VpnType.VpnTypeFeature;
-import org.strongswan.android.logic.TrustedCertificateManager;
-import org.strongswan.android.security.TrustedCertificateEntry;
-
-import android.app.Activity;
-import android.app.AlertDialog;
import android.app.Dialog;
-import android.app.DialogFragment;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
@@ -39,6 +26,9 @@ import android.os.Bundle;
import android.security.KeyChain;
import android.security.KeyChainAliasCallback;
import android.security.KeyChainException;
+import android.support.v7.app.AlertDialog;
+import android.support.v7.app.AppCompatActivity;
+import android.support.v7.app.AppCompatDialogFragment;
import android.text.Html;
import android.util.Log;
import android.view.Menu;
@@ -57,7 +47,17 @@ import android.widget.RelativeLayout;
import android.widget.Spinner;
import android.widget.TextView;
-public class VpnProfileDetailActivity extends Activity
+import org.strongswan.android.R;
+import org.strongswan.android.data.VpnProfile;
+import org.strongswan.android.data.VpnProfileDataSource;
+import org.strongswan.android.data.VpnType;
+import org.strongswan.android.data.VpnType.VpnTypeFeature;
+import org.strongswan.android.logic.TrustedCertificateManager;
+import org.strongswan.android.security.TrustedCertificateEntry;
+
+import java.security.cert.X509Certificate;
+
+public class VpnProfileDetailActivity extends AppCompatActivity
{
private static final int SELECT_TRUSTED_CERTIFICATE = 0;
private static final int MTU_MIN = 1280;
@@ -94,7 +94,7 @@ public class VpnProfileDetailActivity extends Activity
super.onCreate(savedInstanceState);
/* the title is set when we load the profile, if any */
- getActionBar().setDisplayHomeAsUpEnabled(true);
+ getSupportActionBar().setDisplayHomeAsUpEnabled(true);
mDataSource = new VpnProfileDataSource(this);
mDataSource.open();
@@ -146,7 +146,7 @@ public class VpnProfileDetailActivity extends Activity
@Override
public void onClick(View v)
{
- new TncNoticeDialog().show(VpnProfileDetailActivity.this.getFragmentManager(), "TncNotice");
+ new TncNoticeDialog().show(VpnProfileDetailActivity.this.getSupportFragmentManager(), "TncNotice");
}
});
@@ -465,7 +465,7 @@ public class VpnProfileDetailActivity extends Activity
{
String useralias = null, alias = null;
- getActionBar().setTitle(R.string.add_profile);
+ getSupportActionBar().setTitle(R.string.add_profile);
if (mId != null && mId != 0)
{
mProfile = mDataSource.getVpnProfile(mId);
@@ -482,7 +482,7 @@ public class VpnProfileDetailActivity extends Activity
mBlockIPv6.setChecked(mProfile.getSplitTunneling() != null ? (mProfile.getSplitTunneling() & VpnProfile.SPLIT_TUNNELING_BLOCK_IPV6) != 0 : false);
useralias = mProfile.getUserCertificateAlias();
alias = mProfile.getCertificateAlias();
- getActionBar().setTitle(mProfile.getName());
+ getSupportActionBar().setTitle(mProfile.getName());
}
else
{
@@ -633,7 +633,7 @@ public class VpnProfileDetailActivity extends Activity
/**
* Dialog with notification message if EAP-TNC is used.
*/
- public static class TncNoticeDialog extends DialogFragment
+ public static class TncNoticeDialog extends AppCompatDialogFragment
{
@Override
public Dialog onCreateDialog(Bundle savedInstanceState)
diff --git a/src/frontends/android/app/src/main/java/org/strongswan/android/ui/VpnProfileListFragment.java b/src/frontends/android/app/src/main/java/org/strongswan/android/ui/VpnProfileListFragment.java
index fb684b53d..a23df054b 100644
--- a/src/frontends/android/app/src/main/java/org/strongswan/android/ui/VpnProfileListFragment.java
+++ b/src/frontends/android/app/src/main/java/org/strongswan/android/ui/VpnProfileListFragment.java
@@ -109,15 +109,13 @@ public class VpnProfileListFragment extends Fragment
setHasOptionsMenu(true);
}
- Context context = getActivity().getApplicationContext();
-
mDataSource = new VpnProfileDataSource(this.getActivity());
mDataSource.open();
/* cached list of profiles used as backend for the ListView */
mVpnProfiles = mDataSource.getAllVpnProfiles();
- mListAdapter = new VpnProfileAdapter(context, R.layout.profile_list_item, mVpnProfiles);
+ mListAdapter = new VpnProfileAdapter(getActivity(), R.layout.profile_list_item, mVpnProfiles);
}
@Override
diff --git a/src/frontends/android/app/src/main/java/org/strongswan/android/ui/VpnProfileSelectActivity.java b/src/frontends/android/app/src/main/java/org/strongswan/android/ui/VpnProfileSelectActivity.java
index b4d34f5a5..23b66d323 100644
--- a/src/frontends/android/app/src/main/java/org/strongswan/android/ui/VpnProfileSelectActivity.java
+++ b/src/frontends/android/app/src/main/java/org/strongswan/android/ui/VpnProfileSelectActivity.java
@@ -15,15 +15,15 @@
package org.strongswan.android.ui;
+import android.content.Intent;
+import android.os.Bundle;
+import android.support.v7.app.AppCompatActivity;
+
import org.strongswan.android.R;
import org.strongswan.android.data.VpnProfile;
import org.strongswan.android.ui.VpnProfileListFragment.OnVpnProfileSelectedListener;
-import android.app.Activity;
-import android.content.Intent;
-import android.os.Bundle;
-
-public class VpnProfileSelectActivity extends Activity implements OnVpnProfileSelectedListener
+public class VpnProfileSelectActivity extends AppCompatActivity implements OnVpnProfileSelectedListener
{
@Override
protected void onCreate(Bundle savedInstanceState)
diff --git a/src/frontends/android/app/src/main/java/org/strongswan/android/ui/VpnStateFragment.java b/src/frontends/android/app/src/main/java/org/strongswan/android/ui/VpnStateFragment.java
index 160ba951b..c49e5cc7e 100644
--- a/src/frontends/android/app/src/main/java/org/strongswan/android/ui/VpnStateFragment.java
+++ b/src/frontends/android/app/src/main/java/org/strongswan/android/ui/VpnStateFragment.java
@@ -17,19 +17,6 @@
package org.strongswan.android.ui;
-import java.util.ArrayList;
-import java.util.List;
-
-import org.strongswan.android.R;
-import org.strongswan.android.data.VpnProfile;
-import org.strongswan.android.logic.VpnStateService;
-import org.strongswan.android.logic.VpnStateService.ErrorState;
-import org.strongswan.android.logic.VpnStateService.State;
-import org.strongswan.android.logic.VpnStateService.VpnStateListener;
-import org.strongswan.android.logic.imc.ImcState;
-import org.strongswan.android.logic.imc.RemediationInstruction;
-
-import android.app.AlertDialog;
import android.app.Fragment;
import android.app.ProgressDialog;
import android.app.Service;
@@ -40,6 +27,8 @@ import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
+import android.support.v4.content.ContextCompat;
+import android.support.v7.app.AlertDialog;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
@@ -47,6 +36,18 @@ import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
+import org.strongswan.android.R;
+import org.strongswan.android.data.VpnProfile;
+import org.strongswan.android.logic.VpnStateService;
+import org.strongswan.android.logic.VpnStateService.ErrorState;
+import org.strongswan.android.logic.VpnStateService.State;
+import org.strongswan.android.logic.VpnStateService.VpnStateListener;
+import org.strongswan.android.logic.imc.ImcState;
+import org.strongswan.android.logic.imc.RemediationInstruction;
+
+import java.util.ArrayList;
+import java.util.List;
+
public class VpnStateFragment extends Fragment implements VpnStateListener
{
private static final String KEY_ERROR_CONNECTION_ID = "error_connection_id";
@@ -55,7 +56,9 @@ public class VpnStateFragment extends Fragment implements VpnStateListener
private TextView mProfileNameView;
private TextView mProfileView;
private TextView mStateView;
- private int stateBaseColor;
+ private int mColorStateBase;
+ private int mColorStateError;
+ private int mColorStateSuccess;
private Button mActionButton;
private ProgressDialog mConnectDialog;
private ProgressDialog mDisconnectDialog;
@@ -64,7 +67,8 @@ public class VpnStateFragment extends Fragment implements VpnStateListener
private long mErrorConnectionID;
private long mDismissedConnectionID;
private VpnStateService mService;
- private final ServiceConnection mServiceConnection = new ServiceConnection() {
+ private final ServiceConnection mServiceConnection = new ServiceConnection()
+ {
@Override
public void onServiceDisconnected(ComponentName name)
{
@@ -85,6 +89,9 @@ public class VpnStateFragment extends Fragment implements VpnStateListener
{
super.onCreate(savedInstanceState);
+ mColorStateError = ContextCompat.getColor(getActivity(), R.color.error_text);
+ mColorStateSuccess = ContextCompat.getColor(getActivity(), R.color.success_text);
+
/* bind to the service only seems to work from the ApplicationContext */
Context context = getActivity().getApplicationContext();
context.bindService(new Intent(context, VpnStateService.class),
@@ -115,7 +122,8 @@ public class VpnStateFragment extends Fragment implements VpnStateListener
View view = inflater.inflate(R.layout.vpn_state_fragment, null);
mActionButton = (Button)view.findViewById(R.id.action);
- mActionButton.setOnClickListener(new OnClickListener() {
+ mActionButton.setOnClickListener(new OnClickListener()
+ {
@Override
public void onClick(View v)
{
@@ -128,7 +136,7 @@ public class VpnStateFragment extends Fragment implements VpnStateListener
enableActionButton(false);
mStateView = (TextView)view.findViewById(R.id.vpn_state);
- stateBaseColor = mStateView.getCurrentTextColor();
+ mColorStateBase = mStateView.getCurrentTextColor();
mProfileView = (TextView)view.findViewById(R.id.vpn_profile_label);
mProfileNameView = (TextView)view.findViewById(R.id.vpn_profile_name);
@@ -203,26 +211,26 @@ public class VpnStateFragment extends Fragment implements VpnStateListener
showProfile(false);
hideProgressDialog();
mStateView.setText(R.string.state_disabled);
- mStateView.setTextColor(stateBaseColor);
+ mStateView.setTextColor(mColorStateBase);
break;
case CONNECTING:
showProfile(true);
showConnectDialog(name, gateway);
mStateView.setText(R.string.state_connecting);
- mStateView.setTextColor(stateBaseColor);
+ mStateView.setTextColor(mColorStateBase);
break;
case CONNECTED:
showProfile(true);
hideProgressDialog();
enableActionButton(true);
mStateView.setText(R.string.state_connected);
- mStateView.setTextColor(getResources().getColor(R.color.success_text));
+ mStateView.setTextColor(mColorStateSuccess);
break;
case DISCONNECTING:
showProfile(true);
showDisconnectDialog(name);
mStateView.setText(R.string.state_disconnecting);
- mStateView.setTextColor(stateBaseColor);
+ mStateView.setTextColor(mColorStateBase);
break;
}
}
@@ -251,7 +259,7 @@ public class VpnStateFragment extends Fragment implements VpnStateListener
showProfile(true);
enableActionButton(false);
mStateView.setText(R.string.state_error);
- mStateView.setTextColor(getResources().getColor(R.color.error_text));
+ mStateView.setTextColor(mColorStateError);
switch (error)
{
case AUTH_FAILED:
@@ -334,18 +342,18 @@ public class VpnStateFragment extends Fragment implements VpnStateListener
mConnectDialog.setIndeterminate(true);
mConnectDialog.setCancelable(false);
mConnectDialog.setButton(DialogInterface.BUTTON_NEGATIVE,
- getString(android.R.string.cancel),
- new DialogInterface.OnClickListener()
- {
- @Override
- public void onClick(DialogInterface dialog, int which)
- {
- if (mService != null)
- {
- mService.disconnect();
- }
- }
- });
+ getString(android.R.string.cancel),
+ new DialogInterface.OnClickListener()
+ {
+ @Override
+ public void onClick(DialogInterface dialog, int which)
+ {
+ if (mService != null)
+ {
+ mService.disconnect();
+ }
+ }
+ });
mConnectDialog.show();
mProgressDialog = mConnectDialog;
}
@@ -374,7 +382,8 @@ public class VpnStateFragment extends Fragment implements VpnStateListener
mErrorDialog = new AlertDialog.Builder(getActivity())
.setMessage(getString(R.string.error_introduction) + " " + getString(textid))
.setCancelable(false)
- .setNeutralButton(text, new DialogInterface.OnClickListener() {
+ .setNeutralButton(text, new DialogInterface.OnClickListener()
+ {
@Override
public void onClick(DialogInterface dialog, int which)
{
@@ -394,7 +403,8 @@ public class VpnStateFragment extends Fragment implements VpnStateListener
startActivity(intent);
}
})
- .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
+ .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener()
+ {
@Override
public void onClick(DialogInterface dialog, int id)
{
@@ -402,7 +412,8 @@ public class VpnStateFragment extends Fragment implements VpnStateListener
dialog.dismiss();
}
}).create();
- mErrorDialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
+ mErrorDialog.setOnDismissListener(new DialogInterface.OnDismissListener()
+ {
@Override
public void onDismiss(DialogInterface dialog)
{
diff --git a/src/frontends/android/app/src/main/res/drawable/activated_background.xml b/src/frontends/android/app/src/main/res/drawable/activated_background.xml
new file mode 100644
index 000000000..04cf6effb
--- /dev/null
+++ b/src/frontends/android/app/src/main/res/drawable/activated_background.xml
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/frontends/android/app/src/main/res/layout/log_fragment.xml b/src/frontends/android/app/src/main/res/layout/log_fragment.xml
index c2e187a66..601c0a59f 100644
--- a/src/frontends/android/app/src/main/res/layout/log_fragment.xml
+++ b/src/frontends/android/app/src/main/res/layout/log_fragment.xml
@@ -33,7 +33,8 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="9sp"
- android:typeface="monospace" >
+ android:typeface="monospace"
+ android:fontFamily="monospace" >
diff --git a/src/frontends/android/app/src/main/res/layout/trusted_certificates_activity.xml b/src/frontends/android/app/src/main/res/layout/trusted_certificates_activity.xml
index 966ecf25e..aeefd819a 100644
--- a/src/frontends/android/app/src/main/res/layout/trusted_certificates_activity.xml
+++ b/src/frontends/android/app/src/main/res/layout/trusted_certificates_activity.xml
@@ -1,6 +1,6 @@
-
+
-
+
+
+
+
+
diff --git a/src/frontends/android/app/src/main/res/menu/certificates.xml b/src/frontends/android/app/src/main/res/menu/certificates.xml
index 6066cab60..8ce4f62bd 100644
--- a/src/frontends/android/app/src/main/res/menu/certificates.xml
+++ b/src/frontends/android/app/src/main/res/menu/certificates.xml
@@ -13,16 +13,17 @@
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
-->
-
Dazu kann der Betreiber Daten verlangen, wie etwa eine eindeutige Identifikationsnummer, eine Liste der installierten Pakete, Systemeinstellungen oder kryptografische Prüfsummen von Dateien.
Solche Daten werden nur übermittelt nachdem die Identität des Servers geprüft wurde.]]>
CA-Zertifikate
@@ -116,9 +116,9 @@
Passwort eingeben um zu verbinden
Verbinden
Fehler beim Aufsetzen des VPN:
- Gateway-Adresse konnte nicht aufgelöst werden.
- Gateway ist nicht erreichbar.
- Authentifizierung des Gateway ist fehlgeschlagen.
+ Server-Adresse konnte nicht aufgelöst werden.
+ Server ist nicht erreichbar.
+ Authentifizierung des Servers ist fehlgeschlagen.
Benutzerauthentifizierung ist fehlgeschlagen.
Sicherheitsassessment ist fehlgeschlagen.
Unbekannter Fehler während des Verbindens.
diff --git a/src/frontends/android/app/src/main/res/values-pl/strings.xml b/src/frontends/android/app/src/main/res/values-pl/strings.xml
index fb2aba003..26387190b 100644
--- a/src/frontends/android/app/src/main/res/values-pl/strings.xml
+++ b/src/frontends/android/app/src/main/res/values-pl/strings.xml
@@ -50,8 +50,8 @@
Zapisz
Anuluj
Nazwa profilu:
- (użyj adresu bramki)
- Bramka:
+ (użyj adresu serwer)
+ Serwer:
Typ:
Użytkownik:
Hasło:
@@ -71,14 +71,14 @@
Block IPv4 traffic not destined for the VPN
Block IPv6 traffic not destined for the VPN
- Wprowadź adres bramki
+ Wprowadź adres serwer
Wprowadź swoją nazwę użytkownika
Nie wybrano żadnego certyfikatu CA
Wybierz lub uaktywnij jeden Wybierz automatycznie
Please enter a number in the range from %1$d - %2$d
EAP-TNC may affect your privacy
- Device data is sent to the gateway operator
- <p>Trusted Network Connect (TNC) allows gateway operators to assess the health of a client device.</p><p>For that purpose the gateway operator may request data such as a unique identifier, a list of installed packages, system settings, or cryptographic checksums of files.</p><b>Any data will be sent only after verifying the gateway\'s identity.</b>
+ Device data is sent to the server operator
+ <p>Trusted Network Connect (TNC) allows server operators to assess the health of a client device.</p><p>For that purpose the server operator may request data such as a unique identifier, a list of installed packages, system settings, or cryptographic checksums of files.</p><b>Any data will be sent only after verifying the server\'s identity.</b>
Certyfikaty CA
@@ -116,9 +116,9 @@
Wprowadż hasło
Połącz
Nie udało się utworzyć tunelu VPN:
- Nie znaleziono adresu bramki
- Bramka jest nieosiągalna
- Błąd przy weryfikacji bramki
+ Nie znaleziono adresu serwer
+ Serwer jest nieosiągalna
+ Błąd przy weryfikacji serwer
Błąd przy autoryzacji użytkownika
Security assessment failed.
Nieznany błąd w czasie połączenia
diff --git a/src/frontends/android/app/src/main/res/values-ru/strings.xml b/src/frontends/android/app/src/main/res/values-ru/strings.xml
index eabfc084b..ec9d66334 100644
--- a/src/frontends/android/app/src/main/res/values-ru/strings.xml
+++ b/src/frontends/android/app/src/main/res/values-ru/strings.xml
@@ -47,8 +47,8 @@
Сохранить
Отмена
Название профиля:
- (адрес шлюза)
- Шлюз:
+ (адрес cервер)
+ Сервер:
Тип:
Логин:
Пароль:
@@ -68,14 +68,14 @@
Block IPv4 traffic not destined for the VPN
Block IPv6 traffic not destined for the VPN
- Пожалуйста введите адрес шлюза
+ Пожалуйста введите адрес cервер
Пожалуйста введите имя пользователя
Не выбран сертификат CA
Пожалуйста выберите один Выбрать автоматически
Please enter a number in the range from %1$d - %2$d
EAP-TNC may affect your privacy
- Device data is sent to the gateway operator
- <p>Trusted Network Connect (TNC) allows gateway operators to assess the health of a client device.</p><p>For that purpose the gateway operator may request data such as a unique identifier, a list of installed packages, system settings, or cryptographic checksums of files.</p><b>Any data will be sent only after verifying the gateway\'s identity.</b>
+ Device data is sent to the server operator
+ Trusted Network Connect (TNC) allows server operators to assess the health of a client device.For that purpose the server operator may request data such as a unique identifier, a list of installed packages, system settings, or cryptographic checksums of files.
Any data will be sent only after verifying the server\'s identity.]]>
Сертификаты CA
@@ -113,9 +113,9 @@
Введите пароль для соединения
Соединить
Ошибка подключения к VPN:
- Не найден адрес шлюза.
- Шлюз недоступен.
- Ошибка авторизаци при подключении к шлюзу.
+ Не найден адрес сервер.
+ Сервер недоступен.
+ Ошибка авторизаци при подключении к сервер.
Ошибка авторизации пользователя.
Security assessment failed.
Неизвестная ошибка.
diff --git a/src/frontends/android/app/src/main/res/values-ua/strings.xml b/src/frontends/android/app/src/main/res/values-ua/strings.xml
index d7c238370..a5e668b84 100644
--- a/src/frontends/android/app/src/main/res/values-ua/strings.xml
+++ b/src/frontends/android/app/src/main/res/values-ua/strings.xml
@@ -48,8 +48,8 @@
Зберегти
Відміна
Назва профілю:
- (використовувати адресу шлюза)
- Шлюз:
+ (використовувати адресу cервер)
+ Сервер:
Тип:
Логін:
Пароль:
@@ -69,14 +69,14 @@
Block IPv4 traffic not destined for the VPN
Block IPv6 traffic not destined for the VPN
- Введіть адресу шлюза тут
+ Введіть адресу cервер тут
Введіть ім\'я користувача тут
Не вибрано сертифікат CA
Будь ласка виберіть один Вибрати автоматично
Please enter a number in the range from %1$d - %2$d
EAP-TNC may affect your privacy
- Device data is sent to the gateway operator
- <p>Trusted Network Connect (TNC) allows gateway operators to assess the health of a client device.</p><p>For that purpose the gateway operator may request data such as a unique identifier, a list of installed packages, system settings, or cryptographic checksums of files.</p><b>Any data will be sent only after verifying the gateway\'s identity.</b>
+ Device data is sent to the server operator
+ Trusted Network Connect (TNC) allows server operators to assess the health of a client device.For that purpose the server operator may request data such as a unique identifier, a list of installed packages, system settings, or cryptographic checksums of files.
Any data will be sent only after verifying the server\'s identity.]]>
Сертифікати CA
@@ -114,9 +114,9 @@
Введіть пароль для з\'єднання
Підключити
Помилка підлючення VPN:
- Помилка пошуку адреси шлюза.
- Немає зв\'язку зі шлюзом.
- Помилка перевірки данних аутентифікації шлюза.
+ Помилка пошуку адреси сервер.
+ Сервер зв\'язку зі шлюзом.
+ Помилка перевірки данних аутентифікації сервер.
Помилка аутентифікації користувача.
Security assessment failed.
Невідома помилка під час підключення.
diff --git a/src/frontends/android/app/src/main/res/values-v15/styles.xml b/src/frontends/android/app/src/main/res/values-v15/styles.xml
new file mode 100644
index 000000000..bf40c3f26
--- /dev/null
+++ b/src/frontends/android/app/src/main/res/values-v15/styles.xml
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/frontends/android/app/src/main/res/values-v21/styles.xml b/src/frontends/android/app/src/main/res/values-v21/styles.xml
new file mode 100644
index 000000000..32de06b17
--- /dev/null
+++ b/src/frontends/android/app/src/main/res/values-v21/styles.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/frontends/android/app/src/main/res/values/colors.xml b/src/frontends/android/app/src/main/res/values/colors.xml
index 4af28b4d4..f29ae1911 100644
--- a/src/frontends/android/app/src/main/res/values/colors.xml
+++ b/src/frontends/android/app/src/main/res/values/colors.xml
@@ -1,7 +1,7 @@
+ #96BDC2
+
+ #A2042C
+
+ #000000
+
#D9192C
@@ -25,9 +34,12 @@
name="success_text">#99CC00
#333333
+ name="panel_background">#444444
#5a5a5a
+ #5a5a5a
+
diff --git a/src/frontends/android/app/src/main/res/values/strings.xml b/src/frontends/android/app/src/main/res/values/strings.xml
index 5c8ebab57..2b0049f0a 100644
--- a/src/frontends/android/app/src/main/res/values/strings.xml
+++ b/src/frontends/android/app/src/main/res/values/strings.xml
@@ -1,9 +1,9 @@
- Please enter the gateway address here
+ Please enter the server address here
Please enter your username here
No CA certificate selected
Please select one or activate Select automatically
Please enter a number in the range from %1$d - %2$d
EAP-TNC may affect your privacy
- Device data is sent to the gateway operator
- <p>Trusted Network Connect (TNC) allows gateway operators to assess the health of a client device.</p><p>For that purpose the gateway operator may request data such as a unique identifier, a list of installed packages, system settings, or cryptographic checksums of files.</p><b>Any data will be sent only after verifying the gateway\'s identity.</b>
+ Device data is sent to the server operator
+ Trusted Network Connect (TNC) allows server operators to assess the health of a client device.For that purpose the server operator may request data such as a unique identifier, a list of installed packages, system settings, or cryptographic checksums of files.
Any data will be sent only after verifying the server\'s identity.]]>
CA certificates
@@ -116,9 +116,9 @@
Enter password to connect
Connect
Failed to establish VPN:
- Gateway address lookup failed.
- Gateway is unreachable.
- Verifying gateway authentication failed.
+ Server address lookup failed.
+ Server is unreachable.
+ Verifying server authentication failed.
User authentication failed.
Security assessment failed.
Unspecified failure while connecting.
diff --git a/src/frontends/android/app/src/main/res/values/styles.xml b/src/frontends/android/app/src/main/res/values/styles.xml
index 739ba7000..82a957813 100644
--- a/src/frontends/android/app/src/main/res/values/styles.xml
+++ b/src/frontends/android/app/src/main/res/values/styles.xml
@@ -1,7 +1,7 @@
-
+
+
diff --git a/src/frontends/android/build.gradle b/src/frontends/android/build.gradle
index 9b18c6e90..81d32a87b 100644
--- a/src/frontends/android/build.gradle
+++ b/src/frontends/android/build.gradle
@@ -3,7 +3,7 @@ buildscript {
jcenter()
}
dependencies {
- classpath 'com.android.tools.build:gradle:1.3.0'
+ classpath 'com.android.tools.build:gradle:2.1.0'
}
}
diff --git a/src/frontends/android/gradle/wrapper/gradle-wrapper.properties b/src/frontends/android/gradle/wrapper/gradle-wrapper.properties
index 0c71e760d..33892269f 100644
--- a/src/frontends/android/gradle/wrapper/gradle-wrapper.properties
+++ b/src/frontends/android/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
-#Wed Apr 10 15:27:10 PDT 2013
+#Wed Apr 13 11:22:32 CEST 2016
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-2.2.1-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-2.10-all.zip