【问题标题】:How can I make it work HttpsURLConnection and SAX parser to be stable?如何使它工作 HttpsURLConnection 和 SAX 解析器稳定?
【发布时间】:2016-05-24 14:32:22
【问题描述】:

所以我使用了很好的 HttpClient 没有问题,一切正常,直到 Android 6 命中,然后我还必须添加一个 HttpsURLConnection,因为不幸的是我们的客户没有那么幸运拥有更新的 Android 设备,所以我将此代码添加到我已经开发的网络类中:

public static HashMap<String, Object> callSOAPServer(StringBuffer soap, String action) {
    HttpsURLConnection urlConnection = null;
    boolean download = true;
    if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {

        try {
            CertificateFactory cf = CertificateFactory.getInstance("X.509");
            InputStream caInput = IsakApp.appContext.getResources().openRawResource(R.raw.thawte);
            Certificate ca;
            try {
                ca = cf.generateCertificate(caInput);
            } finally {
                caInput.close();
            }

            String keyStoreType = KeyStore.getDefaultType();
            KeyStore keyStore = KeyStore.getInstance(keyStoreType);
            keyStore.load(null, null);
            keyStore.setCertificateEntry("ca", ca);

            String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
            TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
            tmf.init(keyStore);

            SSLContext context = SSLContext.getInstance("TLS");
            context.init(null, tmf.getTrustManagers(), null);

            URL url = new URL("whateverPage.com");

            urlConnection =
                    (HttpsURLConnection) url.openConnection();

            urlConnection.setSSLSocketFactory(context.getSocketFactory());


            urlConnection.setRequestMethod("POST");
            urlConnection.setConnectTimeout(20000);
            urlConnection.setReadTimeout(20000);
            urlConnection.setDoInput(true);
            urlConnection.setDoOutput(true);
            urlConnection.setRequestProperty("Content-type", "text/xml; charset=utf-8");
            urlConnection.setRequestProperty("SOAPAction", action);
            OutputStream reqStream = urlConnection.getOutputStream();
            reqStream.write(soap.toString().getBytes());

            InputStream resStream = urlConnection.getInputStream();


            byte[] data = new byte[1024 * 1024];

            ByteArrayOutputStream buffer = new ByteArrayOutputStream();

            int count = urlConnection.getContentLength();
            int total = 0;
            int size = 0;
            while ((count = resStream.read(data, 0, data.length)) != -1) {
                buffer.write(data, 0, count);
           }

            buffer.flush();
            String str = new String(buffer.toByteArray(), "UTF-8");
            System.out.println("--------");
            System.out.println(str);
            String sn = str.replace("&amp;", "AMP");
            String[] stringArray = sn.split("\\r?\\n");
            String soapNew = stringArray[1];
            byte[] bytes = soapNew.getBytes("UTF-8");
            HashMap<String, Object> xMap = new HashMap<String, Object>();
            xMap.put(IsakApp.STATUS, "true");
            xMap.put("soap", bytes);
            resStream.close();

            return xMap;

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if( urlConnection != null) {
                urlConnection.disconnect();
            }
        }
 }

所以我的问题是,这是非常不可靠的,并不总是下载我需要的所有数据,但是当我使用通过 HttpClient 工作的旧设备时,这个问题并不存在。我的主要问题是:

System.err: org.apache.harmony.xml.ExpatParser$ParseException: At line 1, column 62973: no element found
System.err:     at org.apache.harmony.xml.ExpatParser.finish(ExpatParser.java:545)
System.err:     at org.apache.harmony.xml.ExpatParser.parseDocument(ExpatParser.java:475)
System.err:     at org.apache.harmony.xml.ExpatReader.parse(ExpatReader.java:316)
System.err:     at org.apache.harmony.xml.ExpatReader.parse(ExpatReader.java:279)
System.err:     at com.czami.isakmobileapp.handling.XMLParser.parseSoap(XMLParser.java:153)
System.err:     at com.czami.isakmobileapp.netInteraction.PostList.postList(PostList.java:44)
System.err:     at com.czami.isakmobileapp.services.UpdateOneShot.onHandleIntent(UpdateOneShot.java:338)

问题是,那些 SOAP 消息,如果我将它们写在文件中,它们会正常发送,没有任何问题。而且在 Android 版本低于 6 的情况下,它在 HttpClient 上也能正常工作,如果它被弃用的话。现在我面临着相当大的问题,我不确定这有什么问题。一些 SOAP 消息通过没有问题,但似乎更大的消息不起作用。有人可以指出某个方向吗,我在这个应用程序上还有其他事情要做,这就像尝试了 2 天但仍然没有成功。我可能会查看解释 HttpsURLConnection 的每个页面、此处的每个页面以及代码下方存在此问题的页面。我很绝望。感谢您的任何回答。

【问题讨论】:

    标签: java android soap sax httpsurlconnection


    【解决方案1】:

    您仍然可以在新设备上使用旧的 Apache HTTP API。您只需在 gradle 文件中添加一个依赖项。将此添加到模块 build.gradle 文件的 android {} 块中:

    android {
        useLibrary 'org.apache.http.legacy'
    }
    

    一旦你这样做了,你应该很好地使用你所有的旧 HttpClient 代码。


    编辑

    我想知道您是否可能由于请求大小或类似原因的性能问题而在传输过程中丢失数据。您可以尝试改用一些缓冲类型的阅读器。下面是我在我的一个应用程序中使用的一些代码,用于使用HttpURLConnection 完成 SOAP 请求。也许你可以试试我用的一些东西,看看它们是否有帮助,例如输入流的BufferedReader

    String result = null;
    String requestInput = formatXmlRequest(input[0]); //returns a SOAP request String
    URL url;
    HttpURLConnection connection = null;
    OutputStreamWriter out = null;
    
    try {
        url = new URL(WEB_SERVICE_URL);
        connection = (HttpURLConnection) url.openConnection();
        connection.setDoOutput(true);
        connection.setDoInput(true);
        connection.setRequestProperty("Content-Type", "application/soap+xml");
        connection.setRequestProperty("Accept", "application/soap+xml");
    
        out = new OutputStreamWriter(connection.getOutputStream());
        out.write(requestInput);
        out.flush();
    
        StringBuilder stringBuilder = new StringBuilder();
        int responseCode = connection.getResponseCode();
    
        if(responseCode == HttpURLConnection.HTTP_OK) {
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(connection.getInputStream(), "utf-8"));
            String line;
            while((line = bufferedReader.readLine()) != null) {
                stringBuilder.append(line).append("\n");
            }
        } else {
            Log.d("BAD RESPONSE", "Response from server: "+responseCode);
        }
    
        result = stringBuilder.toString();
    
    } catch (IOException ioe) {
        ioe.printStackTrace();
    } finally {
        if(connection != null) connection.disconnect();
        if(out != null) {
            try {
                out.close();
            } catch (IOException ioe) {
                ioe.printStackTrace();
            }
        }
    }
    
    return result;
    

    【讨论】:

    • 我使用它,但是对于 6 是不行的,它适用于 5。我的 gradle 构建文件中有这个。
    • 我使用HttpURLConnection 在我的一个应用程序中发出 SOAP 请求,它适用于所有 API。我已经发布了我上面使用的代码。也许你可以试试我使用的一些技巧。我想知道您是否需要使用BufferedReader 来获取输入流?可能存在一些性能问题导致您的数据丢失,这可能会有所帮助。
    • 我尝试了您的解决方案并让您知道情况如何,我肯定可能会丢失数据,希望 HttpURLConnection 和 HttpsURLConnection 是同一件事,只是需要一些额外的工作,而这实际上并不涉及其余部分编码。非常感谢!
    • 是的,HttpURLConnectionHttpsURLConnection 基本上可以互换。
    • 我成功了,非常感谢,你是救生员,保重,再次感谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-06-17
    • 2015-04-12
    • 1970-01-01
    • 2012-08-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多