Changed PauseCallService from BroadcastReceiver to PhoneStateListener

This commit is contained in:
Tomer Froumin 2016-02-05 17:03:05 +02:00
parent 2e7ac6af80
commit e67516559d
5 changed files with 59 additions and 75 deletions

View File

@ -71,13 +71,6 @@
<service android:name="org.xbmc.kore.service.IntentActionsService" <service android:name="org.xbmc.kore.service.IntentActionsService"
android:exported="false"/> android:exported="false"/>
<!-- Receivers -->
<receiver android:name="org.xbmc.kore.service.PauseCallService">
<intent-filter>
<action android:name="android.intent.action.PHONE_STATE"/>
</intent-filter>
</receiver>
<uses-library android:required="false" android:name="com.sec.android.app.multiwindow"/> <uses-library android:required="false" android:name="com.sec.android.app.multiwindow"/>
<meta-data android:name="com.sec.android.support.multiwindow" android:value="true" /> <meta-data android:name="com.sec.android.support.multiwindow" android:value="true" />
<meta-data android:name="com.sec.android.multiwindow.DEFAULT_SIZE_W" android:value="632.0dip" /> <meta-data android:name="com.sec.android.multiwindow.DEFAULT_SIZE_W" android:value="632.0dip" />

View File

@ -55,7 +55,7 @@ public class Settings {
// Pause during calls // Pause during calls
public static final String KEY_PREF_PAUSE_DURING_CALLS = "pref_pause_during_calls"; public static final String KEY_PREF_PAUSE_DURING_CALLS = "pref_pause_during_calls";
public static final boolean DEFAULT_PREF_PAUSE_DURING_CALLS = true; public static final boolean DEFAULT_PREF_PAUSE_DURING_CALLS = false;
// Other keys used in preferences.xml // Other keys used in preferences.xml
public static final String KEY_PREF_ABOUT = "pref_about"; public static final String KEY_PREF_ABOUT = "pref_about";

View File

@ -15,14 +15,11 @@
*/ */
package org.xbmc.kore.service; package org.xbmc.kore.service;
import android.content.BroadcastReceiver;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.telephony.PhoneStateListener;
import android.preference.PreferenceManager;
import android.telephony.TelephonyManager; import android.telephony.TelephonyManager;
import org.xbmc.kore.R; import org.xbmc.kore.R;
import org.xbmc.kore.Settings;
import org.xbmc.kore.host.HostConnectionObserver; import org.xbmc.kore.host.HostConnectionObserver;
import org.xbmc.kore.host.HostManager; import org.xbmc.kore.host.HostManager;
import org.xbmc.kore.jsonrpc.method.Player; import org.xbmc.kore.jsonrpc.method.Player;
@ -31,77 +28,42 @@ import org.xbmc.kore.jsonrpc.type.PlayerType;
import org.xbmc.kore.utils.LogUtils; import org.xbmc.kore.utils.LogUtils;
/** /**
* This service maintains a notification in the notification area while * This listener handles changes to the phone state, such as receiving a
* something is playing, and keeps running while it is playing. * call or hanging up, and synchronizes Kodi's currently playing state
* This service stops itself as soon as the playing stops or there's no * in order to prevent missing the movie (or what's playing) while the
* connection. Thus, this should only be started if something is already * viewer is talking on the phone.
* 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 * The listener query Kodi's state on phone state changed event.
* state. This singleton should be the same as used in the app's activities * When a call ends we only resume if it was paused by the listener.
*/ */
public class PauseCallService extends BroadcastReceiver public class PauseCallService extends PhoneStateListener
implements HostConnectionObserver.PlayerEventsObserver { implements HostConnectionObserver.PlayerEventsObserver {
public static final String TAG = LogUtils.makeLogTag(PauseCallService.class); public static final String TAG = LogUtils.makeLogTag(PauseCallService.class);
private static int lastState = TelephonyManager.CALL_STATE_IDLE; private Context context;
private static HostConnectionObserver mHostConnectionObserver = null; private int currentActivePlayerId = -1;
private static int currentActivePlayerId = -1; private boolean isPlaying = false;
private static boolean isPlaying = false; private boolean shouldResume = false;
private static boolean shouldResume = false;
@Override public PauseCallService(Context context) {
public void onReceive(Context context, Intent intent) { this.context = context;
// Check whether we should react to phone state changes
boolean shouldPause = PreferenceManager
.getDefaultSharedPreferences(context)
.getBoolean(Settings.KEY_PREF_PAUSE_DURING_CALLS, Settings.DEFAULT_PREF_PAUSE_DURING_CALLS);
if(!shouldPause) return;
int state = 0;
String stateStr = intent.getExtras().getString(TelephonyManager.EXTRA_STATE);
LogUtils.LOGD(TAG, "onReceive " + stateStr);
// The phone state changed from in call to idle
if(stateStr.equals(TelephonyManager.EXTRA_STATE_IDLE)) {
state = TelephonyManager.CALL_STATE_IDLE;
}
// The phone state changed from idle to in call
else if(stateStr.equals(TelephonyManager.EXTRA_STATE_OFFHOOK)) {
state = TelephonyManager.CALL_STATE_OFFHOOK;
}
// The phone state changed from idle to ringing
else if(stateStr.equals(TelephonyManager.EXTRA_STATE_RINGING)) {
state = TelephonyManager.CALL_STATE_RINGING;
}
if(state == lastState) return;
handleState(context, state);
lastState = state;
} }
protected void handleState(Context context, int state) { @Override
public void onCallStateChanged(int state, String incomingNumber) {
// We won't create a new thread because the request to the host are // 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 // already done in a separate thread. Just fire the request and forget
HostManager hostManager = HostManager.getInstance(context); HostManager hostManager = HostManager.getInstance(context);
if (mHostConnectionObserver != null) { hostManager.getHostConnectionObserver().replyWithLastResult(this);
mHostConnectionObserver.unregisterPlayerObserver(this);
}
mHostConnectionObserver = hostManager.getHostConnectionObserver();
mHostConnectionObserver.registerPlayerObserver(this, true);
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(hostManager.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(hostManager.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), context.getResources().getString(R.string.pause_call_incoming_title),
context.getResources().getString(R.string.pause_call_incoming_message)); context.getResources().getString(R.string.pause_call_incoming_message));
@ -121,17 +83,18 @@ public class PauseCallService extends BroadcastReceiver
public void playerOnPause(PlayerType.GetActivePlayersReturnType getActivePlayerResult, public void playerOnPause(PlayerType.GetActivePlayersReturnType getActivePlayerResult,
PlayerType.PropertyValue getPropertiesResult, PlayerType.PropertyValue getPropertiesResult,
ListType.ItemsAll getItemResult) { ListType.ItemsAll getItemResult) {
if(currentActivePlayerId != getActivePlayerResult.playerid) {
shouldResume = false;
}
currentActivePlayerId = getActivePlayerResult.playerid; currentActivePlayerId = getActivePlayerResult.playerid;
isPlaying = false; isPlaying = false;
} }
@Override @Override
public void playerOnStop() { public void playerOnStop() {
if (mHostConnectionObserver != null) {
mHostConnectionObserver.unregisterPlayerObserver(this);
}
currentActivePlayerId = -1; currentActivePlayerId = -1;
isPlaying = false; isPlaying = false;
shouldResume = false;
} }
@Override @Override
@ -140,13 +103,13 @@ public class PauseCallService extends BroadcastReceiver
} }
@Override @Override
public void playerNoResultsYet() {} public void playerNoResultsYet() {
@Override
public void systemOnQuit() {
playerOnStop(); playerOnStop();
} }
@Override
public void systemOnQuit() {}
@Override @Override
public void inputOnInputRequested(String title, String type, String value) {} public void inputOnInputRequested(String title, String type, String value) {}

View File

@ -15,6 +15,7 @@
*/ */
package org.xbmc.kore.ui; package org.xbmc.kore.ui;
import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.graphics.Point; import android.graphics.Point;
@ -26,6 +27,8 @@ import android.support.v4.view.ViewPager;
import android.support.v4.widget.DrawerLayout; import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBar; import android.support.v7.app.ActionBar;
import android.support.v7.widget.Toolbar; import android.support.v7.widget.Toolbar;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.text.TextUtils; import android.text.TextUtils;
import android.view.KeyEvent; import android.view.KeyEvent;
import android.view.Menu; import android.view.Menu;
@ -53,6 +56,7 @@ 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.NotificationService;
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;
@ -88,6 +92,8 @@ 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;
@ -614,12 +620,28 @@ public class RemoteActivity extends BaseActivity
// Check whether we should show a notification // Check whether we should show a notification
boolean showNotification = PreferenceManager boolean showNotification = PreferenceManager
.getDefaultSharedPreferences(this) .getDefaultSharedPreferences(this)
.getBoolean(Settings.KEY_PREF_SHOW_NOTIFICATION, Settings.DEFAULT_PREF_SHOW_NOTIFICATION); .getBoolean(Settings.KEY_PREF_SHOW_NOTIFICATION,
Settings.DEFAULT_PREF_SHOW_NOTIFICATION);
if (showNotification) { if (showNotification) {
// Let's start the notification service // Let's start the notification service
LogUtils.LOGD(TAG, "Starting notification service"); LogUtils.LOGD(TAG, "Starting notification service");
startService(new Intent(this, NotificationService.class)); startService(new Intent(this, NotificationService.class));
} }
// 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 notification service
LogUtils.LOGD(TAG, "Starting phone state listener");
if(pauseCallService == null) {
pauseCallService = new PauseCallService(this);
((TelephonyManager) this.getSystemService(Context.TELEPHONY_SERVICE)).listen(
pauseCallService, PhoneStateListener.LISTEN_CALL_STATE);
}
}
} }
public void playerOnPause(PlayerType.GetActivePlayersReturnType getActivePlayerResult, public void playerOnPause(PlayerType.GetActivePlayersReturnType getActivePlayerResult,
@ -633,6 +655,12 @@ public class RemoteActivity extends BaseActivity
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

@ -37,7 +37,7 @@
<SwitchPreference <SwitchPreference
android:key="pref_pause_during_calls" android:key="pref_pause_during_calls"
android:title="@string/pause_during_calls" android:title="@string/pause_during_calls"
android:defaultValue="true"/> android:defaultValue="false"/>
<SwitchPreference <SwitchPreference
android:key="pref_use_hardware_volume_keys" android:key="pref_use_hardware_volume_keys"