Fixed bad architecture decision: set read timeout on tcp socket, so that it gets closed automatically after a set period of time. This way there's no need to invoke disconnect() when each activity pauses, so we don't have to maintain this control.
This commit is contained in:
parent
69b436af2b
commit
58c7a5d3f6
|
@ -15,7 +15,7 @@
|
|||
*/
|
||||
package com.syncedsynapse.kore2.jsonrpc;
|
||||
|
||||
import android.os.*;
|
||||
import android.os.Handler;
|
||||
import android.os.Process;
|
||||
import android.util.Base64;
|
||||
|
||||
|
@ -24,7 +24,8 @@ import com.fasterxml.jackson.core.JsonProcessingException;
|
|||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
import com.syncedsynapse.kore2.host.HostInfo;
|
||||
import com.syncedsynapse.kore2.jsonrpc.notification.*;
|
||||
import com.syncedsynapse.kore2.jsonrpc.notification.Input;
|
||||
import com.syncedsynapse.kore2.jsonrpc.notification.Player;
|
||||
import com.syncedsynapse.kore2.jsonrpc.notification.System;
|
||||
import com.syncedsynapse.kore2.utils.LogUtils;
|
||||
|
||||
|
@ -37,7 +38,6 @@ import java.net.HttpURLConnection;
|
|||
import java.net.InetSocketAddress;
|
||||
import java.net.ProtocolException;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketException;
|
||||
import java.net.URL;
|
||||
import java.util.HashMap;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
|
@ -134,31 +134,33 @@ public class HostConnection {
|
|||
|
||||
private ExecutorService executorService;
|
||||
|
||||
private final int connectionTimeout;
|
||||
private final int connectTimeout;
|
||||
|
||||
private static final int DEFAULT_TIMEOUT = 10000; // ms
|
||||
private static final int DEFAULT_CONNECT_TIMEOUT = 5000; // ms
|
||||
|
||||
private static final int TCP_READ_TIMEOUT = 30000; // ms
|
||||
|
||||
/**
|
||||
* Creates a new host connection
|
||||
* @param hostInfo Host info object
|
||||
*/
|
||||
public HostConnection(final HostInfo hostInfo) {
|
||||
this(hostInfo, DEFAULT_TIMEOUT);
|
||||
this(hostInfo, DEFAULT_CONNECT_TIMEOUT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new host connection
|
||||
* @param hostInfo Host info object
|
||||
* @param connectionTimeout Connection timeout in ms
|
||||
* @param connectTimeout Connection timeout in ms
|
||||
*/
|
||||
public HostConnection(final HostInfo hostInfo, int connectionTimeout) {
|
||||
public HostConnection(final HostInfo hostInfo, int connectTimeout) {
|
||||
this.hostInfo = hostInfo;
|
||||
// Start with the default host protocol
|
||||
this.protocol = hostInfo.getProtocol();
|
||||
// Create a single threaded executor
|
||||
this.executorService = Executors.newSingleThreadExecutor();
|
||||
// Set timeout
|
||||
this.connectionTimeout = connectionTimeout;
|
||||
this.connectTimeout = connectTimeout;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -356,8 +358,8 @@ public class HostConnection {
|
|||
// LogUtils.LOGD(TAG, "Opening HTTP connection.");
|
||||
HttpURLConnection connection = (HttpURLConnection) new URL(hostInfo.getJsonRpcHttpEndpoint()).openConnection();
|
||||
connection.setRequestMethod("POST");
|
||||
connection.setConnectTimeout(connectionTimeout);
|
||||
//connection.setReadTimeout(connectionTimeout);
|
||||
connection.setConnectTimeout(connectTimeout);
|
||||
//connection.setReadTimeout(connectTimeout);
|
||||
connection.setRequestProperty("Content-Type", "application/json");
|
||||
connection.setDoOutput(true);
|
||||
|
||||
|
@ -482,10 +484,6 @@ public class HostConnection {
|
|||
*/
|
||||
private <T> void executeThroughTcp(final ApiMethod<T> method, final ApiCallback<T> callback,
|
||||
final Handler handler) {
|
||||
|
||||
// TODO: We're going to create a background listener thread.
|
||||
// Also create a thread that periodically checks if the connection should be shutdown
|
||||
// based on not having activity. Use android timer or Thread.sleep
|
||||
String methodId = String.valueOf(method.getId());
|
||||
try {
|
||||
// Save this method/callback for later response
|
||||
|
@ -534,13 +532,11 @@ public class HostConnection {
|
|||
|
||||
Socket socket = new Socket();
|
||||
final InetSocketAddress address = new InetSocketAddress(hostInfo.getAddress(), hostInfo.getTcpPort());
|
||||
socket.setSoTimeout(0); // No read timeout. Read should block
|
||||
socket.connect(address, connectionTimeout);
|
||||
// We're setting a read timeout on the socket, so no need to explicitly close it
|
||||
socket.setSoTimeout(TCP_READ_TIMEOUT);
|
||||
socket.connect(address, connectTimeout);
|
||||
|
||||
return socket;
|
||||
} catch (SocketException e) {
|
||||
LogUtils.LOGW(TAG, "Failed to open TCP connection to host: " + hostInfo.getAddress());
|
||||
throw new ApiException(ApiException.IO_EXCEPTION_WHILE_CONNECTING, e);
|
||||
} catch (IOException e) {
|
||||
LogUtils.LOGW(TAG, "Failed to open TCP connection to host: " + hostInfo.getAddress());
|
||||
throw new ApiException(ApiException.IO_EXCEPTION_WHILE_CONNECTING, e);
|
||||
|
|
|
@ -35,7 +35,7 @@ import com.syncedsynapse.kore2.utils.Utils;
|
|||
* Controls the presentation of Addons information (list, details)
|
||||
* All the information is presented by specific fragments
|
||||
*/
|
||||
public class AddonsActivity extends HostConnectionActivity
|
||||
public class AddonsActivity extends BaseActivity
|
||||
implements AddonListFragment.OnAddonSelectedListener {
|
||||
private static final String TAG = LogUtils.makeLogTag(AddonsActivity.class);
|
||||
|
||||
|
|
|
@ -1,47 +0,0 @@
|
|||
/*
|
||||
* Copyright 2015 Synced Synapse. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.syncedsynapse.kore2.ui;
|
||||
|
||||
import android.os.Bundle;
|
||||
|
||||
import com.syncedsynapse.kore2.host.HostManager;
|
||||
import com.syncedsynapse.kore2.jsonrpc.HostConnection;
|
||||
|
||||
/**
|
||||
* This activity manages the closing of the {@link HostConnection} singleton provided by
|
||||
* {@link HostManager}.
|
||||
* All activities that plan to use the {@link HostConnection}, or their fragments do,
|
||||
* should inherit from this class to make sure the connection is closed onPause/
|
||||
*/
|
||||
public class HostConnectionActivity extends BaseActivity {
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
|
||||
// Disconnect from the connections used in the fragments
|
||||
HostConnection connection = HostManager.getInstance(this).getConnection();
|
||||
if (connection != null) {
|
||||
connection.disconnect();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -35,7 +35,7 @@ import com.syncedsynapse.kore2.utils.Utils;
|
|||
* Controls the presentation of Movies information (list, details)
|
||||
* All the information is presented by specific fragments
|
||||
*/
|
||||
public class MoviesActivity extends HostConnectionActivity
|
||||
public class MoviesActivity extends BaseActivity
|
||||
implements MovieListFragment.OnMovieSelectedListener {
|
||||
private static final String TAG = LogUtils.makeLogTag(MoviesActivity.class);
|
||||
|
||||
|
|
|
@ -34,7 +34,7 @@ import com.syncedsynapse.kore2.utils.Utils;
|
|||
* Controls the presentation of Music information (list, details)
|
||||
* All the information is presented by specific fragments
|
||||
*/
|
||||
public class MusicActivity extends HostConnectionActivity
|
||||
public class MusicActivity extends BaseActivity
|
||||
implements ArtistListFragment.OnArtistSelectedListener,
|
||||
AlbumListFragment.OnAlbumSelectedListener,
|
||||
AudioGenresListFragment.OnAudioGenreSelectedListener,
|
||||
|
|
|
@ -51,7 +51,7 @@ import butterknife.ButterKnife;
|
|||
import butterknife.InjectView;
|
||||
|
||||
|
||||
public class RemoteActivity extends HostConnectionActivity
|
||||
public class RemoteActivity extends BaseActivity
|
||||
implements HostConnectionObserver.PlayerEventsObserver,
|
||||
NowPlayingFragment.NowPlayingListener,
|
||||
SendTextDialogFragment.SendTextDialogListener {
|
||||
|
|
|
@ -35,7 +35,7 @@ import com.syncedsynapse.kore2.utils.Utils;
|
|||
* Controls the presentation of TV Shows information (list, details)
|
||||
* All the information is presented by specific fragments
|
||||
*/
|
||||
public class TVShowsActivity extends HostConnectionActivity
|
||||
public class TVShowsActivity extends BaseActivity
|
||||
implements TVShowListFragment.OnTVShowSelectedListener,
|
||||
TVShowEpisodeListFragment.OnEpisodeSelectedListener {
|
||||
private static final String TAG = LogUtils.makeLogTag(TVShowsActivity.class);
|
||||
|
|
Loading…
Reference in New Issue