Improved handling if wifi is disconnected.
This commit is contained in:
parent
92768d518b
commit
0184355397
8 changed files with 227 additions and 27 deletions
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
<uses-permission android:name="android.permission.INTERNET"/>
|
<uses-permission android:name="android.permission.INTERNET"/>
|
||||||
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
|
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
|
||||||
|
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
|
||||||
<uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE"/>
|
<uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE"/>
|
||||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
|
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
|
||||||
|
|
||||||
|
|
|
@ -12,5 +12,8 @@
|
||||||
<string name="select_renderer">Please select a renderer</string>
|
<string name="select_renderer">Please select a renderer</string>
|
||||||
<string name="album_art">Album Art</string>
|
<string name="album_art">Album Art</string>
|
||||||
<string name="route_description">DLNA Playback</string>
|
<string name="route_description">DLNA Playback</string>
|
||||||
|
<string name="warning_wifi_not_connected">Wifi needs to be connected for playback</string>
|
||||||
|
<string name="auto_enable_wifi">Enable Wifi automatically on start</string>
|
||||||
|
<string name="dont_show_dialog_again">"Do not show this dialog again"</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -31,6 +31,11 @@ import java.util.List;
|
||||||
|
|
||||||
import org.teleal.cling.support.model.item.Item;
|
import org.teleal.cling.support.model.item.Item;
|
||||||
|
|
||||||
|
import android.app.AlertDialog;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
import android.net.ConnectivityManager;
|
||||||
|
import android.net.NetworkInfo;
|
||||||
|
import android.net.wifi.WifiManager;
|
||||||
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.FragmentManager;
|
||||||
|
@ -42,6 +47,10 @@ import android.support.v7.app.ActionBar.Tab;
|
||||||
import android.support.v7.app.ActionBar.TabListener;
|
import android.support.v7.app.ActionBar.TabListener;
|
||||||
import android.support.v7.app.ActionBarActivity;
|
import android.support.v7.app.ActionBarActivity;
|
||||||
import android.view.KeyEvent;
|
import android.view.KeyEvent;
|
||||||
|
import android.widget.CheckBox;
|
||||||
|
import android.widget.CompoundButton;
|
||||||
|
import android.widget.CompoundButton.OnCheckedChangeListener;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
|
||||||
import com.github.nutomic.controldlna.R;
|
import com.github.nutomic.controldlna.R;
|
||||||
|
|
||||||
|
@ -86,7 +95,8 @@ public class MainActivity extends ActionBarActivity {
|
||||||
ViewPager mViewPager;
|
ViewPager mViewPager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes tab navigation.
|
* Initializes tab navigation. If wifi is not connected,
|
||||||
|
* shows a warning dialog.
|
||||||
*/
|
*/
|
||||||
public void onCreate(Bundle savedInstanceState) {
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
@ -128,6 +138,50 @@ public class MainActivity extends ActionBarActivity {
|
||||||
.setText(R.string.title_renderer)
|
.setText(R.string.title_renderer)
|
||||||
.setTabListener(tabListener));
|
.setTabListener(tabListener));
|
||||||
|
|
||||||
|
ConnectivityManager connManager = (ConnectivityManager) getSystemService(CONNECTIVITY_SERVICE);
|
||||||
|
NetworkInfo wifi = connManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
|
||||||
|
final WifiManager wifiManager = (WifiManager) getSystemService(WIFI_SERVICE);
|
||||||
|
final SharedPreferences prefs = getSharedPreferences("preferences.db", 0);
|
||||||
|
|
||||||
|
if (!wifi.isConnected() && !prefs.getBoolean("wifi_skip_dialog", false) &&
|
||||||
|
!prefs.getBoolean("wifi_auto_enable", false)) {
|
||||||
|
LinearLayout layout = new LinearLayout(this);
|
||||||
|
layout.setOrientation(LinearLayout.VERTICAL);
|
||||||
|
|
||||||
|
CheckBox cbAutoEnable = new CheckBox(this);
|
||||||
|
cbAutoEnable.setText(R.string.auto_enable_wifi);
|
||||||
|
cbAutoEnable.setChecked(prefs.getBoolean("wifi_auto_enable", false));
|
||||||
|
cbAutoEnable.setOnCheckedChangeListener(new OnCheckedChangeListener() {
|
||||||
|
@Override
|
||||||
|
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
|
||||||
|
prefs.edit().putBoolean("wifi_auto_enable", isChecked)
|
||||||
|
.commit();
|
||||||
|
if (isChecked)
|
||||||
|
wifiManager.setWifiEnabled(true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
layout.addView(cbAutoEnable);
|
||||||
|
|
||||||
|
CheckBox cbShowOnce = new CheckBox(this);
|
||||||
|
cbShowOnce.setText(R.string.dont_show_dialog_again);
|
||||||
|
cbShowOnce.setOnCheckedChangeListener(new OnCheckedChangeListener() {
|
||||||
|
@Override
|
||||||
|
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
|
||||||
|
prefs.edit().putBoolean("wifi_skip_dialog", isChecked)
|
||||||
|
.commit();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
layout.addView(cbShowOnce);
|
||||||
|
|
||||||
|
new AlertDialog.Builder(this)
|
||||||
|
.setView(layout)
|
||||||
|
.setTitle(R.string.warning_wifi_not_connected)
|
||||||
|
.setPositiveButton(android.R.string.ok, null)
|
||||||
|
.show();
|
||||||
|
}
|
||||||
|
else if (!wifiManager.isWifiEnabled() && prefs.getBoolean("wifi_auto_enable", false))
|
||||||
|
wifiManager.setWifiEnabled(true);
|
||||||
|
|
||||||
if (savedInstanceState != null) {
|
if (savedInstanceState != null) {
|
||||||
FragmentManager fm = getSupportFragmentManager();
|
FragmentManager fm = getSupportFragmentManager();
|
||||||
mServerFragment = (ServerFragment) fm.getFragment(
|
mServerFragment = (ServerFragment) fm.getFragment(
|
||||||
|
|
|
@ -94,7 +94,7 @@ public class RouteFragment extends MediaRouteDiscoveryFragment implements
|
||||||
|
|
||||||
private FileArrayAdapter mPlaylistAdapter;
|
private FileArrayAdapter mPlaylistAdapter;
|
||||||
|
|
||||||
private boolean mRouteSelected = false;
|
private RouteInfo mSelectedRoute;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If true, the item at this position will be played as soon as a route is selected.
|
* If true, the item at this position will be played as soon as a route is selected.
|
||||||
|
@ -177,7 +177,8 @@ public class RouteFragment extends MediaRouteDiscoveryFragment implements
|
||||||
if (savedInstanceState != null) {
|
if (savedInstanceState != null) {
|
||||||
mListView.onRestoreInstanceState(savedInstanceState.getParcelable("list_state"));
|
mListView.onRestoreInstanceState(savedInstanceState.getParcelable("list_state"));
|
||||||
if (savedInstanceState.getBoolean("route_selected")) {
|
if (savedInstanceState.getBoolean("route_selected")) {
|
||||||
mRouteSelected = true;
|
mSelectedRoute = MediaRouter.getInstance(getActivity())
|
||||||
|
.getSelectedRoute();
|
||||||
mListView.setAdapter(mPlaylistAdapter);
|
mListView.setAdapter(mPlaylistAdapter);
|
||||||
mControls.setVisibility(View.VISIBLE);
|
mControls.setVisibility(View.VISIBLE);
|
||||||
}
|
}
|
||||||
|
@ -188,7 +189,7 @@ public class RouteFragment extends MediaRouteDiscoveryFragment implements
|
||||||
public void onSaveInstanceState(Bundle outState) {
|
public void onSaveInstanceState(Bundle outState) {
|
||||||
super.onSaveInstanceState(outState);
|
super.onSaveInstanceState(outState);
|
||||||
|
|
||||||
outState.putBoolean("route_selected", mRouteSelected);
|
outState.putBoolean("route_selected", mSelectedRoute != null);
|
||||||
outState.putParcelable("list_state", mListView.onSaveInstanceState());
|
outState.putParcelable("list_state", mListView.onSaveInstanceState());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -225,6 +226,10 @@ public class RouteFragment extends MediaRouteDiscoveryFragment implements
|
||||||
@Override
|
@Override
|
||||||
public void onRouteRemoved(MediaRouter router, RouteInfo route) {
|
public void onRouteRemoved(MediaRouter router, RouteInfo route) {
|
||||||
mRouteAdapter.remove(route);
|
mRouteAdapter.remove(route);
|
||||||
|
if (route.equals(mSelectedRoute)) {
|
||||||
|
mPlaying = false;
|
||||||
|
onBackPressed();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -265,8 +270,8 @@ public class RouteFragment extends MediaRouteDiscoveryFragment implements
|
||||||
@Override
|
@Override
|
||||||
public void onItemClick(AdapterView<?> a, View v, final int position, long id) {
|
public void onItemClick(AdapterView<?> a, View v, final int position, long id) {
|
||||||
if (mListView.getAdapter() == mRouteAdapter) {
|
if (mListView.getAdapter() == mRouteAdapter) {
|
||||||
mMediaRouterPlayService.getService().selectRoute(mRouteAdapter.getItem(position));
|
mSelectedRoute = mRouteAdapter.getItem(position);
|
||||||
mRouteSelected = true;
|
mMediaRouterPlayService.getService().selectRoute(mSelectedRoute);
|
||||||
mListView.setAdapter(mPlaylistAdapter);
|
mListView.setAdapter(mPlaylistAdapter);
|
||||||
mControls.setVisibility(View.VISIBLE);
|
mControls.setVisibility(View.VISIBLE);
|
||||||
if (mStartPlayingOnSelect != -1) {
|
if (mStartPlayingOnSelect != -1) {
|
||||||
|
@ -321,7 +326,7 @@ public class RouteFragment extends MediaRouteDiscoveryFragment implements
|
||||||
mControls.setVisibility(View.GONE);
|
mControls.setVisibility(View.GONE);
|
||||||
mListView.setAdapter(mRouteAdapter);
|
mListView.setAdapter(mRouteAdapter);
|
||||||
disableTrackHighlight();
|
disableTrackHighlight();
|
||||||
mRouteSelected = false;
|
mSelectedRoute = null;
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.setNegativeButton(android.R.string.no, null)
|
.setNegativeButton(android.R.string.no, null)
|
||||||
|
@ -331,7 +336,7 @@ public class RouteFragment extends MediaRouteDiscoveryFragment implements
|
||||||
mControls.setVisibility(View.GONE);
|
mControls.setVisibility(View.GONE);
|
||||||
mListView.setAdapter(mRouteAdapter);
|
mListView.setAdapter(mRouteAdapter);
|
||||||
disableTrackHighlight();
|
disableTrackHighlight();
|
||||||
mRouteSelected = false;
|
mSelectedRoute = null;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -406,7 +411,7 @@ public class RouteFragment extends MediaRouteDiscoveryFragment implements
|
||||||
mPlaylistAdapter.addAll(playlist);
|
mPlaylistAdapter.addAll(playlist);
|
||||||
mMediaRouterPlayService.getService().setPlaylist(playlist);
|
mMediaRouterPlayService.getService().setPlaylist(playlist);
|
||||||
|
|
||||||
if (mRouteSelected)
|
if (mSelectedRoute != null)
|
||||||
mMediaRouterPlayService.getService().play(start);
|
mMediaRouterPlayService.getService().play(start);
|
||||||
else {
|
else {
|
||||||
Toast.makeText(getActivity(), R.string.select_renderer, Toast.LENGTH_SHORT)
|
Toast.makeText(getActivity(), R.string.select_renderer, Toast.LENGTH_SHORT)
|
||||||
|
|
|
@ -36,8 +36,6 @@ 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.model.types.UDN;
|
||||||
|
@ -47,10 +45,15 @@ 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.BroadcastReceiver;
|
||||||
import android.content.ComponentName;
|
import android.content.ComponentName;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
import android.content.IntentFilter;
|
||||||
import android.content.ServiceConnection;
|
import android.content.ServiceConnection;
|
||||||
|
import android.net.ConnectivityManager;
|
||||||
|
import android.net.NetworkInfo;
|
||||||
|
import android.net.wifi.WifiManager;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.os.Parcelable;
|
import android.os.Parcelable;
|
||||||
|
@ -115,13 +118,8 @@ public class ServerFragment extends ListFragment implements OnBackPressedListene
|
||||||
public void onServiceConnected(ComponentName className, IBinder service) {
|
public void onServiceConnected(ComponentName className, IBinder service) {
|
||||||
mUpnpService = (AndroidUpnpService) service;
|
mUpnpService = (AndroidUpnpService) service;
|
||||||
mUpnpService.getRegistry().addListener(mServerAdapter);
|
mUpnpService.getRegistry().addListener(mServerAdapter);
|
||||||
for (Device<?, ?, ?> d : mUpnpService.getControlPoint().getRegistry().getDevices()) {
|
for (Device<?, ?, ?> d : mUpnpService.getControlPoint().getRegistry().getDevices())
|
||||||
if (d instanceof LocalDevice)
|
mServerAdapter.deviceAdded(d);
|
||||||
mServerAdapter.localDeviceAdded(mUpnpService.getRegistry(), (LocalDevice) d);
|
|
||||||
else
|
|
||||||
mServerAdapter.remoteDeviceAdded(mUpnpService.getRegistry(), (RemoteDevice) d);
|
|
||||||
}
|
|
||||||
Log.i(TAG, "Starting device search");
|
|
||||||
mUpnpService.getControlPoint().search();
|
mUpnpService.getControlPoint().search();
|
||||||
|
|
||||||
if (mRestoreServer != null) {
|
if (mRestoreServer != null) {
|
||||||
|
@ -141,7 +139,8 @@ public class ServerFragment extends ListFragment implements OnBackPressedListene
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes ListView adapters, launches Cling UPNP service.
|
* Initializes ListView adapters, launches Cling UPNP service, registers
|
||||||
|
* wifi state change listener and restores instance state if possible.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void onActivityCreated(Bundle savedInstanceState) {
|
public void onActivityCreated(Bundle savedInstanceState) {
|
||||||
|
@ -157,6 +156,11 @@ public class ServerFragment extends ListFragment implements OnBackPressedListene
|
||||||
Context.BIND_AUTO_CREATE
|
Context.BIND_AUTO_CREATE
|
||||||
);
|
);
|
||||||
|
|
||||||
|
IntentFilter filter = new IntentFilter();
|
||||||
|
filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
|
||||||
|
filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
|
||||||
|
getActivity().registerReceiver(mWifiReceiver, filter);
|
||||||
|
|
||||||
if (savedInstanceState != null) {
|
if (savedInstanceState != null) {
|
||||||
mRestoreServer = savedInstanceState.getString("current_server");
|
mRestoreServer = savedInstanceState.getString("current_server");
|
||||||
mCurrentPath.addAll(savedInstanceState.getStringArrayList("path"));
|
mCurrentPath.addAll(savedInstanceState.getStringArrayList("path"));
|
||||||
|
@ -166,6 +170,9 @@ public class ServerFragment extends ListFragment implements OnBackPressedListene
|
||||||
mListState.push(getListView().onSaveInstanceState());
|
mListState.push(getListView().onSaveInstanceState());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stores current server and path/list state stacks.
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void onSaveInstanceState(Bundle outState) {
|
public void onSaveInstanceState(Bundle outState) {
|
||||||
super.onSaveInstanceState(outState);
|
super.onSaveInstanceState(outState);
|
||||||
|
@ -232,6 +239,9 @@ public class ServerFragment extends ListFragment implements OnBackPressedListene
|
||||||
* which means we restore scroll position etc.
|
* which means we restore scroll position etc.
|
||||||
*/
|
*/
|
||||||
private void getFiles(final boolean restoreListState) {
|
private void getFiles(final boolean restoreListState) {
|
||||||
|
if (mCurrentServer == null)
|
||||||
|
return;
|
||||||
|
|
||||||
Service<?, ?> service = mCurrentServer.findService(
|
Service<?, ?> service = mCurrentServer.findService(
|
||||||
new ServiceType("schemas-upnp-org", "ContentDirectory"));
|
new ServiceType("schemas-upnp-org", "ContentDirectory"));
|
||||||
mUpnpService.getControlPoint().execute(new Browse(service,
|
mUpnpService.getControlPoint().execute(new Browse(service,
|
||||||
|
@ -274,8 +284,8 @@ public class ServerFragment extends ListFragment implements OnBackPressedListene
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles back button press to traverse directories (while in directory
|
* Handles back button press to traverse directories (while browsing
|
||||||
* browsing mode).
|
* directories).
|
||||||
*/
|
*/
|
||||||
public boolean onBackPressed() {
|
public boolean onBackPressed() {
|
||||||
if (getListAdapter() == mServerAdapter)
|
if (getListAdapter() == mServerAdapter)
|
||||||
|
@ -293,4 +303,46 @@ public class ServerFragment extends ListFragment implements OnBackPressedListene
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Starts device search on wifi connect, removes unreachable
|
||||||
|
* devices on wifi disconnect.
|
||||||
|
*/
|
||||||
|
private BroadcastReceiver mWifiReceiver = new BroadcastReceiver() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onReceive(Context context, Intent intent) {
|
||||||
|
getActivity();
|
||||||
|
ConnectivityManager connManager = (ConnectivityManager)
|
||||||
|
getActivity().getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||||
|
NetworkInfo wifi = connManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
|
||||||
|
|
||||||
|
if (wifi.isConnected()) {
|
||||||
|
if (mUpnpService != null) {
|
||||||
|
for (Device<?, ?, ?> d : mUpnpService.getControlPoint()
|
||||||
|
.getRegistry().getDevices())
|
||||||
|
mServerAdapter.deviceAdded(d);
|
||||||
|
mUpnpService.getControlPoint().search();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
for (int i = 0; i < mServerAdapter.getCount(); i++) {
|
||||||
|
Device<?, ?, ?> d = mServerAdapter.getItem(i);
|
||||||
|
UDN udn = new UDN(d.getIdentity().getUdn().toString());
|
||||||
|
if (mUpnpService.getControlPoint().getRegistry()
|
||||||
|
.getDevice(udn, false) == null) {
|
||||||
|
mServerAdapter.deviceRemoved(d);
|
||||||
|
if (d.equals(mCurrentServer)) {
|
||||||
|
mCurrentPath.clear();
|
||||||
|
mListState.setSize(1);
|
||||||
|
setListAdapter(mServerAdapter);
|
||||||
|
getListView().onRestoreInstanceState(mListState.firstElement());
|
||||||
|
mCurrentServer = null;
|
||||||
|
}
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,6 +49,7 @@ import android.os.IBinder;
|
||||||
import android.support.v4.app.NotificationCompat;
|
import android.support.v4.app.NotificationCompat;
|
||||||
import android.support.v7.media.MediaControlIntent;
|
import android.support.v7.media.MediaControlIntent;
|
||||||
import android.support.v7.media.MediaItemStatus;
|
import android.support.v7.media.MediaItemStatus;
|
||||||
|
import android.support.v7.media.MediaRouteSelector;
|
||||||
import android.support.v7.media.MediaRouter;
|
import android.support.v7.media.MediaRouter;
|
||||||
import android.support.v7.media.MediaRouter.ControlRequestCallback;
|
import android.support.v7.media.MediaRouter.ControlRequestCallback;
|
||||||
import android.support.v7.media.MediaRouter.RouteInfo;
|
import android.support.v7.media.MediaRouter.RouteInfo;
|
||||||
|
@ -89,12 +90,31 @@ public class MediaRouterPlayService extends Service {
|
||||||
|
|
||||||
private String mSessionId;
|
private String mSessionId;
|
||||||
|
|
||||||
private WeakReference<RouteFragment> mRouterFragment = new WeakReference<RouteFragment>(null);
|
private WeakReference<RouteFragment> mRouterFragment =
|
||||||
|
new WeakReference<RouteFragment>(null);
|
||||||
|
|
||||||
private boolean mPollingStatus = false;
|
private boolean mPollingStatus = false;
|
||||||
|
|
||||||
private boolean mBound;
|
private boolean mBound;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Route that is currently being played to. May be invalid.
|
||||||
|
*/
|
||||||
|
private RouteInfo mCurrentRoute;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Stops foreground mode and notification if the current route
|
||||||
|
* has been removed.
|
||||||
|
*/
|
||||||
|
private MediaRouter.Callback mRouteRemovedCallback =
|
||||||
|
new MediaRouter.Callback() {
|
||||||
|
@Override
|
||||||
|
public void onRouteRemoved(MediaRouter router, RouteInfo route) {
|
||||||
|
if (route.equals(mCurrentRoute))
|
||||||
|
stopForeground(true);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a notification after the icon bitmap is loaded.
|
* Creates a notification after the icon bitmap is loaded.
|
||||||
*/
|
*/
|
||||||
|
@ -160,7 +180,14 @@ public class MediaRouterPlayService extends Service {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void selectRoute(RouteInfo route) {
|
public void selectRoute(RouteInfo route) {
|
||||||
|
mMediaRouter.removeCallback(mRouteRemovedCallback);
|
||||||
mMediaRouter.selectRoute(route);
|
mMediaRouter.selectRoute(route);
|
||||||
|
MediaRouteSelector selector = new MediaRouteSelector.Builder()
|
||||||
|
.addControlCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
mMediaRouter.addCallback(selector, mRouteRemovedCallback, 0);
|
||||||
|
mCurrentRoute = route;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sendControlRequest(Intent intent) {
|
public void sendControlRequest(Intent intent) {
|
||||||
|
|
|
@ -29,6 +29,7 @@ package com.github.nutomic.controldlna.upnp;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
import org.teleal.cling.android.AndroidUpnpService;
|
import org.teleal.cling.android.AndroidUpnpService;
|
||||||
import org.teleal.cling.android.AndroidUpnpServiceImpl;
|
import org.teleal.cling.android.AndroidUpnpServiceImpl;
|
||||||
|
@ -43,6 +44,7 @@ import org.teleal.cling.model.meta.RemoteDevice;
|
||||||
import org.teleal.cling.model.meta.StateVariableAllowedValueRange;
|
import org.teleal.cling.model.meta.StateVariableAllowedValueRange;
|
||||||
import org.teleal.cling.model.state.StateVariableValue;
|
import org.teleal.cling.model.state.StateVariableValue;
|
||||||
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.registry.Registry;
|
import org.teleal.cling.registry.Registry;
|
||||||
import org.teleal.cling.registry.RegistryListener;
|
import org.teleal.cling.registry.RegistryListener;
|
||||||
import org.teleal.cling.support.avtransport.callback.GetPositionInfo;
|
import org.teleal.cling.support.avtransport.callback.GetPositionInfo;
|
||||||
|
@ -60,10 +62,15 @@ import org.teleal.cling.support.renderingcontrol.callback.GetVolume;
|
||||||
import org.teleal.cling.support.renderingcontrol.callback.SetVolume;
|
import org.teleal.cling.support.renderingcontrol.callback.SetVolume;
|
||||||
|
|
||||||
import android.app.Service;
|
import android.app.Service;
|
||||||
|
import android.content.BroadcastReceiver;
|
||||||
import android.content.ComponentName;
|
import android.content.ComponentName;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
import android.content.IntentFilter;
|
||||||
import android.content.ServiceConnection;
|
import android.content.ServiceConnection;
|
||||||
|
import android.net.ConnectivityManager;
|
||||||
|
import android.net.NetworkInfo;
|
||||||
|
import android.net.wifi.WifiManager;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.os.Message;
|
import android.os.Message;
|
||||||
import android.os.Messenger;
|
import android.os.Messenger;
|
||||||
|
@ -109,7 +116,6 @@ public class RemotePlayService extends Service implements RegistryListener {
|
||||||
else
|
else
|
||||||
remoteDeviceAdded(mUpnpService.getRegistry(), (RemoteDevice) d);
|
remoteDeviceAdded(mUpnpService.getRegistry(), (RemoteDevice) d);
|
||||||
}
|
}
|
||||||
Log.i(TAG, "Starting device search");
|
|
||||||
mUpnpService.getControlPoint().search();
|
mUpnpService.getControlPoint().search();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -204,8 +210,12 @@ public class RemotePlayService extends Service implements RegistryListener {
|
||||||
mUpnpService.getControlPoint().execute(mSubscriptionCallback);
|
mUpnpService.getControlPoint().execute(mSubscriptionCallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ends selection, stops playback if possible.
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void unselectRenderer(String sessionId) throws RemoteException {
|
public void unselectRenderer(String sessionId) throws RemoteException {
|
||||||
|
if (mDevices.get(sessionId) != null)
|
||||||
stop(sessionId);
|
stop(sessionId);
|
||||||
mSubscriptionCallback.end();
|
mSubscriptionCallback.end();
|
||||||
mCurrentRenderer = null;
|
mCurrentRenderer = null;
|
||||||
|
@ -398,6 +408,9 @@ public class RemotePlayService extends Service implements RegistryListener {
|
||||||
return mBinder;
|
return mBinder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Binds to cling service, registers wifi state change listener.
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void onCreate() {
|
public void onCreate() {
|
||||||
super.onCreate();
|
super.onCreate();
|
||||||
|
@ -406,6 +419,11 @@ public class RemotePlayService extends Service implements RegistryListener {
|
||||||
mUpnpServiceConnection,
|
mUpnpServiceConnection,
|
||||||
Context.BIND_AUTO_CREATE
|
Context.BIND_AUTO_CREATE
|
||||||
);
|
);
|
||||||
|
|
||||||
|
IntentFilter filter = new IntentFilter();
|
||||||
|
filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
|
||||||
|
filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
|
||||||
|
registerReceiver(mWifiReceiver, filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -414,6 +432,38 @@ public class RemotePlayService extends Service implements RegistryListener {
|
||||||
unbindService(mUpnpServiceConnection);
|
unbindService(mUpnpServiceConnection);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Starts device search on wifi connect, removes unreachable
|
||||||
|
* devices on wifi disconnect.
|
||||||
|
*/
|
||||||
|
private BroadcastReceiver mWifiReceiver = new BroadcastReceiver() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onReceive(Context context, Intent intent) {
|
||||||
|
ConnectivityManager connManager = (ConnectivityManager)
|
||||||
|
getSystemService(CONNECTIVITY_SERVICE);
|
||||||
|
NetworkInfo wifi = connManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
|
||||||
|
|
||||||
|
if (wifi.isConnected()) {
|
||||||
|
if (mUpnpService != null) {
|
||||||
|
for (Device<?, ?, ?> d : mUpnpService.getControlPoint().getRegistry().getDevices())
|
||||||
|
deviceAdded(d);
|
||||||
|
mUpnpService.getControlPoint().search();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
for (Entry<String, Device<?, ?, ?>> d : mDevices.entrySet()) {
|
||||||
|
if (mUpnpService.getControlPoint().getRegistry()
|
||||||
|
.getDevice(new UDN(d.getKey()), false) == null) {
|
||||||
|
deviceRemoved(d.getValue());
|
||||||
|
if (d.getValue().equals(mCurrentRenderer))
|
||||||
|
mCurrentRenderer = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a device service by name for direct queries.
|
* Returns a device service by name for direct queries.
|
||||||
*/
|
*/
|
||||||
|
@ -427,6 +477,9 @@ public class RemotePlayService extends Service implements RegistryListener {
|
||||||
* Gather device data and send it to Provider.
|
* Gather device data and send it to Provider.
|
||||||
*/
|
*/
|
||||||
private void deviceAdded(final Device<?, ?, ?> device) {
|
private void deviceAdded(final Device<?, ?, ?> device) {
|
||||||
|
if (mDevices.containsValue(device))
|
||||||
|
return;
|
||||||
|
|
||||||
final org.teleal.cling.model.meta.Service<?, ?> rc =
|
final org.teleal.cling.model.meta.Service<?, ?> rc =
|
||||||
getService(device, "RenderingControl");
|
getService(device, "RenderingControl");
|
||||||
if (rc == null || mListener == null)
|
if (rc == null || mListener == null)
|
||||||
|
|
|
@ -108,7 +108,12 @@ 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.
|
||||||
*/
|
*/
|
||||||
private void deviceAdded(final Device<?, ?, ?> device) {
|
public void deviceAdded(final Device<?, ?, ?> device) {
|
||||||
|
for (int i = 0; i < getCount(); i++) {
|
||||||
|
if (getItem(i).equals(device))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
mActivity.runOnUiThread(new Runnable() {
|
mActivity.runOnUiThread(new Runnable() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -122,7 +127,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).
|
||||||
*/
|
*/
|
||||||
private void deviceRemoved(final Device<?, ?, ?> device) {
|
public void deviceRemoved(final Device<?, ?, ?> device) {
|
||||||
mActivity.runOnUiThread(new Runnable() {
|
mActivity.runOnUiThread(new Runnable() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
Reference in a new issue