【问题标题】:Unable to set headers in HttpsUrlConnection in AndroidApp无法在 Android 应用程序的 HttpUrlConnection 中设置标头
【发布时间】:2015-10-27 17:19:59
【问题描述】:

我正在从 URL 类创建一个 HttpsUrlConnection。我正在使用 setRequestPropety 方法在连接中添加一些标头字段,如下面的代码所示。

URL url = new URL(address);
HttpURLsConnection connection = (HttpsURLConnection) url.openConnection();
connection.disconnect();
connection.setRequestProperty("Accept", "application/json");

我遇到异常,java.lang.IllegalStateException:在执行setRequestMethod 后建立连接后无法设置请求属性。我什至尝试按照上面的代码断开连接。

提前谢谢你。

注意:我也尝试将 setRequestProperty 替换为 addRequestProperty,但在异常方面没有区别。

注意:堆栈跟踪如下

10-27 13:53:40.352 29470-30420/com.MYCOM.po E/AndroidRuntime: FATAL EXCEPTION: AsyncTask #2
10-27 13:53:40.352 29470-30420/com.MYCOM.po E/AndroidRuntime: Process: com.MYCOM.po, PID: 29470
10-27 13:53:40.352 29470-30420/com.MYCOM.po E/AndroidRuntime: java.lang.RuntimeException: An error occured while executing doInBackground()
10-27 13:53:40.352 29470-30420/com.MYCOM.po E/AndroidRuntime:     at android.os.AsyncTask$3.done(AsyncTask.java:300)
10-27 13:53:40.352 29470-30420/com.MYCOM.po E/AndroidRuntime:     at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:355)
10-27 13:53:40.352 29470-30420/com.MYCOM.po E/AndroidRuntime:     at java.util.concurrent.FutureTask.setException(FutureTask.java:222)
10-27 13:53:40.352 29470-30420/com.MYCOM.po E/AndroidRuntime:     at java.util.concurrent.FutureTask.run(FutureTask.java:242)
10-27 13:53:40.352 29470-30420/com.MYCOM.po E/AndroidRuntime:     at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
10-27 13:53:40.352 29470-30420/com.MYCOM.po E/AndroidRuntime:     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
10-27 13:53:40.352 29470-30420/com.MYCOM.po E/AndroidRuntime:     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
10-27 13:53:40.352 29470-30420/com.MYCOM.po E/AndroidRuntime:     at java.lang.Thread.run(Thread.java:818)
10-27 13:53:40.352 29470-30420/com.MYCOM.po E/AndroidRuntime:  Caused by: java.lang.IllegalStateException: Cannot set request property after connection is made
10-27 13:53:40.352 29470-30420/com.MYCOM.po E/AndroidRuntime:     at com.android.okhttp.internal.http.HttpURLConnectionImpl.setRequestProperty(HttpURLConnectionImpl.java:496)
10-27 13:53:40.352 29470-30420/com.MYCOM.po E/AndroidRuntime:     at com.android.okhttp.internal.http.DelegatingHttpsURLConnection.setRequestProperty(DelegatingHttpsURLConnection.java:258)
10-27 13:53:40.352 29470-30420/com.MYCOM.po E/AndroidRuntime:     at com.android.okhttp.internal.http.HttpsURLConnectionImpl.setRequestProperty(HttpsURLConnectionImpl.java:25)
10-27 13:53:40.352 29470-30420/com.MYCOM.po E/AndroidRuntime:     at com.MYCOM.po.LoginActivity$UserLoginTask.doInBackground(LoginActivity.java:386)
10-27 13:53:40.352 29470-30420/com.MYCOM.po E/AndroidRuntime:     at com.MYCOM.po.LoginActivity$UserLoginTask.doInBackground(LoginActivity.java:364)

注意:我使用的是 Studio 提供的 LoginActivity 模板;将应用程序连接到 RESTful Web 服务。

doInBackground 方法如下

    @Override
    protected Boolean doInBackground(Void... params) {

        try {

            URL url = new URL(address);// Stored as a field in AsyncTask

            HttpURLConnection connection;
            connection = (HttpURLConnection) url.openConnection();
            connection.setRequestMethod("POST");
            connection.setRequestProperty("REST-API-Key", "HEXKEY");
            connection.setRequestProperty("Accept", "application/json");
            StringBuilder paramBuilder = new StringBuilder();
            paramBuilder.append("PARAM1=");
            paramBuilder.append("VALUE1");
            paramBuilder.append("&");
            paramBuilder.append("PARAM2=VALUE2");
            paramBuilder.append("&");
            paramBuilder.append("PARAM3=");
            paramBuilder.append("VALUE3");
            connection.setDoOutput(true);
            OutputStreamWriter outputWriter = new OutputStreamWriter(connection.getOutputStream());
            outputWriter.write(paramBuilder.toString());
            outputWriter.flush();
            if(connection == null) {
                Thread.sleep(2000);
                return false;
            }
            BufferedReader responseReader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
            if(responseReader == null){
                throw new IOException("Null Response");
            }
            StringBuilder sb = new StringBuilder();
            String line;
            while((line = responseReader.readLine())!=null){
                sb.append(line+"\n");
            }
            String resp = sb.toString();
            connection.disconnect();


        } catch (InterruptedException|IOException e) {
            return false;
        }


        // TODO: register the new account here.
        return true;
    }

【问题讨论】:

  • 您是否尝试过使用 Postman 或 RestClient 等 RestAPI 工具的请求?您应该看到 this 以获取有关 URLConnection 的完整信息
  • @JavaGhost api 工作正常,我在 cURL 上对其进行了测试。问题出在 HttpURLConnection 中。
  • 将connection.setDoOutput(true);移动到connection = (HttpURLConnection) url.openConnection();旁边
  • @JavaGhost 将抛出 NullPointerException。
  • 非常抱歉,我之前没有注意到 Exception 类的包。您的项目中似乎有 OkHttp 库。使用 OkHttp,您不能使用 HttpURLConnetion。您必须遵循上面链接的示例部分中指定的构建器模式。 OkHttp 实现不允许在打开连接后设置请求标头(使用构建器模式,您在实际使用对象之前设置所有必要的字段和参数以满足其特定需求)希望它有所帮助。

标签: java android androidhttpclient


【解决方案1】:

奇怪,但是我删除了所有断点,除了最后一个检查结果并且它有效。我猜是断点造成的延迟;是问题所在。即使connection.connect() 没有被执行,我仍然不明白为什么它会连接。 解决方案是不要中断网络操作。

【讨论】:

    【解决方案2】:

    请从您的代码中删除connection.disconnect()。

    典型的使用模式是:

    HttpUrlConnection ucon = (HttpUrlConnection) url.openConnection();
    ucon.setRequestProperty("name", "value");
    ...
    InputStream is = null; 
    try {
      is = ucon.getInputStream();
      // read inputstream. ideally wrapping it in a BufferedReader.
    } finally {
      if (is != null) is.close();
    }
    

    【讨论】:

    • 我尝试了断开连接和不断开连接。问题是 HttpUrlConnection 不允许我在建立初始连接后设置标头,这就是我尝试 disconnect() 来检查它是否允许我设置它的原因。
    • 另外你使用的是哪个库或安卓版本?你是把它嵌入到你的应用中还是使用默认版本
    • 你也可以发布堆栈跟踪吗?
    • 我在 AsyncTask 中使用 java.net。
    • 是否有可能在调用 setRequestProperty 之前调用任何最终调用 connect 的方法?例如 getContentLength()、getInputStream()、getResponseCode()。还是曾经重复使用同一个实例进行新连接?
    【解决方案3】:

    您应该在断开连接之前至少设置标题。

    URL url = new URL(address);
    HttpURLConnection connection = (HttpURLConnection) url.openConnection();
    connection.setRequestProperty("Accept", "application/json");
    
    try {
         InputStream in = new BufferedInputStream(connection.getInputStream());
         readStream(in);
    finally {
         connection.disconnect();
    }
    

    【讨论】:

      猜你喜欢
      • 2018-09-06
      • 2014-02-13
      • 2018-12-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多