Use hardware volume keys from anywhere inside Kore (#453)
* Allow the RemoteActivity and BaseMediaActivity to show a volume controller dialog when hardware volume keys are pressed ** The dialog handles the key events and makes callbacks to the activities to handle showing the dialog itself * Minor improvements ** Make HighlightButton render in the IDE GUI Editor ** Minor code cleanup ** set currentActivePlayerId = -1; on playerOnStop in BaseMediaActivity to be more consistent resolves xbmc/Kore#235
This commit is contained in:
parent
8fb24ee806
commit
108fb88b9f
|
@ -28,20 +28,15 @@ import org.xbmc.kore.utils.UIUtils;
|
||||||
*/
|
*/
|
||||||
public abstract class BaseActivity extends AppCompatActivity {
|
public abstract class BaseActivity extends AppCompatActivity {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
|
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
|
||||||
setTheme(UIUtils.getThemeResourceId(
|
setTheme(UIUtils.getThemeResourceId(
|
||||||
prefs.getString(Settings.KEY_PREF_THEME, Settings.DEFAULT_PREF_THEME)));
|
prefs.getString(Settings.KEY_PREF_THEME, Settings.DEFAULT_PREF_THEME)));
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onPause() {
|
|
||||||
super.onPause();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Override
|
// @Override
|
||||||
// public boolean onCreateOptionsMenu(Menu menu) {
|
// public boolean onCreateOptionsMenu(Menu menu) {
|
||||||
// getMenuInflater().inflate(R.menu.global, menu);
|
// getMenuInflater().inflate(R.menu.global, menu);
|
||||||
// return super.onCreateOptionsMenu(menu);
|
// return super.onCreateOptionsMenu(menu);
|
||||||
|
@ -50,8 +45,8 @@ public abstract class BaseActivity extends AppCompatActivity {
|
||||||
// @Override
|
// @Override
|
||||||
// public boolean onOptionsItemSelected(MenuItem item) {
|
// public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
// switch (item.getItemId()) {
|
// switch (item.getItemId()) {
|
||||||
// case R.id.action_settings:
|
// case R.id.action_settings:
|
||||||
// return true;
|
// return true;
|
||||||
// default:
|
// default:
|
||||||
// break;
|
// break;
|
||||||
// }
|
// }
|
||||||
|
|
|
@ -28,6 +28,7 @@ import android.support.v7.app.ActionBar;
|
||||||
import android.support.v7.widget.Toolbar;
|
import android.support.v7.widget.Toolbar;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.transition.TransitionInflater;
|
import android.transition.TransitionInflater;
|
||||||
|
import android.view.KeyEvent;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
@ -48,6 +49,9 @@ 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.ui.generic.NavigationDrawerFragment;
|
import org.xbmc.kore.ui.generic.NavigationDrawerFragment;
|
||||||
import org.xbmc.kore.ui.sections.remote.RemoteActivity;
|
import org.xbmc.kore.ui.sections.remote.RemoteActivity;
|
||||||
|
import org.xbmc.kore.ui.volumecontrollers.OnHardwareVolumeKeyPressedCallback;
|
||||||
|
import org.xbmc.kore.ui.volumecontrollers.VolumeControllerDialogFragmentListener;
|
||||||
|
import org.xbmc.kore.ui.volumecontrollers.VolumeKeyActionHandler;
|
||||||
import org.xbmc.kore.ui.widgets.MediaProgressIndicator;
|
import org.xbmc.kore.ui.widgets.MediaProgressIndicator;
|
||||||
import org.xbmc.kore.ui.widgets.NowPlayingPanel;
|
import org.xbmc.kore.ui.widgets.NowPlayingPanel;
|
||||||
import org.xbmc.kore.ui.widgets.VolumeLevelIndicator;
|
import org.xbmc.kore.ui.widgets.VolumeLevelIndicator;
|
||||||
|
@ -63,7 +67,8 @@ public abstract class BaseMediaActivity extends BaseActivity
|
||||||
implements HostConnectionObserver.ApplicationEventsObserver,
|
implements HostConnectionObserver.ApplicationEventsObserver,
|
||||||
HostConnectionObserver.PlayerEventsObserver,
|
HostConnectionObserver.PlayerEventsObserver,
|
||||||
NowPlayingPanel.OnPanelButtonsClickListener,
|
NowPlayingPanel.OnPanelButtonsClickListener,
|
||||||
MediaProgressIndicator.OnProgressChangeListener {
|
MediaProgressIndicator.OnProgressChangeListener,
|
||||||
|
OnHardwareVolumeKeyPressedCallback {
|
||||||
private static final String TAG = LogUtils.makeLogTag(BaseMediaActivity.class);
|
private static final String TAG = LogUtils.makeLogTag(BaseMediaActivity.class);
|
||||||
|
|
||||||
private static final String NAVICON_ISARROW = "navstate";
|
private static final String NAVICON_ISARROW = "navstate";
|
||||||
|
@ -79,6 +84,7 @@ public abstract class BaseMediaActivity extends BaseActivity
|
||||||
|
|
||||||
private HostManager hostManager;
|
private HostManager hostManager;
|
||||||
private HostConnectionObserver hostConnectionObserver;
|
private HostConnectionObserver hostConnectionObserver;
|
||||||
|
private VolumeKeyActionHandler volumeKeyActionHandler;
|
||||||
|
|
||||||
private boolean showNowPlayingPanel;
|
private boolean showNowPlayingPanel;
|
||||||
|
|
||||||
|
@ -180,7 +186,6 @@ public abstract class BaseMediaActivity extends BaseActivity
|
||||||
.getBoolean(Settings.KEY_PREF_SHOW_NOW_PLAYING_PANEL,
|
.getBoolean(Settings.KEY_PREF_SHOW_NOW_PLAYING_PANEL,
|
||||||
Settings.DEFAULT_PREF_SHOW_NOW_PLAYING_PANEL);
|
Settings.DEFAULT_PREF_SHOW_NOW_PLAYING_PANEL);
|
||||||
|
|
||||||
|
|
||||||
if(showNowPlayingPanel) {
|
if(showNowPlayingPanel) {
|
||||||
setupNowPlayingPanel();
|
setupNowPlayingPanel();
|
||||||
} else {
|
} else {
|
||||||
|
@ -205,6 +210,30 @@ public abstract class BaseMediaActivity extends BaseActivity
|
||||||
hostConnectionObserver.unregisterPlayerObserver(this);
|
hostConnectionObserver.unregisterPlayerObserver(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Override hardware volume keys and send to Kodi
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean dispatchKeyEvent(KeyEvent event) {
|
||||||
|
if (volumeKeyActionHandler == null) {
|
||||||
|
volumeKeyActionHandler = new VolumeKeyActionHandler(hostManager, this, this);
|
||||||
|
}
|
||||||
|
return volumeKeyActionHandler.handleDispatchKeyEvent(event) || super.dispatchKeyEvent(
|
||||||
|
event);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onHardwareVolumeKeyPressed() {
|
||||||
|
showVolumeChangeDialog();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showVolumeChangeDialog() {
|
||||||
|
VolumeControllerDialogFragmentListener volumeControllerDialogFragment =
|
||||||
|
new VolumeControllerDialogFragmentListener();
|
||||||
|
volumeControllerDialogFragment.show(getSupportFragmentManager(),
|
||||||
|
VolumeControllerDialogFragmentListener.class.getName());
|
||||||
|
}
|
||||||
|
|
||||||
public boolean getDrawerIndicatorIsArrow() {
|
public boolean getDrawerIndicatorIsArrow() {
|
||||||
return drawerIndicatorIsArrow;
|
return drawerIndicatorIsArrow;
|
||||||
}
|
}
|
||||||
|
@ -296,6 +325,7 @@ public abstract class BaseMediaActivity extends BaseActivity
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void playerOnStop() {
|
public void playerOnStop() {
|
||||||
|
currentActivePlayerId = -1;
|
||||||
//We delay hiding the panel to prevent hiding the panel when playing
|
//We delay hiding the panel to prevent hiding the panel when playing
|
||||||
// the next item in a playlist
|
// the next item in a playlist
|
||||||
callbackHandler.removeCallbacks(hidePanelRunnable);
|
callbackHandler.removeCallbacks(hidePanelRunnable);
|
||||||
|
|
|
@ -49,7 +49,6 @@ import org.xbmc.kore.jsonrpc.method.Player;
|
||||||
import org.xbmc.kore.jsonrpc.method.Playlist;
|
import org.xbmc.kore.jsonrpc.method.Playlist;
|
||||||
import org.xbmc.kore.jsonrpc.method.System;
|
import org.xbmc.kore.jsonrpc.method.System;
|
||||||
import org.xbmc.kore.jsonrpc.method.VideoLibrary;
|
import org.xbmc.kore.jsonrpc.method.VideoLibrary;
|
||||||
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;
|
||||||
|
@ -59,6 +58,9 @@ import org.xbmc.kore.ui.generic.NavigationDrawerFragment;
|
||||||
import org.xbmc.kore.ui.generic.SendTextDialogFragment;
|
import org.xbmc.kore.ui.generic.SendTextDialogFragment;
|
||||||
import org.xbmc.kore.ui.sections.hosts.AddHostActivity;
|
import org.xbmc.kore.ui.sections.hosts.AddHostActivity;
|
||||||
import org.xbmc.kore.ui.views.CirclePageIndicator;
|
import org.xbmc.kore.ui.views.CirclePageIndicator;
|
||||||
|
import org.xbmc.kore.ui.volumecontrollers.OnHardwareVolumeKeyPressedCallback;
|
||||||
|
import org.xbmc.kore.ui.volumecontrollers.VolumeControllerDialogFragmentListener;
|
||||||
|
import org.xbmc.kore.ui.volumecontrollers.VolumeKeyActionHandler;
|
||||||
import org.xbmc.kore.utils.LogUtils;
|
import org.xbmc.kore.utils.LogUtils;
|
||||||
import org.xbmc.kore.utils.TabsAdapter;
|
import org.xbmc.kore.utils.TabsAdapter;
|
||||||
import org.xbmc.kore.utils.UIUtils;
|
import org.xbmc.kore.utils.UIUtils;
|
||||||
|
@ -77,8 +79,8 @@ import butterknife.InjectView;
|
||||||
public class RemoteActivity extends BaseActivity
|
public class RemoteActivity extends BaseActivity
|
||||||
implements HostConnectionObserver.PlayerEventsObserver,
|
implements HostConnectionObserver.PlayerEventsObserver,
|
||||||
NowPlayingFragment.NowPlayingListener,
|
NowPlayingFragment.NowPlayingListener,
|
||||||
SendTextDialogFragment.SendTextDialogListener {
|
SendTextDialogFragment.SendTextDialogListener, OnHardwareVolumeKeyPressedCallback {
|
||||||
private static final String TAG = LogUtils.makeLogTag(RemoteActivity.class);
|
private static final String TAG = LogUtils.makeLogTag(RemoteActivity.class);
|
||||||
|
|
||||||
|
|
||||||
private static final int NOWPLAYING_FRAGMENT_ID = 1;
|
private static final int NOWPLAYING_FRAGMENT_ID = 1;
|
||||||
|
@ -97,6 +99,8 @@ public class RemoteActivity extends BaseActivity
|
||||||
|
|
||||||
private NavigationDrawerFragment navigationDrawerFragment;
|
private NavigationDrawerFragment navigationDrawerFragment;
|
||||||
|
|
||||||
|
private VolumeKeyActionHandler volumeKeyActionHandler;
|
||||||
|
|
||||||
@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;
|
||||||
|
@ -201,54 +205,20 @@ public class RemoteActivity extends BaseActivity
|
||||||
hostConnectionObserver = null;
|
hostConnectionObserver = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Override hardware volume keys and send to Kodi
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public boolean dispatchKeyEvent(KeyEvent event) {
|
|
||||||
// Check whether we should intercept this
|
|
||||||
boolean useVolumeKeys = PreferenceManager
|
|
||||||
.getDefaultSharedPreferences(this)
|
|
||||||
.getBoolean(Settings.KEY_PREF_USE_HARDWARE_VOLUME_KEYS,
|
|
||||||
Settings.DEFAULT_PREF_USE_HARDWARE_VOLUME_KEYS);
|
|
||||||
if (useVolumeKeys) {
|
|
||||||
int action = event.getAction();
|
|
||||||
int keyCode = event.getKeyCode();
|
|
||||||
switch (keyCode) {
|
|
||||||
case KeyEvent.KEYCODE_VOLUME_UP:
|
|
||||||
if (action == KeyEvent.ACTION_DOWN) {
|
|
||||||
new Application
|
|
||||||
.SetVolume(GlobalType.IncrementDecrement.INCREMENT)
|
|
||||||
.execute(hostManager.getConnection(), null, null);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
case KeyEvent.KEYCODE_VOLUME_DOWN:
|
|
||||||
if (action == KeyEvent.ACTION_DOWN) {
|
|
||||||
new Application
|
|
||||||
.SetVolume(GlobalType.IncrementDecrement.DECREMENT)
|
|
||||||
.execute(hostManager.getConnection(), null, null);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return super.dispatchKeyEvent(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onCreateOptionsMenu(Menu menu) {
|
public boolean onCreateOptionsMenu(Menu menu) {
|
||||||
if (!navigationDrawerFragment.isDrawerOpen()) {
|
if (!navigationDrawerFragment.isDrawerOpen()) {
|
||||||
// Only show items in the action bar relevant to this screen if the drawer is not showing.
|
// Only show items in the action bar relevant to this screen if the drawer is not showing.
|
||||||
// Otherwise, let the drawer decide what to show in the action bar.
|
// Otherwise, let the drawer decide what to show in the action bar.
|
||||||
getMenuInflater().inflate(R.menu.remote, menu);
|
getMenuInflater().inflate(R.menu.remote, menu);
|
||||||
}
|
}
|
||||||
return super.onCreateOptionsMenu(menu);
|
return super.onCreateOptionsMenu(menu);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onOptionsItemSelected(MenuItem item) {
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
// Handle action bar item clicks here.
|
// Handle action bar item clicks here.
|
||||||
switch (item.getItemId()) {
|
switch (item.getItemId()) {
|
||||||
case R.id.action_wake_up:
|
case R.id.action_wake_up:
|
||||||
UIUtils.sendWolAsync(this, hostManager.getHostInfo());
|
UIUtils.sendWolAsync(this, hostManager.getHostInfo());
|
||||||
return true;
|
return true;
|
||||||
|
@ -298,11 +268,30 @@ public class RemoteActivity extends BaseActivity
|
||||||
AudioLibrary.Scan actionScanAudio = new AudioLibrary.Scan();
|
AudioLibrary.Scan actionScanAudio = new AudioLibrary.Scan();
|
||||||
actionScanAudio.execute(hostManager.getConnection(), null, null);
|
actionScanAudio.execute(hostManager.getConnection(), null, null);
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return super.onOptionsItemSelected(item);
|
return super.onOptionsItemSelected(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Override hardware volume keys and send to Kodi
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean dispatchKeyEvent(KeyEvent event) {
|
||||||
|
if (volumeKeyActionHandler == null) {
|
||||||
|
volumeKeyActionHandler = new VolumeKeyActionHandler(hostManager, this, this);
|
||||||
|
}
|
||||||
|
return volumeKeyActionHandler.handleDispatchKeyEvent(event) || super.dispatchKeyEvent(
|
||||||
|
event);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showVolumeChangeDialog() {
|
||||||
|
VolumeControllerDialogFragmentListener volumeControllerDialogFragment =
|
||||||
|
new VolumeControllerDialogFragmentListener();
|
||||||
|
volumeControllerDialogFragment.show(getSupportFragmentManager(),
|
||||||
|
VolumeControllerDialogFragmentListener.class.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -704,4 +693,16 @@ public class RemoteActivity extends BaseActivity
|
||||||
playlistFragment.forceRefreshPlaylist();
|
playlistFragment.forceRefreshPlaylist();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onHardwareVolumeKeyPressed() {
|
||||||
|
int currentPage = viewPager.getCurrentItem();
|
||||||
|
if (!isPageWithVolumeController(currentPage)) {
|
||||||
|
showVolumeChangeDialog();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isPageWithVolumeController(int currentPage) {
|
||||||
|
return currentPage == 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
package org.xbmc.kore.ui.volumecontrollers;
|
||||||
|
|
||||||
|
public interface OnHardwareVolumeKeyPressedCallback {
|
||||||
|
void onHardwareVolumeKeyPressed();
|
||||||
|
}
|
|
@ -0,0 +1,183 @@
|
||||||
|
package org.xbmc.kore.ui.volumecontrollers;
|
||||||
|
|
||||||
|
import android.app.Dialog;
|
||||||
|
import android.content.DialogInterface;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
|
import android.support.v4.app.FragmentManager;
|
||||||
|
import android.support.v7.app.AppCompatDialogFragment;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
|
import org.xbmc.kore.R;
|
||||||
|
import org.xbmc.kore.host.HostConnectionObserver;
|
||||||
|
import org.xbmc.kore.host.HostManager;
|
||||||
|
import org.xbmc.kore.jsonrpc.ApiCallback;
|
||||||
|
import org.xbmc.kore.jsonrpc.ApiMethod;
|
||||||
|
import org.xbmc.kore.jsonrpc.method.Application;
|
||||||
|
import org.xbmc.kore.ui.widgets.HighlightButton;
|
||||||
|
import org.xbmc.kore.ui.widgets.VolumeLevelIndicator;
|
||||||
|
import org.xbmc.kore.utils.LogUtils;
|
||||||
|
|
||||||
|
import butterknife.ButterKnife;
|
||||||
|
import butterknife.InjectView;
|
||||||
|
|
||||||
|
public class VolumeControllerDialogFragmentListener extends AppCompatDialogFragment
|
||||||
|
implements HostConnectionObserver.ApplicationEventsObserver,
|
||||||
|
OnHardwareVolumeKeyPressedCallback, VolumeLevelIndicator.VolumeBarTouchTrackerListener {
|
||||||
|
|
||||||
|
private static final String TAG = LogUtils.makeLogTag(VolumeControllerDialogFragmentListener.class);
|
||||||
|
private static final int AUTO_DISMISS_DELAY = 2000;
|
||||||
|
|
||||||
|
@InjectView(R.id.npp_volume_mute)
|
||||||
|
HighlightButton volumeMuteButton;
|
||||||
|
@InjectView(R.id.npp_volume_muted_indicator)
|
||||||
|
HighlightButton volumeMutedIndicatorButton;
|
||||||
|
@InjectView(R.id.npp_volume_level_indicator)
|
||||||
|
VolumeLevelIndicator volumeLevelIndicator;
|
||||||
|
|
||||||
|
private Handler callbackHandler = new Handler();
|
||||||
|
private VolumeKeyActionHandler volumeKeyActionHandler;
|
||||||
|
private HostManager hostManager = null;
|
||||||
|
private ApiCallback<Integer> defaultIntActionCallback = ApiMethod.getDefaultActionCallback();
|
||||||
|
private View.OnClickListener onMuteToggleOnClickListener = new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
cancelDismissDialog();
|
||||||
|
Application.SetMute action = new Application.SetMute();
|
||||||
|
action.execute(hostManager.getConnection(), new ApiCallback<Boolean>() {
|
||||||
|
@Override
|
||||||
|
public void onSuccess(Boolean result) {
|
||||||
|
//We depend on the listener to correct the mute button state
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onError(int errorCode, String description) {
|
||||||
|
LogUtils.LOGE(TAG,
|
||||||
|
"Got an error calling Application.SetMute. Error code: " + errorCode +
|
||||||
|
", description: " + description);
|
||||||
|
}
|
||||||
|
}, callbackHandler);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
private long lastVolumeChangeInteractionEvent;
|
||||||
|
private Runnable dismissDialog = new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
long timeSinceLastEvent = System.currentTimeMillis() - lastVolumeChangeInteractionEvent;
|
||||||
|
if (timeSinceLastEvent >= AUTO_DISMISS_DELAY) {
|
||||||
|
Dialog dialog = getDialog();
|
||||||
|
if (dialog != null && dialog.isShowing()) {
|
||||||
|
dialog.dismiss();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onResume() {
|
||||||
|
super.onResume();
|
||||||
|
if (volumeKeyActionHandler == null) {
|
||||||
|
volumeKeyActionHandler = new VolumeKeyActionHandler(hostManager, getContext(), this);
|
||||||
|
}
|
||||||
|
getDialog().setOnKeyListener(new DialogInterface.OnKeyListener() {
|
||||||
|
@Override
|
||||||
|
public boolean onKey(android.content.DialogInterface dialog, int keyCode,
|
||||||
|
android.view.KeyEvent event) {
|
||||||
|
|
||||||
|
return volumeKeyActionHandler.handleDispatchKeyEvent(event);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
|
||||||
|
@Nullable Bundle savedInstanceState) {
|
||||||
|
View rootView = inflater.inflate(R.layout.volume_controller_dialog, container, false);
|
||||||
|
ButterKnife.inject(this, rootView);
|
||||||
|
|
||||||
|
return rootView;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void show(FragmentManager manager, String tag) {
|
||||||
|
super.show(manager, tag);
|
||||||
|
delayedDismissDialog();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
|
||||||
|
super.onViewCreated(view, savedInstanceState);
|
||||||
|
hostManager = HostManager.getInstance(getContext());
|
||||||
|
|
||||||
|
setListeners();
|
||||||
|
|
||||||
|
registerObserver();
|
||||||
|
// for orientation change
|
||||||
|
delayedDismissDialog();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void registerObserver() {
|
||||||
|
HostConnectionObserver hostConnectionObserver = hostManager.getHostConnectionObserver();
|
||||||
|
if (hostConnectionObserver == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
hostConnectionObserver.registerApplicationObserver(this, true);
|
||||||
|
hostConnectionObserver.forceRefreshResults();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setListeners() {
|
||||||
|
volumeMuteButton.setOnClickListener(onMuteToggleOnClickListener);
|
||||||
|
volumeMutedIndicatorButton.setOnClickListener(onMuteToggleOnClickListener);
|
||||||
|
|
||||||
|
volumeLevelIndicator.setOnVolumeChangeListener(
|
||||||
|
new VolumeLevelIndicator.OnVolumeChangeListener() {
|
||||||
|
@Override
|
||||||
|
public void onVolumeChanged(int volume) {
|
||||||
|
cancelDismissDialog();
|
||||||
|
new Application.SetVolume(volume).execute(hostManager.getConnection(),
|
||||||
|
defaultIntActionCallback, callbackHandler);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
volumeLevelIndicator.setVolumeBarTouchTrackerListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void applicationOnVolumeChanged(int volume, boolean muted) {
|
||||||
|
volumeLevelIndicator.setVolume(muted, volume);
|
||||||
|
|
||||||
|
volumeMutedIndicatorButton.setVisibility(muted ? View.VISIBLE : View.GONE);
|
||||||
|
volumeMutedIndicatorButton.setHighlight(muted);
|
||||||
|
|
||||||
|
volumeMuteButton.setHighlight(muted);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onHardwareVolumeKeyPressed() {
|
||||||
|
delayedDismissDialog();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void delayedDismissDialog() {
|
||||||
|
cancelDismissDialog();
|
||||||
|
callbackHandler.postDelayed(dismissDialog, AUTO_DISMISS_DELAY);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void cancelDismissDialog() {
|
||||||
|
lastVolumeChangeInteractionEvent = System.currentTimeMillis();
|
||||||
|
callbackHandler.removeCallbacks(dismissDialog);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onStartTrackingTouch() {
|
||||||
|
cancelDismissDialog();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onStopTrackingTouch() {
|
||||||
|
delayedDismissDialog();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,62 @@
|
||||||
|
package org.xbmc.kore.ui.volumecontrollers;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
|
import android.view.KeyEvent;
|
||||||
|
|
||||||
|
import org.xbmc.kore.Settings;
|
||||||
|
import org.xbmc.kore.host.HostManager;
|
||||||
|
import org.xbmc.kore.jsonrpc.method.Application;
|
||||||
|
import org.xbmc.kore.jsonrpc.type.GlobalType;
|
||||||
|
|
||||||
|
public class VolumeKeyActionHandler {
|
||||||
|
|
||||||
|
private final HostManager hostManager;
|
||||||
|
private final Context context;
|
||||||
|
private final OnHardwareVolumeKeyPressedCallback onHardwareVolumeKeyPressedCallback;
|
||||||
|
|
||||||
|
public VolumeKeyActionHandler(HostManager hostManager, Context context,
|
||||||
|
@Nullable OnHardwareVolumeKeyPressedCallback onHardwareVolumeKeyPressedCallback) {
|
||||||
|
this.hostManager = hostManager;
|
||||||
|
this.context = context;
|
||||||
|
this.onHardwareVolumeKeyPressedCallback = onHardwareVolumeKeyPressedCallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean handleDispatchKeyEvent(KeyEvent event) {
|
||||||
|
if (shouldInterceptKey()) {
|
||||||
|
int action = event.getAction();
|
||||||
|
int keyCode = event.getKeyCode();
|
||||||
|
if (keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
|
||||||
|
if (action == KeyEvent.ACTION_DOWN) {
|
||||||
|
notifyCallback();
|
||||||
|
setVolume(GlobalType.IncrementDecrement.INCREMENT);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
|
||||||
|
if (action == KeyEvent.ACTION_DOWN) {
|
||||||
|
notifyCallback();
|
||||||
|
setVolume(GlobalType.IncrementDecrement.DECREMENT);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setVolume(String volume) {
|
||||||
|
new Application.SetVolume(volume).execute(hostManager.getConnection(), null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean shouldInterceptKey() {
|
||||||
|
return android.support.v7.preference.PreferenceManager.getDefaultSharedPreferences(context)
|
||||||
|
.getBoolean(Settings.KEY_PREF_USE_HARDWARE_VOLUME_KEYS,
|
||||||
|
Settings.DEFAULT_PREF_USE_HARDWARE_VOLUME_KEYS);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void notifyCallback() {
|
||||||
|
if (onHardwareVolumeKeyPressedCallback != null) {
|
||||||
|
onHardwareVolumeKeyPressedCallback.onHardwareVolumeKeyPressed();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -23,6 +23,7 @@ import android.util.AttributeSet;
|
||||||
import org.xbmc.kore.R;
|
import org.xbmc.kore.R;
|
||||||
|
|
||||||
public class HighlightButton extends AppCompatImageButton {
|
public class HighlightButton extends AppCompatImageButton {
|
||||||
|
|
||||||
private int colorFilter;
|
private int colorFilter;
|
||||||
|
|
||||||
private boolean highlight;
|
private boolean highlight;
|
||||||
|
@ -56,10 +57,12 @@ public class HighlightButton extends AppCompatImageButton {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setStyle(Context context) {
|
private void setStyle(Context context) {
|
||||||
TypedArray styledAttributes = context.getTheme().obtainStyledAttributes(new int[]{
|
if (!this.isInEditMode()) {
|
||||||
R.attr.colorAccent});
|
TypedArray styledAttributes = context.getTheme().obtainStyledAttributes(
|
||||||
colorFilter = styledAttributes.getColor(styledAttributes.getIndex(0),
|
new int[]{R.attr.colorAccent});
|
||||||
context.getResources().getColor(R.color.accent_default));
|
colorFilter = styledAttributes.getColor(styledAttributes.getIndex(0),
|
||||||
styledAttributes.recycle();
|
context.getResources().getColor(R.color.accent_default));
|
||||||
|
styledAttributes.recycle();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,11 +33,17 @@ public class VolumeLevelIndicator extends LinearLayout {
|
||||||
@InjectView(R.id.vli_volume_text) TextView volumeTextView;
|
@InjectView(R.id.vli_volume_text) TextView volumeTextView;
|
||||||
|
|
||||||
private OnVolumeChangeListener onVolumeChangeListener;
|
private OnVolumeChangeListener onVolumeChangeListener;
|
||||||
|
private VolumeBarTouchTrackerListener volumeBarTouchTrackerListener;
|
||||||
|
|
||||||
public interface OnVolumeChangeListener {
|
public interface OnVolumeChangeListener {
|
||||||
void onVolumeChanged(int volume);
|
void onVolumeChanged(int volume);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public interface VolumeBarTouchTrackerListener {
|
||||||
|
void onStartTrackingTouch();
|
||||||
|
void onStopTrackingTouch();
|
||||||
|
}
|
||||||
|
|
||||||
public VolumeLevelIndicator(Context context) {
|
public VolumeLevelIndicator(Context context) {
|
||||||
super(context);
|
super(context);
|
||||||
initializeView(context);
|
initializeView(context);
|
||||||
|
@ -67,13 +73,19 @@ public class VolumeLevelIndicator extends LinearLayout {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onStartTrackingTouch(SeekBar seekBar) {
|
public void onStartTrackingTouch(SeekBar seekBar) {
|
||||||
|
if (volumeBarTouchTrackerListener != null) {
|
||||||
|
volumeBarTouchTrackerListener.onStartTrackingTouch();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onStopTrackingTouch(SeekBar seekBar) {
|
public void onStopTrackingTouch(SeekBar seekBar) {
|
||||||
if (onVolumeChangeListener != null)
|
if (onVolumeChangeListener != null) {
|
||||||
onVolumeChangeListener.onVolumeChanged(seekBar.getProgress());
|
onVolumeChangeListener.onVolumeChanged(seekBar.getProgress());
|
||||||
|
if (volumeBarTouchTrackerListener != null) {
|
||||||
|
volumeBarTouchTrackerListener.onStopTrackingTouch();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -82,6 +94,11 @@ public class VolumeLevelIndicator extends LinearLayout {
|
||||||
this.onVolumeChangeListener = onVolumeChangeListener;
|
this.onVolumeChangeListener = onVolumeChangeListener;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setVolumeBarTouchTrackerListener(
|
||||||
|
VolumeBarTouchTrackerListener volumeBarTouchTrackerListener) {
|
||||||
|
this.volumeBarTouchTrackerListener = volumeBarTouchTrackerListener;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets UI volume state
|
* Sets UI volume state
|
||||||
* @param muted
|
* @param muted
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="?attr/contentBackgroundColor"
|
||||||
|
android:minWidth="200dp"
|
||||||
|
tools:background="@color/dark_content_background_dim_70pct">
|
||||||
|
|
||||||
|
<org.xbmc.kore.ui.widgets.HighlightButton
|
||||||
|
android:id="@+id/npp_volume_mute"
|
||||||
|
style="@style/Widget.Button.Borderless"
|
||||||
|
android:layout_width="@dimen/default_icon_size"
|
||||||
|
android:layout_height="@dimen/default_icon_size"
|
||||||
|
android:contentDescription="@string/volume_mute"
|
||||||
|
android:src="?attr/iconVolumeMute"
|
||||||
|
tools:src="@drawable/ic_volume_off_white_24dp" />
|
||||||
|
|
||||||
|
<org.xbmc.kore.ui.widgets.HighlightButton
|
||||||
|
android:id="@+id/npp_volume_muted_indicator"
|
||||||
|
style="@style/Widget.Button.Borderless"
|
||||||
|
android:layout_width="@dimen/default_icon_size"
|
||||||
|
android:layout_height="@dimen/default_icon_size"
|
||||||
|
android:contentDescription="@string/volume_mute"
|
||||||
|
android:src="?attr/iconVolumeMute"
|
||||||
|
android:visibility="gone"
|
||||||
|
tools:src="@drawable/ic_volume_off_white_24dp" />
|
||||||
|
|
||||||
|
<org.xbmc.kore.ui.widgets.VolumeLevelIndicator
|
||||||
|
android:id="@+id/npp_volume_level_indicator"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:layout_toRightOf="@id/npp_volume_mute"
|
||||||
|
android:orientation="vertical">
|
||||||
|
</org.xbmc.kore.ui.widgets.VolumeLevelIndicator>
|
||||||
|
</RelativeLayout>
|
Loading…
Reference in New Issue