我遇到了使用WebSocket Secure的问题。我使用这个websocket库:'org.java-websocket:Java-WebSocket:1.3.0'。该问题仅出现在LENOVO智能手机上(并非适用于所有型号,例如联想A6000按预期工作)。例如,Lenovo Vibe设备上发生错误。我在Nexus 4,Nexus 5,Nexus 5x,Nexus 6,Nexus 6P,联想A6000,联想Vibe,三星Galaxy SIII(CyanogenMod Android 4.4.4)上进行了测试。此列表中仅在Lenovo Vibe设备上出现错误。 这是一个错误:
java.nio.channels.UnresolvedAddressException
这是我的代码:
final String url = wss://*****.com/wss;
URI uri=null;
try{
uri = new URI(url);
}
catch (Exception e)
{
}
Map<String, String> headers = new HashMap<>();
headers.put("auth_key", TOKEN);
mWebSocketClient = new WebSocketClient(uri, new Draft_10(), headers, 0) {
@Override
public void onOpen(ServerHandshake handshakedata) {
}
@Override
public void onMessage(String message) {
}
@Override
public void onClose(int code, String reason, boolean remote) {
}
@Override
public void onError(Exception ex) {
//HERE I HANDLE AN ERROR ON LENOVO VIBE
}
};
try{
SSLContext sslContext = SSLContext.getDefault();
mWebSocketClient.setWebSocketFactory(new DefaultSSLWebSocketClientFactory(sslContext));
mWebSocketClient.connect();
}catch (Exception e)
{
}
在库中,在WebSocketClient.java类中出现错误:
private final void interruptableRun() {
if( channel == null ) {
return;// channel will be initialized in the constructor and only be null if no socket channel could be created or if blocking mode could be established
}
try {
String host;
int port ;
if( proxyAddress != null ) {
host = proxyAddress.getHostName();
port = proxyAddress.getPort();
} else {
host = uri.getHost();
port = getPort();
}
channel.connect( new InetSocketAddress( host, port ) );
conn.channel = wrappedchannel = createProxyChannel( wsfactory.wrapChannel( channel, null, host, port ) );
timeout = 0; // since connect is over
sendHandshake();
readthread = new Thread( new WebsocketWriteThread() );
readthread.start();
} catch ( ClosedByInterruptException e ) {
onWebsocketError( null, e );
return;
} catch ( /*IOException | SecurityException | UnresolvedAddressException*/Exception e ) {//
onWebsocketError( conn, e );
conn.closeConnection( CloseFrame.NEVER_CONNECTED, e.getMessage() );
return;
}
ByteBuffer buff = ByteBuffer.allocate( WebSocketImpl.RCVBUF );
try/*IO*/{
while ( channel.isOpen() ) {
if( SocketChannelIOHelper.read( buff, this.conn, wrappedchannel ) ) {
conn.decode( buff );
} else {
conn.eot();
}
if( wrappedchannel instanceof WrappedByteChannel ) {
WrappedByteChannel w = (WrappedByteChannel) wrappedchannel;
if( w.isNeedRead() ) {
while ( SocketChannelIOHelper.readMore( buff, conn, w ) ) {
conn.decode( buff );
}
conn.decode( buff );
}
}
}
} catch ( CancelledKeyException e ) {
conn.eot();
} catch ( IOException e ) {
conn.eot();
} catch ( RuntimeException e ) {
// this catch case covers internal errors only and indicates a bug in this websocket implementation
onError( e );
conn.closeConnection( CloseFrame.ABNORMAL_CLOSE, e.getMessage() );
}
}
在这条线上:
channel.connect( new InetSocketAddress( host, port ) );
此外,如果您知道任何其他适用于所有设备的WebSocket库,我可以使用wss链接并放置自定义标头,请分享。
答案 0 :(得分:0)
最后我找到了一个解决方案..这里是:
1)从libraty重写WebSocketClient.java类(或者只是提取库并将其粘贴到项目中)
2)创建新类:
import java.net.InetAddress;
import java.net.InetSocketAddress;
public class MyInetSocketAddress {
public static InetSocketAddress myInetSocketAddress(String hostname, int port, boolean needResolved)
{
if (hostname == null || port < 0 || port > 65535) {
throw new IllegalArgumentException("host=" + hostname + ", port=" + port);
}
InetAddress addr = null;
if (needResolved) {
try {
addr = InetAddress.getByName(hostname);
}
catch (Exception ignored)
{
}
}
return new InetSocketAddress(addr, port);
}
}
3)打开你的WebSocketClient.java类,找到:
interruptableRun()
方法并替换它:
channel.connect(new InetSocketAddress(host,port));
这一个:
channel.connect(MyInetSocketAddress.myInetSocketAddress(host,port,true));
4)在方法结束时添加try / catch - 替换:
conn.closeConnection(CloseFrame.ABNORMAL_CLOSE,e.getMessage());
使用:
try{
conn.closeConnection( CloseFrame.ABNORMAL_CLOSE, e.getMessage() );
}
catch (Exception e1)
{
}
5)此处另外添加catch(例外e):
private class WebsocketWriteThread implements Runnable {
@Override
public void run() {
Thread.currentThread().setName( "WebsocketWriteThread" );
try {
while ( !Thread.interrupted() ) {
SocketChannelIOHelper.writeBlocking( conn, wrappedchannel );
}
} catch ( IOException e ) {
conn.eot();
} catch ( InterruptedException e ) {
// this thread is regularly terminated via an interrupt
}
}
}
如下所示:
private class WebsocketWriteThread implements Runnable {
@Override
public void run() {
Thread.currentThread().setName( "WebsocketWriteThread" );
try {
while ( !Thread.interrupted() ) {
SocketChannelIOHelper.writeBlocking( conn, wrappedchannel );
}
} catch ( IOException e ) {
conn.eot();
} catch ( InterruptedException e ) {
// this thread is regularly terminated via an interrupt
} catch (Exception e)
{
}
}
}
6)另外,不要忘记使用它:
ProviderInstaller.installIfNeeded(getApplicationContext());
SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
sslContext.init(null, null, null);
mWebSocketClient.setWebSocketFactory(new DefaultSSLWebSocketClientFactory(sslContext));
mWebSocketClient.connect();
如上所述。
希望这会有所帮助!))如果您有任何问题 - 请问我)