]> git.ipfire.org Git - thirdparty/strongswan.git/blame - src/frontends/android/app/src/main/java/org/strongswan/android/ui/ImcStateFragment.java
android: Avoid IllegalStateException in state fragments
[thirdparty/strongswan.git] / src / frontends / android / app / src / main / java / org / strongswan / android / ui / ImcStateFragment.java
CommitLineData
e5bf6dcd
TB
1/*
2 * Copyright (C) 2013 Tobias Brunner
1b671669 3 * HSR Hochschule fuer Technik Rapperswil
e5bf6dcd
TB
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * for more details.
14 */
15
16package org.strongswan.android.ui;
17
e5bf6dcd
TB
18import android.app.Service;
19import android.content.ComponentName;
20import android.content.Context;
21import android.content.Intent;
22import android.content.ServiceConnection;
23import android.os.Bundle;
24import android.os.IBinder;
7c5fec3a
TB
25import android.support.v4.app.Fragment;
26import android.support.v4.app.FragmentManager;
27import android.support.v4.app.FragmentTransaction;
4c5f4a3d 28import android.support.v4.content.ContextCompat;
97f1dfb3 29import android.view.GestureDetector;
e5bf6dcd 30import android.view.LayoutInflater;
97f1dfb3 31import android.view.MotionEvent;
e5bf6dcd 32import android.view.View;
6e872fea 33import android.view.View.OnClickListener;
97f1dfb3
TB
34import android.view.View.OnTouchListener;
35import android.view.ViewConfiguration;
e5bf6dcd 36import android.view.ViewGroup;
6e872fea 37import android.widget.LinearLayout;
e5bf6dcd
TB
38import android.widget.TextView;
39
4c5f4a3d
TB
40import org.strongswan.android.R;
41import org.strongswan.android.logic.VpnStateService;
42import org.strongswan.android.logic.VpnStateService.VpnStateListener;
43import org.strongswan.android.logic.imc.ImcState;
44import org.strongswan.android.logic.imc.RemediationInstruction;
45
46import java.util.ArrayList;
47
e5bf6dcd
TB
48public class ImcStateFragment extends Fragment implements VpnStateListener
49{
4c5f4a3d
TB
50 private int mColorIsolate;
51 private int mColorBlock;
0d9dd4b1 52 private boolean mVisible;
e5bf6dcd 53 private TextView mStateView;
6e872fea
TB
54 private TextView mAction;
55 private LinearLayout mButton;
e5bf6dcd 56 private VpnStateService mService;
4c5f4a3d
TB
57 private final ServiceConnection mServiceConnection = new ServiceConnection()
58 {
e5bf6dcd
TB
59 @Override
60 public void onServiceDisconnected(ComponentName name)
61 {
62 mService = null;
63 }
64
65 @Override
66 public void onServiceConnected(ComponentName name, IBinder service)
67 {
68 mService = ((VpnStateService.LocalBinder)service).getService();
0d9dd4b1
TB
69 if (mVisible)
70 {
71 mService.registerListener(ImcStateFragment.this);
72 updateView();
73 }
e5bf6dcd
TB
74 }
75 };
76
77 @Override
78 public void onCreate(Bundle savedInstanceState)
79 {
80 super.onCreate(savedInstanceState);
81
4c5f4a3d
TB
82 mColorIsolate = ContextCompat.getColor(getActivity(), R.color.warning_text);
83 mColorBlock = ContextCompat.getColor(getActivity(), R.color.error_text);
84
e5bf6dcd
TB
85 /* bind to the service only seems to work from the ApplicationContext */
86 Context context = getActivity().getApplicationContext();
87 context.bindService(new Intent(context, VpnStateService.class),
88 mServiceConnection, Service.BIND_AUTO_CREATE);
873f389b
TB
89 /* hide it initially */
90 getFragmentManager().beginTransaction().hide(this).commit();
e5bf6dcd
TB
91 }
92
93 @Override
94 public View onCreateView(LayoutInflater inflater, ViewGroup container,
95 Bundle savedInstanceState)
96 {
41594a7b 97 View view = inflater.inflate(R.layout.imc_state_fragment, container, false);
e5bf6dcd 98
6e872fea 99 mButton = (LinearLayout)view.findViewById(R.id.imc_state_button);
4c5f4a3d
TB
100 mButton.setOnClickListener(new OnClickListener()
101 {
6e872fea
TB
102 @Override
103 public void onClick(View v)
104 {
105 Intent intent;
106 if (mService != null && !mService.getRemediationInstructions().isEmpty())
107 {
108 intent = new Intent(getActivity(), RemediationInstructionsActivity.class);
109 intent.putParcelableArrayListExtra(RemediationInstructionsFragment.EXTRA_REMEDIATION_INSTRUCTIONS,
110 new ArrayList<RemediationInstruction>(mService.getRemediationInstructions()));
111 }
112 else
113 {
114 intent = new Intent(getActivity(), LogActivity.class);
115 }
116 startActivity(intent);
117 }
118 });
4c5f4a3d
TB
119 final GestureDetector gestures = new GestureDetector(getActivity(), new GestureDetector.SimpleOnGestureListener()
120 {
97f1dfb3
TB
121 /* a better value would be getScaledTouchExplorationTapSlop() but that is hidden */
122 private final int mMinDistance = ViewConfiguration.get(getActivity()).getScaledTouchSlop() * 4;
123
124 @Override
125 public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY)
126 {
127 if (Math.abs(e1.getX() - e2.getX()) >= mMinDistance)
128 { /* only if the user swiped a minimum horizontal distance */
129 if (mService != null)
130 {
131 mService.setImcState(ImcState.UNKNOWN);
132 }
133 return true;
134 }
135 return false;
136 }
137 });
4c5f4a3d
TB
138 mButton.setOnTouchListener(new OnTouchListener()
139 {
97f1dfb3
TB
140 @Override
141 public boolean onTouch(View v, MotionEvent event)
142 {
143 return gestures.onTouchEvent(event);
144 }
145 });
6e872fea 146
e5bf6dcd 147 mStateView = (TextView)view.findViewById(R.id.imc_state);
6e872fea 148 mAction = (TextView)view.findViewById(R.id.action);
e5bf6dcd
TB
149
150 return view;
151 }
152
b4a5b185 153 @Override
7ab8ec7a 154 public void onResume()
b4a5b185 155 {
7ab8ec7a 156 super.onResume();
0d9dd4b1 157 mVisible = true;
b4a5b185
TB
158 if (mService != null)
159 {
160 mService.registerListener(this);
161 updateView();
162 }
163 }
164
165 @Override
7ab8ec7a 166 public void onPause()
b4a5b185 167 {
7ab8ec7a 168 super.onPause();
0d9dd4b1 169 mVisible = false;
b4a5b185
TB
170 if (mService != null)
171 {
172 mService.unregisterListener(this);
173 }
174 }
175
e5bf6dcd
TB
176 @Override
177 public void onDestroy()
178 {
179 super.onDestroy();
180 if (mService != null)
181 {
e5bf6dcd
TB
182 getActivity().getApplicationContext().unbindService(mServiceConnection);
183 }
184 }
185
186 @Override
187 public void stateChanged()
188 {
189 updateView();
190 }
191
192 public void updateView()
193 {
16e9efc0
TB
194 FragmentManager fm = getFragmentManager();
195 if (fm == null)
196 {
197 return;
198 }
199 FragmentTransaction ft = fm.beginTransaction();
e5bf6dcd
TB
200
201 switch (mService.getImcState())
202 {
203 case UNKNOWN:
204 case ALLOW:
205 ft.hide(this);
206 break;
207 case ISOLATE:
208 mStateView.setText(R.string.imc_state_isolate);
4c5f4a3d 209 mStateView.setTextColor(mColorIsolate);
873f389b 210 ft.show(this);
e5bf6dcd
TB
211 break;
212 case BLOCK:
213 mStateView.setText(R.string.imc_state_block);
4c5f4a3d 214 mStateView.setTextColor(mColorBlock);
873f389b 215 ft.show(this);
e5bf6dcd
TB
216 break;
217 }
218 ft.commit();
6e872fea
TB
219
220 mAction.setText(mService.getRemediationInstructions().isEmpty() ? R.string.show_log
221 : R.string.show_remediation_instructions);
e5bf6dcd
TB
222 }
223}