Added proper screen rotation handling.
This commit is contained in:
parent
838ad69360
commit
8ec6b90e92
6 changed files with 227 additions and 60 deletions
|
@ -33,6 +33,7 @@ import org.teleal.cling.support.model.item.Item;
|
||||||
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.v4.app.Fragment;
|
import android.support.v4.app.Fragment;
|
||||||
|
import android.support.v4.app.FragmentManager;
|
||||||
import android.support.v4.app.FragmentStatePagerAdapter;
|
import android.support.v4.app.FragmentStatePagerAdapter;
|
||||||
import android.support.v4.app.FragmentTransaction;
|
import android.support.v4.app.FragmentTransaction;
|
||||||
import android.support.v4.view.ViewPager;
|
import android.support.v4.view.ViewPager;
|
||||||
|
@ -66,7 +67,7 @@ public class MainActivity extends ActionBarActivity {
|
||||||
public Fragment getItem(int position) {
|
public Fragment getItem(int position) {
|
||||||
switch (position) {
|
switch (position) {
|
||||||
case 0: return mServerFragment;
|
case 0: return mServerFragment;
|
||||||
case 1: return mRendererFragment;
|
case 1: return mRouteFragment;
|
||||||
default: return null;
|
default: return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -78,9 +79,9 @@ public class MainActivity extends ActionBarActivity {
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
private ServerFragment mServerFragment = new ServerFragment();
|
private ServerFragment mServerFragment;
|
||||||
|
|
||||||
private RouteFragment mRendererFragment = new RouteFragment();
|
private RouteFragment mRouteFragment;
|
||||||
|
|
||||||
ViewPager mViewPager;
|
ViewPager mViewPager;
|
||||||
|
|
||||||
|
@ -88,7 +89,7 @@ public class MainActivity extends ActionBarActivity {
|
||||||
* Initializes tab navigation.
|
* Initializes tab navigation.
|
||||||
*/
|
*/
|
||||||
public void onCreate(Bundle savedInstanceState) {
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
final ActionBar actionBar = getSupportActionBar();
|
final ActionBar actionBar = getSupportActionBar();
|
||||||
|
|
||||||
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
|
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
|
||||||
|
@ -125,7 +126,30 @@ public class MainActivity extends ActionBarActivity {
|
||||||
.setTabListener(tabListener));
|
.setTabListener(tabListener));
|
||||||
actionBar.addTab(actionBar.newTab()
|
actionBar.addTab(actionBar.newTab()
|
||||||
.setText(R.string.title_renderer)
|
.setText(R.string.title_renderer)
|
||||||
.setTabListener(tabListener));
|
.setTabListener(tabListener));
|
||||||
|
|
||||||
|
if (savedInstanceState != null) {
|
||||||
|
FragmentManager fm = getSupportFragmentManager();
|
||||||
|
mServerFragment = (ServerFragment) fm.getFragment(
|
||||||
|
savedInstanceState, ServerFragment.class.getName());
|
||||||
|
mRouteFragment = (RouteFragment) fm.getFragment(
|
||||||
|
savedInstanceState, RouteFragment.class.getName());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
mServerFragment = new ServerFragment();
|
||||||
|
mRouteFragment = new RouteFragment();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Saves fragments.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected void onSaveInstanceState(Bundle outState) {
|
||||||
|
super.onSaveInstanceState(outState);
|
||||||
|
FragmentManager fm = getSupportFragmentManager();
|
||||||
|
fm.putFragment(outState, ServerFragment.class.getName(), mServerFragment);
|
||||||
|
fm.putFragment(outState, RouteFragment.class.getName(), mRouteFragment);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -148,11 +172,11 @@ public class MainActivity extends ActionBarActivity {
|
||||||
switch (event.getKeyCode()) {
|
switch (event.getKeyCode()) {
|
||||||
case KeyEvent.KEYCODE_VOLUME_UP:
|
case KeyEvent.KEYCODE_VOLUME_UP:
|
||||||
if (event.getAction() == KeyEvent.ACTION_DOWN)
|
if (event.getAction() == KeyEvent.ACTION_DOWN)
|
||||||
mRendererFragment.increaseVolume();
|
mRouteFragment.increaseVolume();
|
||||||
return true;
|
return true;
|
||||||
case KeyEvent.KEYCODE_VOLUME_DOWN:
|
case KeyEvent.KEYCODE_VOLUME_DOWN:
|
||||||
if (event.getAction() == KeyEvent.ACTION_DOWN)
|
if (event.getAction() == KeyEvent.ACTION_DOWN)
|
||||||
mRendererFragment.decreaseVolume();
|
mRouteFragment.decreaseVolume();
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
return super.dispatchKeyEvent(event);
|
return super.dispatchKeyEvent(event);
|
||||||
|
@ -164,7 +188,7 @@ public class MainActivity extends ActionBarActivity {
|
||||||
*/
|
*/
|
||||||
public void play(List<Item> playlist, int start) {
|
public void play(List<Item> playlist, int start) {
|
||||||
mViewPager.setCurrentItem(1);
|
mViewPager.setCurrentItem(1);
|
||||||
mRendererFragment.play(playlist, start);
|
mRouteFragment.play(playlist, start);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -107,7 +107,8 @@ public class RouteFragment extends MediaRouteDiscoveryFragment implements
|
||||||
|
|
||||||
public void onServiceConnected(ComponentName className, IBinder service) {
|
public void onServiceConnected(ComponentName className, IBinder service) {
|
||||||
mMediaRouterPlayService = (MediaRouterPlayServiceBinder) service;
|
mMediaRouterPlayService = (MediaRouterPlayServiceBinder) service;
|
||||||
mMediaRouterPlayService.getService().setRendererFragment(RouteFragment.this);
|
mMediaRouterPlayService.getService().setRouterFragment(RouteFragment.this);
|
||||||
|
mPlaylistAdapter.addAll(mMediaRouterPlayService.getService().getPlaylist());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onServiceDisconnected(ComponentName className) {
|
public void onServiceDisconnected(ComponentName className) {
|
||||||
|
@ -140,6 +141,8 @@ public class RouteFragment extends MediaRouteDiscoveryFragment implements
|
||||||
super.onActivityCreated(savedInstanceState);
|
super.onActivityCreated(savedInstanceState);
|
||||||
|
|
||||||
mRouteAdapter = new RouteAdapter(getActivity());
|
mRouteAdapter = new RouteAdapter(getActivity());
|
||||||
|
mRouteAdapter.addAll(MediaRouter.getInstance(getActivity()).getRoutes());
|
||||||
|
mRouteAdapter.remove(MediaRouter.getInstance(getActivity()).getDefaultRoute());
|
||||||
mPlaylistAdapter = new FileArrayAdapter(getActivity());
|
mPlaylistAdapter = new FileArrayAdapter(getActivity());
|
||||||
|
|
||||||
mListView = (ListView) getView().findViewById(R.id.listview);
|
mListView = (ListView) getView().findViewById(R.id.listview);
|
||||||
|
@ -163,11 +166,36 @@ public class RouteFragment extends MediaRouteDiscoveryFragment implements
|
||||||
mPlayPause.setOnClickListener(this);
|
mPlayPause.setOnClickListener(this);
|
||||||
mPlayPause.setImageResource(R.drawable.ic_media_play);
|
mPlayPause.setImageResource(R.drawable.ic_media_play);
|
||||||
|
|
||||||
getActivity().bindService(
|
getActivity().getApplicationContext().startService(
|
||||||
new Intent(getActivity(), MediaRouterPlayService.class),
|
new Intent(getActivity(), MediaRouterPlayService.class));
|
||||||
mPlayServiceConnection,
|
getActivity().getApplicationContext().bindService(
|
||||||
Context.BIND_AUTO_CREATE
|
new Intent(getActivity(), MediaRouterPlayService.class),
|
||||||
|
mPlayServiceConnection,
|
||||||
|
Context.BIND_AUTO_CREATE
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (savedInstanceState != null) {
|
||||||
|
mListView.onRestoreInstanceState(savedInstanceState.getParcelable("list_state"));
|
||||||
|
if (savedInstanceState.getBoolean("route_selected")) {
|
||||||
|
mRouteSelected = true;
|
||||||
|
mListView.setAdapter(mPlaylistAdapter);
|
||||||
|
mControls.setVisibility(View.VISIBLE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSaveInstanceState(Bundle outState) {
|
||||||
|
super.onSaveInstanceState(outState);
|
||||||
|
|
||||||
|
outState.putBoolean("route_selected", mRouteSelected);
|
||||||
|
outState.putParcelable("list_state", mListView.onSaveInstanceState());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDestroy() {
|
||||||
|
super.onDestroy();
|
||||||
|
getActivity().getApplicationContext().unbindService(mPlayServiceConnection);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -241,9 +269,7 @@ public class RouteFragment extends MediaRouteDiscoveryFragment implements
|
||||||
mRouteSelected = true;
|
mRouteSelected = true;
|
||||||
mListView.setAdapter(mPlaylistAdapter);
|
mListView.setAdapter(mPlaylistAdapter);
|
||||||
mControls.setVisibility(View.VISIBLE);
|
mControls.setVisibility(View.VISIBLE);
|
||||||
if (mStartPlayingOnSelect == -1)
|
if (mStartPlayingOnSelect != -1) {
|
||||||
mPlaylistAdapter.clear();
|
|
||||||
else {
|
|
||||||
mMediaRouterPlayService.getService().play(mStartPlayingOnSelect);
|
mMediaRouterPlayService.getService().play(mStartPlayingOnSelect);
|
||||||
mStartPlayingOnSelect = -1;
|
mStartPlayingOnSelect = -1;
|
||||||
}
|
}
|
||||||
|
@ -256,7 +282,7 @@ public class RouteFragment extends MediaRouteDiscoveryFragment implements
|
||||||
* Sets colored background on the item that is currently playing.
|
* Sets colored background on the item that is currently playing.
|
||||||
*/
|
*/
|
||||||
private void enableTrackHighlight() {
|
private void enableTrackHighlight() {
|
||||||
if (mListView.getAdapter() == mRouteAdapter)
|
if (mListView.getAdapter() == mRouteAdapter || mMediaRouterPlayService == null || !isVisible())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
disableTrackHighlight();
|
disableTrackHighlight();
|
||||||
|
|
|
@ -31,18 +31,28 @@ import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Stack;
|
import java.util.Stack;
|
||||||
|
|
||||||
|
import org.teleal.cling.android.AndroidUpnpService;
|
||||||
|
import org.teleal.cling.android.AndroidUpnpServiceImpl;
|
||||||
import org.teleal.cling.model.action.ActionInvocation;
|
import org.teleal.cling.model.action.ActionInvocation;
|
||||||
import org.teleal.cling.model.message.UpnpResponse;
|
import org.teleal.cling.model.message.UpnpResponse;
|
||||||
import org.teleal.cling.model.meta.Device;
|
import org.teleal.cling.model.meta.Device;
|
||||||
|
import org.teleal.cling.model.meta.LocalDevice;
|
||||||
|
import org.teleal.cling.model.meta.RemoteDevice;
|
||||||
import org.teleal.cling.model.meta.Service;
|
import org.teleal.cling.model.meta.Service;
|
||||||
import org.teleal.cling.model.types.ServiceType;
|
import org.teleal.cling.model.types.ServiceType;
|
||||||
|
import org.teleal.cling.model.types.UDN;
|
||||||
import org.teleal.cling.support.contentdirectory.callback.Browse;
|
import org.teleal.cling.support.contentdirectory.callback.Browse;
|
||||||
import org.teleal.cling.support.model.BrowseFlag;
|
import org.teleal.cling.support.model.BrowseFlag;
|
||||||
import org.teleal.cling.support.model.DIDLContent;
|
import org.teleal.cling.support.model.DIDLContent;
|
||||||
import org.teleal.cling.support.model.container.Container;
|
import org.teleal.cling.support.model.container.Container;
|
||||||
import org.teleal.cling.support.model.item.Item;
|
import org.teleal.cling.support.model.item.Item;
|
||||||
|
|
||||||
|
import android.content.ComponentName;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.ServiceConnection;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.os.IBinder;
|
||||||
import android.os.Parcelable;
|
import android.os.Parcelable;
|
||||||
import android.support.v4.app.ListFragment;
|
import android.support.v4.app.ListFragment;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
@ -50,7 +60,6 @@ import android.view.View;
|
||||||
import android.widget.ListView;
|
import android.widget.ListView;
|
||||||
|
|
||||||
import com.github.nutomic.controldlna.gui.MainActivity.OnBackPressedListener;
|
import com.github.nutomic.controldlna.gui.MainActivity.OnBackPressedListener;
|
||||||
import com.github.nutomic.controldlna.upnp.UpnpController;
|
|
||||||
import com.github.nutomic.controldlna.utility.DeviceArrayAdapter;
|
import com.github.nutomic.controldlna.utility.DeviceArrayAdapter;
|
||||||
import com.github.nutomic.controldlna.utility.FileArrayAdapter;
|
import com.github.nutomic.controldlna.utility.FileArrayAdapter;
|
||||||
|
|
||||||
|
@ -78,6 +87,8 @@ public class ServerFragment extends ListFragment implements OnBackPressedListene
|
||||||
*/
|
*/
|
||||||
private Device<?, ?, ?> mCurrentServer;
|
private Device<?, ?, ?> mCurrentServer;
|
||||||
|
|
||||||
|
private String mRestoreServer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ListView adapter for showing a list of files/folders.
|
* ListView adapter for showing a list of files/folders.
|
||||||
*/
|
*/
|
||||||
|
@ -94,10 +105,40 @@ public class ServerFragment extends ListFragment implements OnBackPressedListene
|
||||||
*/
|
*/
|
||||||
private Stack<Parcelable> mListState = new Stack<Parcelable>();
|
private Stack<Parcelable> mListState = new Stack<Parcelable>();
|
||||||
|
|
||||||
/**
|
protected AndroidUpnpService mUpnpService;
|
||||||
* Manages all UPNP connections including playback.
|
|
||||||
*/
|
private ServiceConnection mUpnpServiceConnection = new ServiceConnection() {
|
||||||
private UpnpController mController = new UpnpController();
|
|
||||||
|
/**
|
||||||
|
* Registers DeviceListener, adds known devices and starts search if requested.
|
||||||
|
*/
|
||||||
|
public void onServiceConnected(ComponentName className, IBinder service) {
|
||||||
|
mUpnpService = (AndroidUpnpService) service;
|
||||||
|
mUpnpService.getRegistry().addListener(mServerAdapter);
|
||||||
|
for (Device<?, ?, ?> d : mUpnpService.getControlPoint().getRegistry().getDevices()) {
|
||||||
|
if (d instanceof LocalDevice)
|
||||||
|
mServerAdapter.localDeviceAdded(mUpnpService.getRegistry(), (LocalDevice) d);
|
||||||
|
else
|
||||||
|
mServerAdapter.remoteDeviceAdded(mUpnpService.getRegistry(), (RemoteDevice) d);
|
||||||
|
}
|
||||||
|
Log.i(TAG, "Starting device search");
|
||||||
|
mUpnpService.getControlPoint().search();
|
||||||
|
|
||||||
|
if (mRestoreServer != null) {
|
||||||
|
mCurrentServer = mUpnpService.getControlPoint().getRegistry()
|
||||||
|
.getDevice(new UDN(mRestoreServer.replace("uuid:", "")), false);
|
||||||
|
if (mCurrentServer != null) {
|
||||||
|
setListAdapter(mFileAdapter);
|
||||||
|
getFiles(true);
|
||||||
|
}
|
||||||
|
getListView().onRestoreInstanceState(mListState.lastElement());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onServiceDisconnected(ComponentName className) {
|
||||||
|
mUpnpService = null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes ListView adapters, launches Cling UPNP service.
|
* Initializes ListView adapters, launches Cling UPNP service.
|
||||||
|
@ -110,26 +151,44 @@ public class ServerFragment extends ListFragment implements OnBackPressedListene
|
||||||
mServerAdapter = new DeviceArrayAdapter(
|
mServerAdapter = new DeviceArrayAdapter(
|
||||||
getActivity(), DeviceArrayAdapter.SERVER);
|
getActivity(), DeviceArrayAdapter.SERVER);
|
||||||
setListAdapter(mServerAdapter);
|
setListAdapter(mServerAdapter);
|
||||||
mController.open(getActivity());
|
getActivity().getApplicationContext().bindService(
|
||||||
mController.addCallback(mServerAdapter);
|
new Intent(getActivity(), AndroidUpnpServiceImpl.class),
|
||||||
|
mUpnpServiceConnection,
|
||||||
|
Context.BIND_AUTO_CREATE
|
||||||
|
);
|
||||||
|
|
||||||
|
if (savedInstanceState != null) {
|
||||||
|
mRestoreServer = savedInstanceState.getString("current_server");
|
||||||
|
mCurrentPath.addAll(savedInstanceState.getStringArrayList("path"));
|
||||||
|
mListState.addAll(savedInstanceState.getParcelableArrayList("list_state"));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
mListState.push(getListView().onSaveInstanceState());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onResume() {
|
public void onSaveInstanceState(Bundle outState) {
|
||||||
super.onResume();
|
super.onSaveInstanceState(outState);
|
||||||
mController.startSearch();
|
outState.putString("current_server", (mCurrentServer != null)
|
||||||
|
? mCurrentServer.getIdentity().getUdn().toString()
|
||||||
|
: "");
|
||||||
|
outState.putStringArrayList("path", new ArrayList<String>(mCurrentPath));
|
||||||
|
mListState.pop();
|
||||||
|
mListState.push(getListView().onSaveInstanceState());
|
||||||
|
outState.putParcelableArrayList("list_state", new ArrayList<Parcelable>(mListState));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPause() {
|
public void onPause() {
|
||||||
super.onPause();
|
super.onPause();
|
||||||
mController.stopSearch();
|
mListState.pop();
|
||||||
|
mListState.push(getListView().onSaveInstanceState());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDestroy() {
|
public void onDestroy() {
|
||||||
super.onDestroy();
|
super.onDestroy();
|
||||||
mController.close(getActivity());
|
getActivity().getApplicationContext().unbindService(mUpnpServiceConnection);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -175,7 +234,7 @@ public class ServerFragment extends ListFragment implements OnBackPressedListene
|
||||||
private void getFiles(final boolean restoreListState) {
|
private void getFiles(final boolean restoreListState) {
|
||||||
Service<?, ?> service = mCurrentServer.findService(
|
Service<?, ?> service = mCurrentServer.findService(
|
||||||
new ServiceType("schemas-upnp-org", "ContentDirectory"));
|
new ServiceType("schemas-upnp-org", "ContentDirectory"));
|
||||||
mController.execute(new Browse(service,
|
mUpnpService.getControlPoint().execute(new Browse(service,
|
||||||
mCurrentPath.peek(), BrowseFlag.DIRECT_CHILDREN) {
|
mCurrentPath.peek(), BrowseFlag.DIRECT_CHILDREN) {
|
||||||
|
|
||||||
@SuppressWarnings("rawtypes")
|
@SuppressWarnings("rawtypes")
|
||||||
|
@ -192,7 +251,7 @@ public class ServerFragment extends ListFragment implements OnBackPressedListene
|
||||||
for (Item i : didl.getItems())
|
for (Item i : didl.getItems())
|
||||||
mFileAdapter.add(i);
|
mFileAdapter.add(i);
|
||||||
if (restoreListState)
|
if (restoreListState)
|
||||||
getListView().onRestoreInstanceState(mListState.pop());
|
getListView().onRestoreInstanceState(mListState.peek());
|
||||||
else
|
else
|
||||||
getListView().setSelectionFromTop(0, 0);
|
getListView().setSelectionFromTop(0, 0);
|
||||||
}
|
}
|
||||||
|
@ -223,14 +282,14 @@ public class ServerFragment extends ListFragment implements OnBackPressedListene
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
mCurrentPath.pop();
|
mCurrentPath.pop();
|
||||||
|
mListState.pop();
|
||||||
if (mCurrentPath.empty()) {
|
if (mCurrentPath.empty()) {
|
||||||
setListAdapter(mServerAdapter);
|
setListAdapter(mServerAdapter);
|
||||||
getListView().onRestoreInstanceState(mListState.pop());
|
getListView().onRestoreInstanceState(mListState.peek());
|
||||||
mCurrentServer = null;
|
mCurrentServer = null;
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
getFiles(true);
|
getFiles(true);
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -90,10 +90,12 @@ public class MediaRouterPlayService extends Service {
|
||||||
|
|
||||||
private String mSessionId;
|
private String mSessionId;
|
||||||
|
|
||||||
private WeakReference<RouteFragment> mRendererFragment = new WeakReference<RouteFragment>(null);
|
private WeakReference<RouteFragment> mRouterFragment = new WeakReference<RouteFragment>(null);
|
||||||
|
|
||||||
private boolean mPollingStatus = false;
|
private boolean mPollingStatus = false;
|
||||||
|
|
||||||
|
private boolean mBound;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a notification after the icon bitmap is loaded.
|
* Creates a notification after the icon bitmap is loaded.
|
||||||
*/
|
*/
|
||||||
|
@ -118,10 +120,8 @@ public class MediaRouterPlayService extends Service {
|
||||||
.setLargeIcon(result)
|
.setLargeIcon(result)
|
||||||
.setSmallIcon(R.drawable.ic_launcher)
|
.setSmallIcon(R.drawable.ic_launcher)
|
||||||
.build();
|
.build();
|
||||||
NotificationManager notificationManager =
|
|
||||||
(NotificationManager) getSystemService(NOTIFICATION_SERVICE);
|
|
||||||
notificationManager.notify(NOTIFICATION_ID, notification);
|
|
||||||
notification.flags |= Notification.FLAG_ONGOING_EVENT;
|
notification.flags |= Notification.FLAG_ONGOING_EVENT;
|
||||||
|
startForeground(NOTIFICATION_ID, notification);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -136,11 +136,28 @@ public class MediaRouterPlayService extends Service {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IBinder onBind(Intent intent) {
|
public IBinder onBind(Intent intent) {
|
||||||
|
mBound = true;
|
||||||
return mBinder;
|
return mBinder;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setRendererFragment(RouteFragment rf) {
|
/**
|
||||||
mRendererFragment = new WeakReference<RouteFragment>(rf);
|
* Stops service after a delay if no media is playing (delay in case the
|
||||||
|
* fragment is recreated for screen rotation).
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean onUnbind(Intent intent) {
|
||||||
|
new Handler().postDelayed(new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
if (!mPollingStatus && !mBound)
|
||||||
|
stopSelf();
|
||||||
|
}
|
||||||
|
}, 5000);
|
||||||
|
mBound = false;
|
||||||
|
return super.onUnbind(intent);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRouterFragment(RouteFragment rf) {
|
||||||
|
mRouterFragment = new WeakReference<RouteFragment>(rf);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void selectRoute(RouteInfo route) {
|
public void selectRoute(RouteInfo route) {
|
||||||
|
@ -256,11 +273,6 @@ public class MediaRouterPlayService extends Service {
|
||||||
public int getCurrentTrack() {
|
public int getCurrentTrack() {
|
||||||
return mCurrentTrack;
|
return mCurrentTrack;
|
||||||
}
|
}
|
||||||
|
|
||||||
public RouteInfo getDefaultRoute() {
|
|
||||||
return mMediaRouter.getDefaultRoute();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Requests playback information every second, as long as RendererFragment
|
* Requests playback information every second, as long as RendererFragment
|
||||||
* is attached or media is playing.
|
* is attached or media is playing.
|
||||||
|
@ -276,13 +288,15 @@ public class MediaRouterPlayService extends Service {
|
||||||
@Override
|
@Override
|
||||||
public void onResult(Bundle data) {
|
public void onResult(Bundle data) {
|
||||||
MediaItemStatus status = MediaItemStatus.fromBundle(data);
|
MediaItemStatus status = MediaItemStatus.fromBundle(data);
|
||||||
if (mRendererFragment.get() != null)
|
if (mRouterFragment.get() != null)
|
||||||
mRendererFragment.get().receivePlaybackStatus(status);
|
mRouterFragment.get().receivePlaybackStatus(status);
|
||||||
|
|
||||||
if (status.getPlaybackState() == MediaItemStatus.PLAYBACK_STATE_FINISHED) {
|
if (status.getPlaybackState() == MediaItemStatus.PLAYBACK_STATE_FINISHED) {
|
||||||
if (mCurrentTrack + 1 < mPlaylist.size())
|
if (mCurrentTrack + 1 < mPlaylist.size())
|
||||||
playNext();
|
playNext();
|
||||||
else {
|
else {
|
||||||
|
if (!mBound)
|
||||||
|
stopSelf();
|
||||||
mPollingStatus = false;
|
mPollingStatus = false;
|
||||||
NotificationManager notificationManager =
|
NotificationManager notificationManager =
|
||||||
(NotificationManager) getSystemService(NOTIFICATION_SERVICE);
|
(NotificationManager) getSystemService(NOTIFICATION_SERVICE);
|
||||||
|
@ -309,5 +323,9 @@ public class MediaRouterPlayService extends Service {
|
||||||
public void decreaseVolume() {
|
public void decreaseVolume() {
|
||||||
mMediaRouter.getSelectedRoute().requestUpdateVolume(-1);
|
mMediaRouter.getSelectedRoute().requestUpdateVolume(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<Item> getPlaylist() {
|
||||||
|
return mPlaylist;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -97,11 +97,8 @@ public class UpnpController implements RegistryListener {
|
||||||
else
|
else
|
||||||
remoteDeviceAdded(mUpnpService.getRegistry(), (RemoteDevice) d);
|
remoteDeviceAdded(mUpnpService.getRegistry(), (RemoteDevice) d);
|
||||||
}
|
}
|
||||||
if (mStartSearchImmediately) {
|
if (mStartSearchImmediately)
|
||||||
Log.i(TAG, "Starting device search");
|
startSearch();
|
||||||
mUpnpService.getControlPoint().search();
|
|
||||||
mStartSearchImmediately = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onServiceDisconnected(ComponentName className) {
|
public void onServiceDisconnected(ComponentName className) {
|
||||||
|
@ -139,6 +136,7 @@ public class UpnpController implements RegistryListener {
|
||||||
if (mUpnpService != null) {
|
if (mUpnpService != null) {
|
||||||
Log.i(TAG, "Starting device search");
|
Log.i(TAG, "Starting device search");
|
||||||
mUpnpService.getControlPoint().search();
|
mUpnpService.getControlPoint().search();
|
||||||
|
mStartSearchImmediately = false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
mStartSearchImmediately = true;
|
mStartSearchImmediately = true;
|
||||||
|
|
|
@ -31,7 +31,10 @@ import java.net.URI;
|
||||||
import java.net.URISyntaxException;
|
import java.net.URISyntaxException;
|
||||||
|
|
||||||
import org.teleal.cling.model.meta.Device;
|
import org.teleal.cling.model.meta.Device;
|
||||||
|
import org.teleal.cling.model.meta.LocalDevice;
|
||||||
import org.teleal.cling.model.meta.RemoteDevice;
|
import org.teleal.cling.model.meta.RemoteDevice;
|
||||||
|
import org.teleal.cling.registry.Registry;
|
||||||
|
import org.teleal.cling.registry.RegistryListener;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
@ -43,7 +46,6 @@ import android.widget.ArrayAdapter;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import com.github.nutomic.controldlna.R;
|
import com.github.nutomic.controldlna.R;
|
||||||
import com.github.nutomic.controldlna.upnp.UpnpController.DeviceListenerCallback;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -54,7 +56,7 @@ import com.github.nutomic.controldlna.upnp.UpnpController.DeviceListenerCallback
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class DeviceArrayAdapter extends ArrayAdapter<Device<?, ?, ?>>
|
public class DeviceArrayAdapter extends ArrayAdapter<Device<?, ?, ?>>
|
||||||
implements DeviceListenerCallback {
|
implements RegistryListener {
|
||||||
|
|
||||||
private static final String TAG = "DeviceArrayAdapter";
|
private static final String TAG = "DeviceArrayAdapter";
|
||||||
|
|
||||||
|
@ -106,8 +108,7 @@ public class DeviceArrayAdapter extends ArrayAdapter<Device<?, ?, ?>>
|
||||||
/**
|
/**
|
||||||
* Adds a new device to the list if its type equals mDeviceType.
|
* Adds a new device to the list if its type equals mDeviceType.
|
||||||
*/
|
*/
|
||||||
@Override
|
private void deviceAdded(final Device<?, ?, ?> device) {
|
||||||
public void deviceAdded(final Device<?, ?, ?> device) {
|
|
||||||
mActivity.runOnUiThread(new Runnable() {
|
mActivity.runOnUiThread(new Runnable() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -121,8 +122,7 @@ public class DeviceArrayAdapter extends ArrayAdapter<Device<?, ?, ?>>
|
||||||
/**
|
/**
|
||||||
* Removes the device from the list (if it is an element).
|
* Removes the device from the list (if it is an element).
|
||||||
*/
|
*/
|
||||||
@Override
|
private void deviceRemoved(final Device<?, ?, ?> device) {
|
||||||
public void deviceRemoved(final Device<?, ?, ?> device) {
|
|
||||||
mActivity.runOnUiThread(new Runnable() {
|
mActivity.runOnUiThread(new Runnable() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -133,8 +133,7 @@ public class DeviceArrayAdapter extends ArrayAdapter<Device<?, ?, ?>>
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
private void deviceUpdated(Device<?, ?, ?> device) {
|
||||||
public void deviceUpdated(Device<?, ?, ?> device) {
|
|
||||||
mActivity.runOnUiThread(new Runnable() {
|
mActivity.runOnUiThread(new Runnable() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -143,4 +142,47 @@ public class DeviceArrayAdapter extends ArrayAdapter<Device<?, ?, ?>>
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void beforeShutdown(Registry registry) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void localDeviceAdded(Registry registry, LocalDevice device) {
|
||||||
|
deviceAdded(device);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void localDeviceRemoved(Registry registry, LocalDevice device) {
|
||||||
|
deviceRemoved(device);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void remoteDeviceAdded(Registry registry, RemoteDevice device) {
|
||||||
|
deviceAdded(device);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void remoteDeviceDiscoveryFailed(Registry registry, RemoteDevice device,
|
||||||
|
Exception exception) {
|
||||||
|
Log.w(TAG, "Remote device discovery failed", exception);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void remoteDeviceDiscoveryStarted(Registry registry, RemoteDevice device) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void remoteDeviceRemoved(Registry registry, RemoteDevice device) {
|
||||||
|
deviceRemoved(device);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void remoteDeviceUpdated(Registry registry, RemoteDevice device) {
|
||||||
|
deviceUpdated(device);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterShutdown() {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Reference in a new issue