Clover Coverage Report - Subsonic-Android Coverage Report
Coverage timestamp: ven dic 19 2014 17:57:13 EST
../../../../../img/srcFileCovDistChart5.png 71% of files have more coverage
169   368   54   9,39
58   296   0,32   18
18     3  
1    
This report was generated with an evaluation server license. Purchase Clover or configure your license.
 
  SearchActivity       Line # 60 169 54 44,5% 0.44489795
 
No Tests
 
1    /*
2    This file is part of Subsonic.
3   
4    Subsonic is free software: you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation, either version 3 of the License, or
7    (at your option) any later version.
8   
9    Subsonic is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12    GNU General Public License for more details.
13   
14    You should have received a copy of the GNU General Public License
15    along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
16   
17    Copyright 2009 (C) Sindre Mehus
18    */
19   
20    package net.sourceforge.subsonic.androidapp.activity;
21   
22    import java.util.ArrayList;
23    import java.util.List;
24    import java.util.Arrays;
25   
26    import android.content.Intent;
27    import android.os.Bundle;
28    import android.view.ContextMenu;
29    import android.view.LayoutInflater;
30    import android.view.MenuInflater;
31    import android.view.View;
32    import android.view.MenuItem;
33    import android.widget.AdapterView;
34    import android.widget.ImageButton;
35    import android.widget.ListAdapter;
36    import android.widget.ListView;
37    import android.widget.TextView;
38    import android.net.Uri;
39    import net.sourceforge.subsonic.androidapp.R;
40    import net.sourceforge.subsonic.androidapp.domain.Artist;
41    import net.sourceforge.subsonic.androidapp.domain.MusicDirectory;
42    import net.sourceforge.subsonic.androidapp.domain.SearchCritera;
43    import net.sourceforge.subsonic.androidapp.domain.SearchResult;
44    import net.sourceforge.subsonic.androidapp.service.MusicService;
45    import net.sourceforge.subsonic.androidapp.service.MusicServiceFactory;
46    import net.sourceforge.subsonic.androidapp.service.DownloadService;
47    import net.sourceforge.subsonic.androidapp.util.ArtistAdapter;
48    import net.sourceforge.subsonic.androidapp.util.BackgroundTask;
49    import net.sourceforge.subsonic.androidapp.util.Constants;
50    import net.sourceforge.subsonic.androidapp.util.EntryAdapter;
51    import net.sourceforge.subsonic.androidapp.util.MergeAdapter;
52    import net.sourceforge.subsonic.androidapp.util.TabActivityBackgroundTask;
53    import net.sourceforge.subsonic.androidapp.util.Util;
54   
55    /**
56    * Performs searches and displays the matching artists, albums and songs.
57    *
58    * @author Sindre Mehus
59    */
 
60    public class SearchActivity extends SubsonicTabActivity {
61   
62    private static final int DEFAULT_ARTISTS = 3;
63    private static final int DEFAULT_ALBUMS = 5;
64    private static final int DEFAULT_SONGS = 10;
65   
66    private static final int MAX_ARTISTS = 10;
67    private static final int MAX_ALBUMS = 20;
68    private static final int MAX_SONGS = 25;
69    private ListView list;
70   
71    private View artistsHeading;
72    private View albumsHeading;
73    private View songsHeading;
74    private TextView searchButton;
75    private View moreArtistsButton;
76    private View moreAlbumsButton;
77    private View moreSongsButton;
78    private SearchResult searchResult;
79    private MergeAdapter mergeAdapter;
80    private ArtistAdapter artistAdapter;
81    private ListAdapter moreArtistsAdapter;
82    private EntryAdapter albumAdapter;
83    private ListAdapter moreAlbumsAdapter;
84    private ListAdapter moreSongsAdapter;
85    private EntryAdapter songAdapter;
86   
 
87  3 toggle @Override
88    public void onCreate(Bundle savedInstanceState) {
89  3 super.onCreate(savedInstanceState);
90  3 setContentView(R.layout.search);
91   
92  3 setTitle(R.string.search_title);
93   
94  3 View buttons = LayoutInflater.from(this).inflate(R.layout.search_buttons, null);
95   
96  3 artistsHeading = buttons.findViewById(R.id.search_artists);
97  3 albumsHeading = buttons.findViewById(R.id.search_albums);
98  3 songsHeading = buttons.findViewById(R.id.search_songs);
99   
100  3 searchButton = (TextView) buttons.findViewById(R.id.search_search);
101  3 moreArtistsButton = buttons.findViewById(R.id.search_more_artists);
102  3 moreAlbumsButton = buttons.findViewById(R.id.search_more_albums);
103  3 moreSongsButton = buttons.findViewById(R.id.search_more_songs);
104   
105  3 list = (ListView) findViewById(R.id.search_list);
106   
107  3 list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
 
108  1 toggle @Override
109    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
110  1 if (view == searchButton) {
111  0 onSearchRequested();
112  1 } else if (view == moreArtistsButton) {
113  0 expandArtists();
114  1 } else if (view == moreAlbumsButton) {
115  0 expandAlbums();
116  1 } else if (view == moreSongsButton) {
117  0 expandSongs();
118    } else {
119  1 Object item = parent.getItemAtPosition(position);
120  1 if (item instanceof Artist) {
121  0 onArtistSelected((Artist) item);
122  1 } else if (item instanceof MusicDirectory.Entry) {
123  1 MusicDirectory.Entry entry = (MusicDirectory.Entry) item;
124  1 if (entry.isDirectory()) {
125  1 onAlbumSelected(entry, false);
126  0 } else if (entry.isVideo()) {
127  0 onVideoSelected(entry);
128    } else {
129  0 onSongSelected(entry, false, true, true, false);
130    }
131   
132    }
133    }
134    }
135    });
136  3 registerForContextMenu(list);
137   
138    // Button 1: gone
139  3 findViewById(R.id.action_button_1).setVisibility(View.GONE);
140   
141    // Button 2: search
142  3 final ImageButton actionSearchButton = (ImageButton)findViewById(R.id.action_button_2);
143  3 actionSearchButton.setImageResource(R.drawable.ic_menu_search);
144  3 actionSearchButton.setOnClickListener(new View.OnClickListener() {
 
145  1 toggle @Override
146    public void onClick(View view) {
147  1 onSearchRequested();
148    }
149    });
150   
151  3 onNewIntent(getIntent());
152    }
153   
 
154  5 toggle @Override
155    protected void onNewIntent(Intent intent) {
156  5 super.onNewIntent(intent);
157  5 String query = intent.getStringExtra(Constants.INTENT_EXTRA_NAME_QUERY);
158  5 boolean autoplay = intent.getBooleanExtra(Constants.INTENT_EXTRA_NAME_AUTOPLAY, false);
159  5 boolean requestsearch = intent.getBooleanExtra(Constants.INTENT_EXTRA_REQUEST_SEARCH, false);
160   
161  5 if (query != null) {
162  1 mergeAdapter = new MergeAdapter();
163  1 list.setAdapter(mergeAdapter);
164  1 search(query, autoplay);
165    } else {
166  4 populateList();
167  4 if (requestsearch)
168  4 onSearchRequested();
169    }
170    }
171   
 
172  1 toggle @Override
173    public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo menuInfo) {
174  1 super.onCreateContextMenu(menu, view, menuInfo);
175   
176  1 AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo;
177  1 Object selectedItem = list.getItemAtPosition(info.position);
178   
179  1 boolean isArtist = selectedItem instanceof Artist;
180  1 boolean isAlbum = selectedItem instanceof MusicDirectory.Entry && ((MusicDirectory.Entry) selectedItem).isDirectory();
181  1 boolean isSong = selectedItem instanceof MusicDirectory.Entry && (!((MusicDirectory.Entry) selectedItem).isDirectory())
182    && (!((MusicDirectory.Entry) selectedItem).isVideo());
183   
184  1 if (isArtist || isAlbum) {
185  1 MenuInflater inflater = getMenuInflater();
186  1 inflater.inflate(R.menu.select_album_context, menu);
187  0 } else if (isSong) {
188  0 MenuInflater inflater = getMenuInflater();
189  0 inflater.inflate(R.menu.select_song_context, menu);
190    }
191    }
192   
 
193  0 toggle @Override
194    public boolean onContextItemSelected(MenuItem menuItem) {
195  0 AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuItem.getMenuInfo();
196  0 Object selectedItem = list.getItemAtPosition(info.position);
197   
198  0 Artist artist = selectedItem instanceof Artist ? (Artist) selectedItem : null;
199  0 MusicDirectory.Entry entry = selectedItem instanceof MusicDirectory.Entry ? (MusicDirectory.Entry) selectedItem : null;
200  0 String id = artist != null ? artist.getId() : entry.getId();
201   
202  0 switch (menuItem.getItemId()) {
203  0 case R.id.album_menu_play_now:
204  0 downloadRecursively(id, false, false, true);
205  0 break;
206  0 case R.id.album_menu_play_last:
207  0 downloadRecursively(id, false, true, false);
208  0 break;
209  0 case R.id.album_menu_pin:
210  0 downloadRecursively(id, true, true, false);
211  0 break;
212  0 case R.id.song_menu_play_now:
213  0 onSongSelected(entry, false, false, true, false);
214  0 break;
215  0 case R.id.song_menu_play_next:
216  0 onSongSelected(entry, false, true, false, true);
217  0 break;
218  0 case R.id.song_menu_play_last:
219  0 onSongSelected(entry, false, true, false, false);
220  0 break;
221  0 default:
222  0 return super.onContextItemSelected(menuItem);
223    }
224   
225  0 return true;
226    }
227   
 
228  1 toggle private void search(final String query, final boolean autoplay) {
229  1 BackgroundTask<SearchResult> task = new TabActivityBackgroundTask<SearchResult>(this) {
 
230  1 toggle @Override
231    protected SearchResult doInBackground() throws Throwable {
232  1 SearchCritera criteria = new SearchCritera(query, MAX_ARTISTS, MAX_ALBUMS, MAX_SONGS);
233  1 MusicService service = MusicServiceFactory.getMusicService(SearchActivity.this);
234  1 return service.search(criteria, SearchActivity.this, this);
235    }
236   
 
237  1 toggle @Override
238    protected void done(SearchResult result) {
239  1 searchResult = result;
240  1 populateList();
241  1 if (autoplay) {
242  0 autoplay();
243    }
244   
245    }
246    };
247  1 task.execute();
248    }
249   
 
250  5 toggle private void populateList() {
251  5 mergeAdapter = new MergeAdapter();
252  5 mergeAdapter.addView(searchButton, true);
253   
254  5 if (searchResult != null) {
255  2 List<Artist> artists = searchResult.getArtists();
256  2 if (!artists.isEmpty()) {
257  0 mergeAdapter.addView(artistsHeading);
258  0 List<Artist> displayedArtists = new ArrayList<Artist>(artists.subList(0, Math.min(DEFAULT_ARTISTS, artists.size())));
259  0 artistAdapter = new ArtistAdapter(this, displayedArtists);
260  0 mergeAdapter.addAdapter(artistAdapter);
261  0 if (artists.size() > DEFAULT_ARTISTS) {
262  0 moreArtistsAdapter = mergeAdapter.addView(moreArtistsButton, true);
263    }
264    }
265   
266  2 List<MusicDirectory.Entry> albums = searchResult.getAlbums();
267  2 if (!albums.isEmpty()) {
268  2 mergeAdapter.addView(albumsHeading);
269  2 List<MusicDirectory.Entry> displayedAlbums = new ArrayList<MusicDirectory.Entry>(albums.subList(0, Math.min(DEFAULT_ALBUMS, albums.size())));
270  2 albumAdapter = new EntryAdapter(this, getImageLoader(), displayedAlbums, false);
271  2 mergeAdapter.addAdapter(albumAdapter);
272  2 if (albums.size() > DEFAULT_ALBUMS) {
273  0 moreAlbumsAdapter = mergeAdapter.addView(moreAlbumsButton, true);
274    }
275    }
276   
277  2 List<MusicDirectory.Entry> songs = searchResult.getSongs();
278  2 if (!songs.isEmpty()) {
279  0 mergeAdapter.addView(songsHeading);
280  0 List<MusicDirectory.Entry> displayedSongs = new ArrayList<MusicDirectory.Entry>(songs.subList(0, Math.min(DEFAULT_SONGS, songs.size())));
281  0 songAdapter = new EntryAdapter(this, getImageLoader(), displayedSongs, false);
282  0 mergeAdapter.addAdapter(songAdapter);
283  0 if (songs.size() > DEFAULT_SONGS) {
284  0 moreSongsAdapter = mergeAdapter.addView(moreSongsButton, true);
285    }
286    }
287   
288  2 boolean empty = searchResult.getArtists().isEmpty() && searchResult.getAlbums().isEmpty() && searchResult.getSongs().isEmpty();
289  2 searchButton.setText(empty ? R.string.search_no_match : R.string.search_search);
290    }
291   
292  5 list.setAdapter(mergeAdapter);
293    }
294   
 
295  0 toggle private void expandArtists() {
296  0 artistAdapter.clear();
297  0 for (Artist artist : searchResult.getArtists()) {
298  0 artistAdapter.add(artist);
299    }
300  0 artistAdapter.notifyDataSetChanged();
301  0 mergeAdapter.removeAdapter(moreArtistsAdapter);
302  0 mergeAdapter.notifyDataSetChanged();
303    }
304   
 
305  0 toggle private void expandAlbums() {
306  0 albumAdapter.clear();
307  0 for (MusicDirectory.Entry album : searchResult.getAlbums()) {
308  0 albumAdapter.add(album);
309    }
310  0 albumAdapter.notifyDataSetChanged();
311  0 mergeAdapter.removeAdapter(moreAlbumsAdapter);
312  0 mergeAdapter.notifyDataSetChanged();
313    }
314   
 
315  0 toggle private void expandSongs() {
316  0 songAdapter.clear();
317  0 for (MusicDirectory.Entry song : searchResult.getSongs()) {
318  0 songAdapter.add(song);
319    }
320  0 songAdapter.notifyDataSetChanged();
321  0 mergeAdapter.removeAdapter(moreSongsAdapter);
322  0 mergeAdapter.notifyDataSetChanged();
323    }
324   
 
325  0 toggle private void onArtistSelected(Artist artist) {
326  0 Intent intent = new Intent(this, SelectAlbumActivity.class);
327  0 intent.putExtra(Constants.INTENT_EXTRA_NAME_ID, artist.getId());
328  0 intent.putExtra(Constants.INTENT_EXTRA_NAME_NAME, artist.getName());
329  0 Util.startActivityWithoutTransition(this, intent);
330    }
331   
 
332  1 toggle private void onAlbumSelected(MusicDirectory.Entry album, boolean autoplay) {
333  1 Intent intent = new Intent(SearchActivity.this, SelectAlbumActivity.class);
334  1 intent.putExtra(Constants.INTENT_EXTRA_NAME_ID, album.getId());
335  1 intent.putExtra(Constants.INTENT_EXTRA_NAME_NAME, album.getTitle());
336  1 intent.putExtra(Constants.INTENT_EXTRA_NAME_AUTOPLAY, autoplay);
337  1 Util.startActivityWithoutTransition(SearchActivity.this, intent);
338    }
339   
 
340  0 toggle private void onSongSelected(MusicDirectory.Entry song, boolean save, boolean append, boolean autoplay, boolean playNext) {
341  0 DownloadService downloadService = getDownloadService();
342  0 if (downloadService != null) {
343  0 if (!append) {
344  0 downloadService.clear();
345    }
346  0 downloadService.download(Arrays.asList(song), save, false, playNext);
347  0 if (autoplay) {
348  0 downloadService.play(downloadService.size() - 1);
349    }
350   
351  0 Util.toast(SearchActivity.this, getResources().getQuantityString(R.plurals.select_album_n_songs_added, 1, 1));
352    }
353    }
354   
 
355  0 toggle private void onVideoSelected(MusicDirectory.Entry entry) {
356  0 Intent intent = new Intent(Intent.ACTION_VIEW);
357  0 intent.setData(Uri.parse(MusicServiceFactory.getMusicService(this).getVideoUrl(this, entry.getId())));
358  0 startActivity(intent);
359    }
360   
 
361  0 toggle private void autoplay() {
362  0 if (!searchResult.getSongs().isEmpty()) {
363  0 onSongSelected(searchResult.getSongs().get(0), false, false, true, false);
364  0 } else if (!searchResult.getAlbums().isEmpty()) {
365  0 onAlbumSelected(searchResult.getAlbums().get(0), true);
366    }
367    }
368    }