android: Show connection errors as banner, not as modal dialog
This commit is contained in:
+46
-64
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2012-2016 Tobias Brunner
|
||||
* Copyright (C) 2012-2018 Tobias Brunner
|
||||
* Copyright (C) 2012 Giuliano Grassi
|
||||
* Copyright (C) 2012 Ralf Sager
|
||||
* HSR Hochschule fuer Technik Rapperswil
|
||||
@@ -20,19 +20,18 @@ package org.strongswan.android.ui;
|
||||
import android.app.Service;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.ServiceConnection;
|
||||
import android.os.Bundle;
|
||||
import android.os.IBinder;
|
||||
import android.support.v4.app.Fragment;
|
||||
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;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.TextView;
|
||||
|
||||
@@ -60,7 +59,10 @@ public class VpnStateFragment extends Fragment implements VpnStateListener
|
||||
private int mColorStateSuccess;
|
||||
private Button mActionButton;
|
||||
private ProgressBar mProgress;
|
||||
private AlertDialog mErrorDialog;
|
||||
private LinearLayout mErrorView;
|
||||
private TextView mErrorText;
|
||||
private Button mErrorDetails;
|
||||
private Button mDismissError;
|
||||
private long mErrorConnectionID;
|
||||
private VpnStateService mService;
|
||||
private final ServiceConnection mServiceConnection = new ServiceConnection()
|
||||
@@ -128,12 +130,25 @@ public class VpnStateFragment extends Fragment implements VpnStateListener
|
||||
});
|
||||
enableActionButton(null);
|
||||
|
||||
mErrorView = view.findViewById(R.id.vpn_error);
|
||||
mErrorText = view.findViewById(R.id.vpn_error_text);
|
||||
mErrorDetails = view.findViewById(R.id.error_details);
|
||||
mDismissError = view.findViewById(R.id.dismiss_error);
|
||||
mProgress = (ProgressBar)view.findViewById(R.id.progress);
|
||||
mStateView = (TextView)view.findViewById(R.id.vpn_state);
|
||||
mColorStateBase = mStateView.getCurrentTextColor();
|
||||
mProfileView = (TextView)view.findViewById(R.id.vpn_profile_label);
|
||||
mProfileNameView = (TextView)view.findViewById(R.id.vpn_profile_name);
|
||||
|
||||
mDismissError.setOnClickListener(new OnClickListener()
|
||||
{
|
||||
@Override
|
||||
public void onClick(View v)
|
||||
{
|
||||
clearError();
|
||||
}
|
||||
});
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
@@ -156,7 +171,6 @@ public class VpnStateFragment extends Fragment implements VpnStateListener
|
||||
{
|
||||
mService.unregisterListener(this);
|
||||
}
|
||||
hideErrorDialog();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -238,13 +252,10 @@ public class VpnStateFragment extends Fragment implements VpnStateListener
|
||||
{
|
||||
if (error == ErrorState.NO_ERROR)
|
||||
{
|
||||
hideErrorDialog();
|
||||
mErrorView.setVisibility(View.GONE);
|
||||
return false;
|
||||
}
|
||||
else if (mErrorDialog != null)
|
||||
{ /* we already show the dialog */
|
||||
return true;
|
||||
}
|
||||
|
||||
mErrorConnectionID = connectionID;
|
||||
mProfileNameView.setText(name);
|
||||
showProfile(true);
|
||||
@@ -257,24 +268,24 @@ public class VpnStateFragment extends Fragment implements VpnStateListener
|
||||
case AUTH_FAILED:
|
||||
if (imcState == ImcState.BLOCK)
|
||||
{
|
||||
showErrorDialog(R.string.error_assessment_failed);
|
||||
showError(R.string.error_assessment_failed);
|
||||
}
|
||||
else
|
||||
{
|
||||
showErrorDialog(R.string.error_auth_failed);
|
||||
showError(R.string.error_auth_failed);
|
||||
}
|
||||
break;
|
||||
case PEER_AUTH_FAILED:
|
||||
showErrorDialog(R.string.error_peer_auth_failed);
|
||||
showError(R.string.error_peer_auth_failed);
|
||||
break;
|
||||
case LOOKUP_FAILED:
|
||||
showErrorDialog(R.string.error_lookup_failed);
|
||||
showError(R.string.error_lookup_failed);
|
||||
break;
|
||||
case UNREACHABLE:
|
||||
showErrorDialog(R.string.error_unreachable);
|
||||
showError(R.string.error_unreachable);
|
||||
break;
|
||||
default:
|
||||
showErrorDialog(R.string.error_generic);
|
||||
showError(R.string.error_generic);
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
@@ -293,75 +304,46 @@ public class VpnStateFragment extends Fragment implements VpnStateListener
|
||||
mActionButton.setVisibility(text != null ? View.VISIBLE : View.GONE);
|
||||
}
|
||||
|
||||
private void hideErrorDialog()
|
||||
{
|
||||
if (mErrorDialog != null)
|
||||
{
|
||||
mErrorDialog.dismiss();
|
||||
mErrorDialog = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void clearError()
|
||||
{
|
||||
if (mService != null)
|
||||
{
|
||||
mService.disconnect();
|
||||
if (mService.getConnectionID() == mErrorConnectionID)
|
||||
{
|
||||
mService.disconnect();
|
||||
mService.setError(ErrorState.NO_ERROR);
|
||||
}
|
||||
}
|
||||
updateView();
|
||||
}
|
||||
|
||||
private void showErrorDialog(int textid)
|
||||
private void showError(int textid)
|
||||
{
|
||||
final List<RemediationInstruction> instructions = mService.getRemediationInstructions();
|
||||
final boolean show_instructions = mService.getImcState() == ImcState.BLOCK && !instructions.isEmpty();
|
||||
int text = show_instructions ? R.string.show_remediation_instructions : R.string.show_log;
|
||||
|
||||
mErrorDialog = new AlertDialog.Builder(getActivity())
|
||||
.setMessage(getString(R.string.error_introduction) + " " + getString(textid))
|
||||
.setCancelable(false)
|
||||
.setNeutralButton(text, new DialogInterface.OnClickListener()
|
||||
{
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which)
|
||||
{
|
||||
clearError();
|
||||
dialog.dismiss();
|
||||
Intent intent;
|
||||
if (show_instructions)
|
||||
{
|
||||
intent = new Intent(getActivity(), RemediationInstructionsActivity.class);
|
||||
intent.putParcelableArrayListExtra(RemediationInstructionsFragment.EXTRA_REMEDIATION_INSTRUCTIONS,
|
||||
new ArrayList<RemediationInstruction>(instructions));
|
||||
}
|
||||
else
|
||||
{
|
||||
intent = new Intent(getActivity(), LogActivity.class);
|
||||
}
|
||||
startActivity(intent);
|
||||
}
|
||||
})
|
||||
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener()
|
||||
{
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int id)
|
||||
{
|
||||
clearError();
|
||||
dialog.dismiss();
|
||||
}
|
||||
}).create();
|
||||
mErrorDialog.setOnDismissListener(new DialogInterface.OnDismissListener()
|
||||
mErrorText.setText(getString(R.string.error_introduction) + " " + getString(textid));
|
||||
mErrorDetails.setText(text);
|
||||
mErrorDetails.setOnClickListener(new OnClickListener()
|
||||
{
|
||||
@Override
|
||||
public void onDismiss(DialogInterface dialog)
|
||||
public void onClick(View v)
|
||||
{
|
||||
mErrorDialog = null;
|
||||
Intent intent;
|
||||
if (show_instructions)
|
||||
{
|
||||
intent = new Intent(getActivity(), RemediationInstructionsActivity.class);
|
||||
intent.putParcelableArrayListExtra(RemediationInstructionsFragment.EXTRA_REMEDIATION_INSTRUCTIONS,
|
||||
new ArrayList<RemediationInstruction>(instructions));
|
||||
}
|
||||
else
|
||||
{
|
||||
intent = new Intent(getActivity(), LogActivity.class);
|
||||
}
|
||||
startActivity(intent);
|
||||
}
|
||||
});
|
||||
mErrorDialog.show();
|
||||
mErrorView.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2018 Tobias Brunner
|
||||
HSR Hochschule fuer Technik Rapperswil
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 2 of the License, or (at your
|
||||
option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
-->
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<item>
|
||||
<shape>
|
||||
<solid
|
||||
android:color="@color/panel_separator" />
|
||||
</shape>
|
||||
</item>
|
||||
|
||||
<item android:bottom="2dp">
|
||||
<shape>
|
||||
<solid
|
||||
android:color="@android:color/white" />
|
||||
</shape>
|
||||
</item>
|
||||
|
||||
</layer-list>
|
||||
@@ -16,7 +16,6 @@
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:paddingBottom="2dp"
|
||||
android:background="@drawable/state_background"
|
||||
android:orientation="vertical" >
|
||||
|
||||
|
||||
@@ -18,80 +18,137 @@
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:paddingBottom="2dp"
|
||||
android:background="@drawable/state_background"
|
||||
android:orientation="vertical" >
|
||||
android:orientation="vertical"
|
||||
android:animateLayoutChanges="true" >
|
||||
|
||||
<GridLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="10dp"
|
||||
android:layout_marginLeft="20dp"
|
||||
android:layout_marginRight="20dp"
|
||||
android:layout_marginTop="10dp"
|
||||
android:columnCount="2"
|
||||
android:rowCount="2" >
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginRight="5dp"
|
||||
android:gravity="top"
|
||||
android:text="@string/state_label"
|
||||
android:textColor="?android:textColorPrimary"
|
||||
android:textSize="20sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/vpn_state"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="top"
|
||||
android:text="@string/state_disabled"
|
||||
android:textColor="?android:textColorSecondary"
|
||||
android:textSize="20sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/vpn_profile_label"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginRight="5dp"
|
||||
android:gravity="top"
|
||||
android:text="@string/profile_label"
|
||||
android:textColor="?android:textColorPrimary"
|
||||
android:textSize="20sp"
|
||||
android:visibility="gone" >
|
||||
</TextView>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/vpn_profile_name"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="top"
|
||||
android:textSize="20sp"
|
||||
android:visibility="gone" >
|
||||
</TextView>
|
||||
</GridLayout>
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progress"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="10dp"
|
||||
android:layout_marginLeft="20dp"
|
||||
android:layout_marginRight="20dp"
|
||||
android:indeterminate="true"
|
||||
<LinearLayout
|
||||
android:id="@+id/vpn_error"
|
||||
android:visibility="gone"
|
||||
style="@style/Widget.AppCompat.ProgressBar.Horizontal" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/action"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="10dp"
|
||||
android:layout_marginLeft="20dp"
|
||||
android:layout_marginRight="20dp"
|
||||
android:text="@string/disconnect"
|
||||
style="?android:attr/borderlessButtonStyle" >
|
||||
</Button>
|
||||
android:layout_height="match_parent"
|
||||
android:background="@drawable/error_background"
|
||||
android:orientation="vertical" >
|
||||
|
||||
<TextView
|
||||
android:id="@+id/vpn_error_text"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="20dp"
|
||||
android:layout_marginTop="24dp"
|
||||
android:layout_marginBottom="12dp"
|
||||
android:text="Failed to establish VPN: Server is unreachable"
|
||||
android:textColor="@color/primary_dark"
|
||||
android:textSize="16sp" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="end" >
|
||||
|
||||
<Button
|
||||
android:id="@+id/dismiss_error"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:text="@string/dismiss"
|
||||
android:textColor="@color/primary"
|
||||
android:textSize="14sp"
|
||||
android:textStyle="bold"
|
||||
style="?android:attr/borderlessButtonStyle" >
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
android:id="@+id/error_details"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/show_log"
|
||||
android:textColor="@color/primary"
|
||||
android:textSize="14sp"
|
||||
android:textStyle="bold"
|
||||
style="?android:attr/borderlessButtonStyle" >
|
||||
</Button>
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@drawable/state_background"
|
||||
android:orientation="vertical" >
|
||||
|
||||
<GridLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="10dp"
|
||||
android:layout_marginLeft="20dp"
|
||||
android:layout_marginRight="20dp"
|
||||
android:layout_marginTop="10dp"
|
||||
android:columnCount="2"
|
||||
android:rowCount="2" >
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginRight="5dp"
|
||||
android:gravity="top"
|
||||
android:text="@string/state_label"
|
||||
android:textColor="?android:textColorPrimary"
|
||||
android:textSize="20sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/vpn_state"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="top"
|
||||
android:text="@string/state_disabled"
|
||||
android:textColor="?android:textColorSecondary"
|
||||
android:textSize="20sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/vpn_profile_label"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginRight="5dp"
|
||||
android:gravity="top"
|
||||
android:text="@string/profile_label"
|
||||
android:textColor="?android:textColorPrimary"
|
||||
android:textSize="20sp"
|
||||
android:visibility="gone" >
|
||||
</TextView>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/vpn_profile_name"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="top"
|
||||
android:textSize="20sp"
|
||||
android:visibility="gone" >
|
||||
</TextView>
|
||||
</GridLayout>
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progress"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="10dp"
|
||||
android:layout_marginLeft="20dp"
|
||||
android:layout_marginRight="20dp"
|
||||
android:indeterminate="true"
|
||||
android:visibility="gone"
|
||||
style="@style/Widget.AppCompat.ProgressBar.Horizontal" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/action"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="10dp"
|
||||
android:layout_marginLeft="20dp"
|
||||
android:layout_marginRight="20dp"
|
||||
android:text="@string/disconnect"
|
||||
style="?android:attr/borderlessButtonStyle" >
|
||||
</Button>
|
||||
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
@@ -163,6 +163,7 @@
|
||||
<string name="state_disconnecting">Trennen…</string>
|
||||
<string name="state_disabled">Kein aktives Profil</string>
|
||||
<string name="state_error">Fehler</string>
|
||||
<string name="dismiss">Ausblenden</string>
|
||||
|
||||
<!-- IMC state fragment -->
|
||||
<string name="imc_state_label">Assessment:</string>
|
||||
|
||||
@@ -163,6 +163,7 @@
|
||||
<string name="state_disconnecting">Przerywam połączenie…</string>
|
||||
<string name="state_disabled">Brak aktywnego VPN</string>
|
||||
<string name="state_error">Błąd</string>
|
||||
<string name="dismiss">Dismiss</string>
|
||||
|
||||
<!-- IMC state fragment -->
|
||||
<string name="imc_state_label">Assessment:</string>
|
||||
|
||||
@@ -160,6 +160,7 @@
|
||||
<string name="state_disconnecting">Отключение…</string>
|
||||
<string name="state_disabled">Нет активных VPN</string>
|
||||
<string name="state_error">Ошибка</string>
|
||||
<string name="dismiss">Dismiss</string>
|
||||
|
||||
<!-- IMC state fragment -->
|
||||
<string name="imc_state_label">Assessment:</string>
|
||||
|
||||
@@ -161,6 +161,7 @@
|
||||
<string name="state_disconnecting">Роз\'єднання…</string>
|
||||
<string name="state_disabled">Немає активних VPN</string>
|
||||
<string name="state_error">Помилка</string>
|
||||
<string name="dismiss">Dismiss</string>
|
||||
|
||||
<!-- IMC state fragment -->
|
||||
<string name="imc_state_label">Assessment:</string>
|
||||
|
||||
@@ -160,6 +160,7 @@
|
||||
<string name="state_disconnecting">断开连接中…</string>
|
||||
<string name="state_disabled">无活跃VPN</string>
|
||||
<string name="state_error">错误</string>
|
||||
<string name="dismiss">Dismiss</string>
|
||||
|
||||
<!-- IMC state fragment -->
|
||||
<string name="imc_state_label">评估详情:</string>
|
||||
|
||||
@@ -160,6 +160,7 @@
|
||||
<string name="state_disconnecting">結束連線中…</string>
|
||||
<string name="state_disabled">無運作中的VPN</string>
|
||||
<string name="state_error">錯誤</string>
|
||||
<string name="dismiss">Dismiss</string>
|
||||
|
||||
<!-- IMC state fragment -->
|
||||
<string name="imc_state_label">評估詳情:</string>
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
name="primary">#A2042C</color>
|
||||
|
||||
<color
|
||||
name="primary_dark">#000000</color>
|
||||
name="primary_dark">#323232</color>
|
||||
|
||||
<color
|
||||
name="error_text">#D9192C</color>
|
||||
|
||||
@@ -163,6 +163,7 @@
|
||||
<string name="state_disconnecting">Disconnecting…</string>
|
||||
<string name="state_disabled">No active VPN</string>
|
||||
<string name="state_error">Error</string>
|
||||
<string name="dismiss">Dismiss</string>
|
||||
|
||||
<!-- IMC state fragment -->
|
||||
<string name="imc_state_label">Assessment:</string>
|
||||
|
||||
Reference in New Issue
Block a user