update connection manager

This commit is contained in:
Luke Pulverenti 2014-10-09 18:14:18 -04:00
parent 63e7b990a4
commit f7d2a22e44
16 changed files with 431 additions and 87 deletions

View File

@ -106,7 +106,9 @@ public class ApiClient extends BaseApiClient {
public void OpenWebSocket(){
if (apiWebSocket == null){
apiWebSocket = new ApiWebSocket(getJsonSerializer(), getLogger(), apiEventListener, this);
Logger.Debug("Creating ApiWebSocket");
apiWebSocket = new ApiWebSocket(getJsonSerializer(), Logger, apiEventListener, this);
}
apiWebSocket.EnsureWebSocket();
@ -1244,7 +1246,7 @@ public class ApiClient extends BaseApiClient {
throw new IllegalArgumentException("info");
}
getLogger().Debug("ReportPlaybackStart: Item {0}", info.getItem());
Logger.Debug("ReportPlaybackStart: Item {0}", info.getItem());
/*if (WebSocketConnection != null && WebSocketConnection.IsConnected)
{

View File

@ -30,20 +30,7 @@ public abstract class BaseApiClient implements IDisposable
//}
}
/**
Gets the logger.
<value>The logger.</value>
*/
private ILogger privateLogger;
public final ILogger getLogger()
{
return privateLogger;
}
public final void setLogger(ILogger value)
{
privateLogger = value;
}
protected ILogger Logger;
/**
Gets the json serializer.
@ -89,7 +76,7 @@ public abstract class BaseApiClient implements IDisposable
}
setJsonSerializer(jsonSerializer);
setLogger(logger);
Logger = logger;
setClientName(clientName);
setDeviceName(deviceName);
@ -114,7 +101,7 @@ public abstract class BaseApiClient implements IDisposable
}
setJsonSerializer(jsonSerializer);
setLogger(logger);
Logger = logger;
setAccessToken(accessToken);
setServerAddress(serverAddress);

View File

@ -80,52 +80,72 @@ public class ConnectionManager implements IConnectionManager {
return (ApiClient)client;
}
private void OnFailedConnection(Response<ConnectionResult> response){
_logger.Debug("No server available");
ConnectionResult result = new ConnectionResult();
result.setState(ConnectionState.Unavailable);
response.onResponse(result);
}
@Override
public void Connect(final Response<ConnectionResult> response) {
GetAvailableServers(new Response<ArrayList<ServerInfo>>(){
_logger.Debug("Entering initial connection workflow");
@Override
public void onResponse(ArrayList<ServerInfo> servers) {
GetAvailableServers(new Response<ArrayList<ServerInfo>>(){
ServerCredentialConfiguration credentials = _credentialProvider.GetCredentials();
@Override
public void onResponse(ArrayList<ServerInfo> servers) {
final String lastServerId = credentials.getLastServerId();
ServerCredentialConfiguration credentials = _credentialProvider.GetCredentials();
Connect(credentials.getServers(), lastServerId, new Response<ConnectionResult>(){
final String lastServerId = credentials.getLastServerId();
@Override
public void onResponse(ConnectionResult result) {
_logger.Debug("Looping through server list");
if (result.getState() != ConnectionState.Unavailable)
{
response.onResponse(result);
return;
Connect(servers, lastServerId, new Response<ConnectionResult>(){
@Override
public void onResponse(ConnectionResult result) {
if (result.getState() != ConnectionState.Unavailable)
{
response.onResponse(result);
return;
}
_logger.Debug("No saved servers available. Attempting discovery process");
FindServers(new Response<ArrayList<ServerInfo>>(){
@Override
public void onResponse(ArrayList<ServerInfo> foundServers) {
Connect(foundServers, lastServerId, response);
}
@Override
public void onError() {
OnFailedConnection(response);
}
});
}
FindServers(new Response<ArrayList<ServerInfo>>(){
@Override
public void onError() {
@Override
public void onResponse(ArrayList<ServerInfo> foundServers) {
OnFailedConnection(response);
}
});
}
Connect(foundServers, lastServerId, response);
}
});
}
@Override
public void onError() {
@Override
public void onError() {
response.onError();
}
});
}
@Override
public void onError() {
response.onError();
}
OnFailedConnection(response);
}
});
}
@ -147,26 +167,207 @@ public class ConnectionManager implements IConnectionManager {
}
if (servers.size() == 0){
ConnectionResult result = new ConnectionResult();
result.setState(ConnectionState.Unavailable);
response.onResponse(result);
OnFailedConnection(response);
return;
}
ConnectToServerAtListIndex(servers, 0, response);
}
private void ConnectToServerAtListIndex(final ArrayList<ServerInfo> servers,
final int index,
final Response<ConnectionResult> response){
ServerInfo server = servers.get(index);
Connect(server, true, new Response<ConnectionResult>() {
private void TryNextServer() {
int nextIndex = index + 1;
if (nextIndex < servers.size()) {
_logger.Debug("Trying next server");
ConnectToServerAtListIndex(servers, nextIndex, response);
} else {
// No connection is available
OnFailedConnection(response);
}
}
@Override
public void onResponse(ConnectionResult result) {
if (result.getState() == ConnectionState.Unavailable) {
TryNextServer();
} else {
_logger.Debug("Connected to server");
response.onResponse(result);
}
}
@Override
public void onError() {
TryNextServer();
}
});
}
@Override
public void Connect(ServerInfo server, Response<ConnectionResult> response) {
public void Connect(final ServerInfo server,
final Response<ConnectionResult> response) {
Connect(server, true, response);
}
private void Connect(final ServerInfo server,
final boolean enableWakeOnLan,
final Response<ConnectionResult> response) {
boolean isConnectedToLocalNetwork = _networkConnectivity.getNetworkStatus().GetIsLocalNetworkAvailable();
if (!tangible.DotNetToJavaStringHelper.isNullOrEmpty(server.getLocalAddress()) && isConnectedToLocalNetwork)
{
TryConnect(server.getLocalAddress(), new Response<PublicSystemInfo>(){
@Override
public void onResponse(PublicSystemInfo result) {
ConnectToFoundServer(server, result, ConnectionMode.Local, true, response);
}
@Override
public void onError() {
// Wake on lan and try again
if (enableWakeOnLan && server.getWakeOnLanInfos().size() > 0)
{
WakeServer(server, new EmptyResponse() {
@Override
public void onResponse() {
// Try local connection again
Connect(server, false, response);
}
@Override
public void onError() {
// No local connection available
TryConnectToRemoteAddress(server, response);
}
});
return;
}
// No local connection available
TryConnectToRemoteAddress(server, response);
}
});
return;
}
TryConnectToRemoteAddress(server, response);
}
private void TryConnectToRemoteAddress(final ServerInfo server,
final Response<ConnectionResult> response){
// If local connection is unavailable, try to connect to the remote address
if (!tangible.DotNetToJavaStringHelper.isNullOrEmpty(server.getRemoteAddress()))
{
TryConnect(server.getRemoteAddress(), new Response<PublicSystemInfo>(){
@Override
public void onResponse(PublicSystemInfo result) {
ConnectToFoundServer(server, result, ConnectionMode.Remote, true, response);
}
@Override
public void onError() {
// Unable to connect
OnFailedConnection(response);
}
});
return;
}
// Unable to connect
OnFailedConnection(response);
}
public void ConnectToFoundServer(final ServerInfo server,
final PublicSystemInfo systemInfo,
final ConnectionMode connectionMode,
boolean verifyAuthentication,
final Response<ConnectionResult> response) {
UpdateServerInfo(server, systemInfo);
if (verifyAuthentication && !tangible.DotNetToJavaStringHelper.isNullOrEmpty(server.getAccessToken()))
{
ValidateAuthentication(server, connectionMode, new EmptyResponse(){
@Override
public void onResponse() {
ConnectToFoundServer(server, systemInfo, connectionMode, false, response);
}
@Override
public void onError() {
response.onError();
}
});
}
ServerCredentialConfiguration credentials = _credentialProvider.GetCredentials();
credentials.AddOrUpdateServer(server);
credentials.setLastServerId(server.getId());
_credentialProvider.SaveCredentials(credentials);
ConnectionResult result = new ConnectionResult();
result.setState(ConnectionState.Unavailable);
result.setApiClient(GetOrAddApiClient(server));
result.setState(tangible.DotNetToJavaStringHelper.isNullOrEmpty(server.getAccessToken()) ?
ConnectionState.ServerSignIn :
ConnectionState.SignedIn);
if (result.getState() == ConnectionState.SignedIn)
{
EnsureWebSocketIfConfigured(result.getApiClient());
}
result.setServerInfo(server);
result.getApiClient().EnableAutomaticNetworking(server, connectionMode, _networkConnectivity);
response.onResponse(result);
}
@Override
public void Connect(String address, Response<ConnectionResult> response) {
address = NormalizeAddress(address);
_logger.Debug("Attempting to connect to server at %s", address);
ServerInfo server = new ServerInfo();
server.setLocalAddress(NormalizeAddress(address));
server.setLocalAddress(address);
Connect(server, response);
}
@ -174,14 +375,16 @@ public class ConnectionManager implements IConnectionManager {
@Override
public void Logout(final Response<ConnectionResult> response) {
LogoutAll(new EmptyResponse(){
_logger.Debug("Logging out of all servers");
@Override
public void onResponse() {
LogoutAll(new EmptyResponse() {
private void OnSuccessOrFail() {
_logger.Debug("Updating saved credentials for all servers");
ServerCredentialConfiguration credentials = _credentialProvider.GetCredentials();
for(ServerInfo server : credentials.getServers()){
for (ServerInfo server : credentials.getServers()) {
server.setAccessToken(null);
server.setUserId(null);
@ -191,6 +394,16 @@ public class ConnectionManager implements IConnectionManager {
Connect(response);
}
@Override
public void onResponse() {
OnSuccessOrFail();
}
@Override
public void onError() {
OnSuccessOrFail();
}
});
}
@ -263,9 +476,7 @@ public class ConnectionManager implements IConnectionManager {
@Override
public void onError() {
PublicSystemInfo obj = null;
response.onResponse(obj);
response.onError();
}
};
@ -354,7 +565,9 @@ public class ConnectionManager implements IConnectionManager {
private void OnAuthenticated(final ApiClient apiClient, final AuthenticationResult result)
{
Response<SystemInfo> systemInfoResponse = new Response<SystemInfo>(){
_logger.Debug("Updating credentials after authentication");
apiClient.GetSystemInfoAsync(new Response<SystemInfo>(){
@Override
public void onResponse(SystemInfo info) {
@ -373,13 +586,14 @@ public class ConnectionManager implements IConnectionManager {
EnsureWebSocketIfConfigured(apiClient);
}
};
apiClient.GetSystemInfoAsync(systemInfoResponse);
});
}
private void GetAvailableServers(final Response<ArrayList<ServerInfo>> response)
{
_logger.Debug("Locating available servers");
_logger.Debug("Getting saved servers via credential provider");
ArrayList<ServerInfo> servers = _credentialProvider.GetCredentials().getServers();
response.onResponse(servers);
@ -420,6 +634,8 @@ public class ConnectionManager implements IConnectionManager {
private void WakeAllServers()
{
_logger.Debug("Waking all servers");
for(ServerInfo server : _credentialProvider.GetCredentials().getServers()){
WakeServer(server, new EmptyResponse());
@ -428,11 +644,14 @@ public class ConnectionManager implements IConnectionManager {
private void WakeServer(ServerInfo info, final EmptyResponse response)
{
_logger.Debug("Waking server: %s, Id: %s", info.getName(), info.getId());
ArrayList<WakeOnLanInfo> wakeList = info.getWakeOnLanInfos();
final int count = wakeList.size();
if (count == 0){
_logger.Debug("Server %s has no saved wake on lan profiles", info.getName());
response.onResponse();
return;
}
@ -443,9 +662,7 @@ public class ConnectionManager implements IConnectionManager {
WakeServer(info, new EmptyResponse(){
@Override
public void onResponse() {
private void OnServerDone(){
synchronized(doneList) {
doneList.add(new EmptyResponse());
@ -453,24 +670,19 @@ public class ConnectionManager implements IConnectionManager {
if (doneList.size() >= count){
response.onResponse();
}
}
}
@Override
public void onResponse() {
OnServerDone();
}
@Override
public void onError() {
synchronized (doneList) {
doneList.add(new EmptyResponse());
if (doneList.size() >= count) {
response.onResponse();
}
}
OnServerDone();
}
});
}

View File

@ -97,6 +97,8 @@ public class ServerDiscovery implements IServerLocator {
ServerDiscoveryInfo[] servers = new ServerDiscoveryInfo[]{ serverInfo};
logger.Debug("Found %d servers", servers.length);
response.onResponse(servers);
//Close the port!

View File

@ -9,13 +9,12 @@ import android.content.Context;
import android.graphics.Bitmap;
import android.text.TextUtils;
import android.util.LruCache;
import com.android.volley.AuthFailureError;
import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.VolleyError;
import com.android.volley.*;
import com.android.volley.toolbox.HttpClientStack;
import com.android.volley.toolbox.ImageLoader;
import com.android.volley.toolbox.StringRequest;
import com.android.volley.toolbox.Volley;
import org.apache.http.impl.client.DefaultHttpClient;
import java.util.HashMap;
import java.util.Map;
@ -48,7 +47,9 @@ public class VolleyHttpClient implements IAsyncHttpClient {
// lazy initialize the request queue, the queue instance will be
// created when it is accessed for the first time
if (mRequestQueue == null) {
mRequestQueue = Volley.newRequestQueue(context, new OkHttpStack());
//mRequestQueue = Volley.newRequestQueue(context, new HttpClientStack(new DefaultHttpClient()));
//mRequestQueue = Volley.newRequestQueue(context);
}

View File

@ -2,6 +2,7 @@ package MediaBrowser.ApiInteraction.Network;
import MediaBrowser.ApiInteraction.EmptyResponse;
import MediaBrowser.ApiInteraction.NetworkStatus;
import MediaBrowser.Model.Logging.ILogger;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
@ -12,14 +13,18 @@ import java.net.*;
public class NetworkConnection implements INetworkConnection {
private Context context;
private ILogger logger;
public NetworkConnection(Context context) {
public NetworkConnection(Context context, ILogger logger) {
this.context = context;
this.logger = logger;
}
@Override
public void SendWakeOnLan(String macAddress, int port, EmptyResponse response) throws IOException
{
logger.Debug("Sending WakeOnLan over broadcast address. Mac: %s, Port: %d", macAddress, port);
byte[] macBytes = getMacBytes(macAddress);
byte[] bytes = new byte[6 + 16 * macBytes.length];
for (int i = 0; i < 6; i++) {
@ -40,6 +45,8 @@ public class NetworkConnection implements INetworkConnection {
public void SendWakeOnLan(String macAddress, String ipAddress, int port, EmptyResponse response)
throws IOException
{
logger.Debug("Sending WakeOnLan to %s. Mac: %s, Port: %d", ipAddress, macAddress, port);
byte[] macBytes = getMacBytes(macAddress);
byte[] bytes = new byte[6 + 16 * macBytes.length];
for (int i = 0; i < 6; i++) {
@ -61,6 +68,8 @@ public class NetworkConnection implements INetworkConnection {
NetworkStatus status = new NetworkStatus();
logger.Debug("Testing local device network connection");
final ConnectivityManager conMgr = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
final NetworkInfo activeNetwork = conMgr.getActiveNetworkInfo();
@ -71,11 +80,19 @@ public class NetworkConnection implements INetworkConnection {
int type = activeNetwork.getType();
if (type == ConnectivityManager.TYPE_MOBILE){
logger.Debug("Local device is connected to a network");
status.setIsRemoteNetworkAvailable(true);
}
else{
logger.Debug("Local device is connected to a mobile network");
}
} else {
logger.Debug("Local device is not connected to the network");
// notify user you are not online
status.setIsNetworkAvailable(false);
}

View File

@ -3,6 +3,8 @@ package MediaBrowser.ApiInteraction;
import MediaBrowser.Model.ApiClient.ServerInfo;
import MediaBrowser.Model.Extensions.StringHelper;
import java.util.ArrayList;
public class ServerCredentialConfiguration {
private String lastServerId;
@ -15,7 +17,7 @@ public class ServerCredentialConfiguration {
lastServerId = value;
}
private java.util.ArrayList<ServerInfo> servers;
private java.util.ArrayList<ServerInfo> servers = new ArrayList<ServerInfo>();
public final java.util.ArrayList<ServerInfo> getServers()
{
return servers;

View File

@ -0,0 +1,77 @@
package MediaBrowser;
import MediaBrowser.ApiInteraction.*;
import MediaBrowser.ApiInteraction.Discovery.ServerDiscovery;
import MediaBrowser.ApiInteraction.Http.VolleyHttpClient;
import MediaBrowser.ApiInteraction.Network.NetworkConnection;
import MediaBrowser.Model.Logging.ILogger;
import MediaBrowser.Model.Serialization.IJsonSerializer;
import MediaBrowser.Model.Session.ClientCapabilities;
import MediaBrowser.Model.System.PublicSystemInfo;
import android.content.Context;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.Robolectric;
import org.robolectric.RobolectricTestRunner;
import static org.junit.Assert.fail;
@RunWith(RobolectricTestRunner.class)
public class ConnectionManagerTests {
private ILogger logger = new ConsoleLogger();
private IConnectionManager connectionManager;
private IJsonSerializer jsonSerializer = new JsonSerializer();
@Before
public void setUp() throws Exception {
// The underlying http stack. Developers can inject their own if desired
Context context = Robolectric.application.getApplicationContext();
IAsyncHttpClient volleyHttpClient = new VolleyHttpClient(logger, context);
ClientCapabilities capabilities = new ClientCapabilities();
ApiEventListener apiEventListener = new ApiEventListener();
connectionManager = new ConnectionManager(new FakeCredentialProvider(),
new NetworkConnection(context, logger),
logger,
new ServerDiscovery(logger, jsonSerializer),
volleyHttpClient,
"App Name",
"App Version",
new FakeDevice(),
capabilities,
apiEventListener);
}
@Test
public void testConnectionManager() throws Exception {
logger.Debug("testConnectionManager");
connectionManager.Connect(new Response<ConnectionResult>(){
@Override
public void onResponse(ConnectionResult result) {
logger.Debug("testConnectionManager: response");
}
@Override
public void onError() {
logger.Debug("testConnectionManager: error");
// Do something with error
fail("Method failed");
}
});
}
}

View File

@ -0,0 +1,19 @@
package MediaBrowser;
import MediaBrowser.ApiInteraction.ICredentialProvider;
import MediaBrowser.ApiInteraction.ServerCredentialConfiguration;
public class FakeCredentialProvider implements ICredentialProvider {
private ServerCredentialConfiguration config = new ServerCredentialConfiguration();
@Override
public ServerCredentialConfiguration GetCredentials() {
return config;
}
@Override
public void SaveCredentials(ServerCredentialConfiguration credentials) {
config = credentials;
}
}

View File

@ -0,0 +1,25 @@
package MediaBrowser;
import MediaBrowser.ApiInteraction.IDevice;
import java.util.Observable;
public class FakeDevice implements IDevice {
@Override
public String getDeviceName() {
return "Device Name";
}
@Override
public String getDeviceId() {
return "Device Id";
}
private Observable resumeFromSleepObservable = new Observable();
@Override
public Observable getResumeFromSleepObservable() {
return resumeFromSleepObservable;
}
}