终于找到了解决办法。
根据此文档,Android API级别16(Android 4.1,Jelly
Bean)支持TLS 1.1和TLS 1.2。 但默认情况下, 直到API级别20+才 启用 (手表使用Android 4.4,Kitkat
Watch和手机5.0,Lollipop Android 5.0)。
因此,我们需要的是在代码中以图形方式启用它们。我们该怎么做?这里有解决此问题的方法,但是它只是解决了您要接受任何证书的情况下的问题。
我们需要做的是做同样的事情,但要使用我们自己的自签名证书。所以我们像下面这样
第一部分就像我之前所做的那样:(
keyStoreInputStream是.pfx文件的输入流)
connection = createConnection(mqttCallback);MqttConnectOptions connOpts = optionsFromModel(connectionModel);connOpts.setSocketFactory(getSSLSocketFactory(keyStoreInputStream, keyStorePassword));connection.addConnectionOptions(connOpts);
的
getSSLSocketFactory方法改变为:
public SSLSocketFactory getSSLSocketFactory (InputStream keyStore, String password) throws MqttSecurityException { try{ SSLContext ctx = null; SSLSocketFactory sslSockFactory=null; KeyStore ks; ks = KeyStore.getInstance("PKCS12"); ks.load(keyStore, password.toCharArray()); TrustManagerFactory tmf = TrustManagerFactory.getInstance("X509"); tmf.init(ks); TrustManager[] tm = tmf.getTrustManagers(); ctx = SSLContext.getInstance("TLS"); ctx.init(null, tm, null); if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT) { sslSockFactory = new TLSSocketFactory(tm); } else { sslSockFactory = ctx.getSocketFactory(); } return sslSockFactory; } catch (KeyStoreException | CertificateException | IOException | NoSuchAlgorithmException | KeyManagementException e) { throw new MqttSecurityException(e); }}与
TLSSocketFactory类象下面这样:
import java.io.IOException;import java.net.InetAddress;import java.net.Socket;import java.net.UnknownHostException;import java.security.KeyManagementException;import java.security.NoSuchAlgorithmException;import javax.net.ssl.SSLContext;import javax.net.ssl.SSLSocket;import javax.net.ssl.SSLSocketFactory;import javax.net.ssl.TrustManager;public class TLSSocketFactory extends SSLSocketFactory {private SSLSocketFactory internalSSLSocketFactory;public TLSSocketFactory(TrustManager[] trustManagers) throws KeyManagementException, NoSuchAlgorithmException { SSLContext context = SSLContext.getInstance("TLS"); context.init(null, trustManagers, null); internalSSLSocketFactory = context.getSocketFactory();}@Overridepublic String[] getDefaultCipherSuites() { return internalSSLSocketFactory.getDefaultCipherSuites();}@Overridepublic String[] getSupportedCipherSuites() { return internalSSLSocketFactory.getSupportedCipherSuites();}@Overridepublic Socket createSocket() throws IOException { return enableTLSonSocket(internalSSLSocketFactory.createSocket());}@Overridepublic Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException { return enableTLSonSocket(internalSSLSocketFactory.createSocket(s, host, port, autoClose));}@Overridepublic Socket createSocket(String host, int port) throws IOException, UnknownHostException { return enableTLSonSocket(internalSSLSocketFactory.createSocket(host, port));}@Overridepublic Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException, UnknownHostException { return enableTLSonSocket(internalSSLSocketFactory.createSocket(host, port, localHost, localPort));}@Overridepublic Socket createSocket(InetAddress host, int port) throws IOException { return enableTLSonSocket(internalSSLSocketFactory.createSocket(host, port));}@Overridepublic Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException { return enableTLSonSocket(internalSSLSocketFactory.createSocket(address, port, localAddress, localPort));}private Socket enableTLSonSocket(Socket socket) { if(socket != null && (socket instanceof SSLSocket)) { ((SSLSocket)socket).setEnabledProtocols(new String[] {"TLSv1.2", "TLSv1.1"}); } return socket;}}


