net.named_data.nfd.WiFiDirectFragment.java Source code

Java tutorial

Introduction

Here is the source code for net.named_data.nfd.WiFiDirectFragment.java

Source

/* -*- Mode:jde; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
 * Copyright (c) 2015-2017 Regents of the University of California
 *
 * This file is part of NFD (Named Data Networking Forwarding Daemon) Android.
 * See AUTHORS.md for complete list of NFD Android authors and contributors.
 *
 * NFD Android 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.
 *
 * NFD Android 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
 * NFD Android, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
 */

package net.named_data.nfd;

import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.SharedPreferences;
import android.net.wifi.p2p.WifiP2pDevice;
import android.net.wifi.p2p.WifiP2pManager;
import android.os.Bundle;
import android.os.Handler;
import android.preference.PreferenceManager;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.CompoundButton;
import android.widget.ListView;
import android.widget.Switch;
import android.widget.TextView;
import android.widget.Toast;

import net.named_data.nfd.wifidirect.model.Peer;
import net.named_data.nfd.wifidirect.utils.NDNController;

import java.util.ArrayList;
import java.util.List;

import static android.app.ProgressDialog.show;
import static net.named_data.nfd.wifidirect.utils.NDNController.myAddress;
import static net.named_data.nfd.wifidirect.utils.NDNController.myDeviceName;

/**
 * A simple {@link Fragment} subclass.
 * Activities that contain this fragment must implement the
 * Use the {@link WiFiDirectFragment#newInstance} factory method to
 * create an instance of this fragment.
 */
public class WiFiDirectFragment extends Fragment {

    private static final String TAG = "WiFiDirectFragment";

    public WiFiDirectFragment() {
        // Required empty public constructor
    }

    /**
     * Use this factory method to create a new instance of
     * this fragment using the provided parameters.
     *
     * @return A new instance of fragment WiFiDirectFragment.
     */
    public static WiFiDirectFragment newInstance() {
        return new WiFiDirectFragment();
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        m_sharedPreferences = PreferenceManager.getDefaultSharedPreferences(getActivity());
        m_handler = new Handler();
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        View view = inflater.inflate(R.layout.fragment_wifidirect, container, false);

        // init UI elements
        m_wdGroupConnStatus = (TextView) view.findViewById(R.id.wd_group_conn_status_textview);
        m_wdIpAddress = (TextView) view.findViewById(R.id.wd_ip_address_textview);
        m_wdDeviceName = (TextView) view.findViewById(R.id.wd_this_device_name_textview);
        m_wdIsGroupOwner = (TextView) view.findViewById(R.id.wd_group_owner_textview);
        m_wdSwitch = (Switch) view.findViewById(R.id.wd_switch);

        if (m_sharedPreferences.getBoolean(PREF_WIFIDIRECT_STATUS, false)) {
            m_wdSwitch.setChecked(true);
            startNDNOverWifiDirect();
            startUiUpdateLoop();
        } else {
            // the button was off, make any desired UI changes
            m_wdGroupConnStatus.setText("");
        }

        m_wdSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                // store state of switch
                m_sharedPreferences.edit().putBoolean(PREF_WIFIDIRECT_STATUS, isChecked).apply();

                if (isChecked) {
                    startNDNOverWifiDirect();
                    startUiUpdateLoop();
                } else {
                    stopNDNOverWifiDirect();
                    stopUiUpdateLoop();
                    resetUi();
                }
            }
        });

        // list view for displaying peers
        m_wdConnectedPeerListview = (ListView) view.findViewById(R.id.wd_connected_peers_listview);
        m_ConnectedPeers = new ArrayList<>(NDNController.getInstance().getConnectedPeers());
        m_DicoveredPeers = new ArrayList<>(NDNController.getInstance().getDiscoveredPeers());

        m_ConnectedPeersAdapter = new ConnectPeerListAdapter(getActivity(), R.layout.row_devices, m_ConnectedPeers);
        m_wdConnectedPeerListview.setAdapter(m_ConnectedPeersAdapter);
        m_wdConnectedPeerListview.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                Peer selectedPeer = (Peer) parent.getItemAtPosition(position);

                // toast a quick message!
                if (selectedPeer == null) {
                    Toast.makeText(getActivity(),
                            getResources().getString(R.string.fragment_wifidirect_toast_peer_no_longer_available),
                            Toast.LENGTH_LONG).show();
                } else {
                    String peerInfo = selectedPeer.getNumProbeTimeouts() == 0
                            ? getResources().getString(R.string.fragment_wifidirect_toast_connection_works_well)
                            : getResources().getString(R.string.fragment_wifidirect_toast_didnt_get_response)
                                    + (selectedPeer.getNumProbeTimeouts() * NDNController.PROBE_DELAY / 1000)
                                    + getResources().getString(R.string.fragment_wifidirect_toast_seconds);
                    Toast.makeText(getActivity(), peerInfo, Toast.LENGTH_LONG).show();
                }
            }
        });

        m_wdDiscoveredPeerListview = (ListView) view.findViewById(R.id.wd_discovered_peers_listview);
        m_DiscoveredPeersAdapter = new DiscoveredPeerListAdapter(getActivity(), R.layout.row_devices,
                m_DicoveredPeers);
        m_wdDiscoveredPeerListview.setAdapter(m_DiscoveredPeersAdapter);

        m_wdDiscoveredPeerListview.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                final WifiP2pDevice device = (WifiP2pDevice) parent.getItemAtPosition(position);

                if (device.status == WifiP2pDevice.INVITED) {
                    AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
                    builder.setMessage(
                            getResources().getString(R.string.fragment_wifidirect_dialog_cancel_invitation)
                                    + device.deviceName + getResources().getString(R.string.question_mark))
                            .setCancelable(false)
                            .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
                                public void onClick(DialogInterface dialog, int id) {
                                    m_progressDialog = show(getActivity(),
                                            getResources()
                                                    .getString(R.string.fragment_wifidirect_dialog_cancelling),
                                            getResources().getString(
                                                    R.string.fragment_wifidirect_dialog_cancelling_invitation)
                                                    + device.deviceName,
                                            true, true);
                                    m_progressDialog.setCancelable(false);

                                    NDNController.getInstance().cancelConnect();
                                }
                            }).setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
                                public void onClick(DialogInterface dialog, int id) {
                                    return;
                                }
                            });
                    AlertDialog dialog = builder.create();
                    dialog.show();
                    return;
                }

                if (device.status == WifiP2pDevice.CONNECTED) {
                    AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
                    String alertMessage = getResources()
                            .getString(R.string.fragment_wifidirect_dialog_disconnect_from) + device.deviceName
                            + getResources().getString(R.string.question_mark);
                    if (NDNController.getInstance().getIsGroupOwner()) {
                        alertMessage = alertMessage
                                + getResources().getString(R.string.fragment_wifidirect_dialog_destroy_group_alter);
                    }
                    builder.setMessage(alertMessage).setCancelable(false)
                            .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
                                public void onClick(DialogInterface dialog, int id) {
                                    m_progressDialog = show(getActivity(),
                                            getResources()
                                                    .getString(R.string.fragment_wifidirect_dialog_disconnecting),
                                            getResources().getString(
                                                    R.string.fragment_wifidirect_dialog_disconnecting_from)
                                                    + device.deviceName,
                                            true, true);
                                    m_progressDialog.setCancelable(false);

                                    NDNController.getInstance().disconnect();
                                }
                            }).setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
                                public void onClick(DialogInterface dialog, int id) {
                                    return;
                                }
                            });
                    AlertDialog dialog = builder.create();
                    dialog.show();
                    return;
                }

                AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
                builder.setMessage(
                        getResources().getString(R.string.fragment_wifidirect_dialog_invite) + device.deviceName
                                + getResources().getString(R.string.fragment_wifidirect_dialog_join_group)
                                + getResources().getString(R.string.question_mark))
                        .setCancelable(false)
                        .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
                            public void onClick(DialogInterface dialog, int id) {
                                m_progressDialog = ProgressDialog.show(getActivity(),
                                        getResources().getString(R.string.fragment_wifidirect_dialog_inviting),
                                        getResources().getString(R.string.fragment_wifidirect_dialog_inviting)
                                                + device.deviceName
                                                + getResources()
                                                        .getString(R.string.fragment_wifidirect_dialog_join_group),
                                        true, true);
                                m_progressDialog.setCancelable(false);

                                NDNController.getInstance().connect(device);
                            }
                        }).setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
                            public void onClick(DialogInterface dialog, int id) {
                                return;
                            }
                        });
                AlertDialog dialog = builder.create();
                dialog.show();
            }
        });
        return view;
    }

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
    }

    @Override
    public void onDetach() {
        super.onDetach();
    }

    @Override
    public void onPause() {
        super.onPause();
        stopUiUpdateLoop();
    }

    @Override
    public void onResume() {
        super.onResume();
        startUiUpdateLoop();
    }

    private void startNDNOverWifiDirect() {
        // this is set so that NDNController has context to start appropriate services
        NDNController.getInstance().setWifiDirectContext(getActivity());

        // only start if the device is not currently connected to a group
        // otherwise, the protocol must have been running to begin with!
        if (myAddress == null) {
            // main wrapper function that begins all elements of the protocol
            NDNController.getInstance().start();
        }
    }

    private void stopNDNOverWifiDirect() {
        // main wrapper function that stops all elements of the protocol
        NDNController.getInstance().stop();
    }

    private void startUiUpdateLoop() {
        // periodically check for changed state
        // to display to user
        m_handler.post(m_UiUpdateRunnable);
    }

    private void stopUiUpdateLoop() {
        m_handler.removeCallbacks(m_UiUpdateRunnable);
    }

    private void resetUi() {
        // simply resets what is displayed to user
        m_wdIpAddress.setText(getResources().getString(R.string.empty_string));
        m_wdGroupConnStatus.setText(getResources().getString(R.string.empty_string));
        m_wdIsGroupOwner.setText(getResources().getString(R.string.empty_string));
        m_ConnectedPeers.clear();
        m_DicoveredPeers.clear();
        m_ConnectedPeersAdapter.notifyDataSetChanged();
        m_DiscoveredPeersAdapter.notifyDataSetChanged();
    }

    /**
     * Array adapter for ListFragment that maintains WifiP2pDevice list.
     */
    private class ConnectPeerListAdapter extends ArrayAdapter<Peer> {

        private List<Peer> items;

        /**
         * @param context
         * @param textViewResourceId
         * @param objects
         */
        public ConnectPeerListAdapter(Context context, int textViewResourceId, List<Peer> objects) {
            super(context, textViewResourceId, objects);
            items = objects;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            View v = convertView;
            if (v == null) {
                LayoutInflater vi = (LayoutInflater) getActivity()
                        .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                v = vi.inflate(R.layout.row_devices, null);
            }
            Peer peer = items.get(position);
            if (peer != null) {
                TextView top = (TextView) v.findViewById(R.id.device_name);
                TextView bottom = (TextView) v.findViewById(R.id.device_details);
                if (top != null) {
                    top.setText(peer.getDevice() == null ? getResources().getString(R.string.empty_string)
                            : peer.getDevice().deviceName);
                }
                if (bottom != null) {
                    bottom.setText(peer.getIpAddress());
                }
            }

            return v;
        }
    }

    /**
     * Array adapter for ListFragment that maintains WifiP2pDevice list.
     */
    private class DiscoveredPeerListAdapter extends ArrayAdapter<WifiP2pDevice> {

        private List<WifiP2pDevice> items;

        /**
         * @param context
         * @param textViewResourceId
         * @param objects
         */
        public DiscoveredPeerListAdapter(Context context, int textViewResourceId, List<WifiP2pDevice> objects) {
            super(context, textViewResourceId, objects);
            items = objects;

        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            View v = convertView;
            if (v == null) {
                LayoutInflater vi = (LayoutInflater) getActivity()
                        .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                v = vi.inflate(R.layout.row_devices, null);
            }
            WifiP2pDevice device = items.get(position);
            if (device != null) {
                TextView top = (TextView) v.findViewById(R.id.device_name);
                TextView bottom = (TextView) v.findViewById(R.id.device_details);
                if (top != null) {
                    top.setText(device.deviceName);
                }
                if (bottom != null) {
                    bottom.setText(getDeviceStatus(device.status));
                }
            }

            return v;
        }
    }

    ////////////////////////////////////////////////////////////////////////////////////
    private ListView m_wdConnectedPeerListview;
    private ListView m_wdDiscoveredPeerListview;
    private Switch m_wdSwitch;
    private TextView m_wdGroupConnStatus;
    private TextView m_wdIpAddress;
    private TextView m_wdDeviceName;
    private TextView m_wdIsGroupOwner;

    private Handler m_handler;
    private Runnable m_UiUpdateRunnable = new Runnable() {
        @Override
        public void run() {
            if (m_progressDialog != null && m_progressDialog.isShowing()) {
                m_progressDialog.dismiss();
            }
            if (myAddress != null) {
                m_wdGroupConnStatus
                        .setText(getResources().getString(R.string.fragment_wifidirect_text_group_connected));
                m_wdIpAddress.setText(myAddress);
                if (NDNController.getInstance().getIsGroupOwner()) {
                    m_wdIsGroupOwner.setText(getResources().getString(R.string.yes));
                } else {
                    m_wdIsGroupOwner.setText(getResources().getString(R.string.no));
                }
            } else {
                if (!m_sharedPreferences.getBoolean(PREF_WIFIDIRECT_STATUS, false)) {
                    m_wdGroupConnStatus.setText("");
                } else {
                    if (NDNController.getInstance().WIFI_STATE == WifiP2pManager.WIFI_P2P_STATE_ENABLED)
                        m_wdGroupConnStatus.setText(
                                getResources().getString(R.string.fragment_wifidirect_text_group_scanning));
                    else {
                        m_wdGroupConnStatus.setText(getResources()
                                .getString(R.string.fragment_wifidirect_text_group_wifi_p2p_disabled));
                    }
                }

                m_wdIpAddress.setText(getResources().getString(R.string.empty_string));
                m_wdIsGroupOwner.setText(getResources().getString(R.string.empty_string));
            }
            if (myDeviceName != null) {
                m_wdDeviceName.setText(myDeviceName);
            } else {
                m_wdDeviceName.setText(getResources().getString(R.string.empty_string));
            }

            // refresh the list of peers
            m_ConnectedPeers.clear();
            m_DicoveredPeers.clear();
            m_ConnectedPeers.addAll(NDNController.getInstance().getConnectedPeers());
            m_DicoveredPeers.addAll(NDNController.getInstance().getDiscoveredPeers());
            m_ConnectedPeersAdapter.notifyDataSetChanged();
            m_DiscoveredPeersAdapter.notifyDataSetChanged();

            // call again in X seconds
            m_handler.postDelayed(m_UiUpdateRunnable, UI_UPDATE_DELAY_MS);
        }
    };

    private static String getDeviceStatus(int deviceStatus) {
        Log.d(TAG, "Peer status :" + deviceStatus);
        switch (deviceStatus) {
        case WifiP2pDevice.AVAILABLE:
            return "Available";
        case WifiP2pDevice.INVITED:
            return "Invited";
        case WifiP2pDevice.CONNECTED:
            return "Connected";
        case WifiP2pDevice.FAILED:
            return "Failed";
        case WifiP2pDevice.UNAVAILABLE:
            return "Unavailable";
        default:
            return "Unknown";
        }
    }

    private SharedPreferences m_sharedPreferences;
    private List<Peer> m_ConnectedPeers;
    private List<WifiP2pDevice> m_DicoveredPeers;
    private ConnectPeerListAdapter m_ConnectedPeersAdapter;
    private DiscoveredPeerListAdapter m_DiscoveredPeersAdapter;
    private ProgressDialog m_progressDialog;

    private final int UI_UPDATE_DELAY_MS = 5000;

    private static final String PREF_WIFIDIRECT_STATUS = "WIFIDIRECT_STATUS";
}