aboutsummaryrefslogtreecommitdiff
path: root/subsonic-android
diff options
context:
space:
mode:
Diffstat (limited to 'subsonic-android')
-rw-r--r--subsonic-android/AndroidManifest.xml6
-rw-r--r--subsonic-android/res/drawable-hdpi-v4/appwidget_bg.9.pngbin2909 -> 3117 bytes
-rw-r--r--subsonic-android/res/drawable/appwidget_bg.9.pngbin1784 -> 0 bytes
-rw-r--r--subsonic-android/res/drawable/btn_bg.xml17
-rw-r--r--subsonic-android/res/drawable/notification_play.pngbin0 -> 807 bytes
-rw-r--r--subsonic-android/res/drawable/widget_background.xml12
-rw-r--r--subsonic-android/res/layout/appwidget.xml4
-rw-r--r--subsonic-android/res/layout/notification.xml162
-rw-r--r--subsonic-android/res/values/colors.xml3
-rw-r--r--subsonic-android/res/xml/appwidget_info.xml5
-rw-r--r--subsonic-android/res/xml/searchable.xml2
-rw-r--r--subsonic-android/src/github/daneren2005/dsub/provider/DSubWidgetProvider.java (renamed from subsonic-android/src/github/daneren2005/dsub/provider/SubsonicAppWidgetProvider1.java)10
-rw-r--r--subsonic-android/src/github/daneren2005/dsub/service/DownloadServiceImpl.java166
-rw-r--r--subsonic-android/src/github/daneren2005/dsub/util/Util.java6
-rw-r--r--subsonic-android/src/github/daneren2005/dsub/util/compat/RemoteControlClientBase.java32
-rw-r--r--subsonic-android/src/github/daneren2005/dsub/util/compat/RemoteControlClientHelper.java27
-rw-r--r--subsonic-android/src/github/daneren2005/dsub/util/compat/RemoteControlClientICS.java71
17 files changed, 327 insertions, 196 deletions
diff --git a/subsonic-android/AndroidManifest.xml b/subsonic-android/AndroidManifest.xml
index 30010066..8956ef8d 100644
--- a/subsonic-android/AndroidManifest.xml
+++ b/subsonic-android/AndroidManifest.xml
@@ -2,8 +2,8 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="github.daneren2005.dsub"
android:installLocation="auto"
- android:versionCode="7"
- android:versionName="3.3.4">
+ android:versionCode="10"
+ android:versionName="3.3.5.1">
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
@@ -100,7 +100,7 @@
</intent-filter>
</receiver>
- <receiver android:name="github.daneren2005.dsub.provider.SubsonicAppWidgetProvider1" >
+ <receiver android:name="github.daneren2005.dsub.provider.DSubWidgetProvider" >
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE"/>
</intent-filter>
diff --git a/subsonic-android/res/drawable-hdpi-v4/appwidget_bg.9.png b/subsonic-android/res/drawable-hdpi-v4/appwidget_bg.9.png
index 3b29eae7..d8f892c3 100644
--- a/subsonic-android/res/drawable-hdpi-v4/appwidget_bg.9.png
+++ b/subsonic-android/res/drawable-hdpi-v4/appwidget_bg.9.png
Binary files differ
diff --git a/subsonic-android/res/drawable/appwidget_bg.9.png b/subsonic-android/res/drawable/appwidget_bg.9.png
deleted file mode 100644
index afe41b67..00000000
--- a/subsonic-android/res/drawable/appwidget_bg.9.png
+++ /dev/null
Binary files differ
diff --git a/subsonic-android/res/drawable/btn_bg.xml b/subsonic-android/res/drawable/btn_bg.xml
new file mode 100644
index 00000000..79d40784
--- /dev/null
+++ b/subsonic-android/res/drawable/btn_bg.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2010 The Android Open Source Project Licensed under the
+ Apache License, Version 2.0 (the "License"); you may not use this file except
+ in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+ Unless required by applicable law or agreed to in writing, software distributed
+ under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES
+ OR CONDITIONS OF ANY KIND, either express or implied. See the License for
+ the specific language governing permissions and limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android" android:exitFadeDuration="@android:integer/config_mediumAnimTime">
+
+ <item android:drawable="@color/ics_opaque" android:state_pressed="true"/>
+ <item android:drawable="@color/ics_opaque" android:state_enabled="true" android:state_focused="true"/>
+
+</selector> \ No newline at end of file
diff --git a/subsonic-android/res/drawable/notification_play.png b/subsonic-android/res/drawable/notification_play.png
new file mode 100644
index 00000000..8c95b6a5
--- /dev/null
+++ b/subsonic-android/res/drawable/notification_play.png
Binary files differ
diff --git a/subsonic-android/res/drawable/widget_background.xml b/subsonic-android/res/drawable/widget_background.xml
new file mode 100644
index 00000000..fe641900
--- /dev/null
+++ b/subsonic-android/res/drawable/widget_background.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_pressed="true"
+ android:drawable="@drawable/appwidget_overlay" />
+
+ <item android:state_focused="true" android:state_enabled="true"
+ android:state_window_focused="true"
+ android:drawable="@drawable/appwidget_overlay" />
+
+ <item android:drawable="@drawable/appwidget_bg" />
+</selector>
+
diff --git a/subsonic-android/res/layout/appwidget.xml b/subsonic-android/res/layout/appwidget.xml
index 233bc93f..6b3c892e 100644
--- a/subsonic-android/res/layout/appwidget.xml
+++ b/subsonic-android/res/layout/appwidget.xml
@@ -3,7 +3,7 @@
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal"
- android:background="@drawable/appwidget_bg">
+ android:background="@drawable/widget_background">
<ImageView
android:id="@+id/appwidget_coverart"
android:layout_height="fill_parent"
@@ -43,7 +43,7 @@
android:id="@+id/artist"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
- android:textColor="@color/appwidget_text"
+ android:textColor="@color/cyan"
android:minHeight="12sp"
android:textSize="12sp"
android:singleLine="true"
diff --git a/subsonic-android/res/layout/notification.xml b/subsonic-android/res/layout/notification.xml
index a234f71e..22e2cb63 100644
--- a/subsonic-android/res/layout/notification.xml
+++ b/subsonic-android/res/layout/notification.xml
@@ -3,93 +3,101 @@
android:id="@+id/statusbar"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
- android:orientation="vertical" >
+ android:orientation="horizontal" >
+
+ <ImageView
+ android:id="@+id/notification_image"
+ android:layout_width="64.0dip"
+ android:layout_height="64.0dip"
+ android:layout_weight="0.0"
+ android:gravity="center" />
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
- android:orientation="horizontal" >
+ android:orientation="vertical"
+ android:paddingLeft="11.0dip">
+
+ <TextView
+ android:id="@+id/notification_title"
+ style="@android:style/TextAppearance.StatusBar.EventContent.Title"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="left"
+ android:ellipsize="marquee"
+ android:focusable="true"
+ android:singleLine="true" />
+
+ <LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:orientation="horizontal" >
- <ImageView
- android:id="@+id/notification_image"
- android:layout_width="64.0dip"
- android:layout_height="64.0dip"
- android:layout_weight="0.0"
- android:gravity="center" />
+ <LinearLayout
+ android:layout_width="0.0dp"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:layout_weight="1.0"
+ android:orientation="vertical">
- <LinearLayout
- android:layout_width="0.0dp"
- android:layout_height="wrap_content"
- android:layout_gravity="center_vertical"
- android:layout_weight="1.0"
- android:orientation="vertical"
- android:paddingLeft="11.0dip" >
+ <TextView
+ android:id="@+id/notification_artist"
+ style="@android:style/TextAppearance.StatusBar.EventContent"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="left"
+ android:ellipsize="end"
+ android:scrollHorizontally="true"
+ android:singleLine="true" />
- <TextView
- android:id="@+id/notification_title"
- style="@android:style/TextAppearance.StatusBar.EventContent.Title"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="left"
- android:ellipsize="marquee"
- android:focusable="true"
- android:singleLine="true" />
+ <TextView
+ android:id="@+id/notification_album"
+ style="@android:style/TextAppearance.StatusBar.EventContent"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="left"
+ android:ellipsize="end"
+ android:scrollHorizontally="true"
+ android:singleLine="true" />
+ </LinearLayout>
- <TextView
- android:id="@+id/notification_artist"
- style="@android:style/TextAppearance.StatusBar.EventContent"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="left"
- android:ellipsize="end"
- android:scrollHorizontally="true"
- android:singleLine="true" />
+ <ImageButton
+ android:id="@+id/control_previous"
+ android:src="@drawable/notification_prev"
+ android:background="@drawable/btn_bg"
+ android:layout_width="34dip"
+ android:layout_height="34dip"
+ android:layout_gravity="center|right"
+ android:layout_marginRight="10dip"
+ android:layout_marginTop="2dip"
+ android:layout_weight="0.0"
+ android:scaleType="fitXY"/>
- <TextView
- android:id="@+id/notification_album"
- style="@android:style/TextAppearance.StatusBar.EventContent"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="left"
- android:ellipsize="end"
- android:scrollHorizontally="true"
- android:singleLine="true" />
- </LinearLayout>
-
- <ImageButton
- android:id="@+id/control_previous"
- android:src="@drawable/notification_prev"
- android:background="@android:color/transparent"
- android:layout_width="40dip"
- android:layout_height="40dip"
- android:layout_gravity="center|right"
- android:layout_marginRight="5dip"
- android:layout_marginTop="2dip"
- android:layout_weight="0.0"/>
-
- <ImageButton
- android:id="@+id/control_pause"
- android:src="@drawable/notification_pause"
- android:background="@android:color/transparent"
- android:layout_width="40dip"
- android:layout_height="40dip"
- android:layout_gravity="center|right"
- android:layout_marginRight="5dip"
- android:layout_marginTop="2dip"
- android:layout_weight="0.0"/>
-
- <ImageButton
- android:id="@+id/control_next"
- android:src="@drawable/notification_next"
- android:background="@android:color/transparent"
- android:layout_width="40dip"
- android:layout_height="40dip"
- android:layout_gravity="center|right"
- android:layout_marginRight="5dip"
- android:layout_marginTop="2dip"
- android:layout_weight="0.0"/>
+ <ImageButton
+ android:id="@+id/control_pause"
+ android:src="@drawable/notification_pause"
+ android:background="@drawable/btn_bg"
+ android:layout_width="34dip"
+ android:layout_height="34dip"
+ android:layout_gravity="center|right"
+ android:layout_marginRight="10dip"
+ android:layout_marginTop="2dip"
+ android:layout_weight="0.0"
+ android:scaleType="fitXY"/>
+ <ImageButton
+ android:id="@+id/control_next"
+ android:src="@drawable/notification_next"
+ android:background="@drawable/btn_bg"
+ android:layout_width="34dip"
+ android:layout_height="34dip"
+ android:layout_gravity="center|right"
+ android:layout_marginRight="10dip"
+ android:layout_marginTop="2dip"
+ android:layout_weight="0.0"
+ android:scaleType="fitXY"/>
+ </LinearLayout>
</LinearLayout>
-
</LinearLayout>
diff --git a/subsonic-android/res/values/colors.xml b/subsonic-android/res/values/colors.xml
index 67bb3933..69ab22a1 100644
--- a/subsonic-android/res/values/colors.xml
+++ b/subsonic-android/res/values/colors.xml
@@ -10,4 +10,7 @@
<color name="wheatBackground">#F1F0E6</color>
<color name="wheatForeground1">#494B26</color>
<color name="wheatForeground2">#830009</color>
+
+ <color name="ics_opaque">#8033b5e5</color>
+ <color name="cyan">#ff0099cc</color>
</resources> \ No newline at end of file
diff --git a/subsonic-android/res/xml/appwidget_info.xml b/subsonic-android/res/xml/appwidget_info.xml
index f1e8e308..7ad17ef9 100644
--- a/subsonic-android/res/xml/appwidget_info.xml
+++ b/subsonic-android/res/xml/appwidget_info.xml
@@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
- android:minWidth="294dip"
- android:minHeight="72dip"
+ android:minWidth="272dip"
+ android:minHeight="56dip"
android:updatePeriodMillis="0"
+ android:resizeMode="horizontal|vertical"
android:initialLayout="@layout/appwidget"/> \ No newline at end of file
diff --git a/subsonic-android/res/xml/searchable.xml b/subsonic-android/res/xml/searchable.xml
index fd68a3ed..80276434 100644
--- a/subsonic-android/res/xml/searchable.xml
+++ b/subsonic-android/res/xml/searchable.xml
@@ -4,6 +4,6 @@
android:hint="@string/search.title"
android:voiceSearchMode="showVoiceSearchButton|launchRecognizer"
android:voiceLanguageModel="web_search"
- android:searchSuggestAuthority="github.daneren2005.dsub.provider.SearchSuggestionProvider"
+ android:searchSuggestAuthority="github.daneren2005.dsub.provider.SearchSuggestionProvider1"
android:searchSuggestSelection=" ?" >
</searchable> \ No newline at end of file
diff --git a/subsonic-android/src/github/daneren2005/dsub/provider/SubsonicAppWidgetProvider1.java b/subsonic-android/src/github/daneren2005/dsub/provider/DSubWidgetProvider.java
index 40655b9d..c6861f0a 100644
--- a/subsonic-android/src/github/daneren2005/dsub/provider/SubsonicAppWidgetProvider1.java
+++ b/subsonic-android/src/github/daneren2005/dsub/provider/DSubWidgetProvider.java
@@ -53,14 +53,14 @@ import github.daneren2005.dsub.util.FileUtil;
*
* @author Sindre Mehus
*/
-public class SubsonicAppWidgetProvider1 extends AppWidgetProvider {
+public class DSubWidgetProvider extends AppWidgetProvider {
- private static SubsonicAppWidgetProvider1 instance;
- private static final String TAG = SubsonicAppWidgetProvider1.class.getSimpleName();
+ private static DSubWidgetProvider instance;
+ private static final String TAG = DSubWidgetProvider.class.getSimpleName();
- public static synchronized SubsonicAppWidgetProvider1 getInstance() {
+ public static synchronized DSubWidgetProvider getInstance() {
if (instance == null) {
- instance = new SubsonicAppWidgetProvider1();
+ instance = new DSubWidgetProvider();
}
return instance;
}
diff --git a/subsonic-android/src/github/daneren2005/dsub/service/DownloadServiceImpl.java b/subsonic-android/src/github/daneren2005/dsub/service/DownloadServiceImpl.java
index bce1cca8..2de8eb46 100644
--- a/subsonic-android/src/github/daneren2005/dsub/service/DownloadServiceImpl.java
+++ b/subsonic-android/src/github/daneren2005/dsub/service/DownloadServiceImpl.java
@@ -18,22 +18,14 @@
*/
package github.daneren2005.dsub.service;
-import android.annotation.TargetApi;
-import android.app.PendingIntent;
-import android.app.Service;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.SharedPreferences;
-import android.media.AudioManager;
-import android.media.MediaMetadataRetriever;
-import android.media.MediaPlayer;
-import android.media.RemoteControlClient;
-import android.os.Build;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.PowerManager;
-import android.util.Log;
+import static github.daneren2005.dsub.domain.PlayerState.COMPLETED;
+import static github.daneren2005.dsub.domain.PlayerState.DOWNLOADING;
+import static github.daneren2005.dsub.domain.PlayerState.IDLE;
+import static github.daneren2005.dsub.domain.PlayerState.PAUSED;
+import static github.daneren2005.dsub.domain.PlayerState.PREPARED;
+import static github.daneren2005.dsub.domain.PlayerState.PREPARING;
+import static github.daneren2005.dsub.domain.PlayerState.STARTED;
+import static github.daneren2005.dsub.domain.PlayerState.STOPPED;
import github.daneren2005.dsub.audiofx.EqualizerController;
import github.daneren2005.dsub.audiofx.VisualizerController;
import github.daneren2005.dsub.domain.MusicDirectory;
@@ -41,10 +33,12 @@ import github.daneren2005.dsub.domain.PlayerState;
import github.daneren2005.dsub.domain.RepeatMode;
import github.daneren2005.dsub.receiver.MediaButtonIntentReceiver;
import github.daneren2005.dsub.util.CancellableTask;
+import github.daneren2005.dsub.util.Constants;
import github.daneren2005.dsub.util.LRUCache;
import github.daneren2005.dsub.util.ShufflePlayBuffer;
import github.daneren2005.dsub.util.SimpleServiceBinder;
import github.daneren2005.dsub.util.Util;
+import github.daneren2005.dsub.util.compat.RemoteControlClientHelper;
import java.io.File;
import java.util.ArrayList;
@@ -52,8 +46,17 @@ import java.util.Collections;
import java.util.Iterator;
import java.util.List;
-import static github.daneren2005.dsub.domain.PlayerState.*;
-import github.daneren2005.dsub.util.*;
+import android.app.Service;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.media.AudioManager;
+import android.media.MediaPlayer;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.PowerManager;
+import android.util.Log;
/**
* @author Sindre Mehus
@@ -71,8 +74,7 @@ public class DownloadServiceImpl extends Service implements DownloadService {
public static final String CMD_NEXT = "github.daneren2005.dsub.CMD_NEXT";
- private RemoteControlClient mRemoteControlClient;
- private ImageLoader imageLoader;
+ private RemoteControlClientHelper mRemoteControl;
private final IBinder binder = new SimpleServiceBinder<DownloadService>(this);
private MediaPlayer mediaPlayer;
@@ -121,12 +123,9 @@ public class DownloadServiceImpl extends Service implements DownloadService {
}
}
- @TargetApi(14)
@Override
public void onCreate() {
super.onCreate();
-
- imageLoader = new ImageLoader(this);
mediaPlayer = new MediaPlayer();
mediaPlayer.setWakeMode(this, PowerManager.PARTIAL_WAKE_LOCK);
@@ -138,73 +137,48 @@ public class DownloadServiceImpl extends Service implements DownloadService {
return false;
}
});
-
-// try {
-// Class.forName("android.media.RemoteControlClient");
- if (Build.VERSION.SDK_INT >= 14) {
-
- Util.requestAudioFocus(this);
- Util.registerMediaButtonEventReceiver(this);
-
- // Use the remote control APIs (if available) to set the playback state
- if (mRemoteControlClient == null) {
- AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
- ComponentName mediaButtonReceiverComponent = new ComponentName(getPackageName(), MediaButtonIntentReceiver.class.getName());
-// audioManager.registerMediaButtonEventReceiver(mediaButtonReceiverComponent);
- // build the PendingIntent for the remote control client
- Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON);
- mediaButtonIntent.setComponent(mediaButtonReceiverComponent);
- PendingIntent mediaPendingIntent = PendingIntent.getBroadcast(getApplicationContext(), 0, mediaButtonIntent, 0);
- // create and register the remote control client
- mRemoteControlClient = new RemoteControlClient(mediaPendingIntent);
- audioManager.registerRemoteControlClient(mRemoteControlClient);
- }
-
- mRemoteControlClient.setPlaybackState(
- RemoteControlClient.PLAYSTATE_STOPPED);
-
- mRemoteControlClient.setTransportControlFlags(
- RemoteControlClient.FLAG_KEY_MEDIA_PLAY |
- RemoteControlClient.FLAG_KEY_MEDIA_PAUSE |
- RemoteControlClient.FLAG_KEY_MEDIA_PLAY_PAUSE |
- RemoteControlClient.FLAG_KEY_MEDIA_PREVIOUS |
- RemoteControlClient.FLAG_KEY_MEDIA_NEXT |
- RemoteControlClient.FLAG_KEY_MEDIA_STOP);
- }
-// } catch (ClassNotFoundException x) {
-// // Ignored.
-// }
-
- if (equalizerAvailable) {
- equalizerController = new EqualizerController(this, mediaPlayer);
- if (!equalizerController.isAvailable()) {
- equalizerController = null;
- } else {
- equalizerController.loadSettings();
- }
- }
- if (visualizerAvailable) {
- visualizerController = new VisualizerController(this, mediaPlayer);
- if (!visualizerController.isAvailable()) {
- visualizerController = null;
- }
+
+ Util.requestAudioFocus(this);
+ Util.registerMediaButtonEventReceiver(this);
+
+ if (mRemoteControl == null) {
+ // Use the remote control APIs (if available) to set the playback state
+ mRemoteControl = RemoteControlClientHelper.createInstance();
+ ComponentName mediaButtonReceiverComponent = new ComponentName(getPackageName(), MediaButtonIntentReceiver.class.getName());
+ mRemoteControl.register(this, mediaButtonReceiverComponent);
}
- PowerManager pm = (PowerManager)getSystemService(Context.POWER_SERVICE);
- wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, this.getClass().getName());
- wakeLock.setReferenceCounted(false);
+ if (equalizerAvailable) {
+ equalizerController = new EqualizerController(this, mediaPlayer);
+ if (!equalizerController.isAvailable()) {
+ equalizerController = null;
+ } else {
+ equalizerController.loadSettings();
+ }
+ }
+ if (visualizerAvailable) {
+ visualizerController = new VisualizerController(this, mediaPlayer);
+ if (!visualizerController.isAvailable()) {
+ visualizerController = null;
+ }
+ }
+
+ PowerManager pm = (PowerManager)getSystemService(Context.POWER_SERVICE);
+ wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, this.getClass().getName());
+ wakeLock.setReferenceCounted(false);
- instance = this;
- lifecycleSupport.onCreate();
+ instance = this;
+ lifecycleSupport.onCreate();
}
@Override
- public void onStart(Intent intent, int startId) {
- super.onStart(intent, startId);
+ public int onStartCommand(Intent intent, int flags, int startId) {
+ super.onStartCommand(intent, flags, startId);
lifecycleSupport.onStart(intent);
+ return START_NOT_STICKY;
}
- @Override
+ @Override
public void onDestroy() {
super.onDestroy();
lifecycleSupport.onDestroy();
@@ -216,6 +190,10 @@ public class DownloadServiceImpl extends Service implements DownloadService {
if (visualizerController != null) {
visualizerController.release();
}
+ if (mRemoteControl != null) {
+ mRemoteControl.unregister(this);
+ mRemoteControl = null;
+ }
instance = null;
}
@@ -445,7 +423,6 @@ public class DownloadServiceImpl extends Service implements DownloadService {
}
}
- @TargetApi(14)
synchronized void setCurrentPlaying(DownloadFile currentPlaying, boolean showNotification) {
this.currentPlaying = currentPlaying;
@@ -462,23 +439,9 @@ public class DownloadServiceImpl extends Service implements DownloadService {
Util.hidePlayingNotification(this, this, handler);
}
- if (mRemoteControlClient != null) {
- MusicDirectory.Entry currentSong = currentPlaying == null ? null: currentPlaying.getSong();
- // Update the remote controls
- mRemoteControlClient.editMetadata(true)
- .putString(MediaMetadataRetriever.METADATA_KEY_ARTIST, currentSong == null ? null : currentSong.getArtist())
- .putString(MediaMetadataRetriever.METADATA_KEY_ALBUM, currentSong == null ? null : currentSong.getAlbum())
- .putString(MediaMetadataRetriever.METADATA_KEY_TITLE, currentSong == null ? null : currentSong.getTitle())
- .putLong(MediaMetadataRetriever.METADATA_KEY_DURATION, currentSong == null ? 0 : currentSong.getDuration())
- .apply();
- if (currentSong == null) {
- mRemoteControlClient.editMetadata(true)
- .putBitmap(RemoteControlClient.MetadataEditor.BITMAP_KEY_ARTWORK, null)
- .apply();
- } else {
- imageLoader.loadImage(this, mRemoteControlClient, currentSong);
- }
- }
+ MusicDirectory.Entry currentSong = (currentPlaying == null) ? null: currentPlaying.getSong();
+ mRemoteControl.updateMetadata(this, currentSong);
+
}
@Override
@@ -688,7 +651,6 @@ public class DownloadServiceImpl extends Service implements DownloadService {
return playerState;
}
- @TargetApi(14)
synchronized void setPlayerState(PlayerState playerState) {
Log.i(TAG, this.playerState.name() + " -> " + playerState.name() + " (" + currentPlaying + ")");
@@ -701,9 +663,7 @@ public class DownloadServiceImpl extends Service implements DownloadService {
Util.broadcastPlaybackStatusChange(this, playerState);
this.playerState = playerState;
- if (mRemoteControlClient != null) {
- mRemoteControlClient.setPlaybackState(playerState.getRemoteControlClientPlayState());
- }
+ mRemoteControl.setPlaybackState(playerState.getRemoteControlClientPlayState());
if (show) {
Util.showPlayingNotification(this, this, handler, currentPlaying.getSong());
diff --git a/subsonic-android/src/github/daneren2005/dsub/util/Util.java b/subsonic-android/src/github/daneren2005/dsub/util/Util.java
index 37dfc6f5..cf3b6ca4 100644
--- a/subsonic-android/src/github/daneren2005/dsub/util/Util.java
+++ b/subsonic-android/src/github/daneren2005/dsub/util/Util.java
@@ -54,7 +54,7 @@ import github.daneren2005.dsub.domain.MusicDirectory;
import github.daneren2005.dsub.domain.PlayerState;
import github.daneren2005.dsub.domain.RepeatMode;
import github.daneren2005.dsub.domain.Version;
-import github.daneren2005.dsub.provider.SubsonicAppWidgetProvider1;
+import github.daneren2005.dsub.provider.DSubWidgetProvider;
import github.daneren2005.dsub.receiver.MediaButtonIntentReceiver;
import github.daneren2005.dsub.service.DownloadServiceImpl;
import org.apache.http.HttpEntity;
@@ -644,7 +644,7 @@ public final class Util {
});
// Update widget
- SubsonicAppWidgetProvider1.getInstance().notifyChange(context, downloadService, true);
+ DSubWidgetProvider.getInstance().notifyChange(context, downloadService, true);
}
public static void hidePlayingNotification(final Context context, final DownloadServiceImpl downloadService, Handler handler) {
@@ -658,7 +658,7 @@ public final class Util {
});
// Update widget
- SubsonicAppWidgetProvider1.getInstance().notifyChange(context, downloadService, false);
+ DSubWidgetProvider.getInstance().notifyChange(context, downloadService, false);
}
public static void sleepQuietly(long millis) {
diff --git a/subsonic-android/src/github/daneren2005/dsub/util/compat/RemoteControlClientBase.java b/subsonic-android/src/github/daneren2005/dsub/util/compat/RemoteControlClientBase.java
new file mode 100644
index 00000000..c3f3f70c
--- /dev/null
+++ b/subsonic-android/src/github/daneren2005/dsub/util/compat/RemoteControlClientBase.java
@@ -0,0 +1,32 @@
+package github.daneren2005.dsub.util.compat;
+
+import github.daneren2005.dsub.domain.MusicDirectory.Entry;
+import android.content.ComponentName;
+import android.content.Context;
+import android.util.Log;
+
+public class RemoteControlClientBase extends RemoteControlClientHelper {
+
+ private static final String TAG = RemoteControlClientBase.class.getSimpleName();
+
+ @Override
+ public void register(Context context, ComponentName mediaButtonReceiverComponent) {
+ Log.w(TAG, "RemoteControlClient requires Android API level 14 or higher.");
+ }
+
+ @Override
+ public void unregister(Context context) {
+ Log.w(TAG, "RemoteControlClient requires Android API level 14 or higher.");
+ }
+
+ @Override
+ public void setPlaybackState(int state) {
+ Log.w(TAG, "RemoteControlClient requires Android API level 14 or higher.");
+ }
+
+ @Override
+ public void updateMetadata(Context context, Entry currentSong) {
+ Log.w(TAG, "RemoteControlClient requires Android API level 14 or higher.");
+ }
+
+}
diff --git a/subsonic-android/src/github/daneren2005/dsub/util/compat/RemoteControlClientHelper.java b/subsonic-android/src/github/daneren2005/dsub/util/compat/RemoteControlClientHelper.java
new file mode 100644
index 00000000..ddaa9f43
--- /dev/null
+++ b/subsonic-android/src/github/daneren2005/dsub/util/compat/RemoteControlClientHelper.java
@@ -0,0 +1,27 @@
+package github.daneren2005.dsub.util.compat;
+
+import github.daneren2005.dsub.domain.MusicDirectory;
+import android.content.ComponentName;
+import android.content.Context;
+import android.os.Build;
+
+public abstract class RemoteControlClientHelper {
+
+ public static RemoteControlClientHelper createInstance() {
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
+ return new RemoteControlClientBase();
+ } else {
+ return new RemoteControlClientICS();
+ }
+ }
+
+ protected RemoteControlClientHelper() {
+ // Avoid instantiation
+ }
+
+ public abstract void register(final Context context, final ComponentName mediaButtonReceiverComponent);
+ public abstract void unregister(final Context context);
+ public abstract void setPlaybackState(final int state);
+ public abstract void updateMetadata(final Context context, final MusicDirectory.Entry currentSong);
+
+}
diff --git a/subsonic-android/src/github/daneren2005/dsub/util/compat/RemoteControlClientICS.java b/subsonic-android/src/github/daneren2005/dsub/util/compat/RemoteControlClientICS.java
new file mode 100644
index 00000000..c5b09876
--- /dev/null
+++ b/subsonic-android/src/github/daneren2005/dsub/util/compat/RemoteControlClientICS.java
@@ -0,0 +1,71 @@
+package github.daneren2005.dsub.util.compat;
+
+import github.daneren2005.dsub.domain.MusicDirectory;
+import github.daneren2005.dsub.util.ImageLoader;
+import android.annotation.TargetApi;
+import android.app.PendingIntent;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.media.AudioManager;
+import android.media.MediaMetadataRetriever;
+import android.media.RemoteControlClient;
+
+@TargetApi(14)
+public class RemoteControlClientICS extends RemoteControlClientHelper {
+
+ private RemoteControlClient mRemoteControl;
+
+ public void register(final Context context, final ComponentName mediaButtonReceiverComponent) {
+ AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
+
+ // build the PendingIntent for the remote control client
+ Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON);
+ mediaButtonIntent.setComponent(mediaButtonReceiverComponent);
+ PendingIntent mediaPendingIntent = PendingIntent.getBroadcast(context.getApplicationContext(), 0, mediaButtonIntent, 0);
+
+ // create and register the remote control client
+ mRemoteControl = new RemoteControlClient(mediaPendingIntent);
+ audioManager.registerRemoteControlClient(mRemoteControl);
+
+ mRemoteControl.setPlaybackState(RemoteControlClient.PLAYSTATE_STOPPED);
+
+ mRemoteControl.setTransportControlFlags(
+ RemoteControlClient.FLAG_KEY_MEDIA_PLAY |
+ RemoteControlClient.FLAG_KEY_MEDIA_PAUSE |
+ RemoteControlClient.FLAG_KEY_MEDIA_PLAY_PAUSE |
+ RemoteControlClient.FLAG_KEY_MEDIA_PREVIOUS |
+ RemoteControlClient.FLAG_KEY_MEDIA_NEXT |
+ RemoteControlClient.FLAG_KEY_MEDIA_STOP);
+ }
+
+ public void unregister(final Context context) {
+ if (mRemoteControl != null) {
+ AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
+ audioManager.unregisterRemoteControlClient(mRemoteControl);
+ }
+ }
+
+ public void setPlaybackState(final int state) {
+ mRemoteControl.setPlaybackState(state);
+ }
+
+ public void updateMetadata(final Context context, final MusicDirectory.Entry currentSong) {
+ // Update the remote controls
+ mRemoteControl.editMetadata(true)
+ .putString(MediaMetadataRetriever.METADATA_KEY_ARTIST, (currentSong == null) ? null : currentSong.getArtist())
+ .putString(MediaMetadataRetriever.METADATA_KEY_ALBUM, (currentSong == null) ? null : currentSong.getAlbum())
+ .putString(MediaMetadataRetriever.METADATA_KEY_TITLE, (currentSong) == null ? null : currentSong.getTitle())
+ .putLong(MediaMetadataRetriever.METADATA_KEY_DURATION, (currentSong == null) ?
+ 0 : ((currentSong.getDuration() == null) ? 0 : currentSong.getDuration()))
+ .apply();
+ if (currentSong == null) {
+ mRemoteControl.editMetadata(true)
+ .putBitmap(RemoteControlClient.MetadataEditor.BITMAP_KEY_ARTWORK, null)
+ .apply();
+ } else {
+ new ImageLoader(context).loadImage(context, mRemoteControl, currentSong);
+ }
+ }
+
+}