2 * Copyright (C) 2012-2018 Tobias Brunner
3 * Copyright (C) 2012 Giuliano Grassi
4 * Copyright (C) 2012 Ralf Sager
5 * HSR Hochschule fuer Technik Rapperswil
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18 package org
.strongswan
.android
.ui
;
20 import android
.app
.Service
;
21 import android
.content
.ComponentName
;
22 import android
.content
.Context
;
23 import android
.content
.Intent
;
24 import android
.content
.ServiceConnection
;
25 import android
.os
.Bundle
;
26 import android
.os
.IBinder
;
27 import android
.support
.v4
.app
.Fragment
;
28 import android
.support
.v4
.content
.ContextCompat
;
29 import android
.view
.LayoutInflater
;
30 import android
.view
.View
;
31 import android
.view
.View
.OnClickListener
;
32 import android
.view
.ViewGroup
;
33 import android
.widget
.Button
;
34 import android
.widget
.LinearLayout
;
35 import android
.widget
.ProgressBar
;
36 import android
.widget
.TextView
;
38 import org
.strongswan
.android
.R
;
39 import org
.strongswan
.android
.data
.VpnProfile
;
40 import org
.strongswan
.android
.logic
.VpnStateService
;
41 import org
.strongswan
.android
.logic
.VpnStateService
.ErrorState
;
42 import org
.strongswan
.android
.logic
.VpnStateService
.State
;
43 import org
.strongswan
.android
.logic
.VpnStateService
.VpnStateListener
;
45 public class VpnStateFragment
extends Fragment
implements VpnStateListener
47 private static final String KEY_ERROR_CONNECTION_ID
= "error_connection_id";
49 private TextView mProfileNameView
;
50 private TextView mProfileView
;
51 private TextView mStateView
;
52 private int mColorStateBase
;
53 private int mColorStateError
;
54 private int mColorStateSuccess
;
55 private Button mActionButton
;
56 private ProgressBar mProgress
;
57 private LinearLayout mErrorView
;
58 private TextView mErrorText
;
59 private Button mErrorRetry
;
60 private Button mShowLog
;
61 private long mErrorConnectionID
;
62 private VpnStateService mService
;
63 private final ServiceConnection mServiceConnection
= new ServiceConnection()
66 public void onServiceDisconnected(ComponentName name
)
72 public void onServiceConnected(ComponentName name
, IBinder service
)
74 mService
= ((VpnStateService
.LocalBinder
)service
).getService();
75 mService
.registerListener(VpnStateFragment
.this);
79 private OnClickListener mDisconnectListener
= new OnClickListener()
82 public void onClick(View v
)
86 mService
.disconnect();
92 public void onCreate(Bundle savedInstanceState
)
94 super.onCreate(savedInstanceState
);
96 mColorStateError
= ContextCompat
.getColor(getActivity(), R
.color
.error_text
);
97 mColorStateSuccess
= ContextCompat
.getColor(getActivity(), R
.color
.success_text
);
99 /* bind to the service only seems to work from the ApplicationContext */
100 Context context
= getActivity().getApplicationContext();
101 context
.bindService(new Intent(context
, VpnStateService
.class),
102 mServiceConnection
, Service
.BIND_AUTO_CREATE
);
104 mErrorConnectionID
= 0;
105 if (savedInstanceState
!= null && savedInstanceState
.containsKey(KEY_ERROR_CONNECTION_ID
))
107 mErrorConnectionID
= (Long
)savedInstanceState
.getSerializable(KEY_ERROR_CONNECTION_ID
);
112 public void onSaveInstanceState(Bundle outState
)
114 super.onSaveInstanceState(outState
);
116 outState
.putSerializable(KEY_ERROR_CONNECTION_ID
, mErrorConnectionID
);
120 public View
onCreateView(LayoutInflater inflater
, ViewGroup container
,
121 Bundle savedInstanceState
)
123 View view
= inflater
.inflate(R
.layout
.vpn_state_fragment
, null);
125 mActionButton
= (Button
)view
.findViewById(R
.id
.action
);
126 mActionButton
.setOnClickListener(v
-> clearError());
127 enableActionButton(null);
129 mErrorView
= view
.findViewById(R
.id
.vpn_error
);
130 mErrorText
= view
.findViewById(R
.id
.vpn_error_text
);
131 mErrorRetry
= view
.findViewById(R
.id
.retry
);
132 mShowLog
= view
.findViewById(R
.id
.show_log
);
133 mProgress
= (ProgressBar
)view
.findViewById(R
.id
.progress
);
134 mStateView
= (TextView
)view
.findViewById(R
.id
.vpn_state
);
135 mColorStateBase
= mStateView
.getCurrentTextColor();
136 mProfileView
= (TextView
)view
.findViewById(R
.id
.vpn_profile_label
);
137 mProfileNameView
= (TextView
)view
.findViewById(R
.id
.vpn_profile_name
);
139 mErrorRetry
.setOnClickListener(v
-> {
140 if (mService
!= null)
142 mService
.reconnect();
145 mShowLog
.setOnClickListener(v
-> {
146 Intent intent
= new Intent(getActivity(), LogActivity
.class);
147 startActivity(intent
);
154 public void onStart()
157 if (mService
!= null)
159 mService
.registerListener(this);
168 if (mService
!= null)
170 mService
.unregisterListener(this);
175 public void onDestroy()
178 if (mService
!= null)
180 getActivity().getApplicationContext().unbindService(mServiceConnection
);
185 public void stateChanged()
190 public void updateView()
192 long connectionID
= mService
.getConnectionID();
193 VpnProfile profile
= mService
.getProfile();
194 State state
= mService
.getState();
195 ErrorState error
= mService
.getErrorState();
198 if (getActivity() == null)
205 name
= profile
.getName();
208 if (reportError(connectionID
, name
, error
))
213 mProfileNameView
.setText(name
);
214 mProgress
.setIndeterminate(true);
220 mProgress
.setVisibility(View
.GONE
);
221 enableActionButton(null);
222 mStateView
.setText(R
.string
.state_disabled
);
223 mStateView
.setTextColor(mColorStateBase
);
227 mProgress
.setVisibility(View
.VISIBLE
);
228 enableActionButton(getString(android
.R
.string
.cancel
));
229 mStateView
.setText(R
.string
.state_connecting
);
230 mStateView
.setTextColor(mColorStateBase
);
234 mProgress
.setVisibility(View
.GONE
);
235 enableActionButton(getString(R
.string
.disconnect
));
236 mStateView
.setText(R
.string
.state_connected
);
237 mStateView
.setTextColor(mColorStateSuccess
);
241 mProgress
.setVisibility(View
.VISIBLE
);
242 enableActionButton(null);
243 mStateView
.setText(R
.string
.state_disconnecting
);
244 mStateView
.setTextColor(mColorStateBase
);
249 private boolean reportError(long connectionID
, String name
, ErrorState error
)
251 if (error
== ErrorState
.NO_ERROR
)
253 mErrorView
.setVisibility(View
.GONE
);
256 mErrorConnectionID
= connectionID
;
257 mProfileNameView
.setText(name
);
259 mStateView
.setText(R
.string
.state_error
);
260 mStateView
.setTextColor(mColorStateError
);
261 enableActionButton(getString(android
.R
.string
.cancel
));
263 int retry
= mService
.getRetryIn();
266 mProgress
.setIndeterminate(false);
267 mProgress
.setMax(mService
.getRetryTimeout());
268 mProgress
.setProgress(retry
);
269 mProgress
.setVisibility(View
.VISIBLE
);
270 mStateView
.setText(getResources().getQuantityString(R
.plurals
.retry_in
, retry
, retry
));
272 else if (mService
.getRetryTimeout() <= 0)
274 mProgress
.setVisibility(View
.GONE
);
277 String text
= getString(R
.string
.error_format
, getString(mService
.getErrorText()));
278 mErrorText
.setText(text
);
279 mErrorView
.setVisibility(View
.VISIBLE
);
283 private void showProfile(boolean show
)
285 mProfileView
.setVisibility(show ? View
.VISIBLE
: View
.GONE
);
286 mProfileNameView
.setVisibility(show ? View
.VISIBLE
: View
.GONE
);
289 private void enableActionButton(String text
)
291 mActionButton
.setText(text
);
292 mActionButton
.setEnabled(text
!= null);
293 mActionButton
.setVisibility(text
!= null ? View
.VISIBLE
: View
.GONE
);
296 private void clearError()
298 if (mService
!= null)
300 mService
.disconnect();
301 if (mService
.getConnectionID() == mErrorConnectionID
)
303 mService
.setError(ErrorState
.NO_ERROR
);