org.klnusbaum.udj.PlayerListFragment.java Source code

Java tutorial

Introduction

Here is the source code for org.klnusbaum.udj.PlayerListFragment.java

Source

/**
 * Copyright 2011 Kurtis L. Nusbaum
 * 
 * This file is part of UDJ.
 * 
 * UDJ 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 2 of the License, or
 * (at your option) any later version.
 * 
 * UDJ 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 UDJ.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.klnusbaum.udj;

import org.klnusbaum.udj.auth.AuthActivity;
import org.klnusbaum.udj.containers.Player;
import org.klnusbaum.udj.network.PlayerCommService;
import org.klnusbaum.udj.network.PlayerCommService.PlayerJoinError;

import java.util.List;

import android.accounts.Account;
import android.accounts.AccountManager;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.support.v4.app.DialogFragment;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.Loader;
import android.util.Log;
import android.view.View;
import android.widget.ListView;
import android.widget.EditText;
import android.widget.Button;
import android.view.ViewGroup;
import android.view.LayoutInflater;
import android.widget.TextView;

import com.handmark.pulltorefresh.extras.listfragment.PullToRefreshListFragment;
import com.handmark.pulltorefresh.library.PullToRefreshBase;
import com.handmark.pulltorefresh.library.PullToRefreshBase.OnRefreshListener;
import com.handmark.pulltorefresh.library.PullToRefreshListView;

public class PlayerListFragment extends PullToRefreshListFragment
        implements LoaderManager.LoaderCallbacks<PlayersLoader.PlayersLoaderResult>, LocationListener,
        OnRefreshListener<ListView> {
    public enum SearchType {
        LOCATION_SEARCH, NAME_SEARCH
    }

    private static final String TAG = "PlayerListFragment";
    private static final String PROG_DIALOG_TAG = "prog_dialog";
    private static final String PLAYER_JOIN_FAIL_TAG = "prog_dialog";
    private static final String PASSWORD_TAG = "password_dialog";
    public static final String PLAYER_SEARCH_QUERY = "org.klnusbaum.udj.PlayerSearchQuery";
    public static final String PLAYER_SEARCH_TYPE_EXTRA = "org.klnusbaum.udj.PlayerSearchType";
    private static final int ACCOUNT_CREATION_REQUEST_CODE = 0;

    private PlayerListAdapter playerAdapter;
    private LocationManager lm;
    private Location lastKnown = null;
    private Account account = null;
    private AccountManager am;
    private SearchType searchType;
    private String nameQuery;

    private BroadcastReceiver playerJoinedReceiver = new BroadcastReceiver() {
        public void onReceive(Context context, Intent intent) {
            Log.d(TAG, "Recieved player broadcats");
            dismissProgress();
            getActivity().unregisterReceiver(playerJoinedReceiver);
            if (intent.getAction().equals(Constants.JOINED_PLAYER_ACTION)) {
                Intent playerActivityIntent = new Intent(context, PlayerActivity.class);
                startActivity(playerActivityIntent);
            } else if (intent.getAction().equals(Constants.PLAYER_JOIN_FAILED_ACTION)) {
                refreshList();
                handlePlayerJoinFail();
            }
        }
    };

    public void onCreate(Bundle icicle) {
        super.onCreate(icicle);
        setHasOptionsMenu(true);
    }

    public void onActivityCreated(Bundle icicle) {
        super.onActivityCreated(icicle);
        am = AccountManager.get(getActivity());
        Account[] udjAccounts = am.getAccountsByType(Constants.ACCOUNT_TYPE);
        Log.d(TAG, "Accounts length was " + udjAccounts.length);
        if (udjAccounts.length < 1) {
            Intent getAccountIntent = new Intent(getActivity(), AuthActivity.class);
            startActivityForResult(getAccountIntent, ACCOUNT_CREATION_REQUEST_CODE);
            return;
        } else if (udjAccounts.length == 1) {
            account = udjAccounts[0];
        } else {
            account = udjAccounts[0];
            //TODO implement if there are more than 1 account
        }

        searchType = (SearchType) getArguments().getSerializable(PLAYER_SEARCH_TYPE_EXTRA);
        if (searchType == SearchType.NAME_SEARCH) {
            nameQuery = getArguments().getString(PLAYER_SEARCH_QUERY);
        }

        setEmptyText(getActivity().getString(R.string.no_player_items));

        getPullToRefreshListView().setOnRefreshListener(this);

        playerAdapter = new PlayerListAdapter(getActivity());
        getPullToRefreshListView().getRefreshableView().setAdapter(playerAdapter);
        setListShown(false);

    }

    public void onStart() {
        super.onStart();

        if (searchType == SearchType.LOCATION_SEARCH) {
            lm = (LocationManager) getActivity().getSystemService(Context.LOCATION_SERVICE);
            List<String> providers = lm.getProviders(false);
            if (providers.contains(LocationManager.GPS_PROVIDER)) {
                lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 50, this);
                if (lastKnown == null) {
                    lastKnown = lm.getLastKnownLocation(LocationManager.GPS_PROVIDER);
                }
            }
            if (providers.contains(LocationManager.NETWORK_PROVIDER)) {
                lm.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 50, this);
                if (lastKnown == null) {
                    lastKnown = lm.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
                }
            }
        }
    }

    public void onActivityResult(final int requestCode, final int resultCode, final Intent data) {
        switch (requestCode) {
        case ACCOUNT_CREATION_REQUEST_CODE:
            if (resultCode == Activity.RESULT_OK) {
                account = (Account) data.getParcelableExtra(Constants.ACCOUNT_EXTRA);
            } else {
                getActivity().setResult(Activity.RESULT_CANCELED);
                getActivity().finish();
            }
            break;
        default:
            super.onActivityResult(requestCode, resultCode, data);
        }

    }

    public void onResume() {
        super.onResume();
        PlayerPasswordFragment pFrag = (PlayerPasswordFragment) getActivity().getSupportFragmentManager()
                .findFragmentByTag(PASSWORD_TAG);
        if (pFrag != null) {
            pFrag.registerPasswordEnteredListener(this);
        }

        if (account != null) {
            int playerState = Utils.getPlayerState(getActivity(), account);
            Log.d(TAG, "Checking Player State");
            if (playerState == Constants.JOINING_PLAYER) {
                Log.d(TAG, "Is joining");
                Log.d(TAG, "Reregistering player listener");
                registerPlayerListener();
            } else if (playerState == Constants.PLAYER_JOIN_FAILED) {
                Log.d(TAG, "Player joining Failed");
                dismissProgress();
                handlePlayerJoinFail();
            } else if (playerState == Constants.IN_PLAYER) {
                Log.d(TAG, "Already signed into player. Checking Progress visibility");
                if (isShowingProgress()) {
                    Log.d(TAG, "Determined progress is indeed showing");
                    dismissProgress();
                }
                Intent startPlayerActivity = new Intent(getActivity(), PlayerActivity.class);
                startActivity(startPlayerActivity);
                return;
            }

            if (playerAdapter == null || playerAdapter.getCount() == 0) {
                refreshList();
            }
        }
    }

    public void onPause() {
        super.onPause();
        if (account != null) {
            int playerState = Utils.getPlayerState(getActivity(), account);
            if (playerState == Constants.JOINING_PLAYER) {
                getActivity().unregisterReceiver(playerJoinedReceiver);
            }
        }

        PlayerPasswordFragment pFrag = (PlayerPasswordFragment) getActivity().getSupportFragmentManager()
                .findFragmentByTag(PASSWORD_TAG);
        if (pFrag != null) {
            pFrag.unregisterPasswordEnteredListener();
        }
    }

    public void onStop() {
        super.onStop();
        if (searchType == SearchType.LOCATION_SEARCH) {
            lm.removeUpdates(this);
        }
    }

    public void onLocationChanged(Location location) {
        lastKnown = location;
    }

    public void onProviderDisabled(String provider) {
    }

    public void onProviderEnabled(String provider) {
    }

    public void onStatusChanged(String provider, int status, Bundle extras) {
    }

    @Override
    public void onListItemClick(ListView l, View v, int position, long id) {
        Player toJoin = (Player) l.getItemAtPosition(position);
        if (toJoin.getHasPassword()) {
            Log.d(TAG, "Joining password player with id: " + toJoin.getId());
            getPasswordForPlayer(toJoin);
        } else {
            Log.d(TAG, "Joining regular player with id: " + toJoin.getId());
            joinPlayer(toJoin);
        }
    }

    public void getPasswordForPlayer(Player toJoin) {
        Bundle playerBundle = toJoin.bundleUp();
        PlayerPasswordFragment passwordFragment = new PlayerPasswordFragment();
        passwordFragment.registerPasswordEnteredListener(this);
        passwordFragment.setArguments(playerBundle);
        passwordFragment.show(getActivity().getSupportFragmentManager(), PASSWORD_TAG);
    }

    public void joinPlayer(Player toJoin) {
        joinPlayer(toJoin, "");
    }

    public void joinPlayer(Player toJoin, String password) {
        Log.d(TAG, "Joining Player with id: " + toJoin.getId());
        am.setUserData(account, Constants.PLAYER_STATE_DATA, String.valueOf(Constants.JOINING_PLAYER));
        showProgress();
        Intent joinPlayerIntent = new Intent(Intent.ACTION_INSERT, Constants.PLAYER_URI, getActivity(),
                PlayerCommService.class);
        joinPlayerIntent.putExtra(Constants.PLAYER_ID_EXTRA, toJoin.getId());
        joinPlayerIntent.putExtra(Constants.PLAYER_NAME_EXTRA, toJoin.getName());
        joinPlayerIntent.putExtra(Constants.PLAYER_OWNER_EXTRA, toJoin.getOwner().getUsername());
        joinPlayerIntent.putExtra(Constants.PLAYER_OWNER_ID_EXTRA, toJoin.getOwner().getId());
        joinPlayerIntent.putExtra(Constants.PLAYER_LAT_EXTRA, toJoin.getLatitude());
        joinPlayerIntent.putExtra(Constants.PLAYER_LONG_EXTRA, toJoin.getLongitude());
        joinPlayerIntent.putExtra(Constants.ACCOUNT_EXTRA, account);
        if (!password.equals("")) {
            joinPlayerIntent.putExtra(Constants.PLAYER_PASSWORD_EXTRA, password);
        }
        getActivity().startService(joinPlayerIntent);
    }

    public Loader<PlayersLoader.PlayersLoaderResult> onCreateLoader(int id, Bundle args) {
        if (searchType == SearchType.LOCATION_SEARCH) {
            return new PlayersLoader(getActivity(), account, lastKnown);
        } else if (searchType == SearchType.NAME_SEARCH) {
            return new PlayersLoader(getActivity(), account, nameQuery);
        } else {
            return null;
        }
    }

    public void onLoadFinished(Loader<PlayersLoader.PlayersLoaderResult> loader,
            PlayersLoader.PlayersLoaderResult data) {
        Log.d(TAG, "Got player search results");
        getPullToRefreshListView().onRefreshComplete();
        switch (data.getError()) {
        case NO_ERROR:
            playerAdapter.updateList(data.getPlayers());
            break;
        case NO_LOCATION:
            setEmptyText(getString(R.string.no_location_error));
            break;
        case SERVER_ERROR:
            setEmptyText(getString(R.string.players_load_error));
            break;
        case NO_CONNECTION:
            setEmptyText(getString(R.string.no_network_connection));
            break;
        case NO_ACCOUNT:
            setEmptyText(getString(R.string.no_account_error));
            break;
        }

        if (isResumed()) {
            setListShown(true);
        } else if (isVisible()) {
            setListShownNoAnimation(true);
        }
    }

    public void onLoaderReset(Loader<PlayersLoader.PlayersLoaderResult> loader) {
    }

    public void refreshList() {
        getLoaderManager().restartLoader(0, null, this);
    }

    @Override
    public void onRefresh(PullToRefreshBase<ListView> listView) {
        refreshList();
    }

    private void showProgress() {
        registerPlayerListener();
        ProgressFragment progFragment = new ProgressFragment();
        progFragment.show(getActivity().getSupportFragmentManager(), PROG_DIALOG_TAG);
    }

    private void registerPlayerListener() {
        getActivity().registerReceiver(playerJoinedReceiver, new IntentFilter(Constants.JOINED_PLAYER_ACTION));
        getActivity().registerReceiver(playerJoinedReceiver, new IntentFilter(Constants.PLAYER_JOIN_FAILED_ACTION));
        Log.d(TAG, "Listener registered");
    }

    private boolean isShowingProgress() {
        ProgressFragment pd = (ProgressFragment) getActivity().getSupportFragmentManager()
                .findFragmentByTag(PROG_DIALOG_TAG);
        return pd != null && pd.getDialog().isShowing();
    }

    private void dismissProgress() {
        ProgressFragment pd = (ProgressFragment) getActivity().getSupportFragmentManager()
                .findFragmentByTag(PROG_DIALOG_TAG);
        //Sometimes the progress dialog is already dimissed. Need to check if it's null
        if (pd != null) {
            pd.dismiss();
        }
    }

    public static class ProgressFragment extends DialogFragment {

        public Dialog onCreateDialog(Bundle icicle) {
            //Stop gap for now. This should be cancelable
            setCancelable(false);
            final ProgressDialog dialog = new ProgressDialog(getActivity());
            dialog.setMessage(getActivity().getString(R.string.joining_player));
            dialog.setIndeterminate(true);
            return dialog;
        }
    }

    private void handlePlayerJoinFail() {
        PlayerJoinError joinError = PlayerJoinError.valueOf(am.getUserData(account, Constants.PLAYER_JOIN_ERROR));
        am.setUserData(account, Constants.PLAYER_STATE_DATA, String.valueOf(Constants.NOT_IN_PLAYER));
        DialogFragment newFrag = new PlayerJoinFailDialog();
        Bundle args = new Bundle();
        args.putInt(Constants.PLAYER_JOIN_ERROR_EXTRA, joinError.ordinal());
        newFrag.setArguments(args);
        newFrag.show(getActivity().getSupportFragmentManager(), PLAYER_JOIN_FAIL_TAG);
    }

    public static class PlayerJoinFailDialog extends DialogFragment {

        @Override
        public Dialog onCreateDialog(Bundle savedInstanceState) {
            Bundle args = getArguments();
            PlayerJoinError joinError = PlayerJoinError.values()[args.getInt(Constants.PLAYER_JOIN_ERROR_EXTRA)];
            AlertDialog.Builder builder = new AlertDialog.Builder(getActivity())
                    .setTitle(R.string.player_join_fail_title);
            String message;
            switch (joinError) {
            case SERVER_ERROR:
                message = getString(R.string.server_join_fail_message);
                break;
            case AUTHENTICATION_ERROR:
                message = getString(R.string.auth_join_fail_message);
                break;
            case PLAYER_INACTIVE_ERROR:
                message = getString(R.string.player_inactive_join_fail_message);
                break;
            case NO_NETWORK_ERROR:
                message = getString(R.string.no_network_join_fail_message);
                break;
            case PLAYER_PASSWORD_ERROR:
                message = getString(R.string.bad_player_password);
                break;
            case PLAYER_FULL_ERROR:
                message = getString(R.string.player_full);
                break;
            case BANNED_ERROR:
                message = getString(R.string.banned_from_player);
                break;
            default:
                message = getString(R.string.unknown_error_message);
            }
            return builder.setMessage(message)
                    .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int whichButton) {
                            dismiss();
                        }
                    }).create();
        }
    }

    public static class PlayerPasswordFragment extends DialogFragment {

        Player toJoin;
        EditText passwordEdit;
        Button okButton;
        PlayerListFragment playerListFragment = null;

        public void onCreate(Bundle icicle) {
            super.onCreate(icicle);
            toJoin = Player.unbundle(getArguments());
            Log.d(TAG, "Player id in PasswordFragment: " + toJoin.getId());
        }

        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle icicle) {
            View v = inflater.inflate(R.layout.player_password, container, false);
            passwordEdit = (EditText) v.findViewById(R.id.player_password_edit);
            okButton = (Button) v.findViewById(R.id.ok_button);
            okButton.setOnClickListener(new View.OnClickListener() {
                public void onClick(View v) {
                    passwordEntered();
                }
            });
            getDialog().setTitle(R.string.password_required);
            return v;
        }

        public void passwordEntered() {
            //TODO handle if they didn't type anything in
            playerListFragment.joinPlayer(toJoin, passwordEdit.getText().toString());
            dismiss();
        }

        public void registerPasswordEnteredListener(PlayerListFragment playerListFragment) {
            this.playerListFragment = playerListFragment;
        }

        public void unregisterPasswordEnteredListener() {
            this.playerListFragment = null;
        }
    }
}