【问题标题】:Android - Sending HTTPS Get RequestAndroid - 发送 HTTPS 获取请求
【发布时间】:2012-04-01 20:38:14
【问题描述】:

我想向谷歌购物 api 发送一个 HTTPS 获取请求,但是没有什么对我有用,例如,这是我目前正在尝试的:

try {        
    HttpClient client = new DefaultHttpClient();
    HttpGet request = new HttpGet();
    request.setURI(new URI("https://www.googleapis.com/shopping/search/v1/public/products/?key={my_key}&country=&q=t-shirts&alt=json&rankByrelevancy="));
    HttpResponse response = client.execute(request);
} catch (URISyntaxException e) {
    e.printStackTrace();
} catch (ClientProtocolException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
} catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}   
return response;

如果有人对如何改进或替换它有任何建议,请告诉我,提前谢谢。

【问题讨论】:

  • 这不是您的完整代码,因为response 变量不在返回语句的范围内。即你在你的 try 块中声明它,这样就行不通了。怎么了?
  • 我已经编辑了我的帖子以包含 try 括号,但仅此而已。我是否应该删除 try 和 catch 括号并只使用“抛出异常...”以便访问响应变量?
  • 什么不起作用?有什么例外,Logcat?当问题来自 httpClient 时,我建议的第一件事是始终检查响应状态代码,即 httpResponse.getStatusLine().getStatusCode();
  • 我尝试按照您的建议检查响应状态,但它带有下划线并给出错误,我使用日志找出返回的响应是“org.apache.http.message” .BasicHttpResponse@46241178" 但是这并不重要,因为这次它没有强制关闭。你知道我如何使用响应值吗,它应该返回一个 JSON 格式的数组,我可以解析它,但它看起来不像。
  • 希望你已经解决了你的问题

标签: android http https get httpclient


【解决方案1】:

你应该得到一个编译错误。

这是正确的版本:

HttpResponse response = null;
try {        
    HttpClient client = new DefaultHttpClient();
    HttpGet request = new HttpGet();
    request.setURI(new URI("https://www.googleapis.com/shopping/search/v1/public/products/?key={my_key}&country=&q=t-shirts&alt=json&rankByrelevancy="));
    response = client.execute(request);
} catch (URISyntaxException e) {
    e.printStackTrace();
} catch (ClientProtocolException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
} catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}   
return response;

因此,现在如果您遇到错误,您的响应将返回为 null。

一旦你得到响应并检查它是否为空,你就会想要获取内容(即你的 JSON)。

http://developer.android.com/reference/org/apache/http/HttpResponse.html http://developer.android.com/reference/org/apache/http/HttpEntity.html http://developer.android.com/reference/java/io/InputStream.html

response.getEntity().getContent();

这为您提供了一个可以使用的 InputStream。如果要将其转换为字符串,请执行以下操作或等效操作:

http://www.mkyong.com/java/how-to-convert-inputstream-to-string-in-java/

public static String convertStreamToString(InputStream inputStream) throws IOException {
    if (inputStream != null) {
        Writer writer = new StringWriter();

        char[] buffer = new char[1024];
        try {
            Reader reader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"),1024);
            int n;
            while ((n = reader.read(buffer)) != -1) {
                writer.write(buffer, 0, n);
            }
        } finally {
            inputStream.close();
        }
        return writer.toString();
    } else {
        return "";
    }
}

当你有这个字符串时,你需要从它创建一个 JSONObject:

http://developer.android.com/reference/org/json/JSONObject.html

JSONObject json = new JSONObject(inputStreamAsString);

完成!

【讨论】:

  • 不适合我?发生 SSLPeerUnspicifiedException :(
【解决方案2】:

您是否将其添加到清单中

<uses-permission android:name="android.permission.INTERNET" />

【讨论】:

    【解决方案3】:

    你可以尝试这种方式,也许使用 URLConnection 类

    String error = ""; // string field
    private String getDataFromUrl(String demoIdUrl) {
    
        String result = null;
        int resCode;
        InputStream in;
        try {
            URL url = new URL(demoIdUrl);
            URLConnection urlConn = url.openConnection();
    
            HttpsURLConnection httpsConn = (HttpsURLConnection) urlConn;
            httpsConn.setAllowUserInteraction(false);
            httpsConn.setInstanceFollowRedirects(true);
            httpsConn.setRequestMethod("GET");
            httpsConn.connect();
            resCode = httpsConn.getResponseCode();
    
            if (resCode == HttpURLConnection.HTTP_OK) {
                in = httpsConn.getInputStream();
    
                BufferedReader reader = new BufferedReader(new InputStreamReader(
                        in, "iso-8859-1"), 8);
                StringBuilder sb = new StringBuilder();
                String line;
                while ((line = reader.readLine()) != null) {
                    sb.append(line).append("\n");
                }
                in.close();
                result = sb.toString();
            } else {
                error += resCode;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return result;
    }
    

    【讨论】:

    • java.lang.ClassCastException: com.android.okhttp.internal.http.HttpURLConnectionImpl 无法转换为 javax.net.ssl.HttpsURLConnection
    • 如果我在这段代码中使用HttpURLConnection 而不是HttpsURLConnection,会有什么区别?由于HttpsURLConnection 继承自HttpURLConnection,来自同一实例的相同方法将在.connect.getInputStream 上调用。我错了吗?
    【解决方案4】:

    我在这里写了两个方法。复制它们。在你的第一个方法中 uri = 你要发送请求的 url:

    第一种方法:

    public  static String Getdata (String uri ){
    
            BufferedReader reader = null;
    
            try {
    
                URL url = new URL(uri);
                HttpURLConnection con = null;
    
                URL testUrlHttps = new URL(uri);
                if (testUrlHttps.getProtocol().toLowerCase().equals("https"))
                {
                    trustAllHosts();
                    HttpsURLConnection https = (HttpsURLConnection) url.openConnection();
                    https.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
                    con = https;
                } else
                {
                    con = (HttpURLConnection) url.openConnection();
                }
    
    
                con.setReadTimeout(15000);
                con.setConnectTimeout(15000);
                StringBuilder sb = new StringBuilder();
                reader = new BufferedReader(new InputStreamReader(con.getInputStream()));
    
                String line;
                while ((line = reader.readLine()) != null) {
                    sb.append(line + "\n");
                }
    
                return sb.toString();
    
            } catch (Exception e) {
                e.printStackTrace();
                return "";
            } finally {
                if (reader != null) {
                    try {
                        reader.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                        return "";
                    }
                }
            }
        }
    

    另一种方法完全信任第一种方法的所有认证。

    第二种方法:

    private static void trustAllHosts()
        {
            // Create a trust manager that does not validate certificate chains
            TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager()
            {
                public java.security.cert.X509Certificate[] getAcceptedIssuers()
                {
                    return new java.security.cert.X509Certificate[] {};
                }
    
                public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException
                {
                }
    
                public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException
                {
                }
            } };
    
            // Install the all-trusting trust manager
            try
            {
                SSLContext sc = SSLContext.getInstance("TLS");
                sc.init(null, trustAllCerts, new java.security.SecureRandom());
                HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
            } catch (Exception e)
            {
                e.printStackTrace();
            }
        }
    

    【讨论】:

      【解决方案5】:

      感谢Make HTTPS / HTTP Request in Android

      添加一个 Java 类 CustomSSLSocketFactory.java

       import java.io.IOException;
       import java.net.Socket;
       import java.net.UnknownHostException;
       import java.security.KeyManagementException;
       import java.security.KeyStore;
       import java.security.KeyStoreException;
       import java.security.NoSuchAlgorithmException;
       import java.security.UnrecoverableKeyException;
       import java.security.cert.CertificateException;
       import java.security.cert.X509Certificate;
       import javax.net.ssl.SSLContext;
       import javax.net.ssl.TrustManager;
       import javax.net.ssl.X509TrustManager;
       import org.apache.http.conn.ssl.SSLSocketFactory;
      
       public class CustomSSLSocketFactory extends SSLSocketFactory{
      SSLContext sslContext = SSLContext.getInstance("TLS");
      /**
       * Generate Certificate for ssl connection
       * @param truststore
       * @throws NoSuchAlgorithmException
       * @throws KeyManagementException
       * @throws KeyStoreException
       * @throws UnrecoverableKeyException
       */
      public CustomSSLSocketFactory(KeyStore truststore)
              throws NoSuchAlgorithmException, KeyManagementException,
              KeyStoreException, UnrecoverableKeyException {
          super(truststore);
          TrustManager tm = new X509TrustManager(){
              @Override
              public void checkClientTrusted(X509Certificate[] arg0, String arg1)
                      throws CertificateException {
              }
              @Override
              public void checkServerTrusted(X509Certificate[] chain,
                                             String authType) throws CertificateException {
              }
              @Override
              public X509Certificate[] getAcceptedIssuers() {
                  return null;
              }
          };
          sslContext.init(null, new TrustManager[] {tm}, null);
      }
      
      @Override
      public Socket createSocket(Socket socket, String host, int port,
                                 boolean autoClose) throws IOException, UnknownHostException {
          return sslContext.getSocketFactory().createSocket(socket, host, port,
                  autoClose);
      }
      
      @Override
      public Socket createSocket() throws IOException {
          return sslContext.getSocketFactory().createSocket();
      }
       }
      

      在您的代码中

          String cloud_url="https://www.google.com";
          HttpClient client = new DefaultHttpClient();
              if(cloud_url.toLowerCase().contains("https://")){
                  KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
                  trustStore.load(null, null);
                  SSLSocketFactory sf = new CustomSSLSocketFactory(trustStore);
                  sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
      
                  HttpParams params = new BasicHttpParams();
                  SchemeRegistry registry = new SchemeRegistry();
                  registry.register(new Scheme("https", sf, 443));
      
                  ClientConnectionManager ccm = new ThreadSafeClientConnManager(params, registry);
                  client= new DefaultHttpClient(ccm, params);
              }
      
      
              HttpGet request= new HttpGet( );
              request.setURI(new URI( cloud_url));
              HttpResponse response = client.execute(request);
      

      也适用于 HttpPost。

      【讨论】:

        【解决方案6】:

        如果你不告诉我们错误是什么,很难确定。

        但是,如果您在 UI 线程上运行此程序,并且 Web 服务器的响应时间超过几秒钟,您将收到来自系统的 Application Not Responding 警告。确保在单独的线程上进行任何网络传输。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2020-09-27
          • 2017-08-02
          • 1970-01-01
          • 2023-03-26
          • 2011-05-13
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多