Refactor Notification and PauseCall services: Create a single connection observer service that manages the notification and call pause/play.

This commit is contained in:
Synced Synapse 2016-05-20 19:24:34 +01:00
parent faab6b8163
commit e65b4536d7
6 changed files with 317 additions and 148 deletions

View File

@ -68,7 +68,7 @@
<!-- Services --> <!-- Services -->
<service android:name=".service.library.LibrarySyncService" <service android:name=".service.library.LibrarySyncService"
android:exported="false"/> android:exported="false"/>
<service android:name="org.xbmc.kore.service.NotificationService" <service android:name="org.xbmc.kore.service.ConnectionObserversManagerService"
android:exported="false"/> android:exported="false"/>
<service android:name="org.xbmc.kore.service.IntentActionsService" <service android:name="org.xbmc.kore.service.IntentActionsService"
android:exported="false"/> android:exported="false"/>

View File

@ -0,0 +1,226 @@
/*
* Copyright 2016 Synced Synapse. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.xbmc.kore.service;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.preference.PreferenceManager;
import org.xbmc.kore.Settings;
import org.xbmc.kore.host.HostConnectionObserver;
import org.xbmc.kore.host.HostManager;
import org.xbmc.kore.jsonrpc.type.ListType;
import org.xbmc.kore.jsonrpc.type.PlayerType;
import org.xbmc.kore.utils.LogUtils;
import java.util.ArrayList;
import java.util.List;
/**
* This service is a wrapper over {@link HostConnectionObserver} that
* manages connection observers, and does it in a service that keeps running
* until the connection is lost.
* The observers are created here.
* This service stops itself as soon as there's no connection.
*
* A {@link HostConnectionObserver} singleton is used to keep track of Kodi's
* state. This singleton should be the same as used in the app's activities
*/
public class ConnectionObserversManagerService extends Service
implements HostConnectionObserver.PlayerEventsObserver {
public static final String TAG = LogUtils.makeLogTag(ConnectionObserversManagerService.class);
private HostConnectionObserver mHostConnectionObserver = null;
private List<HostConnectionObserver.PlayerEventsObserver> mConnectionObservers;
@Override
public void onCreate() {
// We do not create any thread because all the works is supposed to
// be done on the main thread, so that the connection observer
// can be shared with the app, and notify it on the UI thread
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
LogUtils.LOGD(TAG, "onStartCommand");
// Create the observers we are managing
createObservers();
// If no observers created, stop immediately
if (mConnectionObservers.size() == 0) {
LogUtils.LOGD(TAG, "No observers, stopping observer service.");
stopSelf();
}
// Get the connection observer here, not on create to check if
// there has been a change in hosts, and if so unregister the previous one
HostConnectionObserver connectionObserver = HostManager.getInstance(this).getHostConnectionObserver();
// If we are already initialized and the same host, exit
if (mHostConnectionObserver == connectionObserver) {
LogUtils.LOGD(TAG, "Already initialized");
return START_STICKY;
}
// If there's a change in hosts, unregister from the previous one
if (mHostConnectionObserver != null) {
mHostConnectionObserver.unregisterPlayerObserver(this);
}
// Register us on the connection observer
mHostConnectionObserver = connectionObserver;
mHostConnectionObserver.registerPlayerObserver(this, true);
// If we get killed, after returning from here, don't restart
return START_STICKY;
}
private void createObservers() {
mConnectionObservers = new ArrayList<>();
// Check whether we should show a notification
boolean showNotification = PreferenceManager
.getDefaultSharedPreferences(this)
.getBoolean(Settings.KEY_PREF_SHOW_NOTIFICATION,
Settings.DEFAULT_PREF_SHOW_NOTIFICATION);
if (showNotification) {
mConnectionObservers.add(new NotificationObserver(this));
}
// Check whether we should react to phone state changes
boolean shouldPause = PreferenceManager
.getDefaultSharedPreferences(this)
.getBoolean(Settings.KEY_PREF_USE_HARDWARE_VOLUME_KEYS,
Settings.DEFAULT_PREF_USE_HARDWARE_VOLUME_KEYS);
if (shouldPause) {
mConnectionObservers.add(new PauseCallObserver(this));
}
}
@Override
public IBinder onBind(Intent intent) {
// We don't provide binding, so return null
return null;
}
@Override
public void onTaskRemoved (Intent rootIntent) {
// Gracefully stop
for (HostConnectionObserver.PlayerEventsObserver observer : mConnectionObservers) {
observer.playerOnConnectionError(0, "Task removed");
}
LogUtils.LOGD(TAG, "Shutting down observer service - Task removed");
if (mHostConnectionObserver != null) {
mHostConnectionObserver.unregisterPlayerObserver(this);
}
stopSelf();
}
@Override
public void onDestroy() {
// Gracefully stop
for (HostConnectionObserver.PlayerEventsObserver observer : mConnectionObservers) {
observer.playerOnConnectionError(0, "Service destroyed");
}
LogUtils.LOGD(TAG, "Shutting down observer service - destroyed");
if (mHostConnectionObserver != null) {
mHostConnectionObserver.unregisterPlayerObserver(this);
}
}
/**
* HostConnectionObserver.PlayerEventsObserver interface callbacks
*/
public void playerOnPlay(PlayerType.GetActivePlayersReturnType getActivePlayerResult,
PlayerType.PropertyValue getPropertiesResult,
ListType.ItemsAll getItemResult) {
for (HostConnectionObserver.PlayerEventsObserver observer : mConnectionObservers) {
observer.playerOnPlay(getActivePlayerResult, getPropertiesResult, getItemResult);
}
}
public void playerOnPause(PlayerType.GetActivePlayersReturnType getActivePlayerResult,
PlayerType.PropertyValue getPropertiesResult,
ListType.ItemsAll getItemResult) {
for (HostConnectionObserver.PlayerEventsObserver observer : mConnectionObservers) {
observer.playerOnPause(getActivePlayerResult, getPropertiesResult, getItemResult);
}
}
public void playerOnStop() {
for (HostConnectionObserver.PlayerEventsObserver observer : mConnectionObservers) {
observer.playerOnStop();
}
// Stop service
LogUtils.LOGD(TAG, "Player stopped");
// if (mHostConnectionObserver != null) {
// mHostConnectionObserver.unregisterPlayerObserver(this);
// }
// stopSelf();
}
public void playerNoResultsYet() {
for (HostConnectionObserver.PlayerEventsObserver observer : mConnectionObservers) {
observer.playerNoResultsYet();
}
}
public void playerOnConnectionError(int errorCode, String description) {
for (HostConnectionObserver.PlayerEventsObserver observer : mConnectionObservers) {
observer.playerOnConnectionError(errorCode, description);
}
// Stop service
LogUtils.LOGD(TAG, "Shutting down observer service - Connection error");
if (mHostConnectionObserver != null) {
mHostConnectionObserver.unregisterPlayerObserver(this);
}
stopSelf();
}
public void systemOnQuit() {
for (HostConnectionObserver.PlayerEventsObserver observer : mConnectionObservers) {
observer.systemOnQuit();
}
// Stop service
LogUtils.LOGD(TAG, "Shutting down observer service - System quit");
if (mHostConnectionObserver != null) {
mHostConnectionObserver.unregisterPlayerObserver(this);
}
stopSelf();
}
// Ignore this
public void inputOnInputRequested(String title, String type, String value) {
for (HostConnectionObserver.PlayerEventsObserver observer : mConnectionObservers) {
observer.inputOnInputRequested(title, type, value);
}
}
public void observerOnStopObserving() {
for (HostConnectionObserver.PlayerEventsObserver observer : mConnectionObservers) {
observer.observerOnStopObserving();
}
// Called when the user changes host
LogUtils.LOGD(TAG, "Shutting down observer service - Stop observing");
stopSelf();
}
}

View File

@ -46,87 +46,32 @@ import org.xbmc.kore.utils.UIUtils;
import org.xbmc.kore.utils.Utils; import org.xbmc.kore.utils.Utils;
/** /**
* This service maintains a notification in the notification area while * This class mantains a notification on the notification area while something is playing.
* something is playing, and keeps running while it is playing. * It is meant to be used in conjunction with {@link ConnectionObserversManagerService},
* This service stops itself as soon as the playing stops or there's no * which should create an instance of this and manage it
* connection. Thus, this should only be started if something is already
* playing, otherwise it will shutdown automatically.
* It doesn't try to mirror Kodi's state at all times, because that would
* imply running at all times which can be resource consuming.
*
* A {@link HostConnectionObserver} singleton is used to keep track of Kodi's
* state. This singleton should be the same as used in the app's activities
*/ */
public class NotificationService extends Service public class NotificationObserver
implements HostConnectionObserver.PlayerEventsObserver { implements HostConnectionObserver.PlayerEventsObserver {
public static final String TAG = LogUtils.makeLogTag(NotificationService.class); public static final String TAG = LogUtils.makeLogTag(NotificationObserver.class);
private static final int NOTIFICATION_ID = 1; private static final int NOTIFICATION_ID = 1;
private HostConnectionObserver mHostConnectionObserver = null;
private PendingIntent mRemoteStartPendingIntent; private PendingIntent mRemoteStartPendingIntent;
private Context mContext;
@Override public NotificationObserver(Context context) {
public void onCreate() { this.mContext = context;
// We do not create any thread because all the works is supposed to
// be done on the main thread, so that the connection observer
// can be shared with the app, and notify it on the UI thread
// Create the intent to start the remote when the user taps the notification // Create the intent to start the remote when the user taps the notification
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this); TaskStackBuilder stackBuilder = TaskStackBuilder.create(mContext);
stackBuilder.addParentStack(RemoteActivity.class); stackBuilder.addParentStack(RemoteActivity.class);
stackBuilder.addNextIntent(new Intent(this, RemoteActivity.class)); stackBuilder.addNextIntent(new Intent(mContext, RemoteActivity.class));
mRemoteStartPendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT); mRemoteStartPendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
} }
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
LogUtils.LOGD(TAG, "onStartCommand");
// Get the connection observer here, not on create to check if
// there has been a change in hosts, and if so unregister the previous one
HostConnectionObserver connectionObserver = HostManager.getInstance(this).getHostConnectionObserver();
// If we are already initialized and the same host, exit
if (mHostConnectionObserver == connectionObserver) {
LogUtils.LOGD(TAG, "Already initialized");
return START_STICKY;
}
// If there's a change in hosts, unregister from the previous one
if (mHostConnectionObserver != null) {
mHostConnectionObserver.unregisterPlayerObserver(this);
}
// Register us on the connection observer
mHostConnectionObserver = connectionObserver;
mHostConnectionObserver.registerPlayerObserver(this, true);
// If we get killed, after returning from here, don't restart
return START_STICKY;
}
@Override
public IBinder onBind(Intent intent) {
// We don't provide binding, so return null
return null;
}
@Override
public void onTaskRemoved (Intent rootIntent) {
// Gracefully stop
removeNotification();
LogUtils.LOGD(TAG, "Shutting down notification service - Task removed");
if (mHostConnectionObserver != null) {
mHostConnectionObserver.unregisterPlayerObserver(this);
}
stopSelf();
}
/** /**
* HostConnectionObserver.PlayerEventsObserver interface callbacks * HostConnectionObserver.PlayerEventsObserver interface callbacks
*/ */
public void playerOnPlay(PlayerType.GetActivePlayersReturnType getActivePlayerResult, public void playerOnPlay(PlayerType.GetActivePlayersReturnType getActivePlayerResult,
PlayerType.PropertyValue getPropertiesResult, PlayerType.PropertyValue getPropertiesResult,
ListType.ItemsAll getItemResult) { ListType.ItemsAll getItemResult) {
@ -141,12 +86,6 @@ public class NotificationService extends Service
public void playerOnStop() { public void playerOnStop() {
removeNotification(); removeNotification();
// Stop service
LogUtils.LOGD(TAG, "Shutting down notification service - Player stopped");
if (mHostConnectionObserver != null) {
mHostConnectionObserver.unregisterPlayerObserver(this);
}
stopSelf();
} }
public void playerNoResultsYet() { public void playerNoResultsYet() {
@ -155,22 +94,10 @@ public class NotificationService extends Service
public void playerOnConnectionError(int errorCode, String description) { public void playerOnConnectionError(int errorCode, String description) {
removeNotification(); removeNotification();
// Stop service
LogUtils.LOGD(TAG, "Shutting down notification service - Connection error");
if (mHostConnectionObserver != null) {
mHostConnectionObserver.unregisterPlayerObserver(this);
}
stopSelf();
} }
public void systemOnQuit() { public void systemOnQuit() {
removeNotification(); removeNotification();
// Stop service
LogUtils.LOGD(TAG, "Shutting down notification service - System quit");
if (mHostConnectionObserver != null) {
mHostConnectionObserver.unregisterPlayerObserver(this);
}
stopSelf();
} }
// Ignore this // Ignore this
@ -179,8 +106,6 @@ public class NotificationService extends Service
public void observerOnStopObserving() { public void observerOnStopObserving() {
// Called when the user changes host // Called when the user changes host
removeNotification(); removeNotification();
LogUtils.LOGD(TAG, "Shutting down notification service - System quit");
stopSelf();
} }
// Picasso target that will be used to load images // Picasso target that will be used to load images
@ -205,7 +130,7 @@ public class NotificationService extends Service
break; break;
case ListType.ItemsAll.TYPE_EPISODE: case ListType.ItemsAll.TYPE_EPISODE:
title = getItemResult.title; title = getItemResult.title;
String seasonEpisode = String.format(getString(R.string.season_episode_abbrev), String seasonEpisode = String.format(mContext.getString(R.string.season_episode_abbrev),
getItemResult.season, getItemResult.episode); getItemResult.season, getItemResult.episode);
underTitle = String.format("%s | %s", getItemResult.showtitle, seasonEpisode); underTitle = String.format("%s | %s", getItemResult.showtitle, seasonEpisode);
poster = getItemResult.art.poster; poster = getItemResult.art.poster;
@ -253,7 +178,7 @@ public class NotificationService extends Service
} }
// Setup the collpased and expanded notifications // Setup the collpased and expanded notifications
final RemoteViews collapsedRV = new RemoteViews(this.getPackageName(), R.layout.notification_colapsed); final RemoteViews collapsedRV = new RemoteViews(mContext.getPackageName(), R.layout.notification_colapsed);
collapsedRV.setImageViewResource(R.id.rewind, rewindIcon); collapsedRV.setImageViewResource(R.id.rewind, rewindIcon);
collapsedRV.setOnClickPendingIntent(R.id.rewind, rewindPendingItent); collapsedRV.setOnClickPendingIntent(R.id.rewind, rewindPendingItent);
collapsedRV.setImageViewResource(R.id.play, playPauseIcon); collapsedRV.setImageViewResource(R.id.play, playPauseIcon);
@ -263,7 +188,7 @@ public class NotificationService extends Service
collapsedRV.setTextViewText(R.id.title, title); collapsedRV.setTextViewText(R.id.title, title);
collapsedRV.setTextViewText(R.id.text2, underTitle); collapsedRV.setTextViewText(R.id.text2, underTitle);
final RemoteViews expandedRV = new RemoteViews(this.getPackageName(), R.layout.notification_expanded); final RemoteViews expandedRV = new RemoteViews(mContext.getPackageName(), R.layout.notification_expanded);
expandedRV.setImageViewResource(R.id.rewind, rewindIcon); expandedRV.setImageViewResource(R.id.rewind, rewindIcon);
expandedRV.setOnClickPendingIntent(R.id.rewind, rewindPendingItent); expandedRV.setOnClickPendingIntent(R.id.rewind, rewindPendingItent);
expandedRV.setImageViewResource(R.id.play, playPauseIcon); expandedRV.setImageViewResource(R.id.play, playPauseIcon);
@ -284,7 +209,7 @@ public class NotificationService extends Service
} }
// Build the notification // Build the notification
NotificationCompat.Builder builder = new NotificationCompat.Builder(this); NotificationCompat.Builder builder = new NotificationCompat.Builder(mContext);
final Notification notification = builder final Notification notification = builder
.setSmallIcon(smallIcon) .setSmallIcon(smallIcon)
.setShowWhen(false) .setShowWhen(false)
@ -314,7 +239,7 @@ public class NotificationService extends Service
// //
// 4. We specifically resize the image to the same dimensions used in // 4. We specifically resize the image to the same dimensions used in
// the remote, so that Picasso reuses it in the remote and here from the cache // the remote, so that Picasso reuses it in the remote and here from the cache
Resources resources = this.getResources(); Resources resources = mContext.getResources();
final int posterWidth = resources.getDimensionPixelOffset(R.dimen.now_playing_poster_width); final int posterWidth = resources.getDimensionPixelOffset(R.dimen.now_playing_poster_width);
final int posterHeight = isVideo? final int posterHeight = isVideo?
resources.getDimensionPixelOffset(R.dimen.now_playing_poster_height): resources.getDimensionPixelOffset(R.dimen.now_playing_poster_height):
@ -328,7 +253,7 @@ public class NotificationService extends Service
@Override @Override
public void onBitmapFailed(Drawable errorDrawable) { public void onBitmapFailed(Drawable errorDrawable) {
CharacterDrawable avatarDrawable = UIUtils.getCharacterAvatar(NotificationService.this, title); CharacterDrawable avatarDrawable = UIUtils.getCharacterAvatar(mContext, title);
showNotification(Utils.drawableToBitmap(avatarDrawable, posterWidth, posterHeight)); showNotification(Utils.drawableToBitmap(avatarDrawable, posterWidth, posterHeight));
} }
@ -342,14 +267,15 @@ public class NotificationService extends Service
expandedRV.setImageViewBitmap(expandedIconResId, bitmap); expandedRV.setImageViewBitmap(expandedIconResId, bitmap);
} }
NotificationManager notificationManager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE); NotificationManager notificationManager =
(NotificationManager)mContext.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(NOTIFICATION_ID, notification); notificationManager.notify(NOTIFICATION_ID, notification);
picassoTarget = null; picassoTarget = null;
} }
}; };
// Load the image // Load the image
HostManager hostManager = HostManager.getInstance(this); HostManager hostManager = HostManager.getInstance(mContext);
hostManager.getPicasso() hostManager.getPicasso()
.load(hostManager.getHostInfo().getImageUrl(poster)) .load(hostManager.getHostInfo().getImageUrl(poster))
.resize(posterWidth, posterHeight) .resize(posterWidth, posterHeight)
@ -358,15 +284,16 @@ public class NotificationService extends Service
} }
private PendingIntent buildActionPendingIntent(int playerId, String action) { private PendingIntent buildActionPendingIntent(int playerId, String action) {
Intent intent = new Intent(this, IntentActionsService.class) Intent intent = new Intent(mContext, IntentActionsService.class)
.setAction(action) .setAction(action)
.putExtra(IntentActionsService.EXTRA_PLAYER_ID, playerId); .putExtra(IntentActionsService.EXTRA_PLAYER_ID, playerId);
return PendingIntent.getService(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); return PendingIntent.getService(mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
} }
private void removeNotification() { private void removeNotification() {
NotificationManager notificationManager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE); NotificationManager notificationManager =
(NotificationManager)mContext.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.cancel(NOTIFICATION_ID); notificationManager.cancel(NOTIFICATION_ID);
} }
} }

View File

@ -36,38 +36,41 @@ import org.xbmc.kore.utils.LogUtils;
* The listener query Kodi's state on phone state changed event. * The listener query Kodi's state on phone state changed event.
* When a call ends we only resume if it was paused by the listener. * When a call ends we only resume if it was paused by the listener.
*/ */
public class PauseCallService extends PhoneStateListener public class PauseCallObserver extends PhoneStateListener
implements HostConnectionObserver.PlayerEventsObserver { implements HostConnectionObserver.PlayerEventsObserver {
public static final String TAG = LogUtils.makeLogTag(PauseCallService.class); public static final String TAG = LogUtils.makeLogTag(PauseCallObserver.class);
private Context context;
private int currentActivePlayerId = -1; private int currentActivePlayerId = -1;
private boolean isPlaying = false; private boolean isPlaying = false;
private boolean shouldResume = false; private boolean shouldResume = false;
public PauseCallService(Context context) { private Context mContext;
this.context = context; private HostManager mHostManager;
public PauseCallObserver(Context context) {
this.mContext = context;
mHostManager = HostManager.getInstance(context);
((TelephonyManager)mContext
.getSystemService(Context.TELEPHONY_SERVICE))
.listen(this, PhoneStateListener.LISTEN_CALL_STATE);
} }
@Override @Override
public void onCallStateChanged(int state, String incomingNumber) { public void onCallStateChanged(int state, String incomingNumber) {
// We won't create a new thread because the request to the host are
// already done in a separate thread. Just fire the request and forget
HostManager hostManager = HostManager.getInstance(context);
hostManager.getHostConnectionObserver().replyWithLastResult(this);
if (state == TelephonyManager.CALL_STATE_OFFHOOK && isPlaying) { if (state == TelephonyManager.CALL_STATE_OFFHOOK && isPlaying) {
Player.PlayPause action = new Player.PlayPause(currentActivePlayerId); Player.PlayPause action = new Player.PlayPause(currentActivePlayerId);
action.execute(hostManager.getConnection(), null, null); action.execute(mHostManager.getConnection(), null, null);
shouldResume = true; shouldResume = true;
} else if (state == TelephonyManager.CALL_STATE_IDLE && !isPlaying && shouldResume) { } else if (state == TelephonyManager.CALL_STATE_IDLE && !isPlaying && shouldResume) {
Player.PlayPause action = new Player.PlayPause(currentActivePlayerId); Player.PlayPause action = new Player.PlayPause(currentActivePlayerId);
action.execute(hostManager.getConnection(), null, null); action.execute(mHostManager.getConnection(), null, null);
shouldResume = false; shouldResume = false;
} else if (state == TelephonyManager.CALL_STATE_RINGING) { } else if (state == TelephonyManager.CALL_STATE_RINGING) {
Player.Notification action = new Player.Notification( Player.Notification action = new Player.Notification(
context.getResources().getString(R.string.pause_call_incoming_title), mContext.getResources().getString(R.string.pause_call_incoming_title),
context.getResources().getString(R.string.pause_call_incoming_message)); mContext.getResources().getString(R.string.pause_call_incoming_message));
action.execute(hostManager.getConnection(), null, null); action.execute(mHostManager.getConnection(), null, null);
} }
} }
@ -90,11 +93,18 @@ public class PauseCallService extends PhoneStateListener
isPlaying = false; isPlaying = false;
} }
private void stopListener() {
((TelephonyManager)mContext
.getSystemService(Context.TELEPHONY_SERVICE))
.listen(this, PhoneStateListener.LISTEN_NONE);
}
@Override @Override
public void playerOnStop() { public void playerOnStop() {
currentActivePlayerId = -1; currentActivePlayerId = -1;
isPlaying = false; isPlaying = false;
shouldResume = false; shouldResume = false;
stopListener();
} }
@Override @Override
@ -108,11 +118,15 @@ public class PauseCallService extends PhoneStateListener
} }
@Override @Override
public void systemOnQuit() {} public void systemOnQuit() {
playerOnStop();
}
@Override @Override
public void inputOnInputRequested(String title, String type, String value) {} public void inputOnInputRequested(String title, String type, String value) {}
@Override @Override
public void observerOnStopObserving() {} public void observerOnStopObserving() {
playerOnStop();
}
} }

View File

@ -57,8 +57,7 @@ import org.xbmc.kore.jsonrpc.type.GlobalType;
import org.xbmc.kore.jsonrpc.type.ListType; import org.xbmc.kore.jsonrpc.type.ListType;
import org.xbmc.kore.jsonrpc.type.PlayerType; import org.xbmc.kore.jsonrpc.type.PlayerType;
import org.xbmc.kore.jsonrpc.type.PlaylistType; import org.xbmc.kore.jsonrpc.type.PlaylistType;
import org.xbmc.kore.service.NotificationService; import org.xbmc.kore.service.ConnectionObserversManagerService;
import org.xbmc.kore.service.PauseCallService;
import org.xbmc.kore.ui.hosts.AddHostActivity; import org.xbmc.kore.ui.hosts.AddHostActivity;
import org.xbmc.kore.ui.hosts.AddHostFragmentFinish; import org.xbmc.kore.ui.hosts.AddHostFragmentFinish;
import org.xbmc.kore.ui.views.CirclePageIndicator; import org.xbmc.kore.ui.views.CirclePageIndicator;
@ -99,8 +98,6 @@ public class RemoteActivity extends BaseActivity
private NavigationDrawerFragment navigationDrawerFragment; private NavigationDrawerFragment navigationDrawerFragment;
private PauseCallService pauseCallService = null;
@InjectView(R.id.background_image) ImageView backgroundImage; @InjectView(R.id.background_image) ImageView backgroundImage;
@InjectView(R.id.pager_indicator) CirclePageIndicator pageIndicator; @InjectView(R.id.pager_indicator) CirclePageIndicator pageIndicator;
@InjectView(R.id.pager) ViewPager viewPager; @InjectView(R.id.pager) ViewPager viewPager;
@ -622,31 +619,32 @@ public class RemoteActivity extends BaseActivity
} }
lastImageUrl = imageUrl; lastImageUrl = imageUrl;
// Check whether we should show a notification // Start service that manages connection observers
boolean showNotification = PreferenceManager LogUtils.LOGD(TAG, "Starting observer service");
.getDefaultSharedPreferences(this) startService(new Intent(this, ConnectionObserversManagerService.class));
.getBoolean(Settings.KEY_PREF_SHOW_NOTIFICATION,
Settings.DEFAULT_PREF_SHOW_NOTIFICATION);
if (showNotification) {
// Let's start the notification service
LogUtils.LOGD(TAG, "Starting notification service");
startService(new Intent(this, NotificationService.class));
}
// Check whether we should react to phone state changes
boolean shouldPause = PreferenceManager // // Check whether we should show a notification
.getDefaultSharedPreferences(this) // boolean showNotification = PreferenceManager
.getBoolean(Settings.KEY_PREF_USE_HARDWARE_VOLUME_KEYS, // .getDefaultSharedPreferences(this)
Settings.DEFAULT_PREF_USE_HARDWARE_VOLUME_KEYS); // .getBoolean(Settings.KEY_PREF_SHOW_NOTIFICATION,
if (shouldPause) { // Settings.DEFAULT_PREF_SHOW_NOTIFICATION);
// Let's start the notification service // if (showNotification) {
LogUtils.LOGD(TAG, "Starting phone state listener"); // // Let's start the notification service
if(pauseCallService == null) { // LogUtils.LOGD(TAG, "Starting notification service");
pauseCallService = new PauseCallService(this); // startService(new Intent(this, NotificationObserver.class));
((TelephonyManager) this.getSystemService(Context.TELEPHONY_SERVICE)).listen( // }
pauseCallService, PhoneStateListener.LISTEN_CALL_STATE); //
} // // Check whether we should react to phone state changes
} // boolean shouldPause = PreferenceManager
// .getDefaultSharedPreferences(this)
// .getBoolean(Settings.KEY_PREF_USE_HARDWARE_VOLUME_KEYS,
// Settings.DEFAULT_PREF_USE_HARDWARE_VOLUME_KEYS);
// if (shouldPause) {
// // Let's start the listening service
// LogUtils.LOGD(TAG, "Starting phone state listener");
// startService(new Intent(this, PauseCallObserver.class));
// }
} }
public void playerOnPause(PlayerType.GetActivePlayersReturnType getActivePlayerResult, public void playerOnPause(PlayerType.GetActivePlayersReturnType getActivePlayerResult,
@ -656,16 +654,11 @@ public class RemoteActivity extends BaseActivity
} }
public void playerOnStop() { public void playerOnStop() {
LogUtils.LOGD(TAG, "Player stopping");
if (lastImageUrl != null) { if (lastImageUrl != null) {
setImageViewBackground(null); setImageViewBackground(null);
} }
lastImageUrl = null; lastImageUrl = null;
if(pauseCallService != null) {
((TelephonyManager) this.getSystemService(Context.TELEPHONY_SERVICE)).listen(
pauseCallService, PhoneStateListener.LISTEN_NONE);
pauseCallService = null;
}
} }
public void playerNoResultsYet() { public void playerNoResultsYet() {

View File

@ -28,6 +28,7 @@ import android.support.v4.app.TaskStackBuilder;
import org.xbmc.kore.R; import org.xbmc.kore.R;
import org.xbmc.kore.Settings; import org.xbmc.kore.Settings;
import org.xbmc.kore.host.HostManager; import org.xbmc.kore.host.HostManager;
import org.xbmc.kore.service.ConnectionObserversManagerService;
import org.xbmc.kore.utils.LogUtils; import org.xbmc.kore.utils.LogUtils;
import org.xbmc.kore.utils.UIUtils; import org.xbmc.kore.utils.UIUtils;
@ -105,6 +106,14 @@ public class SettingsFragment extends PreferenceFragment
.addNextIntent(new Intent(getActivity(), SettingsActivity.class)) .addNextIntent(new Intent(getActivity(), SettingsActivity.class))
.startActivities(); .startActivities();
} }
// If one of the settings that use the observer service are modified, restart it
if (key.equals(Settings.KEY_PREF_SHOW_NOTIFICATION) || key.equals(Settings.KEY_PREF_PAUSE_DURING_CALLS)) {
LogUtils.LOGD(TAG, "Stoping connection observer service");
Intent intent = new Intent(getActivity(), ConnectionObserversManagerService.class);
getActivity().stopService(intent);
getActivity().startService(intent);
}
} }
/** /**