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. --> - + + app:showAsAction="withText" /> + app:showAsAction="withText" /> diff --git a/src/frontends/android/app/src/main/res/menu/log.xml b/src/frontends/android/app/src/main/res/menu/log.xml index 1af5bd397..cb4c84a07 100644 --- a/src/frontends/android/app/src/main/res/menu/log.xml +++ b/src/frontends/android/app/src/main/res/menu/log.xml @@ -13,11 +13,12 @@ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. --> - + + app:showAsAction="ifRoom|withText" /> diff --git a/src/frontends/android/app/src/main/res/menu/main.xml b/src/frontends/android/app/src/main/res/menu/main.xml index 3dde5227e..599254a5e 100644 --- a/src/frontends/android/app/src/main/res/menu/main.xml +++ b/src/frontends/android/app/src/main/res/menu/main.xml @@ -13,16 +13,17 @@ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. --> - + + app:showAsAction="withText" /> + app:showAsAction="withText" /> - \ No newline at end of file + diff --git a/src/frontends/android/app/src/main/res/menu/profile_edit.xml b/src/frontends/android/app/src/main/res/menu/profile_edit.xml index e69020ed0..280f34d4a 100644 --- a/src/frontends/android/app/src/main/res/menu/profile_edit.xml +++ b/src/frontends/android/app/src/main/res/menu/profile_edit.xml @@ -13,16 +13,17 @@ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. --> - + + app:showAsAction="always|withText" /> + app:showAsAction="ifRoom" /> diff --git a/src/frontends/android/app/src/main/res/menu/profile_list.xml b/src/frontends/android/app/src/main/res/menu/profile_list.xml index 57c9a86a4..8f8838fa1 100644 --- a/src/frontends/android/app/src/main/res/menu/profile_list.xml +++ b/src/frontends/android/app/src/main/res/menu/profile_list.xml @@ -13,10 +13,11 @@ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. --> - + + app:showAsAction="always|withText" /> diff --git a/src/frontends/android/app/src/main/res/menu/profile_list_context.xml b/src/frontends/android/app/src/main/res/menu/profile_list_context.xml index e674ae856..1d6a3dcac 100644 --- a/src/frontends/android/app/src/main/res/menu/profile_list_context.xml +++ b/src/frontends/android/app/src/main/res/menu/profile_list_context.xml @@ -16,9 +16,9 @@ + android:title="@string/edit_profile" /> + android:title="@string/delete_profile" /> - \ No newline at end of file + diff --git a/src/frontends/android/app/src/main/res/values-de/strings.xml b/src/frontends/android/app/src/main/res/values-de/strings.xml index 6cd5ba50a..8b6ff9593 100644 --- a/src/frontends/android/app/src/main/res/values-de/strings.xml +++ b/src/frontends/android/app/src/main/res/values-de/strings.xml @@ -1,9 +1,9 @@ - Bitte geben Sie hier die Gateway-Adresse ein + Bitte geben Sie hier die Server-Adresse ein Bitte geben Sie hier Ihren Benutzernamen ein Kein CA-Zertifikat ausgewählt Bitte wählen Sie eines aus oder aktivieren Sie Automatisch wählen Bitte geben Sie eine Nummer von %1$d - %2$d ein EAP-TNC kann Ihre Privatsphäre beeinträchtigen - Gerätedaten werden an den Gateway-Betreiber gesendet - <p>Trusted Network Connect (TNC) erlaubt Gateway-Betreibern den Gesundheitszustand von Endgeräten zu prüfen.</p><p>Dazu kann der Betreiber Daten verlangen, wie etwa eine eindeutige Identifikationsnummer, eine Liste der installierten Pakete, Systemeinstellungen oder kryptografische Prüfsummen von Dateien.</p><b>Solche Daten werden nur übermittelt nachdem die Identität des Gateways geprüft wurde.</b> + Gerätedaten werden an den Server-Betreiber gesendet + Trusted Network Connect (TNC) erlaubt Server-Betreibern den Gesundheitszustand von Endgeräten zu prüfen.

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