/*
Swisscom Safe Connect
Copyright (C) 2014 Swisscom
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 3 of the License, or
(at your option) any later version.
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.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.swisscom.safeconnect.activity;
import android.app.Dialog;
import android.content.ActivityNotFoundException;
import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.pm.LabeledIntent;
import android.net.Uri;
import android.net.VpnService;
import android.os.Bundle;
import android.os.IBinder;
import android.support.v4.app.DialogFragment;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.Loader;
import android.support.v7.app.AlertDialog;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
import com.swisscom.safeconnect.BuildConfig;
import com.swisscom.safeconnect.R;
import com.swisscom.safeconnect.backend.BackendConnector;
import com.swisscom.safeconnect.backend.SubscriptionsManager;
import com.swisscom.safeconnect.billing.PurchaseManager;
import com.swisscom.safeconnect.fragment.InfoFragment;
import com.swisscom.safeconnect.fragment.PipeDialogFragment;
import com.swisscom.safeconnect.fragment.StatisticsFragment;
import com.swisscom.safeconnect.fragment.VpnInfoDlgFragment;
import com.swisscom.safeconnect.fragment.WaitingIndicatorFragment;
import com.swisscom.safeconnect.fragment.WhatsnewDialogFragment;
import com.swisscom.safeconnect.loader.ConnectionsListLoader;
import com.swisscom.safeconnect.model.PlumberAuthResponse;
import com.swisscom.safeconnect.model.PlumberLastConnectionLogResponseList;
import com.swisscom.safeconnect.model.Subscription;
import com.swisscom.safeconnect.sharing.FacebookSharing;
import com.swisscom.safeconnect.sharing.Sharing;
import com.swisscom.safeconnect.sharing.SharingAdapter;
import com.swisscom.safeconnect.sharing.TwitterSharing;
import com.swisscom.safeconnect.utils.Config;
import com.swisscom.safeconnect.utils.Logger;
import com.swisscom.safeconnect.utils.VpnConfigurator;
import com.swisscom.safeconnect.view.ConnectionStatusView;
import com.swisscom.safeconnect.view.SubscriptionStatusView;
import com.swisscom.safeconnect.view.WorldMapView;
import org.strongswan.android.data.LogContentProvider;
import org.strongswan.android.data.VpnProfile;
import org.strongswan.android.logic.CharonVpnService;
import org.strongswan.android.logic.VpnStateService;
import org.strongswan.android.ui.LogActivity;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
public class DashboardActivity extends PipeActivity implements VpnStateService.VpnStateListener,
LoaderManager.LoaderCallbacks<PlumberLastConnectionLogResponseList> {
public static final String KEY_OPEN_SUBSCRIPTIONS = "DashboardActivity.openSubscriptions";
public static final String KEY_CONN_STATUS = "DashboardActivity.KEY_CONN_STATUS";
private static final int PREPARE_VPN_SERVICE = 0;
private static final String DIALOG_TAG = "Dialog";
private static final int LOADER_ID = "DashboardActivity".hashCode();
private static final long SUBCR_FETCH_REPEAT_INTERVAL = 2000;
private VpnProfile mProfile;
private VpnStateService mService;
private VpnStateService.State mVpnState = VpnStateService.State.DISABLED;
private BackendConnector backendConnector = new BackendConnector(this);
private ConnectionStatusView viewConnStatus;
private SubscriptionStatusView viewSubscrStatus;
private WorldMapView viewMap;
private Button btnRescaleMap;
private WaitingIndicatorFragment waitingFragment = new WaitingIndicatorFragment();
private Subscription[] subscriptions;
private SubscriptionsManager subscrManager;
private boolean mOpenSubscriptions;
private PauseHandler handler = new PauseHandler();
public interface VpnServiceIntentProvider {
public Intent getIntent();
}
private VpnServiceIntentProvider vpnServiceIntentProvider;
private Runnable subscriptionsFetchRunnable = new Runnable() {
@Override
public void run() {
subscrManager.init(new PurchaseManager.Callback<Subscription[]>() {
@Override
public void onRequestCompleted(Subscription[] result) {
subscriptions = result;
getOwnSubscription();
}
@Override
public void onRequestFailed(int code) {
// failed to get the subscriptions, disconnect VPN and try again
if (mVpnState == VpnStateService.State.CONNECTED) {
disconnectVpn();
} else {
showNoConnection();
}
}
});
}
};
private final ServiceConnection mServiceConnection = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
mService = null;
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mService = ((VpnStateService.LocalBinder)service).getService();
mService.registerListener(DashboardActivity.this);
syncVpnState();
}
};
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
subscrManager.onSaveInstanceState(outState);
outState.putBoolean(KEY_OPEN_SUBSCRIPTIONS, mOpenSubscriptions);
outState.putSerializable(KEY_CONN_STATUS, viewConnStatus.getConnectionState());
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.dashboard);
vpnServiceIntentProvider = new VpnServiceIntentProvider() {
@Override
public Intent getIntent() {
Intent intent = new Intent(DashboardActivity.this, CharonVpnService.class);
intent.putExtra(Config.VPN_PROFILE_BUNDLE_KEY, mProfile);
return intent;
}
};
btnRescaleMap = (Button) findViewById(R.id.btn_rescale_map);
btnRescaleMap.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
btnRescaleMap.setVisibility(View.GONE);
viewMap.setAllowRecalcBounds();
}
});
viewSubscrStatus = (SubscriptionStatusView) findViewById(R.id.view_subscr_status);
viewSubscrStatus.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mOpenSubscriptions) return;
// if subscription expired, make sure that the VPN is disconnected before
// opening the subscriptions activity
Subscription cur = viewSubscrStatus.getCurrentSubscription();
if (cur != null && cur.getValidTill()*1000 <= System.currentTimeMillis() &&
mVpnState != VpnStateService.State.DISABLED) {
mOpenSubscriptions = true;
disconnectVpn();
} else {
openSubscriptionsActivity();
}
}
});
viewConnStatus = (ConnectionStatusView) findViewById(R.id.view_conn_status);
viewConnStatus.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
switch (viewConnStatus.getConnectionState()) {
case CONNECTED:
disconnectVpn();
break;
case DISCONNECTED:
case UNAVAILABLE:
connectVpn();
break;
default:
break;
}
}
});
viewMap = (WorldMapView) findViewById(R.id.view_world_map);
viewMap.setOnUserMapInteractionListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
btnRescaleMap.setVisibility(View.VISIBLE);
}
});
if (!Config.getInstance().getAuthToken().isEmpty()) {
bindVpnService();
}
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction().
replace(R.id.frame_sidebar, new InfoFragment()).commit();
// in case DashboardActivity gets killed in the meantime, the intent of a
// newly created DashboardActivity will still contain the old value in its
// intent. onSaveInstanceState works though.
mOpenSubscriptions = getIntent() != null && (getIntent()
.getBooleanExtra(KEY_OPEN_SUBSCRIPTIONS, false) || getIntent().getAction() ==
Intent.ACTION_VIEW && getIntent().getDataString() != null &&
getIntent().getDataString().contains("subscribe"));
} else {
mOpenSubscriptions = savedInstanceState.getBoolean(KEY_OPEN_SUBSCRIPTIONS, false);
viewConnStatus.setConnectionState((ConnectionStatusView.VpnState)
savedInstanceState.get(KEY_CONN_STATUS));
}
subscrManager = new SubscriptionsManager(this, savedInstanceState);
handler.postRunnable(subscriptionsFetchRunnable);
// show what's new if needed
if (Config.getInstance().isAppGotUpdated()) {
Config.getInstance().clearAppUpdatedFlag();
WhatsnewDialogFragment dlg = new WhatsnewDialogFragment();
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
Fragment prev = getSupportFragmentManager().findFragmentByTag("whatsnew");
if (prev != null) {
ft.remove(prev);
}
ft.addToBackStack(null);
dlg.show(ft, "whatsnew");
}
}
private void openSubscriptionsActivity() {
if (subscriptions == null) return;
Intent subscriptionIntent = new Intent(this, SubscriptionActivity.class);
subscriptionIntent.putExtra(SubscriptionsManager.KEY_SUBSCRIPTIONS, subscriptions);
subscriptionIntent.putExtra(SubscriptionsManager.KEY_CURRENT_SUBSCR,
viewSubscrStatus.getCurrentSubscription());
startActivity(subscriptionIntent);
}
@Override
protected void onPause() {
super.onPause();
handler.pause();
}
@Override
protected void onResume() {
super.onResume();
handler.resume();
getOwnSubscription();
syncVpnState();
}
private void bindVpnService() {
Context context = getApplicationContext();
context.bindService(new Intent(context, VpnStateService.class),
mServiceConnection, BIND_AUTO_CREATE);
}
@Override
public void onStart() {
super.onStart();
if (mService != null) {
mService.registerListener(this);
syncVpnState();
}
}
@Override
public void onStop() {
super.onStop();
if (mService != null) {
mService.unregisterListener(this);
}
}
@Override
public void onDestroy() {
super.onDestroy();
if (mService != null) {
getApplicationContext().unbindService(mServiceConnection);
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu)
{
getMenuInflater().inflate(R.menu.main, menu);
if (BuildConfig.TESTING) {
toolbar.getMenu().findItem(R.id.menu_show_log).setVisible(false);
toolbar.getMenu().findItem(R.id.menu_change_num).setVisible(false);
} else if (!BuildConfig.DEBUG) {
toolbar.getMenu().findItem(R.id.menu_show_log).setVisible(false);
toolbar.getMenu().findItem(R.id.menu_change_num).setVisible(false);
toolbar.getMenu().findItem(R.id.menu_send_log).setVisible(false);
}
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item)
{
switch (item.getItemId())
{
case R.id.menu_show_log:
Intent logIntent = new Intent(this, LogActivity.class);
startActivity(logIntent);
return true;
case R.id.menu_send_log:
File log = Logger.saveLogs(this);
File charonlog = new File(getFilesDir(), CharonVpnService.LOG_FILE);
Intent intent = new Intent(Intent.ACTION_SEND_MULTIPLE);
intent.putExtra(Intent.EXTRA_EMAIL, new String[] {"manuel.cianci1@swisscom.com"});
intent.putExtra(Intent.EXTRA_SUBJECT, "PipeOfTrust LogFiles");
intent.setType("text/plain");
ArrayList<Uri> files = new ArrayList<Uri>();
if (charonlog.exists() && charonlog.length() > 0) {
files.add(LogContentProvider.createContentUri());
}
if (log.exists() && log.length() > 0) {
files.add(Uri.fromFile(log));
}
if (files.size() == 0)
{
Toast.makeText(this, "Log is empty!", Toast.LENGTH_SHORT).show();
return true;
}
intent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, files);
startActivity(Intent.createChooser(intent, getString(R.string.send_log)));
return true;
case R.id.menu_change_num:
if (mService.getState() == VpnStateService.State.CONNECTED) {
mService.disconnect();
}
intent = new Intent(this, RegistrationActivity.class);
intent.putExtra(RegistrationActivity.FORCE_ACTIVITY, true);
startActivity(intent);
finish();
return true;
case R.id.menu_help:
startActivity(new Intent(this, FaqActivity.class));
return true;
case R.id.menu_settings:
Intent settingsIntent = new Intent(this, SettingsActivity.class);
startActivity(settingsIntent);
return true;
case R.id.menu_share:
share();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
@Override
public void stateChanged() {
syncVpnState();
}
public void startVpnTunnel(VpnProfile profile) {
prepareVpnService(profile);
}
/**
* Prepare the VpnService. If this succeeds the current VPN profile is
* started.
* @param profile bundle containing the information about the profile to be started
*/
protected void prepareVpnService(VpnProfile profile) {
Intent intent;
try {
intent = VpnService.prepare(this);
}
catch (IllegalStateException ex) {
/* this happens if the always-on VPN feature (Android 4.2+) is activated */
VpnNotSupportedError.showWithMessage(this, R.string.vpn_not_supported_during_lockdown);
return;
}
/* store profile info until the user grants us permission */
mProfile = profile;
if (intent != null) {
try {
startActivityForResult(intent, PREPARE_VPN_SERVICE);
}
catch (ActivityNotFoundException ex) {
/* it seems some devices, even though they come with Android 4,
* don't have the VPN components built into the system image.
* com.android.vpndialogs/com.android.vpndialogs.ConfirmDialog
* will not be found then */
VpnNotSupportedError.showWithMessage(this, R.string.vpn_not_supported);
}
}
else {
/* user already granted permission to use VpnService */
onActivityResult(PREPARE_VPN_SERVICE, RESULT_OK, null);
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
switch (requestCode) {
case PREPARE_VPN_SERVICE:
if (resultCode == RESULT_OK && mProfile != null) {
startService(vpnServiceIntentProvider.getIntent());
}
break;
default:
super.onActivityResult(requestCode, resultCode, data);
}
}
@Override
public Loader<PlumberLastConnectionLogResponseList> onCreateLoader(int id, Bundle args) {
return new ConnectionsListLoader(this);
}
@Override
public void onLoadFinished(Loader<PlumberLastConnectionLogResponseList> loader, PlumberLastConnectionLogResponseList data) {
if (data != null && data.getConnectionLogs() != null) {
viewMap.setConnPoints(data);
}
}
@Override
public void onLoaderReset(Loader<PlumberLastConnectionLogResponseList> loader) {
}
/**
* Class representing an error message which is displayed if VpnService is
* not supported on the current device.
*/
public static class VpnNotSupportedError extends DialogFragment {
static final String ERROR_MESSAGE_ID = "org.strongswan.android.VpnNotSupportedError.MessageId";
public static void showWithMessage(FragmentActivity activity, int messageId) {
Bundle bundle = new Bundle();
bundle.putInt(ERROR_MESSAGE_ID, messageId);
VpnNotSupportedError dialog = new VpnNotSupportedError();
dialog.setArguments(bundle);
dialog.show(activity.getSupportFragmentManager(), DIALOG_TAG);
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
final Bundle arguments = getArguments();
final int messageId = arguments.getInt(ERROR_MESSAGE_ID);
return new AlertDialog.Builder(getActivity(), R.style.AppCompat_Pipe_Dialog_Alert)
.setTitle(R.string.vpn_not_supported_title)
.setMessage(messageId)
.setCancelable(false)
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int id)
{
dialog.dismiss();
}
}).create();
}
}
public VpnStateService getMService() {
return mService;
}
public void runBackendConnection(final String token) {
viewConnStatus.setConnectionState(ConnectionStatusView.VpnState.CONNECTED);
showWaiting();
backendConnector.authenticateUser(Config.getInstance().getPhoneNumber(),
Config.getInstance().getDeviceId(), token,
new BackendConnector.ResponseCallback<PlumberAuthResponse>() {
@Override
public void onRequestComplete(int statusCode, final PlumberAuthResponse response) {
if (isFinishing()) return;
switch (statusCode) {
case 0:
// connections error, most likely no network
showNoConnection();
break;
case 404:
showAuthError();
break;
case 200:
final Runnable vpnConnectRunnable = new Runnable() {
@Override
public void run() {
showVpnConnected();
viewSubscrStatus.setVisibility(View.VISIBLE);
//save new auth token for next use!
Config.getInstance().saveAuthToken(response.getUserToken());
VpnProfile mProfile = VpnConfigurator.getVpnProfile(response.getUsername(),
response.getPassword(), response.getPsk());
startVpnTunnel(mProfile);
}
};
if (Config.getInstance().isFirstVpnLaunch()) {
handler.postRunnable(new Runnable() {
@Override
public void run() {
VpnInfoDlgFragment vpnDlg = new VpnInfoDlgFragment();
vpnDlg.setClickRunnable(vpnConnectRunnable);
vpnDlg.show(getSupportFragmentManager(), "vpn_dlg");
Config.getInstance().setFirstVpnLaunch(false);
}
});
} else {
vpnConnectRunnable.run();
}
break;
default:
// this should never be reached
showNoConnection();
break;
}
}
}
);
}
private void showAuthError() {
handler.postRunnable(new Runnable() {
@Override
public void run() {
PipeDialogFragment dlg = new PipeDialogFragment();
dlg.setTitle(getString(R.string.lab_dlg_rereg_title));
dlg.setMessage(getString(R.string.lab_dlg_rereg_msg));
dlg.setOnPositiveClickListener(new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Intent intent = new Intent(getApplicationContext(), RegistrationActivity.class);
intent.putExtra(RegistrationActivity.FORCE_ACTIVITY, true);
startActivity(intent);
finish();
}
});
dlg.show(getSupportFragmentManager(), "login_error");
}
});
}
private void getOwnSubscription() {
subscrManager.getOwnSubscription(new PurchaseManager.Callback<Subscription>() {
private void changeState() {
if (isFinishing()) return;
boolean subscrValid = viewSubscrStatus.isSubscriptionValid();
viewConnStatus.setActionVisible(subscrValid);
if (!subscrValid) {
setInfo(InfoFragment.State.NO_SUBSCIPTION, false);
} else {
setInfo(InfoFragment.State.DISCONNECTED, false);
}
}
@Override
public void onRequestCompleted(Subscription result) {
if (isFinishing()) return;
if (viewConnStatus.getConnectionState() == ConnectionStatusView.VpnState.UNAVAILABLE) {
viewConnStatus.setConnectionState(ConnectionStatusView.VpnState.DISCONNECTED);
viewMap.showDisconnected();
}
viewSubscrStatus.setVisibility(View.VISIBLE);
viewSubscrStatus.setSubscription(result);
changeState();
if (mOpenSubscriptions) {
// disconnect vpn if no subscription. Subscriptions activity will be
// opened once it's disconnected
if (result.getValidTill()*1000 <= System.currentTimeMillis() &&
mVpnState != VpnStateService.State.DISABLED) {
disconnectVpn();
} else {
mOpenSubscriptions = false;
openSubscriptionsActivity();
}
}
}
@Override
public void onRequestFailed(int code) {
// failed to get the subscriptions, disconnect VPN and try again
if (mVpnState == VpnStateService.State.CONNECTED && subscrManager.isFailed()) {
disconnectVpn();
}
if (code == 404) {
showAuthError();
} else {
showNoConnection();
}
}
});
}
private void share() {
final String appUrl = Config.GPLAY_URL;
final String content = getString(R.string.share_content);
final String subject = getString(R.string.share_subject);
List<Intent> shareIntents = new ArrayList<Intent>();
//fb & twitter
shareIntents.add(new FacebookSharing(this).getIntent(content, appUrl));
shareIntents.add(new TwitterSharing(this).getIntent(content, appUrl));
//favorite sharing apps
for (String packageName : Sharing.favoriteApps){
Intent i = Sharing.getSharingApp(packageName, subject, content + ' ' + appUrl, this);
if (i != null) {
shareIntents.add(i);
}
}
//trigger to load all sharing apps
LabeledIntent share = new LabeledIntent(new Intent(), "", getString(R.string.share_more_apps), 0);
share.putExtra("more", true);
shareIntents.add(share);
AlertDialog.Builder builder = new AlertDialog.Builder(DashboardActivity.this, R.style.AppCompat_Pipe_Dialog_Alert);
builder.setTitle(R.string.share_with);
final SharingAdapter adapter = new SharingAdapter(this, R.layout.item_sharing, shareIntents);
builder.setAdapter(adapter, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Intent i = adapter.getItem(which);
//Trigger to load the standard android sharing dialog
if (i.getBooleanExtra("more", false)) {
Intent intent = Intent.createChooser(Sharing.getSharingIntent(subject, content + ' ' + appUrl), getString(R.string.share_with));
startActivity(intent);
return;
}
//fix exception when launching labeled-intent
if (i instanceof LabeledIntent) {
i = new Intent(i);
}
startActivity(i);
}
});
builder.show();
}
private void setInfo(final InfoFragment.State state, final boolean forceFragment) {
handler.postRunnable(new Runnable() {
@Override
public void run() {
if (isFinishing()) return;
Fragment curFragment = getSupportFragmentManager().findFragmentById(R.id.frame_sidebar);
if (curFragment instanceof InfoFragment) {
((InfoFragment) curFragment).setState(state);
} else if (forceFragment) {
InfoFragment frag = new InfoFragment();
getSupportFragmentManager().beginTransaction().
replace(R.id.frame_sidebar, frag).commit();
frag.setState(state);
}
}
});
}
public void connectVpn() {
if (mService != null) {
runBackendConnection(Config.getInstance().getAuthToken());
}
}
public void disconnectVpn() {
showVpnDisconnected();
if (mService != null) {
mService.disconnect();
}
}
private void showVpnConnected() {
handler.postRunnable(new Runnable() {
@Override
public void run() {
if (getSupportFragmentManager().findFragmentById(R.id.frame_sidebar)
instanceof StatisticsFragment) return;
getSupportFragmentManager().beginTransaction().
replace(R.id.frame_sidebar, new StatisticsFragment()).commit();
startConnectionsLoader();
}
});
}
private void showVpnDisconnected() {
handler.postRunnable(new Runnable() {
@Override
public void run() {
if (getSupportFragmentManager().findFragmentById(R.id.frame_sidebar)
instanceof InfoFragment) return;
viewConnStatus.setConnectionState(ConnectionStatusView.VpnState.DISCONNECTED);
viewConnStatus.setConnectionState(ConnectionStatusView.VpnState.WAITING);
InfoFragment frag = new InfoFragment();
getSupportFragmentManager().beginTransaction().
replace(R.id.frame_sidebar, frag).commit();
stopConnectionsLoader();
viewMap.showDisconnected();
frag.setState(viewSubscrStatus.isSubscriptionValid() ? InfoFragment.State.DISCONNECTED :
InfoFragment.State.NO_SUBSCIPTION);
}
});
}
public void syncVpnState() {
VpnStateService.State curVpnState = VpnStateService.State.DISABLED;
if (mService != null) {
curVpnState = mService.getState();
} else {
return;
}
// state change detected
if (curVpnState != mVpnState || getSupportFragmentManager()
.findFragmentById(R.id.frame_sidebar) instanceof WaitingIndicatorFragment ||
viewConnStatus.getConnectionState() == ConnectionStatusView.VpnState.WAITING) {
switch (curVpnState) {
case DISABLED:
showVpnDisconnected();
handler.postRunnable(new Runnable() {
@Override
public void run() {
viewConnStatus.setConnectionState(ConnectionStatusView.VpnState.DISCONNECTED);
if (subscrManager.isFailed()) {
handler.postRunnable(subscriptionsFetchRunnable);
} else if (mOpenSubscriptions) {
mOpenSubscriptions = false;
openSubscriptionsActivity();
}
}
});
break;
case CONNECTING:
if (!(getSupportFragmentManager().findFragmentById(R.id.frame_sidebar)
instanceof StatisticsFragment)) {
showWaiting();
}
break;
case CONNECTED:
viewConnStatus.setConnectionState(ConnectionStatusView.VpnState.CONNECTED);
showVpnConnected();
break;
case DISCONNECTING:
if (!(getSupportFragmentManager().findFragmentById(R.id.frame_sidebar)
instanceof InfoFragment)) {
showWaiting();
}
break;
}
}
mVpnState = curVpnState;
}
private void showWaiting() {
viewConnStatus.setConnectionState(ConnectionStatusView.VpnState.WAITING);
if (!waitingFragment.isVisible()) {
handler.postRunnable(new Runnable() {
@Override
public void run() {
getSupportFragmentManager().beginTransaction().
replace(R.id.frame_sidebar, waitingFragment).commit();
}
});
}
}
private void startConnectionsLoader() {
viewMap.setAllowRecalcBounds();
btnRescaleMap.setVisibility(View.GONE);
getSupportLoaderManager().restartLoader(LOADER_ID, null, this);
}
private void showNoConnection() {
handler.postDelayedRunnable(subscriptionsFetchRunnable,
SUBCR_FETCH_REPEAT_INTERVAL, true);
viewConnStatus.setConnectionState(ConnectionStatusView.VpnState.UNAVAILABLE);
viewMap.showNoNetwork();
viewSubscrStatus.setVisibility(View.GONE);
setInfo(InfoFragment.State.NO_NETWORK, true);
}
private void stopConnectionsLoader(){
getSupportLoaderManager().destroyLoader(LOADER_ID);
}
}