Fix lock screen album art, massive code cleanup

This commit is contained in:
Joshua Bahnsen 2013-06-06 19:27:45 -07:00
parent ac500a7169
commit fc4bc29a6a
47 changed files with 1217 additions and 1333 deletions

View File

@ -11,7 +11,7 @@
<item name="exit">@drawable/ic_menu_exit_dark</item>
<item name="backward">@drawable/ic_menu_backward_dark</item>
<item name="forward">@drawable/ic_menu_forward_dark</item>
<item name="stop">@drawable/ic_menu_exit_dark</item>
<item name="stop">@drawable/ic_menu_exit_dark</item>
<item name="help">@drawable/ic_menu_help_dark</item>
<item name="home">@drawable/ic_menu_home_dark</item>
<item name="pin">@drawable/ic_menu_pin</item>
@ -25,7 +25,7 @@
<item name="settings">@drawable/ic_menu_settings_dark</item>
<item name="share">@drawable/ic_menu_share_dark</item>
<item name="downloaded">@drawable/ic_stat_downloaded_dark</item>
<item name="downloading">@drawable/ic_stat_downloading_dark</item>
<item name="downloading">@drawable/ic_stat_downloading_dark</item>
<item name="media_previous">@drawable/media_backward_normal_dark</item>
<item name="media_next">@drawable/media_forward_normal_dark</item>
<item name="media_pause">@drawable/media_pause_normal_dark</item>
@ -35,12 +35,11 @@
<item name="media_shuffle">@drawable/media_shuffle_normal_dark</item>
<item name="media_play">@drawable/media_start_normal_dark</item>
<item name="media_play_next">@drawable/media_play_next</item>
<item name="media_play_small">@drawable/ic_stat_play_dark</item>
<item name="media_play_small">@drawable/ic_stat_play_dark</item>
<item name="media_stop">@drawable/media_stop_normal_dark</item>
<item name="media_toggle">@drawable/media_toggle_list_normal_dark</item>
<item name="chat">@drawable/ic_menu_chat_dark</item>
<item name="chat_send">@drawable/ic_menu_chat_send_dark</item>
<item name="chat_send">@drawable/ic_menu_chat_send_dark</item>
<item name="bookmark">@drawable/ic_menu_bookmark_dark</item>
</style>
@ -54,7 +53,7 @@
<item name="exit">@drawable/ic_menu_exit_light</item>
<item name="backward">@drawable/ic_menu_backward_light</item>
<item name="forward">@drawable/ic_menu_forward_light</item>
<item name="stop">@drawable/ic_menu_exit_light</item>
<item name="stop">@drawable/ic_menu_exit_light</item>
<item name="help">@drawable/ic_menu_help_light</item>
<item name="home">@drawable/ic_menu_home_light</item>
<item name="pin">@drawable/ic_menu_pin</item>
@ -68,7 +67,7 @@
<item name="settings">@drawable/ic_menu_settings_light</item>
<item name="share">@drawable/ic_menu_share_light</item>
<item name="downloaded">@drawable/ic_stat_downloaded_light</item>
<item name="downloading">@drawable/ic_stat_downloading_light</item>
<item name="downloading">@drawable/ic_stat_downloading_light</item>
<item name="media_previous">@drawable/media_backward_normal_light</item>
<item name="media_next">@drawable/media_forward_normal_light</item>
<item name="media_pause">@drawable/media_pause_normal_light</item>
@ -77,13 +76,13 @@
<item name="media_repeat_single">@drawable/media_repeat_single</item>
<item name="media_shuffle">@drawable/media_shuffle_normal_light</item>
<item name="media_play">@drawable/media_start_normal_light</item>
<item name="media_play_next">@drawable/media_play_next</item>
<item name="media_play_small">@drawable/ic_stat_play_light</item>
<item name="media_play_next">@drawable/media_play_next</item>
<item name="media_play_small">@drawable/ic_stat_play_light</item>
<item name="media_stop">@drawable/media_stop_normal_light</item>
<item name="media_toggle">@drawable/media_toggle_list_normal_light</item>
<item name="chat">@drawable/ic_menu_chat_light</item>
<item name="chat_send">@drawable/ic_menu_chat_send_light</item>
<item name="bookmark">@drawable/ic_menu_bookmark_light</item>
s </style>
</style>
</resources>

View File

@ -51,11 +51,6 @@
a:key="mediaButtons"
a:summary="@string/settings.media_button_summary"
a:title="@string/settings.media_button_title" />
<CheckBoxPreference
a:defaultValue="false"
a:key="useStreamProxy"
a:summary="@string/settings.use_stream_proxy_summary"
a:title="@string/settings.use_stream_proxy" />
<CheckBoxPreference
a:defaultValue="true"
a:key="transitionToDownloadOnPlay"
@ -76,6 +71,7 @@
a:key="clearBookmark"
a:summary="@string/settings.clear_bookmark_summary"
a:title="@string/settings.clear_bookmark" />
<ListPreference
a:defaultValue="5000"
a:entries="@array/bufferLengthNames"
@ -83,13 +79,13 @@
a:key="incrementTime"
a:title="@string/settings.increment_time" />
</PreferenceCategory>
<PreferenceCategory a:title="@string/settings.notifications_title" >
<PreferenceCategory a:title="@string/settings.notifications_title" >
<CheckBoxPreference
a:defaultValue="true"
a:key="showNowPlaying"
a:summary="@string/settings.show_now_playing_summary"
a:title="@string/settings.show_now_playing" />
<CheckBoxPreference
a:title="@string/settings.show_now_playing" />
<CheckBoxPreference
a:defaultValue="true"
a:key="showNotification"
a:summary="@string/settings.show_notification_summary"
@ -114,7 +110,7 @@
a:key="sendBluetoothAlbumArt"
a:summary="@string/settings.send_bluetooth_album_art_summary"
a:title="@string/settings.send_bluetooth_album_art" />
</PreferenceCategory>
</PreferenceCategory>
<PreferenceCategory a:title="@string/settings.video_title" >
<ListPreference
a:defaultValue="default"

View File

@ -26,6 +26,10 @@ import android.view.View;
import android.widget.AdapterView;
import android.widget.ImageView;
import android.widget.ListView;
import com.handmark.pulltorefresh.library.PullToRefreshBase;
import com.handmark.pulltorefresh.library.PullToRefreshBase.OnRefreshListener;
import com.handmark.pulltorefresh.library.PullToRefreshListView;
import com.thejoshwa.ultrasonic.androidapp.R;
import com.thejoshwa.ultrasonic.androidapp.domain.MusicDirectory;
import com.thejoshwa.ultrasonic.androidapp.domain.MusicDirectory.Entry;
@ -33,18 +37,13 @@ import com.thejoshwa.ultrasonic.androidapp.service.DownloadFile;
import com.thejoshwa.ultrasonic.androidapp.service.MusicService;
import com.thejoshwa.ultrasonic.androidapp.service.MusicServiceFactory;
import com.thejoshwa.ultrasonic.androidapp.util.Constants;
import com.thejoshwa.ultrasonic.androidapp.util.FileUtil;
import com.thejoshwa.ultrasonic.androidapp.util.Pair;
import com.thejoshwa.ultrasonic.androidapp.util.TabActivityBackgroundTask;
import com.thejoshwa.ultrasonic.androidapp.util.Util;
import com.thejoshwa.ultrasonic.androidapp.view.EntryAdapter;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import com.handmark.pulltorefresh.library.PullToRefreshBase;
import com.handmark.pulltorefresh.library.PullToRefreshBase.OnRefreshListener;
import com.handmark.pulltorefresh.library.PullToRefreshListView;
public class BookmarkActivity extends SubsonicTabActivity {
@ -52,16 +51,12 @@ public class BookmarkActivity extends SubsonicTabActivity {
private ListView albumListView;
private View albumButtons;
private View emptyView;
private ImageView selectButton;
private ImageView playNowButton;
private ImageView playNextButton;
private ImageView playLastButton;
private ImageView pinButton;
private ImageView unpinButton;
private ImageView downloadButton;
private ImageView deleteButton;
private ImageView moreButton;
/**
* Called when the activity is first created.
*/
@ -89,31 +84,33 @@ public class BookmarkActivity extends SubsonicTabActivity {
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
if (position >= 0) {
Entry entry = (Entry) parent.getItemAtPosition(position);
if (entry.isVideo()) {
playVideo(entry);
} else {
enableButtons();
if (entry != null) {
if (entry.isVideo()) {
playVideo(entry);
} else {
enableButtons();
}
}
}
}
});
selectButton = (ImageView) findViewById(R.id.select_album_select);
ImageView selectButton = (ImageView) findViewById(R.id.select_album_select);
playNowButton = (ImageView) findViewById(R.id.select_album_play_now);
playNextButton = (ImageView) findViewById(R.id.select_album_play_next);
playLastButton = (ImageView) findViewById(R.id.select_album_play_last);
ImageView playNextButton = (ImageView) findViewById(R.id.select_album_play_next);
ImageView playLastButton = (ImageView) findViewById(R.id.select_album_play_last);
pinButton = (ImageView) findViewById(R.id.select_album_pin);
unpinButton = (ImageView) findViewById(R.id.select_album_unpin);
downloadButton = (ImageView) findViewById(R.id.select_album_download);
deleteButton = (ImageView) findViewById(R.id.select_album_delete);
moreButton = (ImageView) findViewById(R.id.select_album_more);
ImageView oreButton = (ImageView) findViewById(R.id.select_album_more);
emptyView = findViewById(R.id.select_album_empty);
selectButton.setVisibility(View.GONE);
playNextButton.setVisibility(View.GONE);
playLastButton.setVisibility(View.GONE);
moreButton.setVisibility(View.GONE);
oreButton.setVisibility(View.GONE);
playNowButton.setOnClickListener(new View.OnClickListener() {
@Override
@ -169,7 +166,7 @@ public class BookmarkActivity extends SubsonicTabActivity {
}
private void getBookmarks() {
getActionBar().setSubtitle(R.string.button_bar_bookmarks);
setActionBarSubtitle(R.string.button_bar_bookmarks);
new LoadTask() {
@Override
@ -333,14 +330,6 @@ public class BookmarkActivity extends SubsonicTabActivity {
}
}
public void deleteRecursively(MusicDirectory.Entry album) {
File dir = FileUtil.getAlbumDirectory(this, album);
Util.recursiveDelete(dir);
if(Util.isOffline(this)) {
refresh();
}
}
private abstract class LoadTask extends TabActivityBackgroundTask<Pair<MusicDirectory, Boolean>> {
public LoadTask() {

View File

@ -69,9 +69,9 @@ public final class ChatActivity extends SubsonicTabActivity {
String serverName = Util.getServerName(this, Util.getActiveServer(this));
String userName = Util.getUserName(this, Util.getActiveServer(this));
String title = String.format("%s [%s@%s]", getResources().getString(R.string.button_bar_chat), userName, serverName);
getActionBar().setSubtitle(title);
setActionBarSubtitle(title);
messageEditText.setImeActionLabel("Send", KeyEvent.KEYCODE_ENTER);
messageEditText.addTextChangedListener(new TextWatcher() {
@ -164,30 +164,33 @@ public final class ChatActivity extends SubsonicTabActivity {
}
}, refreshInterval, refreshInterval);
}
}
}
private void sendMessage() {
final String message = messageEditText.getText().toString();
if (!Util.isNullOrWhiteSpace(message)) {
messageEditText.setText("");
if (messageEditText != null) {
final String message;
message = messageEditText.getText().toString();
BackgroundTask<Void> task = new TabActivityBackgroundTask<Void>(ChatActivity.this, false) {
@Override
protected Void doInBackground() throws Throwable {
MusicService musicService = MusicServiceFactory.getMusicService(ChatActivity.this);
musicService.addChatMessage(message, ChatActivity.this, this);
return null;
}
if (!Util.isNullOrWhiteSpace(message)) {
messageEditText.setText("");
@Override
protected void done(Void result) {
load();
}
};
BackgroundTask<Void> task = new TabActivityBackgroundTask<Void>(ChatActivity.this, false) {
@Override
protected Void doInBackground() throws Throwable {
MusicService musicService = MusicServiceFactory.getMusicService(ChatActivity.this);
musicService.addChatMessage(message, ChatActivity.this, this);
return null;
}
task.execute();
}
@Override
protected void done(Void result) {
load();
}
};
task.execute();
}
}
}
private synchronized void load() {

View File

@ -82,8 +82,6 @@ public class DownloadActivity extends SubsonicTabActivity implements OnGestureLi
private View startButton;
private ImageView repeatButton;
private ImageButton starImageButton;
private ImageButton bookmarkImageButton;
private ImageButton removeAllImageButton;
private ImageButton saveImageButton;
private ScheduledExecutorService executorService;
private DownloadFile currentPlaying;
@ -138,8 +136,8 @@ public class DownloadActivity extends SubsonicTabActivity implements OnGestureLi
final View shuffleButton = findViewById(R.id.download_shuffle);
repeatButton = (ImageView) findViewById(R.id.download_repeat);
starImageButton = (ImageButton) findViewById(R.id.download_star);
bookmarkImageButton = (ImageButton) findViewById(R.id.download_bookmark);
removeAllImageButton = (ImageButton) findViewById(R.id.download_remove_all);
ImageButton bookmarkImageButton = (ImageButton) findViewById(R.id.download_bookmark);
ImageButton removeAllImageButton = (ImageButton) findViewById(R.id.download_remove_all);
saveImageButton = (ImageButton) findViewById(R.id.download_save_playlist);
visualizerViewLayout = (LinearLayout) findViewById(R.id.download_visualizer_view_layout);
@ -420,63 +418,63 @@ public class DownloadActivity extends SubsonicTabActivity implements OnGestureLi
});
bookmarkImageButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(final View view) {
if (currentSong == null) {
return;
}
@Override
public void onClick(final View view) {
if (currentSong == null) {
return;
}
final String id = currentSong.getId();
final int playerPosition = getDownloadService()
.getPlayerPosition();
final String id = currentSong.getId();
final int playerPosition = getDownloadService()
.getPlayerPosition();
currentSong.setBookmarkPosition(playerPosition);
String bookmarkTime = Util.formatTotalDuration(playerPosition, true);
currentSong.setBookmarkPosition(playerPosition);
new Thread(new Runnable() {
public void run() {
final MusicService musicService = MusicServiceFactory.getMusicService(DownloadActivity.this);
String bookmarkTime = Util.formatTotalDuration(playerPosition, true);
try {
musicService.createBookmark(id, playerPosition, DownloadActivity.this, null);
} catch (Exception e) {
Log.e(TAG, e.getMessage(), e);
}
}
}).start();
new Thread(new Runnable() {
public void run() {
final MusicService musicService = MusicServiceFactory.getMusicService(DownloadActivity.this);
String msg = getResources().getString(R.string.download_bookmark_set_at_position, bookmarkTime);
try {
musicService.createBookmark(id, playerPosition, DownloadActivity.this, null);
} catch (Exception e) {
Log.e(TAG, e.getMessage(), e);
}
}
}).start();
Util.toast(DownloadActivity.this, msg);
}
});
String msg = getResources().getString(R.string.download_bookmark_set_at_position, bookmarkTime);
Util.toast(DownloadActivity.this, msg);
}
});
bookmarkImageButton.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(final View view) {
if (currentSong == null) {
return true;
}
final String id = currentSong.getId();
currentSong.setBookmarkPosition(0);
new Thread(new Runnable() {
public void run() {
final MusicService musicService = MusicServiceFactory.getMusicService(DownloadActivity.this);
try {
musicService.deleteBookmark(id, DownloadActivity.this, null);
} catch (Exception e) {
Log.e(TAG, e.getMessage(), e);
}
}
}).start();
Util.toast(DownloadActivity.this, R.string.download_bookmark_removed);
return true;
if (currentSong == null) {
return true;
}
final String id = currentSong.getId();
currentSong.setBookmarkPosition(0);
new Thread(new Runnable() {
public void run() {
final MusicService musicService = MusicServiceFactory.getMusicService(DownloadActivity.this);
try {
musicService.deleteBookmark(id, DownloadActivity.this, null);
} catch (Exception e) {
Log.e(TAG, e.getMessage(), e);
}
}
}).start();
Util.toast(DownloadActivity.this, R.string.download_bookmark_removed);
return true;
}
});
@ -611,7 +609,10 @@ public class DownloadActivity extends SubsonicTabActivity implements OnGestureLi
final LayoutInflater layoutInflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
final View layout = layoutInflater.inflate(R.layout.save_playlist, (ViewGroup) findViewById(R.id.save_playlist_root));
playlistNameView = (EditText) layout.findViewById(R.id.save_playlist_name);
if (layout != null) {
playlistNameView = (EditText) layout.findViewById(R.id.save_playlist_name);
}
builder = new AlertDialog.Builder(this);
builder.setTitle(R.string.download_playlist_title);
@ -721,10 +722,18 @@ public class DownloadActivity extends SubsonicTabActivity implements OnGestureLi
}
if (song != null && song.getParent() == null) {
menu.findItem(R.id.menu_show_album).setVisible(false);
MenuItem menuItem = menu.findItem(R.id.menu_show_album);
if (menuItem != null) {
menuItem.setVisible(false);
}
}
if (Util.isOffline(this)) {
menu.findItem(R.id.menu_lyrics).setVisible(false);
MenuItem menuItem = menu.findItem(R.id.menu_lyrics);
if (menuItem != null) {
menuItem.setVisible(false);
}
}
}
}
@ -990,22 +999,23 @@ public class DownloadActivity extends SubsonicTabActivity implements OnGestureLi
switch (playerState) {
case DOWNLOADING:
final long bytes = currentPlaying != null ? currentPlaying.getPartialFile().length() : 0;
getActionBar().setSubtitle(getResources().getString(R.string.download_playerstate_downloading, Util.formatLocalizedBytes(bytes, DownloadActivity.this)));
String downloadStatus = getResources().getString(R.string.download_playerstate_downloading, Util.formatLocalizedBytes(bytes, DownloadActivity.this));
setActionBarSubtitle(downloadStatus);
break;
case PREPARING:
getActionBar().setSubtitle(R.string.download_playerstate_buffering);
setActionBarSubtitle(R.string.download_playerstate_buffering);
break;
case STARTED:
final DownloadService downloadService = getDownloadService();
if (downloadService != null && downloadService.isShufflePlayEnabled()) {
getActionBar().setSubtitle(R.string.download_playerstate_playing_shuffle);
setActionBarSubtitle(R.string.download_playerstate_playing_shuffle);
} else {
getActionBar().setSubtitle(null);
setActionBarSubtitle(null);
}
break;
default:
getActionBar().setSubtitle(null);
setActionBarSubtitle(null);
break;
case IDLE:
break;

View File

@ -143,38 +143,42 @@ public class EqualizerActivity extends Activity {
final short band = i;
View bandBar = LayoutInflater.from(this).inflate(R.layout.equalizer_bar, null);
TextView freqTextView = (TextView) bandBar.findViewById(R.id.equalizer_frequency);
final TextView levelTextView = (TextView) bandBar.findViewById(R.id.equalizer_level);
SeekBar bar = (SeekBar) bandBar.findViewById(R.id.equalizer_bar);
TextView freqTextView;
freqTextView.setText((equalizer.getCenterFreq(band) / 1000) + " Hz");
if (bandBar != null) {
freqTextView = (TextView) bandBar.findViewById(R.id.equalizer_frequency);
final TextView levelTextView = (TextView) bandBar.findViewById(R.id.equalizer_level);
SeekBar bar = (SeekBar) bandBar.findViewById(R.id.equalizer_bar);
bars.put(band, bar);
bar.setMax(maxEQLevel - minEQLevel);
short level = equalizer.getBandLevel(band);
bar.setProgress(level - minEQLevel);
bar.setEnabled(equalizer.getEnabled());
updateLevelText(levelTextView, level);
freqTextView.setText((equalizer.getCenterFreq(band) / 1000) + " Hz");
bar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
short level = (short) (progress + minEQLevel);
if (fromUser) {
equalizer.setBandLevel(band, level);
bars.put(band, bar);
bar.setMax(maxEQLevel - minEQLevel);
short level = equalizer.getBandLevel(band);
bar.setProgress(level - minEQLevel);
bar.setEnabled(equalizer.getEnabled());
updateLevelText(levelTextView, level);
bar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
short level = (short) (progress + minEQLevel);
if (fromUser) {
equalizer.setBandLevel(band, level);
}
updateLevelText(levelTextView, level);
}
updateLevelText(levelTextView, level);
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
layout.addView(bandBar);
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
layout.addView(bandBar);
}
}
} catch (Exception e) {
//TODO: Show a dialog

View File

@ -19,11 +19,10 @@
package com.thejoshwa.ultrasonic.androidapp.activity;
import android.app.ActionBar;
import android.app.Activity;
import android.content.Intent;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;
import android.view.MenuItem;
import android.view.View;
@ -33,9 +32,11 @@ import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Button;
import android.widget.ImageView;
import com.thejoshwa.ultrasonic.androidapp.R;
import com.thejoshwa.ultrasonic.androidapp.util.Constants;
import com.thejoshwa.ultrasonic.androidapp.util.Util;
import net.simonvt.menudrawer.MenuDrawer;
import net.simonvt.menudrawer.Position;
@ -45,10 +46,8 @@ import net.simonvt.menudrawer.Position;
* @author Sindre Mehus
*/
public final class HelpActivity extends Activity implements OnClickListener {
private static final String TAG = HelpActivity.class.getSimpleName();
private WebView webView;
private ImageView backButton;
private ImageView stopButton;
private ImageView forwardButton;
private static final String STATE_MENUDRAWER = "com.thejoshwa.ultrasonic.androidapp.menuDrawer";
@ -60,7 +59,6 @@ public final class HelpActivity extends Activity implements OnClickListener {
private int menuActiveViewId;
View chatMenuItem = null;
View bookmarksMenuItem = null;
View menuMain = null;
@Override
protected void onCreate(Bundle bundle) {
@ -92,7 +90,11 @@ public final class HelpActivity extends Activity implements OnClickListener {
findViewById(R.id.menu_about).setOnClickListener(this);
findViewById(R.id.menu_exit).setOnClickListener(this);
getActionBar().setDisplayHomeAsUpEnabled(true);
ActionBar actionBar = getActionBar();
if (actionBar != null) {
actionBar.setDisplayHomeAsUpEnabled(true);
}
View aboutMenuItem = findViewById(R.id.menu_about);
menuDrawer.setActiveView(aboutMenuItem);
@ -114,8 +116,8 @@ public final class HelpActivity extends Activity implements OnClickListener {
webView.goBack();
}
});
stopButton = (ImageView) findViewById(R.id.help_stop);
ImageView stopButton = (ImageView) findViewById(R.id.help_stop);
stopButton.setOnClickListener(new Button.OnClickListener() {
@Override
public void onClick(View view) {
@ -271,17 +273,14 @@ public final class HelpActivity extends Activity implements OnClickListener {
@Override
public void onPageFinished(WebView view, String url) {
setProgressBarIndeterminateVisibility(false);
String versionName = null;
try {
versionName = getPackageManager().getPackageInfo(getPackageName(), 0).versionName;
} catch (NameNotFoundException e) {
Log.e(TAG, e.getMessage(), e);
}
String title = view.getTitle() + " (" + versionName + ")";
getActionBar().setSubtitle(title);
String versionName = Util.getVersionName(HelpActivity.this);
String title = view.getTitle() + " (" + versionName + ")";
ActionBar actionBar = getActionBar();
if (actionBar != null) {
actionBar.setSubtitle(title);
}
backButton.setEnabled(view.canGoBack());
forwardButton.setEnabled(view.canGoForward());
}

View File

@ -184,7 +184,7 @@ public class MainActivity extends SubsonicTabActivity {
final View homeMenuItem = findViewById(R.id.menu_home);
menuDrawer.setActiveView(homeMenuItem);
getActionBar().setTitle(R.string.common_appname);
setActionBarTitle(R.string.common_appname);
setTitle(R.string.common_appname);
// Remember the current theme.
@ -252,7 +252,11 @@ public class MainActivity extends SubsonicTabActivity {
}
if (!checked) {
menu.findItem(getMenuItem(0)).setChecked(true);
MenuItem menuItem = menu.findItem(getMenuItem(0));
if (menuItem != null) {
menuItem.setChecked(true);
}
}
menu.setGroupCheckable(MENU_GROUP_SERVER, true, true);

View File

@ -38,7 +38,7 @@ import com.thejoshwa.ultrasonic.androidapp.R;
import com.thejoshwa.ultrasonic.androidapp.domain.Artist;
import com.thejoshwa.ultrasonic.androidapp.domain.MusicDirectory;
import com.thejoshwa.ultrasonic.androidapp.domain.MusicDirectory.Entry;
import com.thejoshwa.ultrasonic.androidapp.domain.SearchCritera;
import com.thejoshwa.ultrasonic.androidapp.domain.SearchCriteria;
import com.thejoshwa.ultrasonic.androidapp.domain.SearchResult;
import com.thejoshwa.ultrasonic.androidapp.service.MusicService;
import com.thejoshwa.ultrasonic.androidapp.service.MusicServiceFactory;
@ -182,12 +182,29 @@ public class SearchActivity extends SubsonicTabActivity {
@Override
public boolean onContextItemSelected(MenuItem menuItem) {
AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuItem.getMenuInfo();
if (info == null) {
return true;
}
Object selectedItem = list.getItemAtPosition(info.position);
Artist artist = selectedItem instanceof Artist ? (Artist) selectedItem : null;
Entry entry = selectedItem instanceof Entry ? (Entry) selectedItem : null;
String id = artist != null ? artist.getId() : entry.getId();
List<Entry> songs = new ArrayList<Entry>(1);
String entryId = null;
if (entry != null) {
entryId = entry.getId();
}
String id = artist != null ? artist.getId() : entryId;
if (id == null ){
return true;
}
List<Entry> songs = new ArrayList<Entry>(1);
switch (menuItem.getItemId()) {
case R.id.album_menu_play_now:
@ -195,7 +212,7 @@ public class SearchActivity extends SubsonicTabActivity {
break;
case R.id.album_menu_play_next:
downloadRecursively(id, false, true, false, true, false, true, false);
break;
break;
case R.id.album_menu_play_last:
downloadRecursively(id, false, true, false, false, false, false, false);
break;
@ -204,10 +221,10 @@ public class SearchActivity extends SubsonicTabActivity {
break;
case R.id.album_menu_unpin:
downloadRecursively(id, false, false, false, false, false, false, true);
break;
break;
case R.id.album_menu_download:
downloadRecursively(id, false, false, false, false, true, false, false);
break;
break;
case R.id.song_menu_play_now:
if (entry != null) {
songs = new ArrayList<MusicDirectory.Entry>(1);
@ -221,7 +238,7 @@ public class SearchActivity extends SubsonicTabActivity {
songs.add(entry);
download(true, false, false, true, false, songs);
}
break;
break;
case R.id.song_menu_play_last:
if (entry != null) {
songs = new ArrayList<MusicDirectory.Entry>(1);
@ -242,14 +259,14 @@ public class SearchActivity extends SubsonicTabActivity {
Util.toast(SearchActivity.this, getResources().getQuantityString(R.plurals.select_album_n_songs_downloaded, songs.size(), songs.size()));
downloadBackground(false, songs);
}
break;
break;
case R.id.song_menu_unpin:
if (entry != null) {
songs.add(entry);
Util.toast(SearchActivity.this, getResources().getQuantityString(R.plurals.select_album_n_songs_unpinned, songs.size(), songs.size()));
getDownloadService().unpin(songs);
}
break;
break;
default:
return super.onContextItemSelected(menuItem);
}
@ -281,7 +298,7 @@ public class SearchActivity extends SubsonicTabActivity {
BackgroundTask<SearchResult> task = new TabActivityBackgroundTask<SearchResult>(this, true) {
@Override
protected SearchResult doInBackground() throws Throwable {
SearchCritera criteria = new SearchCritera(query, maxArtists, maxAlbums, maxSongs);
SearchCriteria criteria = new SearchCriteria(query, maxArtists, maxAlbums, maxSongs);
MusicService service = MusicServiceFactory.getMusicService(SearchActivity.this);
licenseValid = service.isLicenseValid(SearchActivity.this, this);
return service.search(criteria, SearchActivity.this, this);

View File

@ -32,29 +32,26 @@ import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import com.handmark.pulltorefresh.library.PullToRefreshBase;
import com.handmark.pulltorefresh.library.PullToRefreshBase.OnRefreshListener;
import com.handmark.pulltorefresh.library.PullToRefreshListView;
import com.thejoshwa.ultrasonic.androidapp.R;
import com.thejoshwa.ultrasonic.androidapp.domain.MusicDirectory;
import com.thejoshwa.ultrasonic.androidapp.service.DownloadFile;
import com.thejoshwa.ultrasonic.androidapp.service.MusicService;
import com.thejoshwa.ultrasonic.androidapp.service.MusicServiceFactory;
import com.thejoshwa.ultrasonic.androidapp.util.AlbumHeader;
import com.thejoshwa.ultrasonic.androidapp.util.Constants;
import com.thejoshwa.ultrasonic.androidapp.util.FileUtil;
import com.thejoshwa.ultrasonic.androidapp.util.EntryByDiscAndTrackComparator;
import com.thejoshwa.ultrasonic.androidapp.util.Pair;
import com.thejoshwa.ultrasonic.androidapp.util.TabActivityBackgroundTask;
import com.thejoshwa.ultrasonic.androidapp.util.Util;
import com.thejoshwa.ultrasonic.androidapp.view.EntryAdapter;
import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Random;
import java.util.Set;
import com.handmark.pulltorefresh.library.PullToRefreshBase;
import com.handmark.pulltorefresh.library.PullToRefreshBase.OnRefreshListener;
import com.handmark.pulltorefresh.library.PullToRefreshListView;
public class SelectAlbumActivity extends SubsonicTabActivity {
@ -105,13 +102,13 @@ public class SelectAlbumActivity extends SubsonicTabActivity {
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
if (position >= 0) {
MusicDirectory.Entry entry = (MusicDirectory.Entry) parent.getItemAtPosition(position);
if (entry.isDirectory()) {
if (entry != null && entry.isDirectory()) {
Intent intent = new Intent(SelectAlbumActivity.this, SelectAlbumActivity.class);
intent.putExtra(Constants.INTENT_EXTRA_NAME_ID, entry.getId());
intent.putExtra(Constants.INTENT_EXTRA_NAME_IS_ALBUM, entry.isDirectory());
intent.putExtra(Constants.INTENT_EXTRA_NAME_NAME, entry.getTitle());
Util.startActivityWithoutTransition(SelectAlbumActivity.this, intent);
} else if (entry.isVideo()) {
} else if (entry != null && entry.isVideo()) {
playVideo(entry);
} else {
enableButtons();
@ -236,7 +233,10 @@ public class SelectAlbumActivity extends SubsonicTabActivity {
public boolean onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
playAllButton = menu.findItem(R.id.select_album_play_all);
playAllButton.setVisible(playAllButtonVisible);
if (playAllButton != null) {
playAllButton.setVisible(playAllButtonVisible);
}
return true;
}
@ -312,8 +312,8 @@ public class SelectAlbumActivity extends SubsonicTabActivity {
AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo;
MusicDirectory.Entry entry = (MusicDirectory.Entry) albumListView.getItemAtPosition(info.position);
if (entry.isDirectory()) {
if (entry != null && entry.isDirectory()) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.select_album_context, menu);
}
@ -322,8 +322,17 @@ public class SelectAlbumActivity extends SubsonicTabActivity {
@Override
public boolean onContextItemSelected(MenuItem menuItem) {
AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuItem.getMenuInfo();
if (info == null) {
return true;
}
MusicDirectory.Entry entry = (MusicDirectory.Entry) albumListView.getItemAtPosition(info.position);
if (entry == null) {
return true;
}
switch (menuItem.getItemId()) {
case R.id.album_menu_play_now:
downloadRecursively(entry.getId(), false, false, true, false, false, false, false);
@ -372,7 +381,7 @@ public class SelectAlbumActivity extends SubsonicTabActivity {
}
private void getMusicDirectory(final String id, final String name) {
getActionBar().setSubtitle(name);
setActionBarSubtitle(name);
new LoadTask() {
@Override
@ -384,7 +393,7 @@ public class SelectAlbumActivity extends SubsonicTabActivity {
}
private void getArtist(final String id, final String name) {
getActionBar().setSubtitle(name);
setActionBarSubtitle(name);
new LoadTask() {
@Override
@ -396,7 +405,7 @@ public class SelectAlbumActivity extends SubsonicTabActivity {
}
private void getAlbum(final String id, final String name) {
getActionBar().setSubtitle(name);
setActionBarSubtitle(name);
new LoadTask() {
@Override
@ -408,7 +417,7 @@ public class SelectAlbumActivity extends SubsonicTabActivity {
}
private void getSongsForGenre(final String genre, final int count, final int offset) {
getActionBar().setSubtitle(genre);
setActionBarSubtitle(genre);
new LoadTask() {
@Override
@ -446,7 +455,7 @@ public class SelectAlbumActivity extends SubsonicTabActivity {
}
private void getStarred() {
getActionBar().setSubtitle(R.string.main_songs_starred);
setActionBarSubtitle(R.string.main_songs_starred);
new LoadTask() {
@Override
@ -462,8 +471,8 @@ public class SelectAlbumActivity extends SubsonicTabActivity {
private void getVideos() {
showHeader = false;
getActionBar().setSubtitle(R.string.main_videos);
setActionBarSubtitle(R.string.main_videos);
new LoadTask() {
@Override
@ -475,7 +484,7 @@ public class SelectAlbumActivity extends SubsonicTabActivity {
}
private void getRandom(final int size) {
getActionBar().setSubtitle(R.string.main_songs_random);
setActionBarSubtitle(R.string.main_songs_random);
new LoadTask() {
@Override
@ -486,7 +495,7 @@ public class SelectAlbumActivity extends SubsonicTabActivity {
}
private void getPlaylist(final String playlistId, final String playlistName) {
getActionBar().setSubtitle(playlistName);
setActionBarSubtitle(playlistName);
new LoadTask() {
@Override
@ -498,8 +507,8 @@ public class SelectAlbumActivity extends SubsonicTabActivity {
private void getAlbumList(final String albumListType, final int albumListTitle, final int size, final int offset) {
showHeader = false;
getActionBar().setSubtitle(albumListTitle);
setActionBarSubtitle(albumListTitle);
new LoadTask() {
@Override
@ -667,15 +676,7 @@ public class SelectAlbumActivity extends SubsonicTabActivity {
getDownloadService().unpin(songs);
}
}
public void deleteRecursively(MusicDirectory.Entry album) {
File dir = FileUtil.getAlbumDirectory(this, album);
Util.recursiveDelete(dir);
if(Util.isOffline(this)) {
refresh();
}
}
private abstract class LoadTask extends TabActivityBackgroundTask<Pair<MusicDirectory, Boolean>> {
public LoadTask() {
@ -698,7 +699,7 @@ public class SelectAlbumActivity extends SubsonicTabActivity {
List<MusicDirectory.Entry> entries = musicDirectory.getChildren();
if (Util.getShouldSortByDisc(SelectAlbumActivity.this)){
Collections.sort(entries, new EntryByDiscAndTrackComparer());
Collections.sort(entries, new EntryByDiscAndTrackComparator());
}
String directoryName = musicDirectory.getName();
@ -776,7 +777,7 @@ public class SelectAlbumActivity extends SubsonicTabActivity {
enableButtons();
boolean isAlbumList = getIntent().hasExtra(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_TYPE);
playAllButtonVisible = !(isAlbumList || entries.isEmpty());
playAllButtonVisible = !(isAlbumList || entries.isEmpty()) && !allVideos;
emptyView.setVisibility(entries.isEmpty() ? View.VISIBLE : View.GONE);
@ -793,62 +794,28 @@ public class SelectAlbumActivity extends SubsonicTabActivity {
}
}
private View createHeader(List<MusicDirectory.Entry> entries, String name, int songCount) {
protected View createHeader(List<MusicDirectory.Entry> entries, String name, int songCount) {
ImageView coverArtView = (ImageView) header.findViewById(R.id.select_album_art);
int artworkSelection = random.nextInt(entries.size());
getImageLoader().loadImage(coverArtView, entries.get(artworkSelection), true, Util.getAlbumImageSize(SelectAlbumActivity.this), false, true);
TextView titleView = (TextView) header.findViewById(R.id.select_album_title);
titleView.setText(name != null ? name : getActionBar().getSubtitle());
titleView.setText(name != null ? name : getActionBarSubtitle());
Set<String> artists = new HashSet<String>();
Set<String> grandParents = new HashSet<String>();
Set<String> genres = new HashSet<String>();
boolean allVideo = true;
long totalDuration = 0;
for (MusicDirectory.Entry entry : entries) {
if (!entry.isVideo()) {
allVideo = false;
}
if (!entry.isDirectory()) {
if (Util.shouldUseFolderForArtistName(getBaseContext())) {
String grandParent = Util.getGrandparent(entry.getPath());
if (grandParent != null) {
grandParents.add(grandParent);
}
}
if (entry.getArtist() != null) {
Integer duration = entry.getDuration();
AlbumHeader albumHeader = AlbumHeader.processEntries(SelectAlbumActivity.this, entries);
if (duration != null) {
totalDuration += duration;
}
artists.add(entry.getArtist());
}
if (entry.getGenre() != null) {
genres.add(entry.getGenre());
}
}
}
// Don't show a header if all entries are videos
if (allVideo) {
if (albumHeader.getIsAllVideo()) {
return null;
}
TextView artistView = (TextView) header.findViewById(R.id.select_album_artist);
String artist = null;
String artist;
if (artists.size() == 1) {
artist = artists.iterator().next();
} else if (grandParents.size() == 1) {
artist = grandParents.iterator().next();
if (albumHeader.getArtists().size() == 1) {
artist = albumHeader.getArtists().iterator().next();
} else if (albumHeader.getGrandParents().size() == 1) {
artist = albumHeader.getGrandParents().iterator().next();
} else {
artist = getResources().getString(R.string.common_various_artists);
}
@ -856,10 +823,10 @@ public class SelectAlbumActivity extends SubsonicTabActivity {
artistView.setText(artist);
TextView genreView = (TextView) header.findViewById(R.id.select_album_genre);
String genre = null;
String genre;
if (genres.size() == 1) {
genre = genres.iterator().next();
if (albumHeader.getGenres().size() == 1) {
genre = albumHeader.getGenres().iterator().next();
} else {
genre = getResources().getString(R.string.common_multiple_genres);
}
@ -870,7 +837,7 @@ public class SelectAlbumActivity extends SubsonicTabActivity {
String songs = getResources().getQuantityString(R.plurals.select_album_n_songs, songCount, songCount);
songCountView.setText(songs);
String duration = Util.formatTotalDuration(totalDuration);
String duration = Util.formatTotalDuration(albumHeader.getTotalDuration());
TextView durationView = (TextView) header.findViewById(R.id.select_album_duration);
durationView.setText(duration);
@ -892,23 +859,4 @@ public class SelectAlbumActivity extends SubsonicTabActivity {
return null;
}
}
public class EntryByDiscAndTrackComparer implements Comparator<MusicDirectory.Entry> {
@Override
public int compare(MusicDirectory.Entry x, MusicDirectory.Entry y) {
Integer discX = x.getDiscNumber();
Integer discY = y.getDiscNumber();
Integer trackX = x.getTrack();
Integer trackY = y.getTrack();
int startComparison = compare(discX == null ? 0 : discX, discY == null ? 0 : discY);
return startComparison != 0 ? startComparison : compare(trackX == null ? 0 : trackX, trackY == null ? 0 : trackY);
}
private int compare(long a, long b) {
return a < b ? -1
: a > b ? 1
: 0;
}
}
}

View File

@ -70,18 +70,21 @@ public class SelectArtistActivity extends SubsonicTabActivity implements Adapter
refreshArtistListView = (PullToRefreshListView) findViewById(R.id.select_artist_list);
artistListView = refreshArtistListView.getRefreshableView();
refreshArtistListView.setOnRefreshListener(new OnRefreshListener<ListView>() {
@Override
public void onRefresh(PullToRefreshBase<ListView> refreshView) {
new GetDataTask().execute();
}
});
artistListView.setOnItemClickListener(this);
folderButton = LayoutInflater.from(this).inflate(R.layout.select_artist_header, artistListView, false);
folderName = (TextView) folderButton.findViewById(R.id.select_artist_folder_2);
if (folderButton != null) {
folderName = (TextView) folderButton.findViewById(R.id.select_artist_folder_2);
}
if (!Util.isOffline(this) && !Util.getShouldUseId3Tags(this)) {
artistListView.addHeaderView(folderButton);
@ -91,22 +94,22 @@ public class SelectArtistActivity extends SubsonicTabActivity implements Adapter
String title = getIntent().getStringExtra(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_TITLE);
if (title == null) {
getActionBar().setSubtitle(Util.isOffline(this) ? R.string.music_library_label_offline : R.string.music_library_label);
setActionBarSubtitle(Util.isOffline(this) ? R.string.music_library_label_offline : R.string.music_library_label);
} else {
getActionBar().setSubtitle(title);
setActionBarSubtitle(title);
}
View browseMenuItem = findViewById(R.id.menu_browse);
menuDrawer.setActiveView(browseMenuItem);
musicFolders = null;
load();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
return true;
super.onCreateOptionsMenu(menu);
return true;
}
private void refresh() {
@ -128,41 +131,46 @@ public class SelectArtistActivity extends SubsonicTabActivity implements Adapter
protected Indexes doInBackground() throws Throwable {
boolean refresh = getIntent().getBooleanExtra(Constants.INTENT_EXTRA_NAME_REFRESH, false);
MusicService musicService = MusicServiceFactory.getMusicService(SelectArtistActivity.this);
boolean isOffline = Util.isOffline(SelectArtistActivity.this);
boolean useId3Tags = Util.getShouldUseId3Tags(SelectArtistActivity.this);
if (!isOffline && !useId3Tags) {
musicFolders = musicService.getMusicFolders(refresh, SelectArtistActivity.this, this);
}
String musicFolderId = Util.getSelectedMusicFolderId(SelectArtistActivity.this);
if (!isOffline && useId3Tags) {
return musicService.getArtists(refresh, SelectArtistActivity.this, this);
return musicService.getArtists(refresh, SelectArtistActivity.this, this);
} else {
return musicService.getIndexes(musicFolderId, refresh, SelectArtistActivity.this, this);
return musicService.getIndexes(musicFolderId, refresh, SelectArtistActivity.this, this);
}
}
@Override
protected void done(Indexes result) {
if (result != null) {
List<Artist> artists = new ArrayList<Artist>(result.getShortcuts().size() + result.getArtists().size());
artists.addAll(result.getShortcuts());
artists.addAll(result.getArtists());
artistListView.setAdapter(new ArtistAdapter(SelectArtistActivity.this, artists));
}
if (result != null) {
List<Artist> artists = new ArrayList<Artist>(result.getShortcuts().size() + result.getArtists().size());
artists.addAll(result.getShortcuts());
artists.addAll(result.getArtists());
artistListView.setAdapter(new ArtistAdapter(SelectArtistActivity.this, artists));
}
// Display selected music folder
if (musicFolders != null) {
String musicFolderId = Util.getSelectedMusicFolderId(SelectArtistActivity.this);
if (musicFolderId == null) {
folderName.setText(R.string.select_artist_all_folders);
if (folderName != null) {
folderName.setText(R.string.select_artist_all_folders);
}
} else {
for (MusicFolder musicFolder : musicFolders) {
if (musicFolder.getId().equals(musicFolderId)) {
folderName.setText(musicFolder.getName());
if (folderName != null) {
folderName.setText(musicFolder.getName());
}
break;
}
}
@ -179,10 +187,13 @@ public class SelectArtistActivity extends SubsonicTabActivity implements Adapter
selectFolder();
} else {
Artist artist = (Artist) parent.getItemAtPosition(position);
Intent intent = new Intent(this, SelectAlbumActivity.class);
intent.putExtra(Constants.INTENT_EXTRA_NAME_ID, artist.getId());
intent.putExtra(Constants.INTENT_EXTRA_NAME_NAME, artist.getName());
Util.startActivityWithoutTransition(this, intent);
if (artist != null) {
Intent intent = new Intent(this, SelectAlbumActivity.class);
intent.putExtra(Constants.INTENT_EXTRA_NAME_ID, artist.getId());
intent.putExtra(Constants.INTENT_EXTRA_NAME_NAME, artist.getName());
Util.startActivityWithoutTransition(this, intent);
}
}
}
@ -210,7 +221,7 @@ public class SelectArtistActivity extends SubsonicTabActivity implements Adapter
}
}
}
menu.setGroupCheckable(MENU_GROUP_MUSIC_FOLDER, true, true);
}
}
@ -219,6 +230,10 @@ public class SelectArtistActivity extends SubsonicTabActivity implements Adapter
public boolean onContextItemSelected(MenuItem menuItem) {
AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuItem.getMenuInfo();
if (info == null) {
return true;
}
Artist artist = (Artist) artistListView.getItemAtPosition(info.position);
if (artist != null) {
@ -240,15 +255,14 @@ public class SelectArtistActivity extends SubsonicTabActivity implements Adapter
break;
case R.id.artist_menu_download:
downloadRecursively(artist.getId(), false, false, false, false, true, false, false);
break;
break;
default:
return super.onContextItemSelected(menuItem);
}
} else if (info.position == 1) {
MusicFolder selectedFolder = menuItem.getItemId() == -1 ? null : musicFolders.get(menuItem.getItemId());
String musicFolderId = selectedFolder == null ? null : selectedFolder.getId();
String musicFolderName = selectedFolder == null ? getString(R.string.select_artist_all_folders)
: selectedFolder.getName();
String musicFolderName = selectedFolder == null ? getString(R.string.select_artist_all_folders) : selectedFolder.getName();
Util.setSelectedMusicFolderId(this, musicFolderId);
folderName.setText(musicFolderName);
refresh();
@ -256,23 +270,23 @@ public class SelectArtistActivity extends SubsonicTabActivity implements Adapter
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
menuDrawer.toggleMenu();
return true;
case android.R.id.home:
menuDrawer.toggleMenu();
return true;
case R.id.main_shuffle:
Intent intent = new Intent(this, DownloadActivity.class);
intent.putExtra(Constants.INTENT_EXTRA_NAME_SHUFFLE, true);
Util.startActivityWithoutTransition(this, intent);
return true;
return true;
}
return false;
}
private class GetDataTask extends AsyncTask<Void, Void, String[]> {
@Override
protected void onPostExecute(String[] result) {
@ -280,10 +294,10 @@ public class SelectArtistActivity extends SubsonicTabActivity implements Adapter
super.onPostExecute(result);
}
@Override
protected String[] doInBackground(Void... params) {
refresh();
return null;
}
@Override
protected String[] doInBackground(Void... params) {
refresh();
return null;
}
}
}

View File

@ -80,7 +80,7 @@ public class SelectGenreActivity extends SubsonicTabActivity implements AdapterV
View browseMenuItem = findViewById(R.id.menu_browse);
menuDrawer.setActiveView(browseMenuItem);
getActionBar().setSubtitle(R.string.main_genres_title);
setActionBarSubtitle(R.string.main_genres_title);
load();
}
@ -132,11 +132,14 @@ public class SelectGenreActivity extends SubsonicTabActivity implements AdapterV
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Genre genre = (Genre) parent.getItemAtPosition(position);
Intent intent = new Intent(this, SelectAlbumActivity.class);
intent.putExtra(Constants.INTENT_EXTRA_NAME_GENRE_NAME, genre.getName());
intent.putExtra(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_SIZE, Util.getMaxSongs(this));
intent.putExtra(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_OFFSET, 0);
Util.startActivityWithoutTransition(this, intent);
if (genre != null) {
Intent intent = new Intent(this, SelectAlbumActivity.class);
intent.putExtra(Constants.INTENT_EXTRA_NAME_GENRE_NAME, genre.getName());
intent.putExtra(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_SIZE, Util.getMaxSongs(this));
intent.putExtra(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_OFFSET, 0);
Util.startActivityWithoutTransition(this, intent);
}
}
@Override

View File

@ -18,6 +18,7 @@
*/
package com.thejoshwa.ultrasonic.androidapp.activity;
import android.app.ActionBar;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Build;
@ -83,7 +84,6 @@ public class SettingsActivity extends PreferenceActivity implements SharedPrefer
private ListPreference directoryCacheTime;
private CheckBoxPreference mediaButtonsEnabled;
private CheckBoxPreference lockScreenEnabled;
private CheckBoxPreference gaplessPlaybackEnabled;
private CheckBoxPreference sendBluetoothNotifications;
private CheckBoxPreference sendBluetoothAlbumArt;
private int maxServerCount = 10;
@ -99,7 +99,6 @@ public class SettingsActivity extends PreferenceActivity implements SharedPrefer
private int activeServers = 3;
View chatMenuItem = null;
View bookmarksMenuItem = null;
View menuMain = null;
PreferenceCategory serversCategory;
Preference addServerPreference;
SharedPreferences settings;
@ -132,7 +131,11 @@ public class SettingsActivity extends PreferenceActivity implements SharedPrefer
findViewById(R.id.menu_about).setOnClickListener(this);
findViewById(R.id.menu_exit).setOnClickListener(this);
getActionBar().setDisplayHomeAsUpEnabled(true);
ActionBar actionBar = getActionBar();
if (actionBar != null) {
actionBar.setDisplayHomeAsUpEnabled(true);
}
View browseMenuItem = findViewById(R.id.menu_settings);
menuDrawer.setActiveView(browseMenuItem);
@ -163,7 +166,7 @@ public class SettingsActivity extends PreferenceActivity implements SharedPrefer
directoryCacheTime = (ListPreference) findPreference(Constants.PREFERENCES_KEY_DIRECTORY_CACHE_TIME);
mediaButtonsEnabled = (CheckBoxPreference) findPreference(Constants.PREFERENCES_KEY_MEDIA_BUTTONS);
lockScreenEnabled = (CheckBoxPreference) findPreference(Constants.PREFERENCES_KEY_SHOW_LOCK_SCREEN_CONTROLS);
gaplessPlaybackEnabled = (CheckBoxPreference) findPreference(Constants.PREFERENCES_KEY_GAPLESS_PLAYBACK);
CheckBoxPreference gaplessPlaybackEnabled = (CheckBoxPreference) findPreference(Constants.PREFERENCES_KEY_GAPLESS_PLAYBACK);
sendBluetoothAlbumArt = (CheckBoxPreference) findPreference(Constants.PREFERENCES_KEY_SEND_BLUETOOTH_ALBUM_ART);
sendBluetoothNotifications = (CheckBoxPreference) findPreference(Constants.PREFERENCES_KEY_SEND_BLUETOOTH_NOTIFICATIONS);

View File

@ -18,20 +18,14 @@
*/
package com.thejoshwa.ultrasonic.androidapp.activity;
import java.io.File;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import android.annotation.SuppressLint;
import android.app.ActionBar;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Notification;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
import android.media.AudioManager;
@ -48,11 +42,11 @@ import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnTouchListener;
import android.widget.ExpandableListView;
import android.widget.ImageView;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.RemoteViews;
import android.widget.TextView;
import com.thejoshwa.ultrasonic.androidapp.R;
import com.thejoshwa.ultrasonic.androidapp.domain.MusicDirectory;
import com.thejoshwa.ultrasonic.androidapp.domain.MusicDirectory.Entry;
@ -67,7 +61,6 @@ import com.thejoshwa.ultrasonic.androidapp.service.OfflineException;
import com.thejoshwa.ultrasonic.androidapp.service.ServerTooOldException;
import com.thejoshwa.ultrasonic.androidapp.util.Constants;
import com.thejoshwa.ultrasonic.androidapp.util.ImageLoader;
import com.thejoshwa.ultrasonic.androidapp.util.LoadingTask;
import com.thejoshwa.ultrasonic.androidapp.util.ModalBackgroundTask;
import com.thejoshwa.ultrasonic.androidapp.util.SilentBackgroundTask;
import com.thejoshwa.ultrasonic.androidapp.util.Util;
@ -76,6 +69,11 @@ import com.thejoshwa.ultrasonic.androidapp.util.VideoPlayerType;
import net.simonvt.menudrawer.MenuDrawer;
import net.simonvt.menudrawer.Position;
import java.io.File;
import java.io.PrintWriter;
import java.util.LinkedList;
import java.util.List;
/**
* @author Sindre Mehus
*/
@ -97,7 +95,6 @@ public class SubsonicTabActivity extends Activity implements OnClickListener{
private View nowPlayingView = null;
View chatMenuItem = null;
View bookmarksMenuItem = null;
View menuMain = null;
public static boolean nowPlayingHidden = false;
private static Entry currentSong;
public Bitmap nowPlayingImage;
@ -134,8 +131,8 @@ public class SubsonicTabActivity extends Activity implements OnClickListener{
findViewById(R.id.menu_about).setOnClickListener(this);
findViewById(R.id.menu_exit).setOnClickListener(this);
getActionBar().setDisplayHomeAsUpEnabled(true);
setActionBarDisplayHomeAsUp(true);
TextView activeView = (TextView)findViewById(menuActiveViewId);
if (activeView != null) {
@ -264,8 +261,7 @@ public class SubsonicTabActivity extends Activity implements OnClickListener{
@Override
protected void done(Void result) {
return;
}
}
}.execute();
}
});
@ -385,7 +381,7 @@ public class SubsonicTabActivity extends Activity implements OnClickListener{
private void showNowPlaying(final Context context, final DownloadServiceImpl downloadService, final MusicDirectory.Entry song, final PlayerState playerState) {
nowPlayingView = findViewById(R.id.now_playing);
if (!Util.getShowNowPlayingPreference(SubsonicTabActivity.this)) {
if (!Util.getShowNowPlayingPreference(context)) {
hideNowPlaying();
return;
}
@ -398,9 +394,9 @@ public class SubsonicTabActivity extends Activity implements OnClickListener{
ImageView playButton = (ImageView) nowPlayingView.findViewById(R.id.now_playing_control_play);
if (playerState == PlayerState.PAUSED) {
setImageDrawableOnUiThread(playButton, Util.getDrawableFromAttribute(SubsonicTabActivity.this, R.attr.media_play));
setImageDrawableOnUiThread(playButton, Util.getDrawableFromAttribute(context, R.attr.media_play));
} else if (playerState == PlayerState.STARTED) {
setImageDrawableOnUiThread(playButton, Util.getDrawableFromAttribute(SubsonicTabActivity.this, R.attr.media_pause));
setImageDrawableOnUiThread(playButton, Util.getDrawableFromAttribute(context, R.attr.media_pause));
}
String title = song.getTitle();
@ -413,13 +409,13 @@ public class SubsonicTabActivity extends Activity implements OnClickListener{
this.runOnUiThread( new Runnable() {
@Override
public void run() {
getImageLoader().loadImage(nowPlayingAlbumArtImage, song, true, Util.getNotificationImageSize(SubsonicTabActivity.this), false, true);
getImageLoader().loadImage(nowPlayingAlbumArtImage, song, true, Util.getNotificationImageSize(context), false, true);
}
});
final Intent intent = new Intent(SubsonicTabActivity.this, SelectAlbumActivity.class);
final Intent intent = new Intent(context, SelectAlbumActivity.class);
if (Util.getShouldUseId3Tags(SubsonicTabActivity.this)) {
if (Util.getShouldUseId3Tags(context)) {
intent.putExtra(Constants.INTENT_EXTRA_NAME_IS_ALBUM, true);
intent.putExtra(Constants.INTENT_EXTRA_NAME_ID, song.getAlbumId());
} else {
@ -500,18 +496,7 @@ public class SubsonicTabActivity extends Activity implements OnClickListener{
}
});
}
public void setListAdapterOnListViewOnUiThread(final ListView view, final ListAdapter adapter) {
this.runOnUiThread( new Runnable() {
@Override
public void run() {
if (view != null) {
view.setAdapter(adapter);
}
}
});
}
public void setOnTouchListenerOnUiThread(final View view, final View.OnTouchListener listener) {
this.runOnUiThread( new Runnable() {
@Override
@ -544,18 +529,7 @@ public class SubsonicTabActivity extends Activity implements OnClickListener{
}
});
}
public void setImageResourceOnUiThread(final ImageView view, final int resource) {
this.runOnUiThread( new Runnable() {
@Override
public void run() {
if (view != null && view.getVisibility() != View.GONE) {
view.setImageResource(resource);
}
}
});
}
public void setImageDrawableOnUiThread(final ImageView view, final Drawable drawable) {
this.runOnUiThread( new Runnable() {
@Override
@ -566,18 +540,7 @@ public class SubsonicTabActivity extends Activity implements OnClickListener{
}
});
}
public void setImageBitmapOnUiThread(final ImageView view, final Bitmap bitmap) {
this.runOnUiThread( new Runnable() {
@Override
public void run() {
if (view != null && view.getVisibility() != View.GONE) {
view.setImageBitmap(bitmap);
}
}
});
}
public void setVisibilityOnUiThread(final View view, final int visibility) {
this.runOnUiThread( new Runnable() {
@Override
@ -642,14 +605,7 @@ public class SubsonicTabActivity extends Activity implements OnClickListener{
}
return IMAGE_LOADER;
}
public synchronized static ImageLoader getStaticImageLoader(Context context) {
if (IMAGE_LOADER == null) {
IMAGE_LOADER = new ImageLoader(context);
}
return IMAGE_LOADER;
}
void download(final boolean append, final boolean save, final boolean autoplay, final boolean playNext, final boolean shuffle, final List<Entry> songs) {
if (getDownloadService() == null) {
return;
@ -789,81 +745,8 @@ public class SubsonicTabActivity extends Activity implements OnClickListener{
Util.toast(this, e.getMessage(), false);
}
}
protected void addToPlaylist(final List<MusicDirectory.Entry> songs) {
if(songs.isEmpty()) {
Util.toast(this, "No songs selected");
return;
}
new LoadingTask<List<Playlist>>(this, true) {
@Override
protected List<Playlist> doInBackground() throws Throwable {
MusicService musicService = MusicServiceFactory.getMusicService(SubsonicTabActivity.this);
return musicService.getPlaylists(false, SubsonicTabActivity.this, this);
}
@Override
protected void done(final List<Playlist> playlists) {
List<String> names = new ArrayList<String>();
for(Playlist playlist: playlists) {
names.add(playlist.getName());
}
AlertDialog.Builder builder = new AlertDialog.Builder(SubsonicTabActivity.this);
builder.setTitle("Add to Playlist")
.setItems(names.toArray(new CharSequence[names.size()]), new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
addToPlaylist(playlists.get(which), songs);
}
});
AlertDialog dialog = builder.create();
dialog.show();
}
@Override
protected void error(Throwable error) {
String msg;
if (error instanceof OfflineException || error instanceof ServerTooOldException) {
msg = getErrorMessage(error);
} else {
msg = getResources().getString(R.string.playlist_error) + " " + getErrorMessage(error);
}
Util.toast(SubsonicTabActivity.this, msg, false);
}
}.execute();
}
private void addToPlaylist(final Playlist playlist, final List<MusicDirectory.Entry> songs) {
new SilentBackgroundTask<Void>(this) {
@Override
protected Void doInBackground() throws Throwable {
MusicService musicService = MusicServiceFactory.getMusicService(SubsonicTabActivity.this);
musicService.updatePlaylist(playlist.getId(), songs, SubsonicTabActivity.this, null);
return null;
}
@Override
protected void done(Void result) {
Util.toast(SubsonicTabActivity.this, getResources().getString(R.string.updated_playlist, songs.size(), playlist.getName()));
}
@Override
protected void error(Throwable error) {
String msg;
if (error instanceof OfflineException || error instanceof ServerTooOldException) {
msg = getErrorMessage(error);
} else {
msg = getResources().getString(R.string.updated_playlist_error, playlist.getName()) + " " + getErrorMessage(error);
}
Util.toast(SubsonicTabActivity.this, msg, false);
}
}.execute();
}
protected void checkLicenseAndTrialPeriod(Runnable onValid) {
protected void checkLicenseAndTrialPeriod(Runnable onValid) {
if (licenseValid) {
onValid.run();
return;
@ -917,6 +800,68 @@ public class SubsonicTabActivity extends Activity implements OnClickListener{
builder.create().show();
}
protected void setActionBarDisplayHomeAsUp(boolean enabled) {
ActionBar actionBar = getActionBar();
if (actionBar != null) {
actionBar.setDisplayHomeAsUpEnabled(enabled);
}
}
protected void setActionBarTitle(String title) {
ActionBar actionBar = getActionBar();
if (actionBar != null) {
actionBar.setTitle(title);
}
}
protected void setActionBarTitle(int id) {
ActionBar actionBar = getActionBar();
if (actionBar != null) {
actionBar.setTitle(id);
}
}
protected CharSequence getActionBarTitle() {
ActionBar actionBar = getActionBar();
CharSequence title = null;
if (actionBar != null) {
title = actionBar.getTitle();
}
return title;
}
protected void setActionBarSubtitle(String title) {
ActionBar actionBar = getActionBar();
if (actionBar != null) {
actionBar.setSubtitle(title);
}
}
protected void setActionBarSubtitle(int id) {
ActionBar actionBar = getActionBar();
if (actionBar != null) {
actionBar.setSubtitle(id);
}
}
protected CharSequence getActionBarSubtitle() {
ActionBar actionBar = getActionBar();
CharSequence subtitle = null;
if (actionBar != null) {
subtitle = actionBar.getSubtitle();
}
return subtitle;
}
private void setUncaughtExceptionHandler() {
Thread.UncaughtExceptionHandler handler = Thread.getDefaultUncaughtExceptionHandler();
@ -932,6 +877,7 @@ public class SubsonicTabActivity extends Activity implements OnClickListener{
private final Thread.UncaughtExceptionHandler defaultHandler;
private final Context context;
private static final String filename = "ultrasonic-stacktrace.txt";
private SubsonicUncaughtExceptionHandler(Context context) {
this.context = context;
@ -942,14 +888,13 @@ public class SubsonicTabActivity extends Activity implements OnClickListener{
public void uncaughtException(Thread thread, Throwable throwable) {
File file = null;
PrintWriter printWriter = null;
try {
PackageInfo packageInfo = context.getPackageManager().getPackageInfo("com.thejoshwa.ultrasonic.androidapp", 0);
file = new File(Environment.getExternalStorageDirectory(), "ultrasonic-stacktrace.txt");
try {
file = new File(Environment.getExternalStorageDirectory(), filename);
printWriter = new PrintWriter(file);
printWriter.println("Android API level: " + Build.VERSION.SDK_INT);
printWriter.println("UltraSonic version name: " + packageInfo.versionName);
printWriter.println("UltraSonic version code: " + packageInfo.versionCode);
printWriter.println("UltraSonic version name: " + Util.getVersionName(context));
printWriter.println("UltraSonic version code: " + Util.getVersionCode(context));
printWriter.println();
throwable.printStackTrace(printWriter);
Log.i(TAG, "Stack trace written to " + file);
@ -960,7 +905,6 @@ public class SubsonicTabActivity extends Activity implements OnClickListener{
if (defaultHandler != null) {
defaultHandler.uncaughtException(thread, throwable);
}
}
}
}
@ -1046,16 +990,7 @@ public class SubsonicTabActivity extends Activity implements OnClickListener{
static class SwipeDetector implements OnTouchListener {
public static enum Action {
LeftToRight,
RightToLeft,
TopToBottom,
BottomToTop,
None,
Click
}
public static SwipeDetector Create(SubsonicTabActivity activity, final DownloadService downloadService) {
public static SwipeDetector Create(SubsonicTabActivity activity, final DownloadService downloadService) {
SwipeDetector swipeDetector = new SwipeDetector();
swipeDetector.downloadService = downloadService;
swipeDetector.activity = activity;

View File

@ -97,10 +97,6 @@ public class EqualizerController {
return equalizer != null;
}
public boolean isEnabled() {
return isAvailable() && equalizer.getEnabled();
}
public void release() {
if (isAvailable()) {
released = true;

View File

@ -18,7 +18,6 @@
*/
package com.thejoshwa.ultrasonic.androidapp.audiofx;
import android.content.Context;
import android.media.MediaPlayer;
import android.media.audiofx.Visualizer;
import android.util.Log;
@ -54,7 +53,7 @@ public class VisualizerController {
// Calling here forces class initialization.
}
public VisualizerController(Context context, MediaPlayer mediaPlayer) {
public VisualizerController(MediaPlayer mediaPlayer) {
try {
audioSessionId = mediaPlayer.getAudioSessionId();
visualizer = new Visualizer(audioSessionId);
@ -74,10 +73,6 @@ public class VisualizerController {
return visualizer != null;
}
public boolean isEnabled() {
return isAvailable() && visualizer.getEnabled();
}
public void release() {
if (isAvailable()) {
visualizer.release();

View File

@ -254,7 +254,7 @@ public class MusicDirectory {
}
public Integer getDuration() {
return duration == null ? 0 : duration;
return duration;
}
public void setDuration(Integer duration) {

View File

@ -0,0 +1,55 @@
/*
This file is part of Subsonic.
Subsonic 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.
Subsonic 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 Subsonic. If not, see <http://www.gnu.org/licenses/>.
Copyright 2009 (C) Sindre Mehus
*/
package com.thejoshwa.ultrasonic.androidapp.domain;
/**
* The criteria for a music search.
*
* @author Sindre Mehus
*/
public class SearchCriteria {
private final String query;
private final int artistCount;
private final int albumCount;
private final int songCount;
public SearchCriteria(String query, int artistCount, int albumCount, int songCount) {
this.query = query;
this.artistCount = artistCount;
this.albumCount = albumCount;
this.songCount = songCount;
}
public String getQuery() {
return query;
}
public int getArtistCount() {
return artistCount;
}
public int getAlbumCount() {
return albumCount;
}
public int getSongCount() {
return songCount;
}
}

View File

@ -16,6 +16,7 @@ import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
import android.os.Environment;
import android.util.Log;
import android.view.KeyEvent;
@ -48,10 +49,13 @@ public class UltraSonicAppWidgetProvider extends AppWidgetProvider {
private void pushUpdate(Context context, int[] appWidgetIds, RemoteViews views) {
// Update specific list of appWidgetIds if given, otherwise default to all
final AppWidgetManager manager = AppWidgetManager.getInstance(context);
if (appWidgetIds != null) {
manager.updateAppWidget(appWidgetIds, views);
} else {
manager.updateAppWidget(new ComponentName(context, this.getClass()), views);
if (manager != null) {
if (appWidgetIds != null) {
manager.updateAppWidget(appWidgetIds, views);
} else {
manager.updateAppWidget(new ComponentName(context, this.getClass()), views);
}
}
}
@ -69,7 +73,12 @@ public class UltraSonicAppWidgetProvider extends AppWidgetProvider {
*/
private boolean hasInstances(Context context) {
AppWidgetManager manager = AppWidgetManager.getInstance(context);
int[] appWidgetIds = manager.getAppWidgetIds(new ComponentName(context, getClass()));
int[] appWidgetIds = new int[0];
if (manager != null) {
appWidgetIds = manager.getAppWidgetIds(new ComponentName(context, getClass()));
}
return (appWidgetIds.length > 0);
}
@ -123,7 +132,11 @@ public class UltraSonicAppWidgetProvider extends AppWidgetProvider {
// Set the cover art
try {
int size = context.getResources().getDrawable(R.drawable.appwidget_art_default).getIntrinsicHeight();
int size;
Resources resources = context.getResources();
Drawable drawable = resources.getDrawable(R.drawable.appwidget_art_default);
size = drawable != null ? drawable.getIntrinsicHeight() : 0;
Bitmap bitmap = currentPlaying == null ? null : FileUtil.getAlbumArtBitmap(context, currentPlaying, size, true);
if (bitmap == null) {

View File

@ -42,8 +42,20 @@ public class BluetoothIntentReceiver extends BroadcastReceiver {
Log.d(TAG, "Bluetooth Sink State: " + state);
Log.d(TAG, "Bluetooth Action: " + action);
boolean connected = state == android.bluetooth.BluetoothA2dp.STATE_CONNECTED || action.equals(android.bluetooth.BluetoothDevice.ACTION_ACL_CONNECTED);
boolean disconnected = state == android.bluetooth.BluetoothA2dp.STATE_DISCONNECTED || (action.equals(android.bluetooth.BluetoothDevice.ACTION_ACL_DISCONNECTED) || action.equals(android.bluetooth.BluetoothDevice.ACTION_ACL_DISCONNECT_REQUESTED));
boolean actionConnected = false;
boolean actionDisconnected = false;
if (action != null) {
if (action.equals(android.bluetooth.BluetoothDevice.ACTION_ACL_CONNECTED)) {
actionConnected = true;
} else if (action.equals(android.bluetooth.BluetoothDevice.ACTION_ACL_DISCONNECTED) || action.equals(android.bluetooth.BluetoothDevice.ACTION_ACL_DISCONNECT_REQUESTED)) {
actionDisconnected = true;
}
}
boolean connected = state == android.bluetooth.BluetoothA2dp.STATE_CONNECTED || actionConnected;
boolean disconnected = state == android.bluetooth.BluetoothA2dp.STATE_DISCONNECTED || actionDisconnected;
if (connected) {
Log.i(TAG, "Connected to Bluetooth A2DP, requesting media button focus.");

View File

@ -21,6 +21,7 @@ package com.thejoshwa.ultrasonic.androidapp.receiver;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;
import com.thejoshwa.ultrasonic.androidapp.service.DownloadServiceImpl;
@ -35,26 +36,32 @@ public class MediaButtonIntentReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (Util.getMediaButtonsPreference(context)) {
String intentAction = intent.getAction();
if (!Intent.ACTION_MEDIA_BUTTON.equals(intentAction))
return;
KeyEvent event = (KeyEvent) intent.getExtras().get(Intent.EXTRA_KEY_EVENT);
Log.i(TAG, "Got MEDIA_BUTTON key event: " + event);
if (Util.getMediaButtonsPreference(context)) {
String intentAction = intent.getAction();
Intent serviceIntent = new Intent(context, DownloadServiceImpl.class);
serviceIntent.putExtra(Intent.EXTRA_KEY_EVENT, event);
context.startService(serviceIntent);
if (!Intent.ACTION_MEDIA_BUTTON.equals(intentAction))
return;
try {
if (isOrderedBroadcast()) {
abortBroadcast();
}
} catch (Exception x) {
// Ignored.
}
}
Bundle extras = intent.getExtras();
if (extras == null) {
return;
}
KeyEvent event = (KeyEvent) extras.get(Intent.EXTRA_KEY_EVENT);
Log.i(TAG, "Got MEDIA_BUTTON key event: " + event);
Intent serviceIntent = new Intent(context, DownloadServiceImpl.class);
serviceIntent.putExtra(Intent.EXTRA_KEY_EVENT, event);
context.startService(serviceIntent);
try {
if (isOrderedBroadcast()) {
abortBroadcast();
}
} catch (Exception x) {
// Ignored.
}
}
}
}

View File

@ -35,7 +35,7 @@ import com.thejoshwa.ultrasonic.androidapp.domain.Lyrics;
import com.thejoshwa.ultrasonic.androidapp.domain.MusicDirectory;
import com.thejoshwa.ultrasonic.androidapp.domain.MusicFolder;
import com.thejoshwa.ultrasonic.androidapp.domain.Playlist;
import com.thejoshwa.ultrasonic.androidapp.domain.SearchCritera;
import com.thejoshwa.ultrasonic.androidapp.domain.SearchCriteria;
import com.thejoshwa.ultrasonic.androidapp.domain.SearchResult;
import com.thejoshwa.ultrasonic.androidapp.domain.Share;
import com.thejoshwa.ultrasonic.androidapp.domain.Version;
@ -59,8 +59,7 @@ public class CachedMusicService implements MusicService {
private final LRUCache<String, TimeLimitedCache<MusicDirectory>> cachedAlbum;
private final TimeLimitedCache<Boolean> cachedLicenseValid = new TimeLimitedCache<Boolean>(120, TimeUnit.SECONDS);
private final TimeLimitedCache<Indexes> cachedIndexes = new TimeLimitedCache<Indexes>(60 * 60, TimeUnit.SECONDS);
private final TimeLimitedCache<Indexes> cachedArtists = new TimeLimitedCache<Indexes>(60 * 60, TimeUnit.SECONDS);
private final TimeLimitedCache<MusicDirectory> cachedVideos = new TimeLimitedCache<MusicDirectory>(60 * 60, TimeUnit.SECONDS);
private final TimeLimitedCache<Indexes> cachedArtists = new TimeLimitedCache<Indexes>(60 * 60, TimeUnit.SECONDS);
private final TimeLimitedCache<List<Playlist>> cachedPlaylists = new TimeLimitedCache<List<Playlist>>(3600, TimeUnit.SECONDS);
private final TimeLimitedCache<List<MusicFolder>> cachedMusicFolders = new TimeLimitedCache<List<MusicFolder>>(10 * 3600, TimeUnit.SECONDS);
private final TimeLimitedCache<List<Genre>> cachedGenres = new TimeLimitedCache<List<Genre>>(10 * 3600, TimeUnit.SECONDS);
@ -180,7 +179,7 @@ public class CachedMusicService implements MusicService {
}
@Override
public SearchResult search(SearchCritera criteria, Context context, ProgressListener progressListener) throws Exception {
public SearchResult search(SearchCriteria criteria, Context context, ProgressListener progressListener) throws Exception {
return musicService.search(criteria, context, progressListener);
}

View File

@ -56,20 +56,19 @@ public class DownloadFile {
private boolean save;
private boolean failed;
private int bitRate;
private boolean isPlaying = false;
private boolean saveWhenDone = false;
private boolean completeWhenDone = false;
private volatile boolean isPlaying = false;
private volatile boolean saveWhenDone = false;
private volatile boolean completeWhenDone = false;
public DownloadFile(Context context, MusicDirectory.Entry song, boolean save) {
this.context = context;
this.song = song;
this.save = save;
saveFile = FileUtil.getSongFile(context, song);
bitRate = Util.getMaxBitrate(context);
partialFile = new File(saveFile.getParent(), FileUtil.getBaseName(saveFile.getName()) +
".partial." + FileUtil.getExtension(saveFile.getName()));
completeFile = new File(saveFile.getParent(), FileUtil.getBaseName(saveFile.getName()) +
".complete." + FileUtil.getExtension(saveFile.getName()));
bitRate = Util.getMaxBitRate(context);
partialFile = new File(saveFile.getParent(), FileUtil.getBaseName(saveFile.getName()) + ".partial." + FileUtil.getExtension(saveFile.getName()));
completeFile = new File(saveFile.getParent(), FileUtil.getBaseName(saveFile.getName()) + ".complete." + FileUtil.getExtension(saveFile.getName()));
mediaStoreService = new MediaStoreService(context);
}
@ -81,21 +80,25 @@ public class DownloadFile {
* Returns the effective bit rate.
*/
public int getBitRate() {
if(!partialFile.exists()) {
bitRate = Util.getMaxBitrate(context);
if (!partialFile.exists()) {
bitRate = Util.getMaxBitRate(context);
}
if (bitRate > 0) {
return bitRate;
}
return song.getBitRate() == null ? 160 : song.getBitRate();
}
public synchronized void download() {
FileUtil.createDirectoryForParent(saveFile);
failed = false;
if(!partialFile.exists()) {
bitRate = Util.getMaxBitrate(context);
if (!partialFile.exists()) {
bitRate = Util.getMaxBitRate(context);
}
downloadTask = new DownloadTask();
downloadTask.start();
}
@ -193,16 +196,17 @@ public class DownloadFile {
public void setPlaying(boolean isPlaying) {
try {
if(saveWhenDone && isPlaying == false) {
if (saveWhenDone && !isPlaying) {
Util.renameFile(completeFile, saveFile);
saveWhenDone = false;
} else if(completeWhenDone && isPlaying == false) {
if(save) {
} else if(completeWhenDone && !isPlaying) {
if (save) {
Util.renameFile(partialFile, saveFile);
mediaStoreService.saveInMediaStore(DownloadFile.this);
} else {
Util.renameFile(partialFile, completeFile);
}
completeWhenDone = false;
}
} catch(IOException ex) {
@ -211,9 +215,6 @@ public class DownloadFile {
this.isPlaying = isPlaying;
}
public boolean getPlaying() {
return isPlaying;
}
@Override
public String toString() {
@ -229,8 +230,8 @@ public class DownloadFile {
FileOutputStream out = null;
PowerManager.WakeLock wakeLock = null;
WifiManager.WifiLock wifiLock = null;
try {
try {
if (Util.isScreenLitOnDownload(context)) {
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
wakeLock = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK | PowerManager.ON_AFTER_RELEASE, toString());
@ -247,7 +248,7 @@ public class DownloadFile {
}
if (completeFile.exists()) {
if (save) {
if(isPlaying) {
if (isPlaying) {
saveWhenDone = true;
} else {
Util.renameFile(completeFile, saveFile);
@ -262,16 +263,27 @@ public class DownloadFile {
// Some devices seem to throw error on partial file which doesn't exist
boolean compare;
Integer duration = song.getDuration();
long fileLength = 0;
if (!partialFile.exists()) {
fileLength = partialFile.length();
}
try {
compare = (bitRate == 0) || (song.getDuration() == 0) || (partialFile.length() == 0) || (bitRate * song.getDuration() * 1000 / 8) > partialFile.length();
compare = (bitRate == 0) || (duration == null || duration == 0) || (fileLength == 0);
//(bitRate * song.getDuration() * 1000 / 8) > partialFile.length();
} catch(Exception e) {
compare = true;
}
if(compare) {
if (compare) {
// Attempt partial HTTP GET, appending to the file if it exists.
HttpResponse response = musicService.getDownloadInputStream(context, song, partialFile.length(), bitRate, DownloadTask.this);
in = response.getEntity().getContent();
boolean partial = response.getStatusLine().getStatusCode() == HttpStatus.SC_PARTIAL_CONTENT;
if (partial) {
Log.i(TAG, "Executed partial HTTP GET, skipping " + partialFile.length() + " bytes");
}
@ -289,10 +301,10 @@ public class DownloadFile {
downloadAndSaveCoverArt(musicService);
}
if(isPlaying) {
if (isPlaying) {
completeWhenDone = true;
} else {
if(save) {
if (save) {
Util.renameFile(partialFile, saveFile);
mediaStoreService.saveInMediaStore(DownloadFile.this);
} else {

View File

@ -83,18 +83,12 @@ public class DownloadServiceImpl extends Service implements DownloadService {
public static final String CMD_STOP = "com.thejoshwa.ultrasonic.androidapp.CMD_STOP";
public static final String CMD_PREVIOUS = "com.thejoshwa.ultrasonic.androidapp.CMD_PREVIOUS";
public static final String CMD_NEXT = "com.thejoshwa.ultrasonic.androidapp.CMD_NEXT";
public static final String PLAYSTATUS_REQUEST = "com.android.music.playstatusrequest";
public static final String PLAYSTATUS_RESPONSE = "com.android.music.playstatusresponse";
public static final int lockScreenAlbumArtSize = 500;
private final IBinder binder = new SimpleServiceBinder<DownloadService>(this);
private Looper mediaPlayerLooper;
private MediaPlayer mediaPlayer;
private MediaPlayer nextMediaPlayer;
private boolean nextSetup = false;
private boolean isPartial = true;
private boolean nextSetup = false;
private final List<DownloadFile> downloadList = new ArrayList<DownloadFile>();
private final List<DownloadFile> backgroundDownloadList = new ArrayList<DownloadFile>();
private final Handler handler = new Handler();
@ -136,8 +130,10 @@ public class DownloadServiceImpl extends Service implements DownloadService {
private AudioManager audioManager;
private int secondaryProgress = -1;
private boolean autoPlayStart = false;
static {
private static Bitmap lockScreenBitmap;
private final static int lockScreenBitmapSize = 500;
static {
try {
EqualizerController.checkAvailable();
equalizerAvailable = true;
@ -164,6 +160,10 @@ public class DownloadServiceImpl extends Service implements DownloadService {
public void run() {
Looper.prepare();
if (mediaPlayer instanceof MediaPlayer && mediaPlayer != null) {
mediaPlayer.release();
}
mediaPlayer = new MediaPlayer();
mediaPlayer.setWakeMode(DownloadServiceImpl.this, PowerManager.PARTIAL_WAKE_LOCK);
@ -191,6 +191,11 @@ public class DownloadServiceImpl extends Service implements DownloadService {
}).start();
audioManager = (AudioManager) this.getSystemService(Context.AUDIO_SERVICE);
if (mediaPlayer instanceof MediaPlayer && mediaPlayer != null) {
mediaPlayer.release();
}
mediaPlayer = new MediaPlayer();
mediaPlayer.setWakeMode(this, PowerManager.PARTIAL_WAKE_LOCK);
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
@ -223,7 +228,7 @@ public class DownloadServiceImpl extends Service implements DownloadService {
}
}
if (visualizerAvailable) {
visualizerController = new VisualizerController(this, mediaPlayer);
visualizerController = new VisualizerController(mediaPlayer);
if (!visualizerController.isAvailable()) {
visualizerController = null;
}
@ -507,7 +512,7 @@ public class DownloadServiceImpl extends Service implements DownloadService {
currentDownloading.cancelDownload();
currentDownloading = null;
}
setCurrentPlaying(null, false);
setCurrentPlaying(null);
if (serialize) {
lifecycleSupport.serializeDownloadQueue();
@ -529,7 +534,7 @@ public class DownloadServiceImpl extends Service implements DownloadService {
}
if (downloadFile == currentPlaying) {
reset();
setCurrentPlaying(null, false);
setCurrentPlaying(null);
}
downloadList.remove(downloadFile);
backgroundDownloadList.remove(downloadFile);
@ -555,15 +560,15 @@ public class DownloadServiceImpl extends Service implements DownloadService {
}
}
synchronized void setCurrentPlaying(int currentPlayingIndex, boolean showNotification) {
synchronized void setCurrentPlaying(int currentPlayingIndex) {
try {
setCurrentPlaying(downloadList.get(currentPlayingIndex), showNotification);
setCurrentPlaying(downloadList.get(currentPlayingIndex));
} catch (IndexOutOfBoundsException x) {
// Ignored
}
}
synchronized void setCurrentPlaying(DownloadFile currentPlaying, boolean showNotification) {
synchronized void setCurrentPlaying(DownloadFile currentPlaying) {
this.currentPlaying = currentPlaying;
if (currentPlaying != null) {
@ -711,7 +716,7 @@ public class DownloadServiceImpl extends Service implements DownloadService {
nextPlayingTask = null;
}
setCurrentPlaying(index, start);
setCurrentPlaying(index);
if (start) {
if (jukeboxEnabled) {
@ -729,7 +734,7 @@ public class DownloadServiceImpl extends Service implements DownloadService {
private synchronized void resetPlayback() {
reset();
setCurrentPlaying(null, false);
setCurrentPlaying(null);
lifecycleSupport.serializeDownloadQueue();
}
@ -744,7 +749,7 @@ public class DownloadServiceImpl extends Service implements DownloadService {
MediaPlayer tmp = mediaPlayer;
mediaPlayer = nextMediaPlayer;
nextMediaPlayer = tmp;
setCurrentPlaying(nextPlaying, true);
setCurrentPlaying(nextPlaying);
setPlayerState(PlayerState.STARTED);
setupHandlers(currentPlaying, false);
setNextPlaying();
@ -760,7 +765,7 @@ public class DownloadServiceImpl extends Service implements DownloadService {
public synchronized void togglePlayPause() {
if (playerState == PAUSED || playerState == COMPLETED || playerState == STOPPED) {
start();
} else if (playerState == STOPPED || playerState == IDLE) {
} else if (playerState == IDLE) {
autoPlayStart = true;
play();
} else if (playerState == STARTED) {
@ -815,7 +820,7 @@ public class DownloadServiceImpl extends Service implements DownloadService {
MusicService musicService = MusicServiceFactory.getMusicService(DownloadServiceImpl.this);
try {
musicService.deleteBookmark(song.getId(), DownloadServiceImpl.this, null);
} catch (Exception e) {
} catch (Exception ignored) {
}
}
@ -964,9 +969,8 @@ public class DownloadServiceImpl extends Service implements DownloadService {
}
boolean showWhenPaused = (this.playerState == PlayerState.PAUSED && Util.isNotificationAlwaysEnabled(this));
boolean show = this.playerState == PlayerState.STARTED || showWhenPaused;
boolean hide = this.playerState == PlayerState.IDLE || this.playerState == PlayerState.STOPPED || !showWhenPaused;
Util.broadcastPlaybackStatusChange(this, this.playerState);
Util.broadcastA2dpPlayStatusChange(this, this.playerState, getInstance());
@ -983,15 +987,13 @@ public class DownloadServiceImpl extends Service implements DownloadService {
if (show) {
int size = Util.getNotificationImageSize(this);
Bitmap bitmap = FileUtil.getAlbumArtBitmap(this, currentPlaying.getSong(), size, true);
if (currentPlaying != null) {
if (tabInstance != null) {
tabInstance.nowPlayingImage = bitmap;
tabInstance.showNotification(handler, currentPlaying.getSong(), this, this.notification, this.playerState);
tabInstance.showNowPlaying();
}
}
} else if (hide) {
if (tabInstance != null) {
tabInstance.nowPlayingImage = bitmap;
tabInstance.showNotification(handler, currentPlaying.getSong(), this, this.notification, this.playerState);
tabInstance.showNowPlaying();
}
} else {
if (tabInstance != null) {
tabInstance.nowPlayingImage = null;
tabInstance.hidePlayingNotification(handler, this);
@ -1068,7 +1070,7 @@ public class DownloadServiceImpl extends Service implements DownloadService {
@Override
public VisualizerController getVisualizerController() {
if (visualizerAvailable && visualizerController == null) {
visualizerController = new VisualizerController(this, mediaPlayer);
visualizerController = new VisualizerController(mediaPlayer);
if (!visualizerController.isAvailable()) {
visualizerController = null;
}
@ -1142,6 +1144,7 @@ public class DownloadServiceImpl extends Service implements DownloadService {
if (currentPlaying != null) {
if (currentSong != currentPlaying.getSong()) {
currentSong = currentPlaying.getSong();
lockScreenBitmap = FileUtil.getAlbumArtBitmap(this, currentSong, lockScreenBitmapSize, true);
} else {
return;
}
@ -1151,11 +1154,6 @@ public class DownloadServiceImpl extends Service implements DownloadService {
String title = artist + " - " + currentSong.getTitle();
Integer duration = currentSong.getDuration();
// Reuse albumArt for lockscreen and Bluetooth
if (Util.albumArtBitmap == null) {
Util.albumArtBitmap = FileUtil.getAlbumArtBitmap(this, currentSong, Util.albumArtImageSize, true);
}
// Update the remote controls
remoteControlClient
.editMetadata(true)
@ -1170,13 +1168,11 @@ public class DownloadServiceImpl extends Service implements DownloadService {
.putLong(MediaMetadataRetriever.METADATA_KEY_DURATION, duration)
.apply();
}
if (Util.albumArtBitmap != null) {
remoteControlClient
.editMetadata(false)
.putBitmap(RemoteControlClient.MetadataEditor.BITMAP_KEY_ARTWORK, Util.albumArtBitmap)
.apply();
}
remoteControlClient
.editMetadata(false)
.putBitmap(RemoteControlClient.MetadataEditor.BITMAP_KEY_ARTWORK, lockScreenBitmap)
.apply();
}
}
catch (Exception e) {
@ -1200,7 +1196,7 @@ public class DownloadServiceImpl extends Service implements DownloadService {
try {
downloadFile.setPlaying(true);
final File file = downloadFile.isCompleteFileAvailable() ? downloadFile.getCompleteFile() : downloadFile.getPartialFile();
isPartial = file.equals(downloadFile.getPartialFile());
boolean partial = file.equals(downloadFile.getPartialFile());
downloadFile.updateModificationDate();
mediaPlayer.setOnCompletionListener(null);
@ -1210,7 +1206,7 @@ public class DownloadServiceImpl extends Service implements DownloadService {
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
String dataSource = file.getPath();
if(isPartial) {
if(partial) {
if (proxy == null) {
proxy = new StreamProxy(this);
proxy.start();
@ -1236,7 +1232,7 @@ public class DownloadServiceImpl extends Service implements DownloadService {
SeekBar progressBar = DownloadActivity.getProgressBar();
MusicDirectory.Entry song = downloadFile.getSong();
if (progressBar != null && song.getTranscodedContentType() == null && Util.getMaxBitrate(getApplicationContext()) == 0) {
if (progressBar != null && song.getTranscodedContentType() == null && Util.getMaxBitRate(getApplicationContext()) == 0) {
secondaryProgress = (int) (((double)percent / (double)100) * progressBar.getMax());
progressBar.setSecondaryProgress(secondaryProgress);
}
@ -1276,7 +1272,7 @@ public class DownloadServiceImpl extends Service implements DownloadService {
}
});
setupHandlers(downloadFile, isPartial);
setupHandlers(downloadFile, partial);
mediaPlayer.prepareAsync();
} catch (Exception x) {
@ -1381,7 +1377,7 @@ public class DownloadServiceImpl extends Service implements DownloadService {
// If file is not completely downloaded, restart the playback from the current position.
synchronized (DownloadServiceImpl.this) {
if(downloadFile.isWorkDone()) {
if (downloadFile.isWorkDone()) {
// Complete was called early even though file is fully buffered
Log.i(TAG, "Requesting restart from " + pos + " of " + duration);
reset();

View File

@ -103,9 +103,11 @@ public class JukeboxService {
while (true) {
JukeboxTask task = null;
try {
task = tasks.take();
JukeboxStatus status = task.execute();
onStatusUpdate(status);
if (!Util.isOffline(downloadService)) {
task = tasks.take();
JukeboxStatus status = task.execute();
onStatusUpdate(status);
}
} catch (Throwable x) {
onError(task, x);
}
@ -119,7 +121,7 @@ public class JukeboxService {
// Track change?
Integer index = jukeboxStatus.getCurrentPlayingIndex();
if (index != null && index != -1 && index != downloadService.getCurrentPlayingIndex()) {
downloadService.setCurrentPlaying(index, true);
downloadService.setCurrentPlaying(index);
}
}

View File

@ -64,13 +64,16 @@ public class MediaStoreService {
Uri uri = contentResolver.insert(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, values);
// Look up album, and add cover art if found.
Cursor cursor = contentResolver.query(uri, new String[]{MediaStore.Audio.AudioColumns.ALBUM_ID}, null, null, null);
if (cursor.moveToFirst()) {
int albumId = cursor.getInt(0);
insertAlbumArt(albumId, downloadFile);
if (uri != null) {
// Look up album, and add cover art if found.
Cursor cursor = contentResolver.query(uri, new String[]{MediaStore.Audio.AudioColumns.ALBUM_ID}, null, null, null);
if (cursor != null && cursor.moveToFirst()) {
int albumId = cursor.getInt(0);
insertAlbumArt(albumId, downloadFile);
cursor.close();
}
}
cursor.close();
}
public void deleteFromMediaStore(DownloadFile downloadFile) {
@ -89,10 +92,15 @@ public class MediaStoreService {
private void insertAlbumArt(int albumId, DownloadFile downloadFile) {
ContentResolver contentResolver = context.getContentResolver();
Uri uri = Uri.withAppendedPath(ALBUM_ART_URI, String.valueOf(albumId));
Cursor cursor = contentResolver.query(Uri.withAppendedPath(ALBUM_ART_URI, String.valueOf(albumId)), null, null, null, null);
if (!cursor.moveToFirst()) {
if (uri == null) {
return;
}
Cursor cursor = contentResolver.query(uri, null, null, null, null);
if (cursor != null && !cursor.moveToFirst()) {
// No album art found, add it.
File albumArtFile = FileUtil.getAlbumArtFile(context, downloadFile.getSong());
if (albumArtFile.exists()) {
@ -102,8 +110,8 @@ public class MediaStoreService {
contentResolver.insert(ALBUM_ART_URI, values);
Log.i(TAG, "Added album art: " + albumArtFile);
}
}
cursor.close();
}
cursor.close();
}
}
}

View File

@ -34,7 +34,7 @@ import com.thejoshwa.ultrasonic.androidapp.domain.Lyrics;
import com.thejoshwa.ultrasonic.androidapp.domain.MusicDirectory;
import com.thejoshwa.ultrasonic.androidapp.domain.MusicFolder;
import com.thejoshwa.ultrasonic.androidapp.domain.Playlist;
import com.thejoshwa.ultrasonic.androidapp.domain.SearchCritera;
import com.thejoshwa.ultrasonic.androidapp.domain.SearchCriteria;
import com.thejoshwa.ultrasonic.androidapp.domain.SearchResult;
import com.thejoshwa.ultrasonic.androidapp.domain.Share;
import com.thejoshwa.ultrasonic.androidapp.domain.Version;
@ -68,7 +68,7 @@ public interface MusicService {
MusicDirectory getAlbum(String id, String name, boolean refresh, Context context, ProgressListener progressListener) throws Exception;
SearchResult search(SearchCritera criteria, Context context, ProgressListener progressListener) throws Exception;
SearchResult search(SearchCriteria criteria, Context context, ProgressListener progressListener) throws Exception;
MusicDirectory getPlaylist(String id, String name, Context context, ProgressListener progressListener) throws Exception;

View File

@ -44,7 +44,7 @@ import com.thejoshwa.ultrasonic.androidapp.domain.Lyrics;
import com.thejoshwa.ultrasonic.androidapp.domain.MusicDirectory;
import com.thejoshwa.ultrasonic.androidapp.domain.MusicFolder;
import com.thejoshwa.ultrasonic.androidapp.domain.Playlist;
import com.thejoshwa.ultrasonic.androidapp.domain.SearchCritera;
import com.thejoshwa.ultrasonic.androidapp.domain.SearchCriteria;
import com.thejoshwa.ultrasonic.androidapp.domain.SearchResult;
import com.thejoshwa.ultrasonic.androidapp.util.Constants;
import com.thejoshwa.ultrasonic.androidapp.util.FileUtil;
@ -77,7 +77,7 @@ public class OfflineMusicService extends RESTMusicService {
try {
artistIndex = file.getName().substring(0, 1);
}
catch (Exception ex) { }
catch (Exception ignored) { }
artist.setIndex(artistIndex);
@ -156,7 +156,7 @@ public class OfflineMusicService extends RESTMusicService {
duration = mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
hasVideo = mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_HAS_VIDEO);
mmr.release();
} catch (Exception ex) { }
} catch (Exception ignored) { }
entry.setArtist(artist != null ? artist : file.getParentFile().getParentFile().getName());
entry.setAlbum(album != null ? album : file.getParentFile().getName());
@ -201,7 +201,7 @@ public class OfflineMusicService extends RESTMusicService {
discValue = Integer.parseInt(disc);
}
catch(Exception ex) { }
catch(Exception ignored) { }
entry.setDiscNumber(discValue);
}
@ -211,7 +211,7 @@ public class OfflineMusicService extends RESTMusicService {
try {
yearValue = Integer.parseInt(year);
} catch(Exception ex) { }
} catch(Exception ignored) { }
entry.setYear(yearValue);
}
@ -236,7 +236,7 @@ public class OfflineMusicService extends RESTMusicService {
try {
durationValue = Long.parseLong(duration);
durationValue = TimeUnit.MILLISECONDS.toSeconds(durationValue);
} catch(Exception ex) { }
} catch(Exception ignored) { }
entry.setDuration(durationValue);
}
@ -278,16 +278,17 @@ public class OfflineMusicService extends RESTMusicService {
}
@Override
public SearchResult search(SearchCritera criteria, Context context, ProgressListener progressListener) throws Exception {
public SearchResult search(SearchCriteria criteria, Context context, ProgressListener progressListener) throws Exception {
List<Artist> artists = new ArrayList<Artist>();
List<MusicDirectory.Entry> albums = new ArrayList<MusicDirectory.Entry>();
List<MusicDirectory.Entry> songs = new ArrayList<MusicDirectory.Entry>();
File root = FileUtil.getMusicDirectory(context);
int closeness = 0;
int closeness;
for (File artistFile : FileUtil.listFiles(root)) {
String artistName = artistFile.getName();
if (artistFile.isDirectory()) {
if((closeness = matchCriteria(criteria, artistName)) > 0) {
if ((closeness = matchCriteria(criteria, artistName)) > 0) {
Artist artist = new Artist();
artist.setId(artistFile.getPath());
artist.setIndex(artistFile.getName().substring(0, 1));
@ -343,7 +344,7 @@ public class OfflineMusicService extends RESTMusicService {
return new SearchResult(artists, albums, songs);
}
private void recursiveAlbumSearch(String artistName, File file, SearchCritera criteria, Context context, List<MusicDirectory.Entry> albums, List<MusicDirectory.Entry> songs) {
private void recursiveAlbumSearch(String artistName, File file, SearchCriteria criteria, Context context, List<MusicDirectory.Entry> albums, List<MusicDirectory.Entry> songs) {
int closeness;
for(File albumFile : FileUtil.listMediaFiles(file)) {
if(albumFile.isDirectory()) {
@ -381,7 +382,7 @@ public class OfflineMusicService extends RESTMusicService {
}
}
}
private int matchCriteria(SearchCritera criteria, String name) {
private int matchCriteria(SearchCriteria criteria, String name) {
String query = criteria.getQuery().toLowerCase();
String[] queryParts = query.split(" ");
String[] nameParts = name.toLowerCase().split(" ");

View File

@ -18,57 +18,14 @@
*/
package com.thejoshwa.ultrasonic.androidapp.service;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.Reader;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.conn.params.ConnManagerParams;
import org.apache.http.conn.params.ConnPerRouteBean;
import org.apache.http.conn.scheme.PlainSocketFactory;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.scheme.SocketFactory;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
import org.apache.http.message.BasicHeader;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.protocol.ExecutionContext;
import org.apache.http.protocol.HttpContext;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.pm.PackageInfo;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.util.Log;
import com.thejoshwa.ultrasonic.androidapp.R;
import com.thejoshwa.ultrasonic.androidapp.domain.Bookmark;
import com.thejoshwa.ultrasonic.androidapp.domain.ChatMessage;
@ -79,7 +36,7 @@ import com.thejoshwa.ultrasonic.androidapp.domain.Lyrics;
import com.thejoshwa.ultrasonic.androidapp.domain.MusicDirectory;
import com.thejoshwa.ultrasonic.androidapp.domain.MusicFolder;
import com.thejoshwa.ultrasonic.androidapp.domain.Playlist;
import com.thejoshwa.ultrasonic.androidapp.domain.SearchCritera;
import com.thejoshwa.ultrasonic.androidapp.domain.SearchCriteria;
import com.thejoshwa.ultrasonic.androidapp.domain.SearchResult;
import com.thejoshwa.ultrasonic.androidapp.domain.ServerInfo;
import com.thejoshwa.ultrasonic.androidapp.domain.Share;
@ -110,6 +67,50 @@ import com.thejoshwa.ultrasonic.androidapp.util.FileUtil;
import com.thejoshwa.ultrasonic.androidapp.util.ProgressListener;
import com.thejoshwa.ultrasonic.androidapp.util.Util;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.conn.params.ConnManagerParams;
import org.apache.http.conn.params.ConnPerRouteBean;
import org.apache.http.conn.scheme.PlainSocketFactory;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.scheme.SocketFactory;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
import org.apache.http.message.BasicHeader;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.protocol.ExecutionContext;
import org.apache.http.protocol.HttpContext;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.Reader;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
/**
* @author Sindre Mehus
*/
@ -219,22 +220,16 @@ public class RESTMusicService implements MusicService {
return cachedIndexes;
}
long lastModified = (cachedIndexes == null || refresh) ? 0L : cachedIndexes.getLastModified();
List<String> parameterNames = new ArrayList<String>();
List<Object> parameterValues = new ArrayList<Object>();
if(lastModified != 0L) {
parameterNames.add("ifModifiedSince");
parameterValues.add(lastModified);
}
if (musicFolderId != null) {
parameterNames.add("musicFolderId");
parameterValues.add(musicFolderId);
}
Reader reader = getReader(context, progressListener, "getIndexes", null, parameterNames, parameterValues);
try {
Indexes indexes = new IndexesParser(context).parse(reader, progressListener);
if (indexes != null) {
@ -416,7 +411,7 @@ public class RESTMusicService implements MusicService {
}
@Override
public SearchResult search(SearchCritera critera, Context context, ProgressListener progressListener) throws Exception {
public SearchResult search(SearchCriteria critera, Context context, ProgressListener progressListener) throws Exception {
try {
if (!Util.isOffline(context) && Util.getShouldUseId3Tags(context)) {
return search3(critera, context, progressListener);
@ -432,7 +427,7 @@ public class RESTMusicService implements MusicService {
/**
* Search using the "search" REST method.
*/
private SearchResult searchOld(SearchCritera critera, Context context, ProgressListener progressListener) throws Exception {
private SearchResult searchOld(SearchCriteria critera, Context context, ProgressListener progressListener) throws Exception {
List<String> parameterNames = Arrays.asList("any", "songCount");
List<Object> parameterValues = Arrays.<Object>asList(critera.getQuery(), critera.getSongCount());
Reader reader = getReader(context, progressListener, "search", null, parameterNames, parameterValues);
@ -446,7 +441,7 @@ public class RESTMusicService implements MusicService {
/**
* Search using the "search2" REST method, available in 1.4.0 and later.
*/
private SearchResult search2(SearchCritera critera, Context context, ProgressListener progressListener) throws Exception {
private SearchResult search2(SearchCriteria critera, Context context, ProgressListener progressListener) throws Exception {
checkServerVersion(context, "1.4", "Search2 not supported.");
List<String> parameterNames = Arrays.asList("query", "artistCount", "albumCount", "songCount");
@ -460,7 +455,7 @@ public class RESTMusicService implements MusicService {
}
}
private SearchResult search3(SearchCritera critera, Context context, ProgressListener progressListener) throws Exception {
private SearchResult search3(SearchCriteria critera, Context context, ProgressListener progressListener) throws Exception {
checkServerVersion(context, "1.8", "Searching by ID3 tag not supported.");
List<String> parameterNames = Arrays.asList("query", "artistCount", "albumCount", "songCount");
@ -708,8 +703,7 @@ public class RESTMusicService implements MusicService {
@Override
public Version getLocalVersion(Context context) throws Exception {
PackageInfo packageInfo = context.getPackageManager().getPackageInfo("com.thejoshwa.ultrasonic.androidapp", 0);
return new Version(packageInfo.versionName);
return new Version(Util.getVersionName(context));
}
@Override
@ -736,7 +730,11 @@ public class RESTMusicService implements MusicService {
public Bitmap getCoverArt(Context context, MusicDirectory.Entry entry, int size, boolean saveToFile, boolean highQuality, ProgressListener progressListener) throws Exception {
// Synchronize on the entry so that we don't download concurrently for
// the same song.
synchronized (entry) {
if (entry == null) {
return null;
}
synchronized (entry) {
// Use cached file, if existing.
Bitmap bitmap = FileUtil.getAlbumArtBitmap(context, entry, size, highQuality);
boolean serverScaling = Util.isServerScalingEnabled(context);
@ -771,6 +769,7 @@ public class RESTMusicService implements MusicService {
byte[] bytes = Util.toByteArray(in);
File albumDir = FileUtil.getAlbumDirectory(context, entry);
if (albumDir.exists()) {
OutputStream out = null;
try {
@ -784,6 +783,7 @@ public class RESTMusicService implements MusicService {
// If we aren't allowing server-side scaling, always save the file to disk because it will be unmodified
if (!serverScaling || saveToFile) {
OutputStream out = null;
try {
out = new FileOutputStream(FileUtil.getAlbumArtFile(context, entry));
out.write(bytes);
@ -874,9 +874,11 @@ public class RESTMusicService implements MusicService {
int n = ids.size();
List<String> parameterNames = new ArrayList<String>(n + 1);
parameterNames.add("action");
for (int i = 0; i < n; i++) {
for (String ignored : ids) {
parameterNames.add("id");
}
List<Object> parameterValues = new ArrayList<Object>();
parameterValues.add("set");
parameterValues.addAll(ids);
@ -985,7 +987,7 @@ public class RESTMusicService implements MusicService {
Log.i(TAG, "Using URL " + url);
SharedPreferences prefs = Util.getPreferences(context);
int networkTimeout = Integer.parseInt(prefs.getString(Constants.PREFERENCES_KEY_NETWORK_TIMEOUT, "15000"));
int networkTimeout = Util.getNetworkTimeout(context);
HttpParams newParams = httpClient.getParams();
HttpConnectionParams.setSoTimeout(newParams, networkTimeout);
httpClient.setParams(newParams);

View File

@ -1,17 +0,0 @@
package com.thejoshwa.ultrasonic.androidapp.service;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import com.thejoshwa.ultrasonic.androidapp.service.ssl.TrustStrategy;
public class TrustSelfSignedStrategy implements TrustStrategy {
@Override
public boolean isTrusted(X509Certificate[] chain, String authType)
throws CertificateException {
// TODO Auto-generated method stub
return false;
}
}

View File

@ -41,8 +41,10 @@ public class BookmarkParser extends MusicDirectoryEntryParser {
bookmark.setPosition(getInteger("position"));
bookmark.setUsername(get("username"));
} else if ("entry".equals(name)) {
bookmark.setEntry(parseEntry(null, false, bookmark.getPosition()));
dir.add(bookmark);
if (bookmark != null) {
bookmark.setEntry(parseEntry(null, false, bookmark.getPosition()));
dir.add(bookmark);
}
} else if ("error".equals(name)) {
handleError();
}

View File

@ -53,7 +53,7 @@ public class GenreParser extends AbstractParser {
try {
BufferedReader br = new BufferedReader(reader);
String xml = null;
String line = null;
String line;
while ((line = br.readLine()) != null) {
if (xml == null) {
@ -63,19 +63,23 @@ public class GenreParser extends AbstractParser {
}
}
br.close();
// Replace double escaped ampersand (&amp;apos;)
xml = xml.replaceAll("(?:&amp;)(amp;|lt;|gt;|#37;|apos;)", "&$1");
// Replace unescaped ampersand
xml = xml.replaceAll("&(?!amp;|lt;|gt;|#37;|apos;)", "&amp;");
// Replace unescaped percent symbol
// Replace possible unescaped XML characters
// No replacements for <> at this time
xml = xml.replaceAll("%", "&#37;");
xml = xml.replaceAll("'", "&apos;");
if (xml != null) {
// Replace double escaped ampersand (&amp;apos;)
xml = xml.replaceAll("(?:&amp;)(amp;|lt;|gt;|#37;|apos;)", "&$1");
// Replace unescaped ampersand
xml = xml.replaceAll("&(?!amp;|lt;|gt;|#37;|apos;)", "&amp;");
// Replace unescaped percent symbol
xml = xml.replaceAll("%", "&#37;");
// Replace unescaped apostrophe
xml = xml.replaceAll("'", "&apos;");
}
sr = new StringReader(xml);
} catch (IOException ioe) {
Log.e(TAG, "Error parsing Genre XML", ioe);
@ -104,13 +108,12 @@ public class GenreParser extends AbstractParser {
}
} else if (eventType == XmlPullParser.TEXT) {
if (genre != null) {
String value = getText();
if (genre != null) {
genre.setName(value);
genre.setIndex(value.substring(0, 1));
result.add(genre);
genre = null;
}
String value = getText();
genre.setName(value);
genre.setIndex(value.substring(0, 1));
result.add(genre);
genre = null;
}
}
} while (eventType != XmlPullParser.END_DOCUMENT);

View File

@ -44,7 +44,9 @@ public class ShareParser extends MusicDirectoryEntryParser {
share.setUsername(get("username"));
share.setVisitCount(getLong("visitCount"));
} else if ("entry".equals(name)) {
share.addEntry(parseEntry(null, false, 0));
if (share != null) {
share.addEntry(parseEntry(null, false, 0));
}
} else if ("error".equals(name)) {
handleError();
}

View File

@ -31,13 +31,22 @@ import org.apache.http.conn.ConnectTimeoutException;
import org.apache.http.conn.scheme.HostNameResolver;
import org.apache.http.conn.scheme.LayeredSocketFactory;
import org.apache.http.conn.ssl.AllowAllHostnameVerifier;
import org.apache.http.conn.ssl.BrowserCompatHostnameVerifier;
import org.apache.http.conn.ssl.StrictHostnameVerifier;
import org.apache.http.conn.ssl.X509HostnameVerifier;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import javax.net.ssl.HttpsURLConnection;
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketTimeoutException;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.UnrecoverableKeyException;
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
@ -46,19 +55,6 @@ import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.UnrecoverableKeyException;
/**
* Layered socket factory for TLS/SSL connections.
* <p>
@ -142,255 +138,116 @@ import java.security.UnrecoverableKeyException;
public class SSLSocketFactory implements LayeredSocketFactory {
public static final String TLS = "TLS";
public static final String SSL = "SSL";
public static final String SSLV2 = "SSLv2";
public static final X509HostnameVerifier ALLOW_ALL_HOSTNAME_VERIFIER
= new AllowAllHostnameVerifier();
public static final X509HostnameVerifier BROWSER_COMPATIBLE_HOSTNAME_VERIFIER
= new BrowserCompatHostnameVerifier();
public static final X509HostnameVerifier STRICT_HOSTNAME_VERIFIER
= new StrictHostnameVerifier();
public static final X509HostnameVerifier ALLOW_ALL_HOSTNAME_VERIFIER = new AllowAllHostnameVerifier();
/**
* The default factory using the default JVM settings for secure connections.
*/
private static final SSLSocketFactory DEFAULT_FACTORY = new SSLSocketFactory();
/**
* Gets the default factory, which uses the default JVM settings for secure
* connections.
*
* @return the default factory
*/
public static SSLSocketFactory getSocketFactory() {
return DEFAULT_FACTORY;
}
private final javax.net.ssl.SSLSocketFactory socketfactory;
private final javax.net.ssl.SSLSocketFactory socketFactory;
private final HostNameResolver nameResolver;
// TODO: make final
private volatile X509HostnameVerifier hostnameVerifier;
private static SSLContext createSSLContext(
String algorithm,
final KeyStore keystore,
final String keystorePassword,
final KeyStore truststore,
final SecureRandom random,
final TrustStrategy trustStrategy)
throws NoSuchAlgorithmException, KeyStoreException, UnrecoverableKeyException, KeyManagementException {
private static SSLContext createSSLContext(String algorithm, final KeyStore keystore, final String keyStorePassword, final SecureRandom random, final TrustStrategy trustStrategy) throws NoSuchAlgorithmException, KeyStoreException, UnrecoverableKeyException, KeyManagementException {
if (algorithm == null) {
algorithm = TLS;
}
KeyManagerFactory kmfactory = KeyManagerFactory.getInstance(
KeyManagerFactory.getDefaultAlgorithm());
kmfactory.init(keystore, keystorePassword != null ? keystorePassword.toCharArray(): null);
KeyManager[] keymanagers = kmfactory.getKeyManagers();
TrustManagerFactory tmfactory = TrustManagerFactory.getInstance(
TrustManagerFactory.getDefaultAlgorithm());
tmfactory.init(keystore);
TrustManager[] trustmanagers = tmfactory.getTrustManagers();
if (trustmanagers != null && trustStrategy != null) {
for (int i = 0; i < trustmanagers.length; i++) {
TrustManager tm = trustmanagers[i];
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyManagerFactory.init(keystore, keyStorePassword != null ? keyStorePassword.toCharArray() : null);
KeyManager[] keyManagers = keyManagerFactory.getKeyManagers();
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(keystore);
TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
if (trustManagers != null && trustStrategy != null) {
for (int i = 0; i < trustManagers.length; i++) {
TrustManager tm = trustManagers[i];
if (tm instanceof X509TrustManager) {
trustmanagers[i] = new TrustManagerDecorator(
(X509TrustManager) tm, trustStrategy);
trustManagers[i] = new TrustManagerDecorator((X509TrustManager) tm, trustStrategy);
}
}
}
SSLContext sslcontext = SSLContext.getInstance(algorithm);
sslcontext.init(keymanagers, trustmanagers, random);
sslcontext.init(keyManagers, trustManagers, random);
return sslcontext;
}
/**
* @deprecated Use {@link #SSLSocketFactory(String, KeyStore, String, KeyStore, SecureRandom, X509HostnameVerifier)}
* @since 4.1
*/
@Deprecated
public SSLSocketFactory(
final String algorithm,
final KeyStore keystore,
final String keystorePassword,
final KeyStore truststore,
final SecureRandom random,
final HostNameResolver nameResolver)
throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException {
this(createSSLContext(
algorithm, keystore, keystorePassword, truststore, random, null),
nameResolver);
public SSLSocketFactory(String algorithm, final KeyStore keystore, final String keyStorePassword, final SecureRandom random, final TrustStrategy trustStrategy, final X509HostnameVerifier hostnameVerifier) throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException {
this(createSSLContext(algorithm, keystore, keyStorePassword, random, trustStrategy), hostnameVerifier);
}
/**
* @since 4.1
*/
public SSLSocketFactory(
String algorithm,
final KeyStore keystore,
final String keystorePassword,
final KeyStore truststore,
final SecureRandom random,
final X509HostnameVerifier hostnameVerifier)
throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException {
this(createSSLContext(
algorithm, keystore, keystorePassword, truststore, random, null),
hostnameVerifier);
public SSLSocketFactory(final TrustStrategy trustStrategy, final X509HostnameVerifier hostnameVerifier) throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException {
this(TLS, null, null, null, trustStrategy, hostnameVerifier);
}
/**
* @since 4.1
*/
public SSLSocketFactory(
String algorithm,
final KeyStore keystore,
final String keystorePassword,
final KeyStore truststore,
final SecureRandom random,
final TrustStrategy trustStrategy,
final X509HostnameVerifier hostnameVerifier)
throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException {
this(createSSLContext(
algorithm, keystore, keystorePassword, truststore, random, trustStrategy),
hostnameVerifier);
}
public SSLSocketFactory(
final KeyStore keystore,
final String keystorePassword,
final KeyStore truststore)
throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException {
this(TLS, keystore, keystorePassword, truststore, null, null, BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
}
public SSLSocketFactory(
final KeyStore keystore,
final String keystorePassword)
throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException{
this(TLS, keystore, keystorePassword, null, null, null, BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
}
public SSLSocketFactory(
final KeyStore truststore)
throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException {
this(TLS, null, null, truststore, null, null, BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
}
/**
* @since 4.1
*/
public SSLSocketFactory(
final TrustStrategy trustStrategy,
final X509HostnameVerifier hostnameVerifier)
throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException {
this(TLS, null, null, null, null, trustStrategy, hostnameVerifier);
}
/**
* @since 4.1
*/
public SSLSocketFactory(
final TrustStrategy trustStrategy)
throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException {
this(TLS, null, null, null, null, trustStrategy, BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
}
public SSLSocketFactory(final SSLContext sslContext) {
this(sslContext, BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
}
/**
* @deprecated Use {@link #SSLSocketFactory(SSLContext)}
*/
@Deprecated
public SSLSocketFactory(
final SSLContext sslContext, final HostNameResolver nameResolver) {
public SSLSocketFactory(final SSLContext sslContext, final X509HostnameVerifier hostnameVerifier) {
super();
this.socketfactory = sslContext.getSocketFactory();
this.hostnameVerifier = BROWSER_COMPATIBLE_HOSTNAME_VERIFIER;
this.nameResolver = nameResolver;
}
/**
* @since 4.1
*/
public SSLSocketFactory(
final SSLContext sslContext, final X509HostnameVerifier hostnameVerifier) {
super();
this.socketfactory = sslContext.getSocketFactory();
this.socketFactory = sslContext.getSocketFactory();
this.hostnameVerifier = hostnameVerifier;
this.nameResolver = null;
}
private SSLSocketFactory() {
super();
this.socketfactory = HttpsURLConnection.getDefaultSSLSocketFactory();
this.hostnameVerifier = null;
this.nameResolver = null;
}
/**
* @param params Optional parameters. Parameters passed to this method will have no effect.
* This method will create a unconnected instance of {@link Socket} class
* using {@link javax.net.ssl.SSLSocketFactory#createSocket()} method.
* @since 4.1
*/
@SuppressWarnings("cast")
public Socket createSocket(final HttpParams params) throws IOException {
// the cast makes sure that the factory is working as expected
return (SSLSocket) this.socketfactory.createSocket();
}
@SuppressWarnings("cast")
public Socket createSocket() throws IOException {
// the cast makes sure that the factory is working as expected
return (SSLSocket) this.socketfactory.createSocket();
return this.socketFactory.createSocket();
}
/**
* @since 4.1
*/
public Socket connectSocket(
final Socket sock,
final InetSocketAddress remoteAddress,
final InetSocketAddress localAddress,
final HttpParams params) throws IOException, UnknownHostException, ConnectTimeoutException {
public Socket connectSocket(final Socket sock, final InetSocketAddress remoteAddress, final InetSocketAddress localAddress, final HttpParams params) throws IOException {
if (remoteAddress == null) {
throw new IllegalArgumentException("Remote address may not be null");
}
if (params == null) {
throw new IllegalArgumentException("HTTP parameters may not be null");
}
SSLSocket sslsock = (SSLSocket) (sock != null ? sock : createSocket());
SSLSocket sslSocket = (SSLSocket) (sock != null ? sock : createSocket());
if (localAddress != null) {
// sslsock.setReuseAddress(HttpConnectionParams.getSoReuseaddr(params));
sslsock.bind(localAddress);
// sslSocket.setReuseAddress(HttpConnectionParams.getSoReuseaddr(params));
sslSocket.bind(localAddress);
}
int connTimeout = HttpConnectionParams.getConnectionTimeout(params);
int soTimeout = HttpConnectionParams.getSoTimeout(params);
try {
sslsock.connect(remoteAddress, connTimeout);
sslSocket.connect(remoteAddress, connTimeout);
} catch (SocketTimeoutException ex) {
throw new ConnectTimeoutException("Connect to " + remoteAddress.getHostName() + "/"
+ remoteAddress.getAddress() + " timed out");
throw new ConnectTimeoutException("Connect to " + remoteAddress.getHostName() + "/" + remoteAddress.getAddress() + " timed out");
}
sslsock.setSoTimeout(soTimeout);
sslSocket.setSoTimeout(soTimeout);
if (this.hostnameVerifier != null) {
try {
this.hostnameVerifier.verify(remoteAddress.getHostName(), sslsock);
this.hostnameVerifier.verify(remoteAddress.getHostName(), sslSocket);
// verifyHostName() didn't blowup - good!
} catch (IOException iox) {
// close the socket before re-throwing the exception
try { sslsock.close(); } catch (Exception x) { /*ignore*/ }
try { sslSocket.close(); } catch (Exception x) { /*ignore*/ }
throw iox;
}
}
return sslsock;
return sslSocket;
}
@ -412,74 +269,60 @@ public class SSLSocketFactory implements LayeredSocketFactory {
if (sock == null) {
throw new IllegalArgumentException("Socket may not be null");
}
// This instanceof check is in line with createSocket() above.
if (!(sock instanceof SSLSocket)) {
throw new IllegalArgumentException("Socket not created by this factory");
}
// This check is performed last since it calls the argument object.
if (sock.isClosed()) {
throw new IllegalArgumentException("Socket is closed");
}
return true;
}
/**
* @since 4.1
*/
public Socket createLayeredSocket(
final Socket socket,
final String host,
final int port,
final boolean autoClose) throws IOException, UnknownHostException {
SSLSocket sslSocket = (SSLSocket) this.socketfactory.createSocket(
socket,
host,
port,
autoClose
);
public Socket createLayeredSocket(final Socket socket, final String host, final int port, final boolean autoClose) throws IOException {
SSLSocket sslSocket = (SSLSocket) this.socketFactory.createSocket(socket, host, port, autoClose);
if (this.hostnameVerifier != null) {
this.hostnameVerifier.verify(host, sslSocket);
}
// verifyHostName() didn't blowup - good!
return sslSocket;
}
@Deprecated
public void setHostnameVerifier(X509HostnameVerifier hostnameVerifier) {
if ( hostnameVerifier == null ) {
throw new IllegalArgumentException("Hostname verifier may not be null");
}
this.hostnameVerifier = hostnameVerifier;
}
public X509HostnameVerifier getHostnameVerifier() {
return this.hostnameVerifier;
}
/**
* @deprecated Use {@link #connectSocket(Socket, InetSocketAddress, InetSocketAddress, HttpParams)}
*/
@Deprecated
public Socket connectSocket(
final Socket socket,
final String host, int port,
final InetAddress localAddress, int localPort,
final HttpParams params) throws IOException, UnknownHostException, ConnectTimeoutException {
public Socket connectSocket(final Socket socket, final String host, int port, final InetAddress localAddress, int localPort, final HttpParams params) throws IOException {
InetSocketAddress local = null;
if (localAddress != null || localPort > 0) {
// we need to bind explicitly
if (localPort < 0) {
localPort = 0; // indicates "any"
}
local = new InetSocketAddress(localAddress, localPort);
}
InetAddress remoteAddress;
if (this.nameResolver != null) {
remoteAddress = this.nameResolver.resolve(host);
} else {
remoteAddress = InetAddress.getByName(host);
}
InetSocketAddress remote = new InetSocketAddress(remoteAddress, port);
return connectSocket(socket, remote, local, params);
}
@ -487,11 +330,7 @@ public class SSLSocketFactory implements LayeredSocketFactory {
* @deprecated Use {@link #createLayeredSocket(Socket, String, int, boolean)}
*/
@Deprecated
public Socket createSocket(
final Socket socket,
final String host, int port,
boolean autoClose) throws IOException, UnknownHostException {
public Socket createSocket(final Socket socket, final String host, int port, boolean autoClose) throws IOException {
return createLayeredSocket(socket, host, port, autoClose);
}
}
}

View File

@ -31,7 +31,6 @@ import java.security.cert.X509Certificate;
import javax.net.ssl.X509TrustManager;
/**
* @since 4.1
*/
@ -46,13 +45,11 @@ class TrustManagerDecorator implements X509TrustManager {
this.trustStrategy = trustStrategy;
}
public void checkClientTrusted(
final X509Certificate[] chain, final String authType) throws CertificateException {
public void checkClientTrusted(final X509Certificate[] chain, final String authType) throws CertificateException {
this.trustManager.checkClientTrusted(chain, authType);
}
public void checkServerTrusted(
final X509Certificate[] chain, final String authType) throws CertificateException {
public void checkServerTrusted(final X509Certificate[] chain, final String authType) throws CertificateException {
if (!this.trustStrategy.isTrusted(chain, authType)) {
this.trustManager.checkServerTrusted(chain, authType);
}
@ -61,5 +58,4 @@ class TrustManagerDecorator implements X509TrustManager {
public X509Certificate[] getAcceptedIssuers() {
return this.trustManager.getAcceptedIssuers();
}
}

View File

@ -0,0 +1,85 @@
package com.thejoshwa.ultrasonic.androidapp.util;
import android.content.Context;
import com.thejoshwa.ultrasonic.androidapp.domain.MusicDirectory;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class AlbumHeader {
private boolean isAllVideo;
private long totalDuration;
private Set<String> artists;
private Set<String> grandParents;
private Set<String> genres;
public boolean getIsAllVideo() {
return isAllVideo;
}
public long getTotalDuration() {
return totalDuration;
}
public Set<String> getArtists () {
return artists;
}
public Set<String> getGrandParents () {
return this.grandParents;
}
public Set<String> getGenres () {
return this.genres;
}
public AlbumHeader() {
this.artists = new HashSet<String>();
this.grandParents = new HashSet<String>();
this.genres = new HashSet<String>();
this.isAllVideo = true;
this.totalDuration = 0;
}
public static AlbumHeader processEntries(Context context, List<MusicDirectory.Entry> entries) {
AlbumHeader albumHeader = new AlbumHeader();
for (MusicDirectory.Entry entry : entries) {
if (!entry.isVideo()) {
albumHeader.isAllVideo = false;
}
if (!entry.isDirectory()) {
if (Util.shouldUseFolderForArtistName(context)) {
albumHeader.processGrandParents(entry);
}
if (entry.getArtist() != null) {
Integer duration = entry.getDuration();
if (duration != null) {
albumHeader.totalDuration += duration;
}
albumHeader.artists.add(entry.getArtist());
}
if (entry.getGenre() != null) {
albumHeader.genres.add(entry.getGenre());
}
}
}
return albumHeader;
}
private void processGrandParents(MusicDirectory.Entry entry) {
String grandParent = Util.getGrandparent(entry.getPath());
if (grandParent != null) {
this.grandParents.add(grandParent);
}
}
}

View File

@ -54,16 +54,18 @@ public class CacheCleaner {
}
File[] children = dir.listFiles();
// No songs left in the folder
if(children.length == 1 && children[0].getPath().equals(FileUtil.getAlbumArtFile(dir).getPath())) {
Util.delete(FileUtil.getAlbumArtFile(dir));
children = dir.listFiles();
}
// Delete empty directory
if (children.length == 0) {
Util.delete(dir);
if (children != null) {
// No songs left in the folder
if (children.length == 1 && children[0].getPath().equals(FileUtil.getAlbumArtFile(dir).getPath())) {
Util.delete(FileUtil.getAlbumArtFile(dir));
children = dir.listFiles();
}
// Delete empty directory
if (children != null && children.length == 0) {
Util.delete(dir);
}
}
}
}

View File

@ -38,7 +38,6 @@ public final class Constants {
public static final String INTENT_EXTRA_NAME_ARTIST = "subsonic.artist";
public static final String INTENT_EXTRA_NAME_TITLE = "subsonic.title";
public static final String INTENT_EXTRA_NAME_AUTOPLAY = "subsonic.playall";
public static final String INTENT_EXTRA_NAME_ERROR = "subsonic.error";
public static final String INTENT_EXTRA_NAME_QUERY = "subsonic.query";
public static final String INTENT_EXTRA_NAME_PLAYLIST_ID = "subsonic.playlist.id";
public static final String INTENT_EXTRA_NAME_PLAYLIST_NAME = "subsonic.playlist.name";
@ -58,7 +57,6 @@ public final class Constants {
// Notification IDs.
public static final int NOTIFICATION_ID_PLAYING = 100;
public static final int NOTIFICATION_ID_ERROR = 101;
// Preferences keys.
public static final String PREFERENCES_KEY_SERVER = "server";
@ -93,9 +91,6 @@ public final class Constants {
public static final String PREFERENCES_KEY_SERVER_SCALING = "serverScaling";
public static final String PREFERENCES_KEY_REPEAT_MODE = "repeatMode";
public static final String PREFERENCES_KEY_WIFI_REQUIRED_FOR_DOWNLOAD = "wifiRequiredForDownload";
public static final String PREFERENCES_KEY_SHUFFLE_START_YEAR = "startYear";
public static final String PREFERENCES_KEY_SHUFFLE_END_YEAR = "endYear";
public static final String PREFERENCES_KEY_SHUFFLE_GENRE = "genre";
public static final String PREFERENCES_KEY_BUFFER_LENGTH = "bufferLength";
public static final String PREFERENCES_KEY_NETWORK_TIMEOUT = "networkTimeout";
public static final String PREFERENCES_KEY_SHOW_NOTIFICATION = "showNotification";
@ -107,14 +102,11 @@ public final class Constants {
public static final String PREFERENCES_KEY_DEFAULT_ALBUMS = "defaultAlbums";
public static final String PREFERENCES_KEY_DEFAULT_SONGS = "defaultSongs";
public static final String PREFERENCES_KEY_DEFAULT_ARTISTS = "defaultArtists";
public static final String PREFERENCES_KEY_USE_STREAM_PROXY = "useStreamProxy";
public static final String PREFERENCES_KEY_SHOW_NOW_PLAYING = "showNowPlaying";
public static final String PREFERENCES_KEY_GAPLESS_PLAYBACK = "gaplessPlayback";
public static final String PREFERENCES_KEY_CLEAR_SEARCH_HISTORY = "clearSearchHistory";
public static final String PREFERENCES_KEY_TEST_CONNECTION = "testConnection";
public static final String PREFERENCES_EQUALIZER_ON = "equalizerOn";
public static final String PREFERENCES_EQUALIZER_SETTINGS = "equalizerSettings";
public static final String PREFERENCES_KEY_DOWNLOAD_TRANSITION = "transitionToDownloadOnPlay";
public static final String PREFERENCES_KEY_DOWNLOAD_TRANSITION = "transitionToDownloadOnPlay";
public static final String PREFERENCES_KEY_INCREMENT_TIME = "incrementTime";
public static final String PREFERENCES_KEY_ID3_TAGS = "useId3Tags";
public static final String PREFERENCES_KEY_TEMP_LOSS = "tempLoss";

View File

@ -0,0 +1,24 @@
package com.thejoshwa.ultrasonic.androidapp.util;
import com.thejoshwa.ultrasonic.androidapp.domain.MusicDirectory;
import java.util.Comparator;
public class EntryByDiscAndTrackComparator implements Comparator<MusicDirectory.Entry> {
@Override
public int compare(MusicDirectory.Entry x, MusicDirectory.Entry y) {
Integer discX = x.getDiscNumber();
Integer discY = y.getDiscNumber();
Integer trackX = x.getTrack();
Integer trackY = y.getTrack();
int startComparison = compare(discX == null ? 0 : discX, discY == null ? 0 : discY);
return startComparison != 0 ? startComparison : compare(trackX == null ? 0 : trackX, trackY == null ? 0 : trackY);
}
private int compare(long a, long b) {
return a < b ? -1
: a > b ? 1
: 0;
}
}

View File

@ -52,25 +52,6 @@ public class FileUtil {
private static final List<String> PLAYLIST_FILE_EXTENSIONS = Arrays.asList("m3u");
private static final File DEFAULT_MUSIC_DIR = createDirectory("music");
public static File getAnySong(Context context) {
File dir = getMusicDirectory(context);
return getAnySong(context, dir);
}
private static File getAnySong(Context context, File dir) {
for(File file: dir.listFiles()) {
if(file.isDirectory()) {
return getAnySong(context, file);
}
String extension = getExtension(file.getName());
if(MUSIC_FILE_EXTENSIONS.contains(extension)) {
return file;
}
}
return null;
}
public static File getSongFile(Context context, MusicDirectory.Entry song) {
File dir = getAlbumDirectory(context, song);
@ -98,13 +79,8 @@ public class FileUtil {
File playlistDir = getPlaylistDirectory();
return new File(playlistDir, fileSystemSafe(name) + ".m3u");
}
public static File getOldPlaylistFile(String name) {
File playlistDir = getPlaylistDirectory();
return new File(playlistDir, name);
}
public static File getPlaylistDirectory() {
public static File getPlaylistDirectory() {
File playlistDir = new File(getUltraSonicDirectory(), "playlists");
ensureDirectoryExistsAndIsReadWritable(playlistDir);
return playlistDir;
@ -154,22 +130,9 @@ public class FileUtil {
return null;
}
public static Bitmap scaleDownBitmap(Bitmap photo, int newHeight, Context context) {
final float densityMultiplier = context.getResources().getDisplayMetrics().density;
int h= (int) (newHeight*densityMultiplier);
int w= (int) (h * photo.getWidth()/((double) photo.getHeight()));
photo=Bitmap.createScaledBitmap(photo, w, h, true);
return photo;
}
public static File getArtistDirectory(Context context, Artist artist) {
File dir = new File(getMusicDirectory(context).getPath() + "/" + fileSystemSafe(artist.getName()));
return dir;
public static File getArtistDirectory(Context context, Artist artist) {
return new File(getMusicDirectory(context).getPath() + "/" + fileSystemSafe(artist.getName()));
}
public static File getAlbumArtDirectory() {
@ -180,7 +143,12 @@ public class FileUtil {
}
public static File getAlbumDirectory(Context context, MusicDirectory.Entry entry) {
if (entry == null) {
return null;
}
File dir;
if (entry.getPath() != null) {
File f = new File(fileSystemSafeDir(entry.getPath()));
dir = new File(getMusicDirectory(context).getPath() + "/" + (entry.isDirectory() ? f.getPath() : f.getParent()));
@ -192,6 +160,7 @@ public class FileUtil {
}
dir = new File(getMusicDirectory(context).getPath() + "/" + artist + "/" + album);
}
return dir;
}
@ -324,17 +293,7 @@ public class FileUtil {
return MUSIC_FILE_EXTENSIONS.contains(extension) || VIDEO_FILE_EXTENSIONS.contains(extension);
}
public static boolean isMusicFile(File file) {
String extension = getExtension(file.getName());
return MUSIC_FILE_EXTENSIONS.contains(extension);
}
public static boolean isVideoFile(File file) {
String extension = getExtension(file.getName());
return VIDEO_FILE_EXTENSIONS.contains(extension);
}
public static boolean isPlaylistFile(File file) {
public static boolean isPlaylistFile(File file) {
String extension = getExtension(file.getName());
return PLAYLIST_FILE_EXTENSIONS.contains(extension);
}
@ -362,19 +321,6 @@ public class FileUtil {
int index = name.lastIndexOf('.');
return index == -1 ? name : name.substring(0, index);
}
public static long getUsedSize(Context context, File file) {
long size = 0L;
if(file.isFile()) {
return file.length();
} else {
for (File child : FileUtil.listFiles(file)) {
size += getUsedSize(context, child);
}
return size;
}
}
public static <T extends Serializable> boolean serialize(Context context, T obj, String fileName) {
File file = new File(context.getCacheDir(), fileName);

View File

@ -19,6 +19,7 @@
package com.thejoshwa.ultrasonic.androidapp.util;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
@ -60,10 +61,13 @@ public class ImageLoader implements Runnable {
this.context = context;
queue = new LinkedBlockingQueue<Task>(500);
Resources resources = context.getResources();
Drawable drawable = resources.getDrawable(R.drawable.unknown_album);
// Determine the density-dependent image sizes.
imageSizeDefault = context.getResources().getDrawable(R.drawable.unknown_album).getIntrinsicHeight();
imageSizeDefault = drawable.getIntrinsicHeight();
DisplayMetrics metrics = context.getResources().getDisplayMetrics();
imageSizeLarge = (int) Math.round(Math.min(metrics.widthPixels, metrics.heightPixels));
imageSizeLarge = Math.round(Math.min(metrics.widthPixels, metrics.heightPixels));
for (int i = 0; i < CONCURRENCY; i++) {
new Thread(this, "ImageLoader").start();
@ -75,10 +79,13 @@ public class ImageLoader implements Runnable {
private void createLargeUnknownImage(Context context) {
BitmapDrawable drawable = (BitmapDrawable) context.getResources().getDrawable(R.drawable.unknown_album_large);
Log.i(TAG, "createLargeUnknownImage");
largeUnknownImage = Util.scaleBitmap(drawable.getBitmap(), imageSizeLarge);
if (drawable != null) {
largeUnknownImage = Util.scaleBitmap(drawable.getBitmap(), imageSizeLarge);
}
}
public void loadImage(View view, MusicDirectory.Entry entry, boolean large, int size, boolean crossfade, boolean highQuality) {
public void loadImage(View view, MusicDirectory.Entry entry, boolean large, int size, boolean crossFade, boolean highQuality) {
if (entry == null) {
setUnknownImage(view, large);
return;
@ -106,18 +113,18 @@ public class ImageLoader implements Runnable {
setUnknownImage(view, large);
}
queue.offer(new Task(view, entry, size, large, large, crossfade, highQuality));
queue.offer(new Task(view, entry, size, large, crossFade, highQuality));
}
private String getKey(String coverArtId, int size) {
return coverArtId + size;
}
private void setImageBitmap(View view, Bitmap bitmap, boolean crossfade) {
private void setImageBitmap(View view, Bitmap bitmap, boolean crossFade) {
if (view instanceof ImageView) {
ImageView imageView = (ImageView) view;
if (crossfade) {
if (crossFade) {
Drawable existingDrawable = imageView.getDrawable();
Drawable newDrawable = Util.createDrawableFromBitmap(this.context, bitmap);
@ -174,12 +181,12 @@ public class ImageLoader implements Runnable {
private final boolean crossfade;
private final boolean highQuality;
public Task(View view, MusicDirectory.Entry entry, int size, boolean reflection, boolean saveToFile, boolean crossfade, boolean highQuality) {
public Task(View view, MusicDirectory.Entry entry, int size, boolean saveToFile, boolean crossFade, boolean highQuality) {
this.view = view;
this.entry = entry;
this.size = size;
this.saveToFile = saveToFile;
this.crossfade = crossfade;
this.crossfade = crossFade;
this.highQuality = highQuality;
handler = new Handler();
}

View File

@ -22,8 +22,6 @@ import java.lang.ref.SoftReference;
import java.util.HashMap;
import java.util.Map;
import android.graphics.drawable.Drawable;
/**
* @author Sindre Mehus
*/
@ -100,16 +98,4 @@ public class LRUCache<K,V>{
timestamp = System.currentTimeMillis();
}
}
protected int sizeOf(String key, Drawable drawable) {
// TODO Auto-generated method stub
return 0;
}
protected void entryRemoved(boolean evicted, String key,
Drawable oldDrawable, Drawable newDrawable) {
// TODO Auto-generated method stub
}
}

View File

@ -39,6 +39,7 @@ import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.wifi.WifiManager;
import android.os.Environment;
import android.os.Parcelable;
import android.preference.PreferenceManager;
import android.util.DisplayMetrics;
import android.util.Log;
@ -104,7 +105,7 @@ public class Util extends DownloadActivity {
public static final String CM_AVRCP_PLAYSTATE_CHANGED = "com.android.music.playstatechanged";
public static final String CM_AVRCP_METADATA_CHANGED = "com.android.music.metachanged";
public final static int albumArtImageSize = 300;
//public final static int albumArtImageSize = 300;
private static boolean hasFocus = false;
private static boolean pauseFocus = false;
@ -116,32 +117,29 @@ public class Util extends DownloadActivity {
private static final char[] HEX_DIGITS = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
private static Toast toast;
public static Bitmap albumArtBitmap;
//public static Bitmap albumArtBitmap;
private static Entry currentSong;
private Util() {
}
public static boolean isOffline(Context context) {
if (context == null)
return false;
else
return getActiveServer(context) == 0;
return context != null && getActiveServer(context) == 0;
}
public static boolean isScreenLitOnDownload(Context context) {
SharedPreferences prefs = getPreferences(context);
return prefs.getBoolean(Constants.PREFERENCES_KEY_SCREEN_LIT_ON_DOWNLOAD, false);
SharedPreferences preferences = getPreferences(context);
return preferences.getBoolean(Constants.PREFERENCES_KEY_SCREEN_LIT_ON_DOWNLOAD, false);
}
public static RepeatMode getRepeatMode(Context context) {
SharedPreferences prefs = getPreferences(context);
return RepeatMode.valueOf(prefs.getString(Constants.PREFERENCES_KEY_REPEAT_MODE, RepeatMode.OFF.name()));
SharedPreferences preferences = getPreferences(context);
return RepeatMode.valueOf(preferences.getString(Constants.PREFERENCES_KEY_REPEAT_MODE, RepeatMode.OFF.name()));
}
public static void setRepeatMode(Context context, RepeatMode repeatMode) {
SharedPreferences prefs = getPreferences(context);
SharedPreferences.Editor editor = prefs.edit();
SharedPreferences preferences = getPreferences(context);
SharedPreferences.Editor editor = preferences.edit();
editor.putString(Constants.PREFERENCES_KEY_REPEAT_MODE, repeatMode.name());
editor.commit();
}
@ -150,48 +148,43 @@ public class Util extends DownloadActivity {
if (isOffline(context)) {
return false;
}
SharedPreferences prefs = getPreferences(context);
return prefs.getBoolean(Constants.PREFERENCES_KEY_SCROBBLE, false);
SharedPreferences preferences = getPreferences(context);
return preferences.getBoolean(Constants.PREFERENCES_KEY_SCROBBLE, false);
}
public static boolean isServerScalingEnabled(Context context) {
if (isOffline(context)) {
return false;
}
SharedPreferences prefs = getPreferences(context);
return prefs.getBoolean(Constants.PREFERENCES_KEY_SERVER_SCALING, false);
SharedPreferences preferences = getPreferences(context);
return preferences.getBoolean(Constants.PREFERENCES_KEY_SERVER_SCALING, false);
}
public static boolean isNotificationEnabled(Context context) {
SharedPreferences prefs = getPreferences(context);
return prefs.getBoolean(Constants.PREFERENCES_KEY_SHOW_NOTIFICATION, false);
SharedPreferences preferences = getPreferences(context);
return preferences.getBoolean(Constants.PREFERENCES_KEY_SHOW_NOTIFICATION, false);
}
public static boolean isNotificationAlwaysEnabled(Context context) {
SharedPreferences prefs = getPreferences(context);
return prefs.getBoolean(Constants.PREFERENCES_KEY_ALWAYS_SHOW_NOTIFICATION, false);
SharedPreferences preferences = getPreferences(context);
return preferences.getBoolean(Constants.PREFERENCES_KEY_ALWAYS_SHOW_NOTIFICATION, false);
}
public static boolean isLockScreenEnabled(Context context) {
SharedPreferences prefs = getPreferences(context);
return prefs.getBoolean(Constants.PREFERENCES_KEY_SHOW_LOCK_SCREEN_CONTROLS, false);
}
public static boolean isStreamProxyEnabled(Context context) {
SharedPreferences prefs = getPreferences(context);
return prefs.getBoolean(Constants.PREFERENCES_KEY_USE_STREAM_PROXY, false);
SharedPreferences preferences = getPreferences(context);
return preferences.getBoolean(Constants.PREFERENCES_KEY_SHOW_LOCK_SCREEN_CONTROLS, false);
}
public static void setActiveServer(Context context, int instance) {
SharedPreferences prefs = getPreferences(context);
SharedPreferences.Editor editor = prefs.edit();
SharedPreferences preferences = getPreferences(context);
SharedPreferences.Editor editor = preferences.edit();
editor.putInt(Constants.PREFERENCES_KEY_SERVER_INSTANCE, instance);
editor.commit();
}
public static int getActiveServer(Context context) {
SharedPreferences prefs = getPreferences(context);
return prefs.getInt(Constants.PREFERENCES_KEY_SERVER_INSTANCE, 1);
SharedPreferences preferences = getPreferences(context);
return preferences.getInt(Constants.PREFERENCES_KEY_SERVER_INSTANCE, 1);
}
public static int getActiveServers(Context context) {
@ -203,32 +196,32 @@ public class Util extends DownloadActivity {
if (instance == 0) {
return context.getResources().getString(R.string.main_offline);
}
SharedPreferences prefs = getPreferences(context);
return prefs.getString(Constants.PREFERENCES_KEY_SERVER_NAME + instance, null);
SharedPreferences preferences = getPreferences(context);
return preferences.getString(Constants.PREFERENCES_KEY_SERVER_NAME + instance, null);
}
public static String getUserName(Context context, int instance) {
if (instance == 0) {
return context.getResources().getString(R.string.main_offline);
}
SharedPreferences prefs = getPreferences(context);
return prefs.getString(Constants.PREFERENCES_KEY_USERNAME + instance, null);
SharedPreferences preferences = getPreferences(context);
return preferences.getString(Constants.PREFERENCES_KEY_USERNAME + instance, null);
}
public static boolean getServerEnabled(Context context, int instance) {
if (instance == 0) {
return true;
}
SharedPreferences prefs = getPreferences(context);
return prefs.getBoolean(Constants.PREFERENCES_KEY_SERVER_ENABLED + instance, true);
SharedPreferences preferences = getPreferences(context);
return preferences.getBoolean(Constants.PREFERENCES_KEY_SERVER_ENABLED + instance, true);
}
public static boolean getJukeboxEnabled(Context context, int instance) {
if (instance == 0) {
return false;
}
SharedPreferences prefs = getPreferences(context);
return prefs.getBoolean(Constants.PREFERENCES_KEY_JUKEBOX_BY_DEFAULT + instance, false);
SharedPreferences preferences = getPreferences(context);
return preferences.getBoolean(Constants.PREFERENCES_KEY_JUKEBOX_BY_DEFAULT + instance, false);
}
public static void setServerRestVersion(Context context, Version version) {
@ -240,18 +233,18 @@ public class Util extends DownloadActivity {
}
public static void removeInstanceName(Context context, int instance, int activeInstance) {
SharedPreferences prefs = getPreferences(context);
SharedPreferences.Editor editor = prefs.edit();
SharedPreferences preferences = getPreferences(context);
SharedPreferences.Editor editor = preferences.edit();
int newInstance = instance + 1;
String server = prefs.getString(Constants.PREFERENCES_KEY_SERVER + newInstance, null);
String serverName = prefs.getString(Constants.PREFERENCES_KEY_SERVER_NAME + newInstance, null);
String serverUrl = prefs.getString(Constants.PREFERENCES_KEY_SERVER_URL + newInstance, null);
String userName = prefs.getString(Constants.PREFERENCES_KEY_USERNAME + newInstance, null);
String password = prefs.getString(Constants.PREFERENCES_KEY_PASSWORD + newInstance, null);
boolean serverEnabled = prefs.getBoolean(Constants.PREFERENCES_KEY_SERVER_ENABLED + newInstance, true);
boolean jukeboxEnabled = prefs.getBoolean(Constants.PREFERENCES_KEY_JUKEBOX_BY_DEFAULT + newInstance, true);
String server = preferences.getString(Constants.PREFERENCES_KEY_SERVER + newInstance, null);
String serverName = preferences.getString(Constants.PREFERENCES_KEY_SERVER_NAME + newInstance, null);
String serverUrl = preferences.getString(Constants.PREFERENCES_KEY_SERVER_URL + newInstance, null);
String userName = preferences.getString(Constants.PREFERENCES_KEY_USERNAME + newInstance, null);
String password = preferences.getString(Constants.PREFERENCES_KEY_PASSWORD + newInstance, null);
boolean serverEnabled = preferences.getBoolean(Constants.PREFERENCES_KEY_SERVER_ENABLED + newInstance, true);
boolean jukeboxEnabled = preferences.getBoolean(Constants.PREFERENCES_KEY_JUKEBOX_BY_DEFAULT + newInstance, true);
editor.putString(Constants.PREFERENCES_KEY_SERVER + instance, server);
editor.putString(Constants.PREFERENCES_KEY_SERVER_NAME + instance, serverName);
@ -281,56 +274,58 @@ public class Util extends DownloadActivity {
public static void setSelectedMusicFolderId(Context context, String musicFolderId) {
int instance = getActiveServer(context);
SharedPreferences prefs = getPreferences(context);
SharedPreferences.Editor editor = prefs.edit();
SharedPreferences preferences = getPreferences(context);
SharedPreferences.Editor editor = preferences.edit();
editor.putString(Constants.PREFERENCES_KEY_MUSIC_FOLDER_ID + instance, musicFolderId);
editor.commit();
}
public static String getSelectedMusicFolderId(Context context) {
SharedPreferences prefs = getPreferences(context);
SharedPreferences preferences = getPreferences(context);
int instance = getActiveServer(context);
return prefs.getString(Constants.PREFERENCES_KEY_MUSIC_FOLDER_ID + instance, null);
return preferences.getString(Constants.PREFERENCES_KEY_MUSIC_FOLDER_ID + instance, null);
}
public static String getTheme(Context context) {
SharedPreferences prefs = getPreferences(context);
return prefs.getString(Constants.PREFERENCES_KEY_THEME, "dark");
SharedPreferences preferences = getPreferences(context);
return preferences.getString(Constants.PREFERENCES_KEY_THEME, "dark");
}
public static int getMaxBitrate(Context context) {
public static int getMaxBitRate(Context context) {
ConnectivityManager manager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = manager.getActiveNetworkInfo();
if (networkInfo == null) {
return 0;
}
boolean wifi = networkInfo.getType() == ConnectivityManager.TYPE_WIFI;
SharedPreferences prefs = getPreferences(context);
return Integer.parseInt(prefs.getString(wifi ? Constants.PREFERENCES_KEY_MAX_BITRATE_WIFI : Constants.PREFERENCES_KEY_MAX_BITRATE_MOBILE, "0"));
SharedPreferences preferences = getPreferences(context);
return Integer.parseInt(preferences.getString(wifi ? Constants.PREFERENCES_KEY_MAX_BITRATE_WIFI : Constants.PREFERENCES_KEY_MAX_BITRATE_MOBILE, "0"));
}
public static int getPreloadCount(Context context) {
SharedPreferences prefs = getPreferences(context);
int preloadCount = Integer.parseInt(prefs.getString(Constants.PREFERENCES_KEY_PRELOAD_COUNT, "-1"));
SharedPreferences preferences = getPreferences(context);
int preloadCount = Integer.parseInt(preferences.getString(Constants.PREFERENCES_KEY_PRELOAD_COUNT, "-1"));
return preloadCount == -1 ? Integer.MAX_VALUE : preloadCount;
}
public static int getCacheSizeMB(Context context) {
SharedPreferences prefs = getPreferences(context);
int cacheSize = Integer.parseInt(prefs.getString(Constants.PREFERENCES_KEY_CACHE_SIZE, "-1"));
SharedPreferences preferences = getPreferences(context);
int cacheSize = Integer.parseInt(preferences.getString(Constants.PREFERENCES_KEY_CACHE_SIZE, "-1"));
return cacheSize == -1 ? Integer.MAX_VALUE : cacheSize;
}
public static String getRestUrl(Context context, String method) {
StringBuilder builder = new StringBuilder();
SharedPreferences prefs = getPreferences(context);
SharedPreferences preferences = getPreferences(context);
int instance = prefs.getInt(Constants.PREFERENCES_KEY_SERVER_INSTANCE, 1);
String serverUrl = prefs.getString(Constants.PREFERENCES_KEY_SERVER_URL + instance, null);
String username = prefs.getString(Constants.PREFERENCES_KEY_USERNAME + instance, null);
String password = prefs.getString(Constants.PREFERENCES_KEY_PASSWORD + instance, null);
int instance = preferences.getInt(Constants.PREFERENCES_KEY_SERVER_INSTANCE, 1);
String serverUrl = preferences.getString(Constants.PREFERENCES_KEY_SERVER_URL + instance, null);
String username = preferences.getString(Constants.PREFERENCES_KEY_USERNAME + instance, null);
String password = preferences.getString(Constants.PREFERENCES_KEY_PASSWORD + instance, null);
// Slightly obfuscate password
password = "enc:" + Util.utf8HexEncode(password);
@ -360,12 +355,12 @@ public class Util extends DownloadActivity {
}
public static int getRemainingTrialDays(Context context) {
SharedPreferences prefs = getPreferences(context);
long installTime = prefs.getLong(Constants.PREFERENCES_KEY_INSTALL_TIME, 0L);
SharedPreferences preferences = getPreferences(context);
long installTime = preferences.getLong(Constants.PREFERENCES_KEY_INSTALL_TIME, 0L);
if (installTime == 0L) {
installTime = System.currentTimeMillis();
SharedPreferences.Editor editor = prefs.edit();
SharedPreferences.Editor editor = preferences.edit();
editor.putLong(Constants.PREFERENCES_KEY_INSTALL_TIME, installTime);
editor.commit();
}
@ -398,10 +393,12 @@ public class Util extends DownloadActivity {
byte[] buffer = new byte[1024 * 4];
long count = 0;
int n;
while (-1 != (n = input.read(buffer))) {
output.write(buffer, 0, n);
count += n;
}
return count;
}
@ -409,6 +406,7 @@ public class Util extends DownloadActivity {
FileInputStream in = null;
FileOutputStream out = null;
File tmp = null;
try {
tmp = new File(to.getPath() + ".tmp");
in = new FileInputStream(from);
@ -458,24 +456,6 @@ public class Util extends DownloadActivity {
}
return true;
}
public static boolean recursiveDelete(File dir) {
if (dir != null && dir.exists()) {
for(File file: dir.listFiles()) {
if(file.isDirectory()) {
if(!recursiveDelete(file)) {
return false;
}
} else if(file.exists()) {
if(!file.delete()) {
return false;
}
}
}
return dir.delete();
}
return false;
}
public static void toast(Context context, int messageId) {
toast(context, messageId, true);
@ -587,32 +567,8 @@ public class Util extends DownloadActivity {
return BYTE_LOCALIZED_FORMAT.format((double) byteCount);
}
public static String formatDuration(Integer seconds) {
if (seconds == null) {
return null;
}
int minutes = seconds / 60;
int secs = seconds % 60;
StringBuilder builder = new StringBuilder(6);
builder.append(minutes).append(":");
if (secs < 10) {
builder.append("0");
}
builder.append(secs);
return builder.toString();
}
public static boolean equals(Object object1, Object object2) {
if (object1 == object2) {
return true;
}
if (object1 == null || object2 == null) {
return false;
}
return object1.equals(object2);
return object1 == object2 || !(object1 == null || object2 == null) && object1.equals(object2);
}
/**
@ -625,12 +581,15 @@ public class Util extends DownloadActivity {
if (s == null) {
return null;
}
byte[] utf8;
try {
utf8 = s.getBytes(Constants.UTF_8);
} catch (UnsupportedEncodingException x) {
throw new RuntimeException(x);
}
return hexEncode(utf8);
}
@ -645,11 +604,13 @@ public class Util extends DownloadActivity {
public static String hexEncode(byte[] data) {
int length = data.length;
char[] out = new char[length << 1];
// two characters form the hex value.
for (int i = 0, j = 0; i < length; i++) {
out[j++] = HEX_DIGITS[(0xF0 & data[i]) >>> 4];
out[j++] = HEX_DIGITS[0x0F & data[i]];
}
return new String(out);
}
@ -700,23 +661,23 @@ public class Util extends DownloadActivity {
}
private static boolean isWifiRequiredForDownload(Context context) {
SharedPreferences prefs = getPreferences(context);
return prefs.getBoolean(Constants.PREFERENCES_KEY_WIFI_REQUIRED_FOR_DOWNLOAD, false);
SharedPreferences preferences = getPreferences(context);
return preferences.getBoolean(Constants.PREFERENCES_KEY_WIFI_REQUIRED_FOR_DOWNLOAD, false);
}
public static boolean shouldDisplayBitrateWithArtist(Context context) {
SharedPreferences prefs = getPreferences(context);
return prefs.getBoolean(Constants.PREFERENCES_KEY_DISPLAY_BITRATE_WITH_ARTIST, true);
SharedPreferences preferences = getPreferences(context);
return preferences.getBoolean(Constants.PREFERENCES_KEY_DISPLAY_BITRATE_WITH_ARTIST, true);
}
public static boolean shouldUseFolderForArtistName(Context context) {
SharedPreferences prefs = getPreferences(context);
return prefs.getBoolean(Constants.PREFERENCES_KEY_USE_FOLDER_FOR_ALBUM_ARTIST, false);
SharedPreferences preferences = getPreferences(context);
return preferences.getBoolean(Constants.PREFERENCES_KEY_USE_FOLDER_FOR_ALBUM_ARTIST, false);
}
public static boolean shouldShowTrackNumber(Context context) {
SharedPreferences prefs = getPreferences(context);
return prefs.getBoolean(Constants.PREFERENCES_KEY_SHOW_TRACK_NUMBER, false);
SharedPreferences preferences = getPreferences(context);
return preferences.getBoolean(Constants.PREFERENCES_KEY_SHOW_TRACK_NUMBER, false);
}
public static void info(Context context, int titleId, int messageId) {
@ -770,9 +731,13 @@ public class Util extends DownloadActivity {
public static Drawable getDrawableFromAttribute(Context context, int attr) {
int[] attrs = new int[] { attr };
android.content.res.TypedArray ta = context.obtainStyledAttributes(attrs);
Drawable drawableFromTheme = ta.getDrawable(0);
ta.recycle();
Drawable drawableFromTheme = null;
if (ta != null) {
drawableFromTheme = ta.getDrawable(0);
ta.recycle();
}
return drawableFromTheme;
}
@ -890,9 +855,12 @@ public class Util extends DownloadActivity {
avrcpIntent.putExtra("album_name", "");
if (Util.getShouldSendBluetoothAlbumArt(context)) {
albumArtBitmap = Bitmap.createBitmap(albumArtImageSize, albumArtImageSize, Bitmap.Config.ARGB_8888);
avrcpIntent.putExtra("cover", albumArtBitmap);
avrcpIntent.putExtra("coverart", albumArtBitmap);
avrcpIntent.putExtra("coverart", (Parcelable) null);
avrcpIntent.putExtra("cover", (Parcelable) null);
//albumArtBitmap = Bitmap.createBitmap(albumArtImageSize, albumArtImageSize, Bitmap.Config.ARGB_8888);
//avrcpIntent.putExtra("cover", albumArtBitmap);
//avrcpIntent.putExtra("coverart", albumArtBitmap);
}
avrcpIntent.putExtra("ListSize", (long) 0);
@ -904,7 +872,7 @@ public class Util extends DownloadActivity {
currentSong = song;
if (Util.getShouldSendBluetoothAlbumArt(context)) {
albumArtBitmap = FileUtil.getAlbumArtBitmap(context, song, albumArtImageSize, false);
//albumArtBitmap = FileUtil.getAlbumArtBitmap(context, song, albumArtImageSize, false);
}
}
@ -924,8 +892,12 @@ public class Util extends DownloadActivity {
avrcpIntent.putExtra("album_name", album);
if (Util.getShouldSendBluetoothAlbumArt(context)) {
avrcpIntent.putExtra("cover", albumArtBitmap);
avrcpIntent.putExtra("coverart", albumArtBitmap);
File albumArtFile = FileUtil.getAlbumArtFile(context, song);
avrcpIntent.putExtra("coverart", albumArtFile.getAbsolutePath());
avrcpIntent.putExtra("cover", albumArtFile.getAbsolutePath());
//avrcpIntent.putExtra("cover", albumArtBitmap);
//avrcpIntent.putExtra("coverart", albumArtBitmap);
}
if (playerPosition != null) {
@ -965,7 +937,7 @@ public class Util extends DownloadActivity {
if (song != currentSong) {
currentSong = song;
if (Util.getShouldSendBluetoothAlbumArt(context)) {
albumArtBitmap = FileUtil.getAlbumArtBitmap(context, song, albumArtImageSize, false);
//albumArtBitmap = FileUtil.getAlbumArtBitmap(context, song, albumArtImageSize, false);
}
}
@ -985,8 +957,12 @@ public class Util extends DownloadActivity {
avrcpIntent.putExtra("album_name", album);
if (Util.getShouldSendBluetoothAlbumArt(context)) {
avrcpIntent.putExtra("cover", albumArtBitmap);
avrcpIntent.putExtra("coverart", albumArtBitmap);
File albumArtFile = FileUtil.getAlbumArtFile(context, song);
avrcpIntent.putExtra("coverart", albumArtFile.getAbsolutePath());
avrcpIntent.putExtra("cover", albumArtFile.getAbsolutePath());
//avrcpIntent.putExtra("cover", albumArtBitmap);
//avrcpIntent.putExtra("coverart", albumArtBitmap);
}
if (playerPosition != null) {
@ -1054,10 +1030,10 @@ public class Util extends DownloadActivity {
public static int getNotificationImageSize(Context context) {
DisplayMetrics metrics = context.getResources().getDisplayMetrics();
int imageSizeLarge = (int) Math.round(Math.min(metrics.widthPixels, metrics.heightPixels));
int imageSizeLarge = Math.round(Math.min(metrics.widthPixels, metrics.heightPixels));
int size = 64;
int size;
if (imageSizeLarge <= 480) {
size = 64;
} else if (imageSizeLarge <= 768) {
@ -1071,9 +1047,9 @@ public class Util extends DownloadActivity {
public static int getAlbumImageSize(Context context) {
DisplayMetrics metrics = context.getResources().getDisplayMetrics();
int imageSizeLarge = (int) Math.round(Math.min(metrics.widthPixels, metrics.heightPixels));
int imageSizeLarge = Math.round(Math.min(metrics.widthPixels, metrics.heightPixels));
int size = 128;
int size;
if (imageSizeLarge <= 480) {
size = 128;
@ -1095,8 +1071,8 @@ public class Util extends DownloadActivity {
DownloadServiceImpl downloadService = (DownloadServiceImpl)context;
if((focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT || focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK) && !downloadService.isJukeboxEnabled()) {
if(downloadService.getPlayerState() == PlayerState.STARTED) {
SharedPreferences prefs = getPreferences(context);
int lossPref = Integer.parseInt(prefs.getString(Constants.PREFERENCES_KEY_TEMP_LOSS, "1"));
SharedPreferences preferences = getPreferences(context);
int lossPref = Integer.parseInt(preferences.getString(Constants.PREFERENCES_KEY_TEMP_LOSS, "1"));
if(lossPref == 2 || (lossPref == 1 && focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK)) {
lowerFocus = true;
downloadService.setVolume(0.1f);
@ -1152,21 +1128,6 @@ public class Util extends DownloadActivity {
return inSampleSize;
}
public static Bitmap decodeSampledBitmapFromFile(String path, int reqWidth, int reqHeight) {
// First decode with inJustDecodeBounds=true to check dimensions
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(path, options);
// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
return BitmapFactory.decodeFile(path, options);
}
public static void linkButtons(Context context, RemoteViews views, boolean playerActive) {
Intent intent = new Intent(context, playerActive ? DownloadActivity.class : MainActivity.class);
@ -1199,97 +1160,85 @@ public class Util extends DownloadActivity {
pendingIntent = PendingIntent.getService(context, 0, intent, 0);
views.setOnClickPendingIntent(R.id.control_stop, pendingIntent);
}
public static int getMaxVideoBitrate(Context context) {
ConnectivityManager manager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = manager.getActiveNetworkInfo();
if (networkInfo == null) {
return 0;
}
boolean wifi = networkInfo.getType() == ConnectivityManager.TYPE_WIFI;
SharedPreferences prefs = getPreferences(context);
return Integer.parseInt(prefs.getString(wifi ? Constants.PREFERENCES_KEY_MAX_VIDEO_BITRATE_WIFI : Constants.PREFERENCES_KEY_MAX_VIDEO_BITRATE_MOBILE, "0"));
}
public static int getNetworkTimeout(Context context) {
SharedPreferences prefs = getPreferences(context);
return Integer.parseInt(prefs.getString(Constants.PREFERENCES_KEY_NETWORK_TIMEOUT, "15000"));
SharedPreferences preferences = getPreferences(context);
return Integer.parseInt(preferences.getString(Constants.PREFERENCES_KEY_NETWORK_TIMEOUT, "15000"));
}
public static int getDefaultAlbums(Context context) {
SharedPreferences prefs = getPreferences(context);
return Integer.parseInt(prefs.getString(Constants.PREFERENCES_KEY_DEFAULT_ALBUMS, "5"));
SharedPreferences preferences = getPreferences(context);
return Integer.parseInt(preferences.getString(Constants.PREFERENCES_KEY_DEFAULT_ALBUMS, "5"));
}
public static int getMaxAlbums(Context context) {
SharedPreferences prefs = getPreferences(context);
return Integer.parseInt(prefs.getString(Constants.PREFERENCES_KEY_MAX_ALBUMS, "20"));
SharedPreferences preferences = getPreferences(context);
return Integer.parseInt(preferences.getString(Constants.PREFERENCES_KEY_MAX_ALBUMS, "20"));
}
public static int getDefaultSongs(Context context) {
SharedPreferences prefs = getPreferences(context);
return Integer.parseInt(prefs.getString(Constants.PREFERENCES_KEY_DEFAULT_SONGS, "10"));
SharedPreferences preferences = getPreferences(context);
return Integer.parseInt(preferences.getString(Constants.PREFERENCES_KEY_DEFAULT_SONGS, "10"));
}
public static int getMaxSongs(Context context) {
SharedPreferences prefs = getPreferences(context);
return Integer.parseInt(prefs.getString(Constants.PREFERENCES_KEY_MAX_SONGS, "25"));
SharedPreferences preferences = getPreferences(context);
return Integer.parseInt(preferences.getString(Constants.PREFERENCES_KEY_MAX_SONGS, "25"));
}
public static int getMaxArtists(Context context) {
SharedPreferences prefs = getPreferences(context);
return Integer.parseInt(prefs.getString(Constants.PREFERENCES_KEY_MAX_ARTISTS, "10"));
SharedPreferences preferences = getPreferences(context);
return Integer.parseInt(preferences.getString(Constants.PREFERENCES_KEY_MAX_ARTISTS, "10"));
}
public static int getDefaultArtists(Context context) {
SharedPreferences prefs = getPreferences(context);
return Integer.parseInt(prefs.getString(Constants.PREFERENCES_KEY_DEFAULT_ARTISTS, "3"));
SharedPreferences preferences = getPreferences(context);
return Integer.parseInt(preferences.getString(Constants.PREFERENCES_KEY_DEFAULT_ARTISTS, "3"));
}
public static int getBufferLength(Context context) {
SharedPreferences prefs = getPreferences(context);
return Integer.parseInt(prefs.getString(Constants.PREFERENCES_KEY_BUFFER_LENGTH, "5"));
SharedPreferences preferences = getPreferences(context);
return Integer.parseInt(preferences.getString(Constants.PREFERENCES_KEY_BUFFER_LENGTH, "5"));
}
public static int getIncrementTime(Context context) {
SharedPreferences prefs = getPreferences(context);
return Integer.parseInt(prefs.getString(Constants.PREFERENCES_KEY_INCREMENT_TIME, "5"));
SharedPreferences preferences = getPreferences(context);
return Integer.parseInt(preferences.getString(Constants.PREFERENCES_KEY_INCREMENT_TIME, "5"));
}
public static boolean getMediaButtonsPreference(Context context) {
SharedPreferences prefs = getPreferences(context);
return prefs.getBoolean(Constants.PREFERENCES_KEY_MEDIA_BUTTONS, true);
SharedPreferences preferences = getPreferences(context);
return preferences.getBoolean(Constants.PREFERENCES_KEY_MEDIA_BUTTONS, true);
}
public static boolean getShowNowPlayingPreference(Context context) {
SharedPreferences prefs = getPreferences(context);
return prefs.getBoolean(Constants.PREFERENCES_KEY_SHOW_NOW_PLAYING, true);
SharedPreferences preferences = getPreferences(context);
return preferences.getBoolean(Constants.PREFERENCES_KEY_SHOW_NOW_PLAYING, true);
}
public static boolean getGaplessPlaybackPreference(Context context) {
SharedPreferences prefs = getPreferences(context);
return prefs.getBoolean(Constants.PREFERENCES_KEY_GAPLESS_PLAYBACK, true);
SharedPreferences preferences = getPreferences(context);
return preferences.getBoolean(Constants.PREFERENCES_KEY_GAPLESS_PLAYBACK, true);
}
public static boolean getShouldTransitionOnPlaybackPreference(Context context) {
SharedPreferences prefs = getPreferences(context);
return prefs.getBoolean(Constants.PREFERENCES_KEY_DOWNLOAD_TRANSITION, true);
SharedPreferences preferences = getPreferences(context);
return preferences.getBoolean(Constants.PREFERENCES_KEY_DOWNLOAD_TRANSITION, true);
}
public static boolean getShouldUseId3Tags(Context context) {
SharedPreferences prefs = getPreferences(context);
return prefs.getBoolean(Constants.PREFERENCES_KEY_ID3_TAGS, false);
SharedPreferences preferences = getPreferences(context);
return preferences.getBoolean(Constants.PREFERENCES_KEY_ID3_TAGS, false);
}
public static int getChatRefreshInterval(Context context) {
SharedPreferences prefs = getPreferences(context);
return Integer.parseInt(prefs.getString(Constants.PREFERENCES_KEY_CHAT_REFRESH_INTERVAL, "5000"));
SharedPreferences preferences = getPreferences(context);
return Integer.parseInt(preferences.getString(Constants.PREFERENCES_KEY_CHAT_REFRESH_INTERVAL, "5000"));
}
public static int getDirectoryCacheTime(Context context) {
SharedPreferences prefs = getPreferences(context);
return Integer.parseInt(prefs.getString(Constants.PREFERENCES_KEY_DIRECTORY_CACHE_TIME, "300"));
SharedPreferences preferences = getPreferences(context);
return Integer.parseInt(preferences.getString(Constants.PREFERENCES_KEY_DIRECTORY_CACHE_TIME, "300"));
}
public static boolean isNullOrWhiteSpace(String string) {
@ -1301,18 +1250,18 @@ public class Util extends DownloadActivity {
}
public static boolean getShouldClearPlaylist(Context context) {
SharedPreferences prefs = getPreferences(context);
return prefs.getBoolean(Constants.PREFERENCES_KEY_CLEAR_PLAYLIST, false);
SharedPreferences preferences = getPreferences(context);
return preferences.getBoolean(Constants.PREFERENCES_KEY_CLEAR_PLAYLIST, false);
}
public static boolean getShouldSortByDisc(Context context) {
SharedPreferences prefs = getPreferences(context);
return prefs.getBoolean(Constants.PREFERENCES_KEY_DISC_SORT, false);
SharedPreferences preferences = getPreferences(context);
return preferences.getBoolean(Constants.PREFERENCES_KEY_DISC_SORT, false);
}
public static boolean getShouldClearBookmark(Context context) {
SharedPreferences prefs = getPreferences(context);
return prefs.getBoolean(Constants.PREFERENCES_KEY_CLEAR_BOOKMARK, false);
SharedPreferences preferences = getPreferences(context);
return preferences.getBoolean(Constants.PREFERENCES_KEY_CLEAR_BOOKMARK, false);
}
public static String formatTotalDuration(long totalDuration, boolean inMilliseconds) {
@ -1340,30 +1289,72 @@ public class Util extends DownloadActivity {
}
public static VideoPlayerType getVideoPlayerType(Context context) {
SharedPreferences prefs = getPreferences(context);
return VideoPlayerType.forKey(prefs.getString(Constants.PREFERENCES_KEY_VIDEO_PLAYER, VideoPlayerType.MX.getKey()));
SharedPreferences preferences = getPreferences(context);
return VideoPlayerType.forKey(preferences.getString(Constants.PREFERENCES_KEY_VIDEO_PLAYER, VideoPlayerType.MX.getKey()));
}
public static boolean isPackageInstalled(Context context, String packageName) {
PackageManager pm = context.getPackageManager();
List<ApplicationInfo> packages = pm.getInstalledApplications(0);
for (ApplicationInfo packageInfo : packages) {
if (packageInfo.packageName.equals(packageName)) {
return true;
}
}
return false;
List<ApplicationInfo> packages = null;
if (pm != null) {
packages = pm.getInstalledApplications(0);
}
if (packages != null) {
for (ApplicationInfo packageInfo : packages) {
if (packageInfo.packageName.equals(packageName)) {
return true;
}
}
}
return false;
}
public static String getVersionName(Context context) {
String versionName = null;
PackageManager pm = context.getPackageManager();
if (pm != null) {
String packageName = context.getPackageName();
try {
versionName = pm.getPackageInfo(packageName, 0).versionName;
} catch (PackageManager.NameNotFoundException ignored) {
}
}
return versionName;
}
public static int getVersionCode(Context context) {
int versionCode = 0;
PackageManager pm = context.getPackageManager();
if (pm != null) {
String packageName = context.getPackageName();
try {
versionCode = pm.getPackageInfo(packageName, 0).versionCode;
} catch (PackageManager.NameNotFoundException ignored) {
}
}
return versionCode;
}
public static boolean getShouldSendBluetoothNotifications(Context context) {
SharedPreferences prefs = getPreferences(context);
return prefs.getBoolean(Constants.PREFERENCES_KEY_SEND_BLUETOOTH_NOTIFICATIONS, true);
SharedPreferences preferences = getPreferences(context);
return preferences.getBoolean(Constants.PREFERENCES_KEY_SEND_BLUETOOTH_NOTIFICATIONS, true);
}
public static boolean getShouldSendBluetoothAlbumArt(Context context) {
SharedPreferences prefs = getPreferences(context);
return prefs.getBoolean(Constants.PREFERENCES_KEY_SEND_BLUETOOTH_ALBUM_ART, true);
SharedPreferences preferences = getPreferences(context);
return preferences.getBoolean(Constants.PREFERENCES_KEY_SEND_BLUETOOTH_ALBUM_ART, true);
}
}

View File

@ -62,21 +62,27 @@ public class ChatAdapter extends ArrayAdapter<ChatMessage> {
holder.layout = layout;
convertView = LayoutInflater.from(activity).inflate(holder.layout, parent, false);
TextView usernameView = (TextView) convertView.findViewById(R.id.chat_username);
TextView timeView = (TextView) convertView.findViewById(R.id.chat_time);
TextView messageView = (TextView) convertView.findViewById(R.id.chat_message);
messageView.setMovementMethod(LinkMovementMethod.getInstance());
Linkify.addLinks(messageView, Linkify.EMAIL_ADDRESSES);
Linkify.addLinks(messageView, Linkify.WEB_URLS);
Linkify.addLinks(messageView, phoneMatcher, "tel:");
holder.message = messageView;
holder.username = usernameView;
holder.time = timeView;
convertView.setTag(holder);
TextView usernameView;
TextView timeView;
TextView messageView;
if (convertView != null) {
usernameView = (TextView) convertView.findViewById(R.id.chat_username);
timeView = (TextView) convertView.findViewById(R.id.chat_time);
messageView = (TextView) convertView.findViewById(R.id.chat_message);
messageView.setMovementMethod(LinkMovementMethod.getInstance());
Linkify.addLinks(messageView, Linkify.EMAIL_ADDRESSES);
Linkify.addLinks(messageView, Linkify.WEB_URLS);
Linkify.addLinks(messageView, phoneMatcher, "tel:");
holder.message = messageView;
holder.username = usernameView;
holder.time = timeView;
convertView.setTag(holder);
}
}
else
{

View File

@ -30,9 +30,8 @@ import com.thejoshwa.ultrasonic.androidapp.domain.Playlist;
* @author Sindre Mehus
*/
public class PlaylistView extends UpdateView {
private static final String TAG = PlaylistView.class.getSimpleName();
private TextView titleView;
private TextView titleView;
public PlaylistView(Context context) {
super(context);
LayoutInflater.from(context).inflate(R.layout.playlist_list_item, this, true);

View File

@ -49,10 +49,7 @@ public class SongView extends UpdateView implements Checkable {
private static final String TAG = SongView.class.getSimpleName();
private CheckedTextView checkedTextView;
private ImageView starImageView;
private TextView trackTextView;
private TextView titleTextView;
private TextView artistTextView;
private TextView durationTextView;
private TextView statusTextView;
private Entry song;
private Context context;
@ -75,10 +72,10 @@ public class SongView extends UpdateView implements Checkable {
checkedTextView = (CheckedTextView) findViewById(R.id.song_check);
starImageView = (ImageView) findViewById(R.id.song_star);
trackTextView = (TextView) findViewById(R.id.song_track);
TextView trackTextView = (TextView) findViewById(R.id.song_track);
titleTextView = (TextView) findViewById(R.id.song_title);
artistTextView = (TextView) findViewById(R.id.song_artist);
durationTextView = (TextView) findViewById(R.id.song_duration);
TextView artistTextView = (TextView) findViewById(R.id.song_artist);
TextView durationTextView = (TextView) findViewById(R.id.song_duration);
statusTextView = (TextView) findViewById(R.id.song_status);
@ -91,7 +88,8 @@ public class SongView extends UpdateView implements Checkable {
VideoPlayerType videoPlayer = Util.getVideoPlayerType(getContext());
String fileFormat = null;
String fileFormat;
if (song.getTranscodedSuffix() == null || song.getTranscodedSuffix().equals(song.getSuffix()) || (song.isVideo() && videoPlayer != VideoPlayerType.FLASH)) {
fileFormat = song.getSuffix();
} else {

View File

@ -22,12 +22,11 @@ public class UpdateView extends LinearLayout {
public UpdateView(Context context) {
super(context);
setLayoutParams(new AbsListView.LayoutParams(
ViewGroup.LayoutParams.FILL_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT));
setLayoutParams(new AbsListView.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
INSTANCES.put(this, null);
int instanceCount = INSTANCES.size();
if (instanceCount > 50) {
Log.w(TAG, instanceCount + " live UpdateView instances");
}
@ -65,12 +64,14 @@ public class UpdateView extends LinearLayout {
private static void updateAll() {
try {
List<UpdateView> views = new ArrayList<UpdateView>();;
List<UpdateView> views = new ArrayList<UpdateView>();
for (UpdateView view : INSTANCES.keySet()) {
if (view.isShown()) {
views.add(view);
}
}
updateAllLive(views);
} catch (Throwable x) {
Log.w(TAG, "Error when updating song views.", x);
@ -95,7 +96,7 @@ public class UpdateView extends LinearLayout {
@Override
public void run() {
try {
for(UpdateView view: views) {
for (UpdateView view: views) {
view.updateBackground();
}
uiHandler.post(runnable);