com.namelessdev.mpdroid.SearchActivity.java Source code

Java tutorial

Introduction

Here is the source code for com.namelessdev.mpdroid.SearchActivity.java

Source

/*
 * Copyright (C) 2010-2014 The MPDroid Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.namelessdev.mpdroid;

import com.namelessdev.mpdroid.MPDroidActivities.MPDroidActivity;
import com.namelessdev.mpdroid.adapters.SeparatedListAdapter;
import com.namelessdev.mpdroid.helpers.MPDAsyncHelper.AsyncExecListener;
import com.namelessdev.mpdroid.library.SimpleLibraryActivity;
import com.namelessdev.mpdroid.tools.Tools;
import com.namelessdev.mpdroid.views.SearchResultDataBinder;

import org.a0z.mpd.exception.MPDException;
import org.a0z.mpd.item.Album;
import org.a0z.mpd.item.Artist;
import org.a0z.mpd.item.Item;
import org.a0z.mpd.item.Music;

import android.app.SearchManager;
import android.content.Intent;
import android.os.Bundle;
import android.os.Parcelable;
import android.provider.SearchRecentSuggestions;
import android.support.annotation.StringRes;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v7.app.ActionBar;
import android.util.Log;
import android.view.ContextMenu;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MenuItem.OnMenuItemClickListener;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.AdapterContextMenuInfo;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListAdapter;
import android.widget.ListView;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class SearchActivity extends MPDroidActivity
        implements OnMenuItemClickListener, AsyncExecListener, OnItemClickListener, ActionBar.TabListener {

    public static final int ADD = 0;

    public static final int ADD_PLAY = 2;

    public static final int ADD_REPLACE = 1;

    public static final int ADD_REPLACE_PLAY = 3;

    public static final int GOTO_ALBUM = 4;

    public static final int MAIN = 0;

    public static final int PLAYLIST = 3;

    private static final String PLAY_SERVICES_ACTION_SEARCH = "com.google.android.gms.actions.SEARCH_ACTION";

    private static final String TAG = "SearchActivity";

    private final ArrayList<Album> mAlbumResults;

    private final ArrayList<Artist> mArtistResults;

    private final ArrayList<Music> mSongResults;

    protected int mJobID = -1;

    protected View mLoadingView;

    protected View mNoResultAlbumsView;

    protected View mNoResultArtistsView;

    protected View mNoResultSongsView;

    protected ViewPager mPager;

    @StringRes
    private int mAddString;

    @StringRes
    private int mAddedString;

    private ListView mListAlbums = null;

    private View mListAlbumsFrame = null;

    private ListView mListArtists = null;

    private View mListArtistsFrame = null;

    private ListView mListSongs = null;

    private View mListSongsFrame = null;

    private String mSearchKeywords = null;

    private ActionBar.Tab mTabAlbums;

    private ActionBar.Tab mTabArtists;

    private ActionBar.Tab mTabSongs;

    public SearchActivity() {
        super();
        mAddString = R.string.addSong;
        mAddedString = R.string.songAdded;
        mArtistResults = new ArrayList<>();
        mAlbumResults = new ArrayList<>();
        mSongResults = new ArrayList<>();
    }

    protected void add(final Artist artist, final Album album, final boolean replace, final boolean play) {
        String note = null;

        try {
            if (artist == null) {
                final Artist albumArtist = album.getArtist();

                mApp.oMPDAsyncHelper.oMPD.add(album, replace, play);
                if (albumArtist != null) {
                    note = albumArtist.getName() + " - " + album.getName();
                }
            } else if (album == null) {
                mApp.oMPDAsyncHelper.oMPD.add(artist, replace, play);
                note = artist.getName();
            }
        } catch (final IOException | MPDException e) {
            Log.e(TAG, "Failed to add.", e);
        }

        if (note != null) {
            Tools.notifyUser(mAddedString, note);
        }
    }

    protected void add(final Music music, final boolean replace, final boolean play) {
        try {
            mApp.oMPDAsyncHelper.oMPD.add(music, replace, play);
            Tools.notifyUser(R.string.songAdded, music.getTitle(), music.getName());
        } catch (final IOException | MPDException e) {
            Log.e(TAG, "Failed to add.", e);
        }
    }

    protected void add(final Object object, final boolean replace, final boolean play) {
        setContextForObject(object);
        if (object instanceof Music) {
            add((Music) object, replace, play);
        } else if (object instanceof Artist) {
            add((Artist) object, null, replace, play);
        } else if (object instanceof Album) {
            add(null, (Album) object, replace, play);
        }
    }

    @Override
    public void asyncExecSucceeded(final int jobID) {
        if (mJobID == jobID) {
            updateFromItems();
        }
    }

    protected void asyncUpdate() {
        final String finalSearch = mSearchKeywords.toLowerCase();

        List<Music> arrayMusic = null;

        try {
            arrayMusic = mApp.oMPDAsyncHelper.oMPD.search("any", finalSearch);
        } catch (final IOException | MPDException e) {
            Log.e(TAG, "MPD search failure.", e);

        }

        if (arrayMusic == null) {
            return;
        }

        mArtistResults.clear();
        mAlbumResults.clear();
        mSongResults.clear();

        String tmpValue;
        boolean valueFound;
        for (final Music music : arrayMusic) {
            if (music.getTitle() != null && music.getTitle().toLowerCase().contains(finalSearch)) {
                mSongResults.add(music);
            }
            valueFound = false;
            Artist artist = music.getAlbumArtistAsArtist();
            if (artist == null || artist.isUnknown()) {
                artist = music.getArtistAsArtist();
            }
            if (artist != null) {
                final String name = artist.getName();
                if (name != null) {
                    tmpValue = name.toLowerCase();
                    if (tmpValue.contains(finalSearch)) {
                        for (final Artist artistItem : mArtistResults) {
                            final String artistItemName = artistItem.getName();
                            if (artistItemName != null && artistItemName.equalsIgnoreCase(tmpValue)) {
                                valueFound = true;
                            }
                        }
                        if (!valueFound) {
                            mArtistResults.add(artist);
                        }
                    }
                }
            }

            valueFound = false;
            final Album album = music.getAlbumAsAlbum();
            if (album != null) {
                final String albumName = album.getName();
                if (albumName != null) {
                    tmpValue = albumName.toLowerCase();
                    if (tmpValue.contains(finalSearch)) {
                        for (final Album albumItem : mAlbumResults) {
                            final String albumItemName = albumItem.getName();
                            if (albumItemName.equalsIgnoreCase(tmpValue)) {
                                valueFound = true;
                            }
                        }
                        if (!valueFound) {
                            mAlbumResults.add(album);
                        }
                    }
                }
            }
        }

        Collections.sort(mArtistResults);
        Collections.sort(mAlbumResults);
        Collections.sort(mSongResults, Music.COMPARE_WITHOUT_TRACK_NUMBER);

        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                mTabArtists.setText(getString(R.string.artists) + " (" + mArtistResults.size() + ')');
                mTabAlbums.setText(getString(R.string.albums) + " (" + mAlbumResults.size() + ')');
                mTabSongs.setText(getString(R.string.songs) + " (" + mSongResults.size() + ')');
            }
        });
    }

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

        setContentView(R.layout.search_results);

        final SearchResultsPagerAdapter adapter = new SearchResultsPagerAdapter();
        final ActionBar actionBar = getSupportActionBar();

        mPager = (ViewPager) findViewById(R.id.pager);
        mPager.setAdapter(adapter);
        mPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
            @Override
            public void onPageSelected(final int position) {
                // When swiping between pages, select the corresponding tab.
                actionBar.setSelectedNavigationItem(position);
            }
        });

        actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);

        mTabArtists = actionBar.newTab().setText(R.string.artists).setTabListener(this);
        actionBar.addTab(mTabArtists);

        mTabAlbums = actionBar.newTab().setText(R.string.albums).setTabListener(this);
        actionBar.addTab(mTabAlbums);

        mTabSongs = actionBar.newTab().setText(R.string.songs).setTabListener(this);
        actionBar.addTab(mTabSongs);

        mListArtistsFrame = findViewById(R.id.list_artists_frame);
        mNoResultArtistsView = mListArtistsFrame.findViewById(R.id.no_artist_result);
        mListArtists = (ListView) mListArtistsFrame.findViewById(android.R.id.list);
        mListArtists.setOnItemClickListener(this);

        mListAlbumsFrame = findViewById(R.id.list_albums_frame);
        mNoResultAlbumsView = mListAlbumsFrame.findViewById(R.id.no_album_result);
        mListAlbums = (ListView) mListAlbumsFrame.findViewById(android.R.id.list);
        mListAlbums.setOnItemClickListener(this);

        mListSongsFrame = findViewById(R.id.list_songs_frame);
        mNoResultSongsView = mListSongsFrame.findViewById(R.id.no_song_result);
        mListSongs = (ListView) mListSongsFrame.findViewById(android.R.id.list);
        mListSongs.setOnItemClickListener(this);

        mLoadingView = findViewById(R.id.loadingLayout);
        mLoadingView.setVisibility(View.VISIBLE);

        final Intent queryIntent = getIntent();
        final String queryAction = queryIntent.getAction();

        if (Intent.ACTION_SEARCH.equals(queryAction) || PLAY_SERVICES_ACTION_SEARCH.equals(queryAction)) {
            mSearchKeywords = queryIntent.getStringExtra(SearchManager.QUERY).trim();
            final SearchRecentSuggestions suggestions = new SearchRecentSuggestions(this,
                    SearchRecentProvider.AUTHORITY, SearchRecentProvider.MODE);
            suggestions.saveRecentQuery(mSearchKeywords, null);
        } else {
            return; // Bye !
        }

        setTitle(getTitle() + " : " + mSearchKeywords);

        registerForContextMenu(mListArtists);
        registerForContextMenu(mListAlbums);
        registerForContextMenu(mListSongs);

        updateList();
        actionBar.setDisplayHomeAsUpEnabled(true);
    }

    @Override
    public void onCreateContextMenu(final ContextMenu menu, final View v,
            final ContextMenu.ContextMenuInfo menuInfo) {
        super.onCreateContextMenu(menu, v, menuInfo);

        final AdapterContextMenuInfo info = (AdapterContextMenuInfo) menuInfo;

        switch (mPager.getCurrentItem()) {
        case 0:
            final Artist artist = mArtistResults.get((int) info.id);
            menu.setHeaderTitle(artist.mainText());
            setContextForObject(artist);
            break;
        case 1:
            final Album album = mAlbumResults.get((int) info.id);
            menu.setHeaderTitle(album.mainText());
            setContextForObject(album);
            break;
        case 2:
            final Music music = mSongResults.get((int) info.id);
            final MenuItem gotoAlbumItem = menu.add(Menu.NONE, GOTO_ALBUM, 0, R.string.goToAlbum);
            gotoAlbumItem.setOnMenuItemClickListener(this);
            menu.setHeaderTitle(music.mainText());
            setContextForObject(music);
            break;
        default:
            break;
        }

        final MenuItem addItem = menu.add(Menu.NONE, ADD, 0, getString(mAddString));
        final MenuItem addAndReplaceItem = menu.add(Menu.NONE, ADD_REPLACE, 0, R.string.addAndReplace);
        final MenuItem addReplacePlayItem = menu.add(Menu.NONE, ADD_REPLACE_PLAY, 0, R.string.addAndReplacePlay);
        final MenuItem addAndPlayItem = menu.add(Menu.NONE, ADD_PLAY, 0, R.string.addAndPlay);

        addItem.setOnMenuItemClickListener(this);
        addAndReplaceItem.setOnMenuItemClickListener(this);
        addReplacePlayItem.setOnMenuItemClickListener(this);
        addAndPlayItem.setOnMenuItemClickListener(this);
    }

    @Override
    public boolean onCreateOptionsMenu(final Menu menu) {
        super.onCreateOptionsMenu(menu);
        getMenuInflater().inflate(R.menu.mpd_searchmenu, menu);
        return true;
    }

    @Override
    public void onDestroy() {
        mApp.oMPDAsyncHelper.removeAsyncExecListener(this);
        super.onDestroy();
    }

    @Override
    public void onItemClick(final AdapterView<?> parent, final View view, final int position, final long id) {
        final Object selectedItem = parent.getAdapter().getItem(position);
        if (selectedItem instanceof Music) {
            add((Music) selectedItem, false, false);
        } else if (selectedItem instanceof Artist) {
            final Intent intent = new Intent(this, SimpleLibraryActivity.class);
            intent.putExtra("artist", (Parcelable) selectedItem);
            startActivityForResult(intent, -1);
        } else if (selectedItem instanceof Album) {
            final Intent intent = new Intent(this, SimpleLibraryActivity.class);
            intent.putExtra("album", (Parcelable) selectedItem);
            startActivityForResult(intent, -1);
        }
    }

    @Override
    public boolean onMenuItemClick(final MenuItem item) {
        final AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
        final List<? extends Item> targetArray;
        switch (mPager.getCurrentItem()) {
        case 1:
            targetArray = mAlbumResults;
            break;
        case 2:
            targetArray = mSongResults;
            break;
        case 0:
        default:
            targetArray = mArtistResults;
            break;
        }
        final Object selectedItem = targetArray.get((int) info.id);
        if (item.getItemId() == GOTO_ALBUM) {
            if (selectedItem instanceof Music) {
                final Music music = (Music) selectedItem;
                final Intent intent = new Intent(this, SimpleLibraryActivity.class);
                final Parcelable artist = new Artist(music.getAlbumArtistOrArtist());
                intent.putExtra("artist", artist);
                intent.putExtra("album", music.getAlbumAsAlbum());
                startActivityForResult(intent, -1);
            }
        } else {
            mApp.oMPDAsyncHelper.execAsync(new Runnable() {
                @Override
                public void run() {
                    boolean replace = false;
                    boolean play = false;
                    switch (item.getItemId()) {
                    case ADD_REPLACE_PLAY:
                        replace = true;
                        play = true;
                        break;
                    case ADD_REPLACE:
                        replace = true;
                        break;
                    case ADD_PLAY:
                        play = true;
                        break;
                    default:
                        break;
                    }
                    add(selectedItem, replace, play);
                }
            });
        }
        return false;
    }

    @Override
    public boolean onOptionsItemSelected(final MenuItem item) {
        boolean handled = true;

        switch (item.getItemId()) {
        case R.id.menu_search:
            onSearchRequested();
            break;
        case android.R.id.home:
            final Intent intent = new Intent(this, MainMenuActivity.class);
            intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
            startActivity(intent);
            break;
        default:
            handled = false;
            break;
        }

        return handled;
    }

    @Override
    public void onStart() {
        super.onStart();
        mApp.setActivity(this);
    }

    @Override
    public void onStop() {
        super.onStop();
        mApp.unsetActivity(this);
    }

    @Override
    public void onTabReselected(final ActionBar.Tab tab, final FragmentTransaction ft) {
    }

    @Override
    public void onTabSelected(final ActionBar.Tab tab, final FragmentTransaction ft) {
        mPager.setCurrentItem(tab.getPosition());
    }

    @Override
    public void onTabUnselected(final ActionBar.Tab tab, final FragmentTransaction ft) {
    }

    private void setContextForObject(final Object object) {
        if (object instanceof Music) {
            mAddString = R.string.addSong;
            mAddedString = R.string.songAdded;
        } else if (object instanceof Artist) {
            mAddString = R.string.addArtist;
            mAddedString = R.string.artistAdded;
        } else if (object instanceof Album) {
            mAddString = R.string.addAlbum;
            mAddedString = R.string.albumAdded;
        }
    }

    /**
     * This updates a specific ListView for search results.
     *
     * @param listView      The ListView to update with search results.
     * @param resultList    The List of results to enter into the ListView.
     * @param noResultsView The View to hide if there are no results.
     */
    private void update(final ListView listView, final List<? extends Item> resultList, final View noResultsView) {
        final ListAdapter separatedListAdapter = new SeparatedListAdapter(this, R.layout.search_list_item,
                new SearchResultDataBinder(), resultList);

        listView.setAdapter(separatedListAdapter);

        try {
            listView.setEmptyView(noResultsView);
            mLoadingView.setVisibility(View.GONE);
        } catch (final RuntimeException e) {
            Log.e(TAG, "Failed to update items.", e);
        }
    }

    /**
     * Update the view from the items list if items is set.
     */
    public void updateFromItems() {
        update(mListArtists, mArtistResults, mNoResultArtistsView);
        update(mListAlbums, mAlbumResults, mNoResultAlbumsView);
        update(mListSongs, mSongResults, mNoResultSongsView);
    }

    public void updateList() {
        mApp.oMPDAsyncHelper.addAsyncExecListener(this);
        mJobID = mApp.oMPDAsyncHelper.execAsync(new Runnable() {
            @Override
            public void run() {
                asyncUpdate();
            }
        });
    }

    class SearchResultsPagerAdapter extends PagerAdapter {

        @Override
        public void destroyItem(final ViewGroup container, final int position, final Object object) {
            container.removeView((View) object);
        }

        @Override
        public int getCount() {
            return 3;
        }

        @Override
        public Object instantiateItem(final ViewGroup container, final int position) {

            final View v;
            switch (position) {
            case 1:
                v = mListAlbumsFrame;
                break;
            case 2:
                v = mListSongsFrame;
                break;
            case 0:
            default:
                v = mListArtistsFrame;
                break;
            }
            if (v.getParent() == null) {
                mPager.addView(v);
            }
            return v;
        }

        @Override
        public boolean isViewFromObject(final View arg0, final Object arg1) {
            return arg0.equals(arg1);
        }
    }

}