com.adamas.client.android.MainActivity.java Source code

Java tutorial

Introduction

Here is the source code for com.adamas.client.android.MainActivity.java

Source

/*
 * Adamas -- An application to securely and anonymously tunnel IP
 *           networks over other Internet protocols. It consists of Adamas
 *           Client, Adamas Connector and Adamas Server.
 *
 * Copyright (C) 2016 <adamasvpn@gmail.com>
 *
 * This file is part of Adamas Client or Connector, or both.
 *
 * Adamas Client and Adamas Connector are free software: you can
 * redistribute them and/or modify them 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.
 *
 * Adamas Client and Adamas Connector are distributed in the hope
 * that they 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 Adamas Client and Adamas Connector. If not, see
 * <http://www.gnu.org/licenses/>.
 */

package com.adamas.client.android;

import android.Manifest;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.support.design.widget.TabLayout;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.content.ContextCompat;
import android.support.v4.view.ViewPager;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CompoundButton;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.Switch;

import com.adamas.client.R;
import com.adamas.client.android.service.DmVpnService;
import com.adamas.client.android.service.DmVpnServiceStatusCallback;
import com.adamas.client.android.service.VpnStatus;
import com.adamas.client.android.ui.ConnectorsFragment;
import com.adamas.client.android.ui.StatisticsFragment;
import com.adamas.client.android.util.DefaultSettings;
import com.adamas.client.android.util.Store;
import com.adamas.client.android.util.ToastType;
import com.adamas.common.util.Converter;
import com.adamas.common.util.UuidConverter;
import com.adamas.connector.Connector;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.MultiFormatReader;
import com.google.zxing.RGBLuminanceSource;
import com.google.zxing.Result;
import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.integration.android.IntentIntegrator;
import com.google.zxing.integration.android.IntentResult;

import org.pedro.fonseca.CryptUtil;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicBoolean;

import au.com.ninthavenue.patterns.android.dialogs.FileChooser;

public class MainActivity extends BaseActivity
        implements ConnectorsFragment.OnFragmentInteractionListener, Handler.Callback {
    private final static int MY_PERMISSIONS_REQUEST_CAMERA = 100;

    //////////////// bellow is new code ////////////////////////
    public static final int SCANNER_REQUEST_CODE = 100;
    public static final int IMPORT_CONNECTOR_REQUEST_CODE = 200;
    public static final int MANUALLY_ADD_CONNECTOR_REQUEST_CODE = 300;
    public static final int MANUALLY_EDIT_CONNECTOR_REQUEST_CODE = 400;
    public static final int IMPORT_FROM_TEXT_REQUEST_CODE = 500;
    public static final int IMPORT_FROM_FILE_REQUEST_CODE = 600;

    private enum ConnectorType {
        automatic, manual
    };

    public static final int FRAGMENT_CONNECTORS = 0;
    public static final int FRAGMENT_STATISTICS = 1;
    private int _currentActiveFragment = FRAGMENT_CONNECTORS;
    ConnectorsFragment _connectorfragment = null;
    StatisticsFragment _statisticsFragment = null;

    /**
     * The {@link android.support.v4.view.PagerAdapter} that will provide
     * fragments for each of the sections. We use a
     * {@link FragmentPagerAdapter} derivative, which will keep every
     * loaded fragment in memory. If this becomes too memory intensive, it
     * may be best to switch to a
     * {@link android.support.v4.app.FragmentStatePagerAdapter}.
     */
    private SectionsPagerAdapter mSectionsPagerAdapter;

    /**
     * The {@link ViewPager} that will host the section contents.
     */
    private ViewPager mViewPager;
    private MenuItem _menuItemStartStop = null;
    //////////////// above is new code ////////////////////////

    //////////////// bellow is old code from OldMainActivity ////////////////////////
    private static final int MSG_UPDATE_VPN_STATE = 1;
    private static final int VPNSERVICE_PERMISSION = 100;
    private static Boolean FIRST_TIME_RUN = null;

    //in milli-seconds
    private static final int MIN_FLASH_INTERVAL = 200;
    private static final int MAX_FLASH_INTERVAL = 1000;
    private static final int FLASH_INTERVAL_DELTA = 100;
    private static final AtomicBoolean _connecting = new AtomicBoolean(false);
    private static final AtomicBoolean _disconnecting = new AtomicBoolean(false);

    private static Connector _connectedAdamasConnector;

    private ImageView connectDisconnectImage;

    private Handler mHandler;

    private boolean _connected = false;

    private DmVpnService mService;
    boolean _serviceBound = false;

    //TODO
    private Connector _selectedAdamasConnector;
    private boolean connectClicked = false;

    DmVpnServiceStatusCallback mCallback = new DmVpnServiceStatusCallback() {
        /**
         * This is called by the remote service regularly to tell us about
         * new values.  Note that IPC calls are dispatched through a thread
         * pool running in each process, so the code executing here will
         * NOT be running in our main thread like most other things -- so,
         * to update the UI, we need to use a Handler to hop over there.
         */
        public void update(int vpnStatus) {
            Message msg = Message.obtain(mHandler, MSG_UPDATE_VPN_STATE,
                    getResources().getStringArray(R.array.vpn_state_array)[vpnStatus]);
            msg.arg1 = vpnStatus;

            if (vpnStatus == VpnStatus.CONNECTED) {
                _connecting.set(false);
                _connected = true;
            } else {
                _connected = false;
                if (vpnStatus == VpnStatus.NOT_CONNECTED) {
                    _connecting.set(false);
                    _disconnecting.set(false);
                    _connectedAdamasConnector = null;
                    //a little bit ugly here. if we do not null them, startVpn will not run again when previous connection fails.
                    mService.nullAll();
                }
            }
            msg.sendToTarget();
        }
    };
    private ServiceConnection mConnection = new ServiceConnection() {
        // Called when the connection with the service is established
        public void onServiceConnected(ComponentName className, IBinder service) {
            // Because we have bound to an explicit
            // service that is running in our own process, we can
            // cast its IBinder to a concrete class and directly access it.
            DmVpnService.LocalBinder binder = (DmVpnService.LocalBinder) service;
            mService = binder.getService();
            _serviceBound = true;
            mService.registerStatusCallback(mCallback);
            //            _imageConnected.setVisibility(mService.isConnected() ? View.VISIBLE : View.GONE);
        }

        // Called when the connection with the service disconnects unexpectedly
        public void onServiceDisconnected(ComponentName className) {
            _serviceBound = false;
            mService = null;
        }
    };
    //////////////// above is old code from OldMainActivity////////////////////////

    //////////////// bellow is new code ////////////////////////
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mHandler = new Handler(this);

        setContentView(R.layout.activity_main);

        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        // Create the adapter that will return a fragment for each of the three
        // primary sections of the activity.
        mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());

        // Set up the ViewPager with the sections adapter.
        mViewPager = (ViewPager) findViewById(R.id.container);
        mViewPager.setAdapter(mSectionsPagerAdapter);

        mViewPager.addOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
            public void onPageSelected(int position) {
                _currentActiveFragment = position;
                if (_currentActiveFragment == FRAGMENT_CONNECTORS) {
                    changeHomeImage();
                }
                refreshMenu();
            }
        });

        View floatingactionbutton = findViewById(R.id.floating_action_button);
        floatingactionbutton.setVisibility(View.INVISIBLE);

        TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs);
        tabLayout.setupWithViewPager(mViewPager);

        initUuid();

        //////////////// bellow is old code from OldMainActivity /////////////////
        {
            //            mHandler = new Handler(this);
            bindService();
            changeHomeImage();
        }
        //////////////// above is old code from OldMainActivity /////////////////

    }

    private Boolean _checked = null;

    public void refreshMenu() {
        if (_menuItemStartStop != null) {
            final Switch mySwitch = (Switch) _menuItemStartStop.getActionView()
                    .findViewById(R.id.switchForStartStopConnector);
            _checked = Boolean.valueOf(mySwitch.isChecked());
        }
        invalidateOptionsMenu();
        //        openOptionsMenu();
        //        closeOptionsMenu();
    }

    boolean _runProcessConnectDisconnectKey = true;

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu_main, menu);

        _menuItemStartStop = menu.findItem(R.id.action_start_stop_vpn);
        final Switch mySwitch = (Switch) _menuItemStartStop.getActionView()
                .findViewById(R.id.switchForStartStopConnector);
        if (_checked != null) {
            mySwitch.setChecked(_checked.booleanValue());
            _checked = null;
        } else {
            mySwitch.setChecked(_connected);
        }
        if (_connecting.get() || _disconnecting.get()) {
            _menuItemStartStop.getActionView().findViewById(R.id.switchForStartStopConnector)
                    .setVisibility(View.GONE);
            _menuItemStartStop.getActionView().findViewById(R.id.progressBarConnecting).setVisibility(View.VISIBLE);
        }
        //attach a listener to check for changes in state
        mySwitch.setOnCheckedChangeListener(new Switch.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                if (_runProcessConnectDisconnectKey) {
                    if (isChecked) {
                        processConnectDisconnectKey();
                    } else {
                        processConnectDisconnectKey();
                    }
                } else {
                    _runProcessConnectDisconnectKey = true;
                }
            }
        });

        return true;
    }

    @Override
    public boolean onPrepareOptionsMenu(Menu menu) {
        _menuItemStartStop = menu.findItem(R.id.action_start_stop_vpn);
        MenuItem scan = menu.findItem(R.id.action_scan_qr_code);
        MenuItem delete = menu.findItem(R.id.action_delete_connector);
        MenuItem edit = menu.findItem(R.id.action_edit_connector);
        MenuItem importConnectorFile = menu.findItem(R.id.action_import_connector_from_image);
        MenuItem importConnectorText = menu.findItem(R.id.action_import_connector_from_text);
        MenuItem add = menu.findItem(R.id.action_add_connector_manually);
        MenuItem settings = menu.findItem(R.id.action_settings);

        if (_menuItemStartStop != null) {
            if (_currentActiveFragment == FRAGMENT_CONNECTORS) {
                _menuItemStartStop.setVisible(true);
                scan.setVisible(true);
                importConnectorFile.setVisible(true);
                importConnectorText.setVisible(true);
                add.setVisible(true);
                settings.setVisible(true);
                if (_selectedAdamasConnector != null) {
                    delete.setVisible(true);
                    edit.setVisible(true);
                } else {
                    delete.setVisible(false);
                    edit.setVisible(false);
                }
            } else if (_currentActiveFragment == FRAGMENT_STATISTICS) {
                _menuItemStartStop.setVisible(false);
                scan.setVisible(false);
                importConnectorFile.setVisible(false);
                importConnectorText.setVisible(false);
                add.setVisible(false);
                settings.setVisible(true);
                delete.setVisible(false);
                edit.setVisible(false);
            }
        }
        return super.onPrepareOptionsMenu(menu);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        } else if (id == R.id.action_scan_qr_code) {
            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
                IntentIntegrator integrator = new IntentIntegrator(this);
                integrator.initiateScan();
            } else {
                checkCameraPermission();
            }
        } else if (id == R.id.action_delete_connector) {
            if (_connectorfragment != null) {
                _connectorfragment.deleteConnector(_selectedAdamasConnector);
            }
        } else if (id == R.id.action_add_connector_manually) {
            Intent intent = new Intent(this, AddConnectorActivity.class);
            startActivityForResult(intent, MANUALLY_ADD_CONNECTOR_REQUEST_CODE);
        } else if (id == R.id.action_edit_connector) {
            Intent intent = new Intent(this, EditConnectorActivity.class);
            Bundle mBundle = new Bundle();
            mBundle.putSerializable(EditConnectorActivity.ADAMAS_CONNECTOR, _selectedAdamasConnector);
            intent.putExtras(mBundle);
            startActivityForResult(intent, MANUALLY_EDIT_CONNECTOR_REQUEST_CODE);
        } else if (id == R.id.action_import_connector_from_text) {
            Intent intent = new Intent(this, ImportTextActivity.class);
            startActivityForResult(intent, IMPORT_FROM_TEXT_REQUEST_CODE);
        } else if (id == R.id.action_import_connector_from_image) {
            if (false) {
                FileChooser fileChooser = new FileChooser(this);
                fileChooser.setFileListener(new FileChooser.FileSelectedListener() {
                    @Override
                    public void fileSelected(final File file) {
                        String name = file.getAbsolutePath();
                        name = name;
                    }
                });
                fileChooser.showDialog();
            } else {
                // this is much better
                Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
                Uri uri = Uri.parse(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)
                        .getAbsolutePath());
                intent.setDataAndType(uri, "image/jpeg");
                startActivityForResult(Intent.createChooser(intent, getString(R.string.open)),
                        IMPORT_FROM_FILE_REQUEST_CODE);
            }
        }

        return super.onOptionsItemSelected(item);
    }

    private static String makeFragmentName(int viewPagerId, int index) {
        return "android:switcher:" + viewPagerId + ":" + index;
    }

    /**
     * A {@link FragmentPagerAdapter} that returns a fragment corresponding to
     * one of the sections/tabs/pages.
     */
    public class SectionsPagerAdapter extends FragmentPagerAdapter {

        public SectionsPagerAdapter(FragmentManager fm) {
            super(fm);
        }

        @Override
        public Fragment getItem(int position) {
            // getItem is called to instantiate the fragment for the given page.
            // Return a PlaceholderFragment (defined as a static inner class below).
            // Do NOT try to save references to the Fragments in getItem(),
            // because getItem() is not always called. If the Fragment
            // was already created then it will be retrieved from the FragmentManger
            // and not here (i.e. getItem() won't be called again).
            switch (position) {
            case FRAGMENT_CONNECTORS:
                return ConnectorsFragment.newInstance(FRAGMENT_CONNECTORS);
            case FRAGMENT_STATISTICS:
                return StatisticsFragment.newInstance(FRAGMENT_STATISTICS);
            default:
                return null;
            }
        }

        // Here we can finally safely save a reference to the created
        // Fragment, no matter where it came from (either getItem() or
        // FragmentManger). Simply save the returned Fragment from
        // super.instantiateItem() into an appropriate reference depending
        // on the ViewPager position.
        @Override
        public Object instantiateItem(ViewGroup container, int position) {
            Fragment createdFragment = (Fragment) super.instantiateItem(container, position);
            // save the appropriate reference depending on position
            switch (position) {
            case FRAGMENT_CONNECTORS:
                _connectorfragment = (ConnectorsFragment) createdFragment;
                break;
            case FRAGMENT_STATISTICS:
                _statisticsFragment = (StatisticsFragment) createdFragment;
                break;
            }
            return createdFragment;
        }

        @Override
        public int getCount() {
            // Show 2 total pages.
            return 2;
        }

        @Override
        public CharSequence getPageTitle(int position) {
            switch (position) {
            case FRAGMENT_CONNECTORS:
                return getString(R.string.fragment_connectors);
            case FRAGMENT_STATISTICS:
                return getString(R.string.fragment_statistics);
            }
            return null;
        }
    }

    @Override
    public void onFragmentInteraction(Uri uri) {
        //TODO
    }

    public boolean isConnected() {
        return _connected;
    }

    public int getCurrentActiveFragment() {
        return _currentActiveFragment;
    }

    public void setCurrentActiveFragment(int currentActiveFragment) {
        //This works very slow. Better using mViewPager.addOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener()
    }

    public void processFloatingActionButton(View view) {
    }

    public void changeMonitorImage(View view) {

    }
    //////////////// above is new code ////////////////////////

    //////////////// bellow is old code from OldMainActivity ////////////////////////
    private void bindService() {
        _serviceBound = false;
        Intent intent = new Intent(this, DmVpnService.class);
        //        bindService(createExplicitFromImplicitIntent(getApplicationContext(), intent), mConnection, Context.BIND_AUTO_CREATE);
        bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
        _serviceBound = true;
    }

    public void changeHomeImage() {
        if (_connected) {
            if (_menuItemStartStop != null) {
                _menuItemStartStop.getActionView().findViewById(R.id.switchForStartStopConnector)
                        .setVisibility(View.VISIBLE);
                _menuItemStartStop.getActionView().findViewById(R.id.progressBarConnecting)
                        .setVisibility(View.GONE);
            }
        }

        FrameLayout frameLayout = (FrameLayout) findViewById(R.id.layouthelpinghand);
        //        if (frameLayout != null) {
        //            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        //                if (_connected) {
        //                    frameLayout.setBackground(getResources().getDrawable(R.drawable.helpinghand_hold, getTheme()));
        ////                    frameLayout.getBackground().setTint(getResources().getColor(R.color.material_yellow_300));
        //                    frameLayout.getBackground().setTintMode(PorterDuff.Mode.SCREEN);
        //                } else {
        //                    frameLayout.setBackground(getResources().getDrawable(R.drawable.helpinghand, getTheme()));
        //                    frameLayout.getBackground().setTintMode(PorterDuff.Mode.SCREEN);
        //                    frameLayout.getBackground().setTint(getResources().getColor(R.color.material_grey_100));
        //                }
        //            } else {
        //                if (_connected) {
        //                    frameLayout.setBackgroundDrawable(getResources().getDrawable(R.drawable.helpinghand_hold));
        //                } else {
        //                    frameLayout.setBackgroundDrawable(getResources().getDrawable(R.drawable.helpinghand));
        //                }
        //            }
        //        }
    }

    private void processQrCodeText(String content) {
        if (content != null && content.trim().length() == 32) {
            //Connector key
            content = content.trim();
            SharedPreferences sharedPref = getSharedPreferences(Store.STORE_ADAMAS_CONNECTORS,
                    Context.MODE_PRIVATE);
            Store.saveConnectorKey(sharedPref, Converter.hexToBytes(content));
            toast(getString(R.string.toast_connector_key_saved), ToastType.info);
        } else if (content != null && content.trim().length() > 0) {
            Connector connector = Connector.parseStringFromQrCode(content);
            if (connector == null) {
                //maybe it is encrypted, let's decrypt it
                SharedPreferences sharedPref = getSharedPreferences(Store.STORE_ADAMAS_CONNECTORS,
                        Context.MODE_PRIVATE);
                List<byte[]> keys = Store.loadConnectorKeys(sharedPref);
                byte[] bytes = Converter.hexToBytes(content.trim());
                for (byte[] key : keys) {
                    byte[] decrypted = CryptUtil.decrypt(key, bytes);
                    if (decrypted != null) {
                        connector = Connector.parseStringFromQrCode(new String(decrypted));
                        if (connector != null) {
                            break;
                        }
                    }
                }
            }
            if (connector != null) {
                Intent importIntent = new Intent(this, ImportConnectorActivity.class);
                Bundle mBundle = new Bundle();
                mBundle.putSerializable(ImportConnectorActivity.ADAMAS_CONNECTOR, connector);
                importIntent.putExtras(mBundle);
                startActivityForResult(importIntent, IMPORT_CONNECTOR_REQUEST_CODE);
            }
        }
    }

    public void onActivityResult(int requestCode, int resultCode, Intent intent) {
        IntentResult scanResult = IntentIntegrator.parseActivityResult(requestCode, resultCode, intent);
        if (scanResult != null) {
            // handle scan result
            String content = scanResult.getContents();
            processQrCodeText(content);
        } else {
            if (resultCode == Activity.RESULT_OK) {
                if (requestCode == VPNSERVICE_PERMISSION) {
                    DefaultSettings.USERNAME = _selectedAdamasConnector.getUsername();
                    DefaultSettings.PASSWORD = _selectedAdamasConnector.getPassword();
                    connectOpenvpn(_selectedAdamasConnector);
                } else if (IMPORT_CONNECTOR_REQUEST_CODE == requestCode) {

                } else if (MANUALLY_ADD_CONNECTOR_REQUEST_CODE == requestCode) {

                } else if (MANUALLY_EDIT_CONNECTOR_REQUEST_CODE == requestCode) {

                } else if (IMPORT_FROM_TEXT_REQUEST_CODE == requestCode) {

                } else if (IMPORT_FROM_FILE_REQUEST_CODE == requestCode) {
                    Uri selectedimg = intent.getData();
                    try {
                        Result result = decode(selectedimg);
                        String content = result.getText();
                        processQrCodeText(content);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                } else {

                }
            } else {
                if (requestCode == VPNSERVICE_PERMISSION) {
                    _runProcessConnectDisconnectKey = false;
                    ((Switch) findViewById(R.id.switchForStartStopConnector)).setChecked(false);
                }
            }
        }

        //TODO - refresh vpnlist
        if (_connectorfragment != null) {
            _connectorfragment.processRefreshKey();
        }
    };

    protected Result decode(Uri uri) {
        try {
            InputStream inputStream = getContentResolver().openInputStream(uri);
            Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
            if (bitmap == null) {
                return null;
            }
            int width = bitmap.getWidth(), height = bitmap.getHeight();
            int[] pixels = new int[width * height];
            bitmap.getPixels(pixels, 0, width, 0, 0, width, height);
            bitmap.recycle();
            bitmap = null;
            RGBLuminanceSource source = new RGBLuminanceSource(width, height, pixels);
            BinaryBitmap bBitmap = new BinaryBitmap(new HybridBinarizer(source));
            MultiFormatReader reader = new MultiFormatReader();
            try {
                com.google.zxing.Result result = reader.decode(bBitmap);
                return result;
            } catch (Exception e) {
                return null;
            }
        } catch (FileNotFoundException e) {
            return null;
        }
    }

    @Override
    protected void onStop() {
        super.onStop();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (_serviceBound) {
            unbindService(mConnection);
            _serviceBound = false;
        }
    }

    private void connectOpenvpn(Connector adamasConnector) {
        if (_connected) {
            //do nothing
        } else {
            ConnectOpenvpnTask task = new ConnectOpenvpnTask();
            task.execute(adamasConnector);
        }
    }

    private void processConnectDisconnectKey() {
        if (_connected) {
            DisconnectOpenvpnTask task = new DisconnectOpenvpnTask();
            task.execute();
        } else {
            if (_selectedAdamasConnector != null) {
                _connectedAdamasConnector = _selectedAdamasConnector;
                // Request permission to use the API
                Intent i = mService.prepare(getApplicationContext());
                if (i != null) {
                    startActivityForResult(i, VPNSERVICE_PERMISSION);
                } else {
                    onActivityResult(VPNSERVICE_PERMISSION, Activity.RESULT_OK, null);
                }
            } else {
                Switch mySwitch = (Switch) _menuItemStartStop.getActionView()
                        .findViewById(R.id.switchForStartStopConnector);
                mySwitch.setChecked(_connected);
                if (_connectorfragment != null) {
                    if (_connectorfragment.getConnectorCount() == 0) {
                        toast(getResources().getString(R.string.toast_add_a_connector), ToastType.warning);
                    } else {
                        toast(getResources().getString(R.string.toast_select_a_connector), ToastType.warning);
                    }
                }
            }
        }
    }

    private class ConnectOpenvpnTask extends AsyncTask<Connector, Integer, Long> {
        private Connector adamasConnector = null;

        protected Long doInBackground(Connector... adamasConnectors) {
            connectClicked = true;
            adamasConnector = adamasConnectors[0];
            publishProgress(1);
            try {
                if (_connecting.compareAndSet(false, true)) {
                    mCallback.update(VpnStatus.CONNECTING);
                    mService.startVpn(adamasConnector);
                }
            } catch (Exception ex) {
                mCallback.update(VpnStatus.NOT_CONNECTED);
                ex.printStackTrace();
            }
            return 100L;
        }

        protected void onProgressUpdate(Integer... progress) {
            //TODO
        }

        protected void onPostExecute(Long result) {

        }
    }

    private class DisconnectOpenvpnTask extends AsyncTask<Connector, Integer, Long> {
        Connector adamasConnector = null;

        protected Long doInBackground(Connector... adamasConnectors) {
            if (adamasConnectors != null && adamasConnectors.length > 0) {
                adamasConnector = adamasConnectors[0];
            }
            publishProgress(1);
            try {
                if (_disconnecting.compareAndSet(false, true)) {
                    mCallback.update(VpnStatus.DISCONNECTING);
                    mService.stopVpn();
                }
                // let's wait for a while; otherwise download config task may fail after this task
                Thread.sleep(1000);
            } catch (Exception ex) {
                ex.printStackTrace();
            }
            return 100L;
        }

        protected void onProgressUpdate(Integer... progress) {
        }

        protected void onPostExecute(Long result) {
        }
    }

    @Override
    public boolean handleMessage(Message msg) {
        if (_menuItemStartStop == null) {
            return true;
        }
        if (msg.what == MSG_UPDATE_VPN_STATE) {
            String state = (String) msg.obj;
            int code = msg.arg1;
            if (code == VpnStatus.CONNECTED || code == VpnStatus.NOT_CONNECTED) {
                _menuItemStartStop.getActionView().findViewById(R.id.switchForStartStopConnector)
                        .setVisibility(View.VISIBLE);
                _menuItemStartStop.getActionView().findViewById(R.id.progressBarConnecting)
                        .setVisibility(View.GONE);

                Switch myswitch = (Switch) _menuItemStartStop.getActionView()
                        .findViewById(R.id.switchForStartStopConnector);
                if (code == VpnStatus.CONNECTED && !myswitch.isChecked()) {
                    _runProcessConnectDisconnectKey = false;
                    myswitch.setChecked(true);
                } else if (code == VpnStatus.NOT_CONNECTED && myswitch.isChecked()) {
                    _runProcessConnectDisconnectKey = false;
                    myswitch.setChecked(false);
                }

                if (code == VpnStatus.CONNECTED) {
                    toast(getResources().getString(R.string.vpn_is_connected), ToastType.info);
                    if (connectClicked) {
                        connectClicked = false;
                        showHomeUrl();
                    }
                } else {
                    toast(getResources().getString(R.string.vpn_is_not_connected), ToastType.error);
                }

                if (_connectorfragment != null) {
                    _connectorfragment.vpnAdaptorNotifyDataSetChanged();
                }
            } else if (code == VpnStatus.CONNECTING || code == VpnStatus.DISCONNECTING) {
                _menuItemStartStop.getActionView().findViewById(R.id.switchForStartStopConnector)
                        .setVisibility(View.GONE);
                _menuItemStartStop.getActionView().findViewById(R.id.progressBarConnecting)
                        .setVisibility(View.VISIBLE);
            } else {
                //TODO impossible to get here
                _menuItemStartStop.getActionView().findViewById(R.id.switchForStartStopConnector)
                        .setVisibility(View.VISIBLE);
                _menuItemStartStop.getActionView().findViewById(R.id.progressBarConnecting)
                        .setVisibility(View.GONE);
                toast(getResources().getString(R.string.vpn_is_not_connected), ToastType.error);
                if (_connectorfragment != null) {
                    _connectorfragment.vpnAdaptorNotifyDataSetChanged();
                }
            }
        }

        changeHomeImage();
        return true;
    }

    private void showHomeUrl() {
        String url = getString(R.string.home_url);
        Intent i = new Intent(Intent.ACTION_VIEW);
        i.setData(Uri.parse(url));
        startActivity(i);
    }

    public void setSelectedAdamasConnector(Connector connector) {
        _selectedAdamasConnector = connector;
        refreshMenu();
    }

    public Connector getSelectedAdamasConnector() {
        return _selectedAdamasConnector;
    }

    public Connector getConnectedAdamasConnector() {
        return _connectedAdamasConnector;
    }
    //////////////// above is old code from OldMainActivity ////////////////////////

    private void checkCameraPermission() {
        if (ContextCompat.checkSelfPermission(this,
                Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
            // Should we show an explanation?
            if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.CAMERA)) {
                // Show an expanation to the user *asynchronously* -- don't block
                // this thread waiting for the user's response! After the user
                // sees the explanation, try again to request the permission.
            } else {
                // No explanation needed, we can request the permission.
                ActivityCompat.requestPermissions(this, new String[] { Manifest.permission.CAMERA },
                        MY_PERMISSIONS_REQUEST_CAMERA);
                // MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
                // app-defined int constant. The callback method gets the
                // result of the request.
            }
        } else {
            onRequestPermissionsResult(MY_PERMISSIONS_REQUEST_CAMERA, new String[0],
                    new int[] { PackageManager.PERMISSION_GRANTED });
        }
    }

    public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
        switch (requestCode) {
        case MY_PERMISSIONS_REQUEST_CAMERA: {
            // If request is cancelled, the result arrays are empty.
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                // permission was granted, yay! Do the
                // contacts-related task you need to do.
                IntentIntegrator integrator = new IntentIntegrator(this);
                integrator.initiateScan();
            } else {
                // permission denied, boo! Disable the
                // functionality that depends on this permission.
            }
            return;
        }
        // other 'case' lines to check for other
        // permissions this app might request
        }
    }

    private void initUuid() {
        String uuid = Store.getUuid(getSharedPreferences(Store.STORE_ADAMAS_CONNECTORS, Context.MODE_PRIVATE));
        UUID u = null;
        if (uuid == null) {
            u = UUID.randomUUID();
            uuid = u.toString();
            Store.saveUuid(getSharedPreferences(Store.STORE_ADAMAS_CONNECTORS, Context.MODE_PRIVATE), uuid);
        } else {
            u = UUID.fromString(uuid);
        }
        Setting.uuid = UuidConverter.getBytesFromUUID(u);
        Log.i(MainActivity.class.getName(), "UUID is " + uuid);
    }
}