BlackBerry OS 5 - 7 - 尝试获取JSON响应并获取错误代码500

时间:2013-11-02 00:40:57

标签: android json mobile blackberry

我一直试图从我公司的json webservice获取json响应。这是代码:

public final static String GOINOUT_HOST_NAME = "http://ec2-54-254-123-244.ap-southeast-1.compute.amazonaws.com";
public final static String GOINOUT_API_VERSION = "/api/v1";

public final static String GOINOUT_FACEBOOK_AUTHENTICATE = GOINOUT_HOST_NAME + GOINOUT_API_VERSION + "/facebook_authenticate";

public static JSONObject loginGoinoutWithFacebook(String accessToken) {
    JSONObject goinoutUserJsonObject = null;
    try {
        Hashtable params = new Hashtable();
        params.put("access_token", accessToken);
        String paramsString = StringUtil.toURLParameters(params);

        Hashtable properties = new Hashtable();
        String response = HttpUtils.sendGoinoutJsonRequest(GOINOUT_FACEBOOK_AUTHENTICATE + "?" + paramsString, paramsString, HttpUtils.TIMEOUT, properties, HttpConnection.POST);
        Dialog.alert("res: " + response);
        JSONObject goinoutJsonObject = new JSONObject(response);
        goinoutUserJsonObject = new JSONObject(goinoutJsonObject.getString("user"));
    } catch (IOException e) {
        Dialog.alert("e1: " + e.getMessage());
        e.printStackTrace();
    } catch (JSONException e1) {
        Dialog.alert("e2: " + e1.getMessage());
        e1.printStackTrace();
    }
    return goinoutUserJsonObject;
}

以下代码块是goinout json请求:

public static String sendGoinoutJsonRequest(String url,String data,long timeout, Hashtable properties, String method) throws IOException {

    HttpConnectionFactory factory = new HttpConnectionFactory(Util.getTransportPriority());
    while(true) {

        HttpConnectionIOSession httpConnectionIOSession = null;
        try {

            HttpConnection httpConnection = factory.getHttpConnection(url);
            if(httpConnection == null) throw new IOException();
            try {

                httpConnection.setRequestMethod(method);
                httpConnection.setRequestProperty("If-Modified-Since","29 Oct 1999 19:43:31 GMT");
                httpConnection.setRequestProperty("User-Agent","Profile/MIDP-2.0 Configuration/CLDC-1.0");
                httpConnection.setRequestProperty("Content-Type","application/x-www-form-urlencoded");
                httpConnection.setRequestProperty("Accept","application/json");                    
                httpConnection.setRequestProperty("Content-Length",data.getBytes().length + "");
                httpConnection.setRequestProperty("Content-Language","en-US");
                httpConnection.setRequestProperty("x-rim-transcode-content","none");
                Enumeration keys = properties.keys();
                while(keys.hasMoreElements()) {
                    String key = (String) keys.nextElement();
                    String value = (String) properties.get(key);
                    httpConnection.setRequestProperty(key, value);
                }
                OutputStream outputStream = httpConnection.openOutputStream();
                InputStream inputStream = null;
                if(timeout != -1) {

                    httpConnectionIOSession = new HttpConnectionIOSession(httpConnection,inputStream,outputStream,timeout);

                }
                outputStream.write(data.getBytes());
                outputStream.close();
                int responseCode = httpConnection.getResponseCode();
                if(responseCode != HttpConnection.HTTP_OK) {

                    if(responseCode == HttpConnection.HTTP_BAD_REQUEST) {

                        continue;

                    }
                    if(timeout != -1 && HttpUtils.TIMEOUT + 2000 <= TIMEOUT_MIN) {

                        HttpUtils.TIMEOUT += 2000;

                    }
                    throw new IOException("HTTP " + responseCode + " error code.");

                }
                inputStream = httpConnection.openInputStream();
                final ByteBuffer byteBuffer = new ByteBuffer(inputStream);
                final String response = byteBuffer.getString();
                close(httpConnection,inputStream,outputStream);

                if(timeout != -1 && HttpUtils.TIMEOUT - 1000 >= TIMEOUT_MIN) {

                    HttpUtils.TIMEOUT -= 1000;

                }
                if(httpConnectionIOSession != null) httpConnectionIOSession.interrupt();
                return response;

            } catch(IOException ioException) {

                if(timeout != -1 && HttpUtils.TIMEOUT + 2000 <= TIMEOUT_MIN) {

                    HttpUtils.TIMEOUT += 2000;

                }
                throw ioException;


            }

        } catch(IOException ioException) {

            if(timeout != -1 && HttpUtils.TIMEOUT + 2000 <= TIMEOUT_MIN) {

                HttpUtils.TIMEOUT += 2000;

            }
            throw ioException;

        } finally {
            if(httpConnectionIOSession != null) httpConnectionIOSession.interrupt();
        }

    }

}

查看我设置的属性。如果我使用以下属性:

httpConnection.setRequestProperty("Content-Type","application/x-www-form-urlencoded");
httpConnection.setRequestProperty("Accept","application/json");

发生的事情是我可以从我的BB模拟器和使用wifi连接的真实设备中检索JSON数据。但是,当我使用移动服务提供商使用REAL DEVICE时,我将始终获得IOException:stream closed。

如果我使用以下代码:

httpConnection.setRequestProperty("Content-Type","application/json");
httpConnection.setRequestProperty("Accept","application/json");   

我总是在模拟器中获得HTTP错误代码500。如果我在使用移动服务提供商的真实设备中使用此属性,代码将继续运行,因为while(true)存在。我想知道你们是否可以帮助我。

事实上,这段代码已被证明可以从Facebook API和Tumblr API获取json数据。我总是使用这个代码,没有问题。我想知道服务器端是否有问题,或者我应该添加另一个属性???非常感谢你。

Ntt请求HttpConnectionFactory:

package com.hammyliem.abateify.ui.network;

import java.io.IOException;
import java.io.OutputStream;
import java.util.Vector;

import javax.microedition.io.Connector;
import javax.microedition.io.HttpConnection;

import net.rim.device.api.io.http.HttpHeaders;
import net.rim.device.api.io.http.HttpProtocolConstants;
import net.rim.device.api.servicebook.ServiceBook;
import net.rim.device.api.servicebook.ServiceRecord;
import net.rim.device.api.system.Branding;
import net.rim.device.api.system.CoverageInfo;
import net.rim.device.api.system.DeviceInfo;
import net.rim.device.api.system.WLANInfo;

public class HttpConnectionFactory {

  public static final int TRANSPORT_WIFI = 1;
  public static final int TRANSPORT_BES = 2;
  public static final int TRANSPORT_BIS = 4;
  public static final int TRANSPORT_DIRECT_TCP = 8;
  public static final int TRANSPORT_WAP2 = 16;
  public static final int TRANSPORT_SIM = 32;

  public static final int TRANSPORTS_ANY = TRANSPORT_WIFI | TRANSPORT_BES | TRANSPORT_BIS | TRANSPORT_DIRECT_TCP | TRANSPORT_WAP2 | TRANSPORT_SIM;
  public static final int TRANSPORTS_AVOID_CARRIER = TRANSPORT_WIFI | TRANSPORT_BES | TRANSPORT_BIS | TRANSPORT_SIM;
  public static final int TRANSPORTS_CARRIER_ONLY = TRANSPORT_DIRECT_TCP | TRANSPORT_WAP2 | TRANSPORT_SIM;

  public static final int DEFAULT_TRANSPORT_ORDER[] = { TRANSPORT_WIFI, TRANSPORT_SIM, TRANSPORT_BIS, TRANSPORT_BES, TRANSPORT_WAP2, TRANSPORT_DIRECT_TCP };

  private static final int TRANSPORT_COUNT = DEFAULT_TRANSPORT_ORDER.length;

  // private static ServiceRecord srMDS[], srBIS[], srWAP2[], srWiFi[];
  private static ServiceRecord srWAP2[];
  private static boolean serviceRecordsLoaded = false;

  private int transports[];
  private int lastTransport = -1;

  public HttpConnectionFactory() {
    this(0);
  }

  public HttpConnectionFactory(int allowedTransports) {
    this(transportMaskToArray(allowedTransports));
  }

  public HttpConnectionFactory(int transportPriority[]) {
    if (!serviceRecordsLoaded) {
      loadServiceBooks(false);
    }
    transports = transportPriority;
  }

  public static String getUserAgent() {
    StringBuffer sb = new StringBuffer();
    sb.append("BlackBerry");
    sb.append(DeviceInfo.getDeviceName());
    sb.append("/");
    sb.append(DeviceInfo.getSoftwareVersion());
    sb.append(" Profile/");
    sb.append(System.getProperty("microedition.profiles"));
    sb.append(" Configuration/");
    sb.append(System.getProperty("microedition.configuration"));
    sb.append(" VendorID/");
    sb.append(Branding.getVendorId());

    return sb.toString();
  }

  public static String getProfile() {
    StringBuffer sb = new StringBuffer();
    sb.append("http://www.blackberry.net/go/mobile/profiles/uaprof/");
    sb.append(DeviceInfo.getDeviceName());
    sb.append("/");
    sb.append(DeviceInfo.getSoftwareVersion().substring(0, 3)); //RDF file format is 4.5.0.rdf (does not include build version)
    sb.append(".rdf");

    return sb.toString();
  }

  public HttpConnection getHttpConnection(String pURL) {
    return getHttpConnection(pURL, null, null);
  }

  public HttpConnection getHttpConnection(String pURL, HttpHeaders headers) {
    return getHttpConnection(pURL, headers, null);
  }

  public HttpConnection getHttpConnection(String pURL, byte[] data) {
    return getHttpConnection(pURL, null, data);
  }

  public HttpConnection getHttpConnection(String pURL, HttpHeaders headers, byte[] data) {

    int curIndex = 0;
    HttpConnection con = null;

    while ((con = tryHttpConnection(pURL, curIndex, headers, data)) == null) {
      try {
        curIndex = nextTransport(curIndex);
      } catch (HttpConnectionFactoryException e) {
        e.printStackTrace();
        break;
      } finally {
      }
    }

    if (con != null) {
      setLastTransport(transports[curIndex]);
    }

    return con;
  }

  private int nextTransport(int curIndex) throws HttpConnectionFactoryException {
    if ((curIndex >= 0) && (curIndex < transports.length - 1)) {
      return curIndex + 1;
    } else {
      throw new HttpConnectionFactoryException("No more transport available.");
    }
  }

  private HttpConnection tryHttpConnection(String pURL, int tIndex, HttpHeaders headers, byte[] data) {

    HttpConnection con = null;
    OutputStream os = null;

    switch (transports[tIndex]) {
    case TRANSPORT_SIM:
      try {
        con = getSimConnection(pURL, false);
      } catch (IOException e) {
      } finally {
        break;
      }
    case TRANSPORT_WIFI:
      try {
        con = getWifiConnection(pURL);
      } catch (IOException e) {
      } finally {
        break;
      }
    case TRANSPORT_BES:
      try {
        con = getBesConnection(pURL);
      } catch (IOException e) {
      } finally {
        break;
      }
    case TRANSPORT_BIS:
      try {
        con = getBisConnection(pURL);
      } catch (IOException e) {
      } finally {
        break;
      }
    case TRANSPORT_DIRECT_TCP:
      try {
        con = getTcpConnection(pURL);
      } catch (IOException e) {
      } finally {
        break;
      }
    case TRANSPORT_WAP2:
      try {
        con = getWap2Connection(pURL);
      } catch (IOException e) {
      } finally {
        break;
      }
    }

    if (con != null) {
      try {
        //add headers to connection
        if (headers != null) {
          int size = headers.size();

          for (int i = 0; i < size;) {
            String header = headers.getPropertyKey(i);
            String value = headers.getPropertyValue(i++);

            if (value != null) {
              con.setRequestProperty(header, value);

            }
          }
        }
        // post data
        if (data != null) {
          con.setRequestMethod(HttpConnection.POST);
          con.setRequestProperty(HttpProtocolConstants.HEADER_CONTENT_TYPE, HttpProtocolConstants.CONTENT_TYPE_APPLICATION_X_WWW_FORM_URLENCODED);
          con.setRequestProperty(HttpProtocolConstants.HEADER_CONTENT_LENGTH, String.valueOf(data.length));

          os = con.openOutputStream();
          os.write(data);
        } else {
          con.setRequestMethod(HttpConnection.GET);
        }

      } catch (IOException e) {
        e.printStackTrace();
      }
    }

    return con;
  }

  public int getLastTransport() {
    return lastTransport;
  }

  public String getLastTransportName() {
    return getTransportName(getLastTransport());
  }

  private void setLastTransport(int pLastTransport) {
    lastTransport = pLastTransport;
  }

  private HttpConnection getSimConnection(String pURL, boolean mdsSimulatorRunning) throws IOException {
    if (DeviceInfo.isSimulator()) {
      if (mdsSimulatorRunning) {
        return getConnection(pURL, ";deviceside=false", null);
      } else {
        return getConnection(pURL, ";deviceside=true", null);
      }
    }
    return null;
  }

  private HttpConnection getBisConnection(String pURL) throws IOException {
    if (CoverageInfo.isCoverageSufficient(4 /* CoverageInfo.COVERAGE_BIS_B */)) {
      return getConnection(pURL, ";deviceside=false;ConnectionType=mds-public", null);
    }
    return null;
  }

  private HttpConnection getBesConnection(String pURL) throws IOException {
    if (CoverageInfo.isCoverageSufficient(2 /* CoverageInfo.COVERAGE_MDS */)) {
      return getConnection(pURL, ";deviceside=false", null);
    }
    return null;
  }

  private HttpConnection getWifiConnection(String pURL) throws IOException {
    if (WLANInfo.getWLANState() == WLANInfo.WLAN_STATE_CONNECTED) {
      return getConnection(pURL, ";interface=wifi", null);
    }
    return null;
  }

  private HttpConnection getWap2Connection(String pURL) throws IOException {
    if (CoverageInfo.isCoverageSufficient(1 /* CoverageInfo.COVERAGE_DIRECT */) && (srWAP2 != null) && (srWAP2.length != 0)) {
      return getConnection(pURL, ";deviceside=true;ConnectionUID=", srWAP2[0].getUid());
    }
    return null;
  }

  private HttpConnection getTcpConnection(String pURL) throws IOException {
    if (CoverageInfo.isCoverageSufficient(1 /* CoverageInfo.COVERAGE_DIRECT */)) {
      return getConnection(pURL, ";deviceside=true", null);
    }
    return null;
  }

  private HttpConnection getConnection(String pURL, String transportExtras1, String transportExtras2) throws IOException {
    StringBuffer fullUrl = new StringBuffer();
    fullUrl.append(pURL);
    if (transportExtras1 != null) {
      fullUrl.append(transportExtras1);
    }
    if (transportExtras2 != null) {
      fullUrl.append(transportExtras2);
    }
    return (HttpConnection) Connector.open(fullUrl.toString());
  }

  public static void reloadServiceBooks() {
    loadServiceBooks(true);
  }

  private static synchronized void loadServiceBooks(boolean reload) {
    if (serviceRecordsLoaded && !reload) {
      return;
    }
    ServiceBook sb = ServiceBook.getSB();
    ServiceRecord[] records = sb.getRecords();
    Vector mdsVec = new Vector();
    Vector bisVec = new Vector();
    Vector wap2Vec = new Vector();
    Vector wifiVec = new Vector();

    if (!serviceRecordsLoaded) {
      for (int i = 0; i < records.length; i++) {
        ServiceRecord myRecord = records[i];
        String cid, uid;

        if (myRecord.isValid() && !myRecord.isDisabled()) {
          cid = myRecord.getCid().toLowerCase();
          uid = myRecord.getUid().toLowerCase();
          if ((cid.indexOf("wptcp") != -1) && (uid.indexOf("wap2") != -1) && (uid.indexOf("wifi") == -1) && (uid.indexOf("mms") == -1)) {
            wap2Vec.addElement(myRecord);
          }
        }
      }

      srWAP2 = new ServiceRecord[wap2Vec.size()];
      wap2Vec.copyInto(srWAP2);
      wap2Vec.removeAllElements();
      wap2Vec = null;

      serviceRecordsLoaded = true;
    }
  }

  public static int[] transportMaskToArray(int mask) {
    if (mask == 0) {
      mask = TRANSPORTS_ANY;
    }
    int numTransports = 0;
    for (int i = 0; i < TRANSPORT_COUNT; i++) {
      if ((DEFAULT_TRANSPORT_ORDER[i] & mask) != 0) {
        numTransports++;
      }
    }
    int transports[] = new int[numTransports];
    int index = 0;
    for (int i = 0; i < TRANSPORT_COUNT; i++) {
      if ((DEFAULT_TRANSPORT_ORDER[i] & mask) != 0) {
        transports[index++] = DEFAULT_TRANSPORT_ORDER[i];
      }
    }
    return transports;
  }

  private static String getTransportName(int transport) {
    String tName;
    switch (transport) {
    case TRANSPORT_WIFI:
      tName = "WIFI";
      break;
    case TRANSPORT_BES:
      tName = "BES";
      break;
    case TRANSPORT_BIS:
      tName = "BIS";
      break;
    case TRANSPORT_DIRECT_TCP:
      tName = "TCP";
      break;
    case TRANSPORT_WAP2:
      tName = "WAP2";
      break;
    case TRANSPORT_SIM:
      tName = "SIM";
      break;
    default:
      tName = "UNKNOWN";
      break;
    }
    return tName;
  }

}

2 个答案:

答案 0 :(得分:0)

首先,我有点不清楚为什么这个问题被标记为android。也许现在为时已晚,而且我错过了一些东西。无论如何,我将此作为 BlackBerry 问题回答。

首先,如果您使用正常的网址编码为请求编码一组参数,并在响应中期待JSON,那么您的原始代码:

httpConnection.setRequestProperty("Content-Type","application/x-www-form-urlencoded");
httpConnection.setRequestProperty("Accept","application/json");                    

是对的。如果您的请求内容是URL编码参数,请不要将Content-Type设置为application/json

其次,我不是百分百肯定,但我相信你是在UI线程上执行这个网络请求。即使我看不到调用loginGoinoutWithFacebook()的代码,我相信你是在UI线程上做的,因为该方法包含对Dialog.alert()的调用,这是一种UI方法。

不要在UI线程上进行网络调用!

可能正在发生的事情(假设您将内容类型设置为application/x-www-form-urlencoded)是通过Wi-Fi,网络请求非常快速地完成,并且UI不会被阻止太长时间。它出现

但是,当您使用移动运营商网络时,一切都会变慢。您阻止UI线程太长时间,这会导致问题。我不记得究竟是什么在UI线程上进行网络调用的症状是(因为我从来没有这样做),但我敢打赌,这是你的问题。

使用后台Thread / Runnable执行网络电话:

Thread worker = new Thread(new Runnable() {
   // this method is run on a background thread:
   public void run() {
      final JSONObject response = loginGoinoutWithFacebook(token);

      // to update the UI with the response, we must use the UI thread:
      UiApplication.getUiApplication().invokeLater(new Runnable() {
          public void run() {
              // this just shows an alert, but you can insert your
              //  own code to update the UI properly with the response
              //  contents
              Dialog.alert(response.toString());
          }
      });
   }
});

worker.start();

答案 1 :(得分:0)

我怀疑除了你在Nate指出的事件线程上运行代码的可能性之外,还有两个不同的问题。

我不确定您是否在事件线程上运行,因为如果您的应用程序将以应用程序无响应异常终止。但正如Nate指出的那样,如果你尝试从事件线程执行一个Dialog,你将得到一个例外。所以无论如何我都会期待一个例外......

总结报告的问题,您似乎得到以下其中一项: a)在设备上使用无线数据服务运行时的连接上的IOException(而不是WiFi) b)在发送具有特定报头的数据时的HTTP代码500。这意味着服务器已经返回了您的请求,告诉您它没有理解它。所以你发错了。

首先,我建议您调查IOException - 基本上打印出您获得的异常的详细信息(toString()将执行此操作)。这将为您提供有关该问题的更多详细信息。有很多选择,我猜这将是一个超时,但在我尝试提出解决方案之前想知道。

我可以参考回到您之前的帖子:blackberry-get-error-code-411请再次阅读我的回复。

其中有两点对所有通信都至关重要,而不仅仅是411错误:

  1. 用于传输数据的编码
  2. 使用的连接方法。
  3. 编码可能是500返回代码的关键。当您告诉服务器您正在发送JSON数据时,它可能希望数据将是UTF-8编码的。但是,您发送的数据似乎不是。如果您只使用标准的Latin-1字符,那么这将不是问题。如果您的JSON数据包含该字符集中未包含的字符,则数据将无法正确编码,这可能是您的服务器无法理解的原因。

    为了安全起见,在发送JSON数据时,我建议您对UTF-8进行编码(并记住生成的字节数不一定与字符串中的字符数相同)。

    关于500错误代码(实际上是任何错误代码),我建议您在收到的响应中转储标题。他们可能会识别实际返回请求的服务器。它可能不是您的服务器 - 在通过移动网络进行处理时,因为涉及其他网关可以拒绝请求。

    总之,为了调查此问题(或任何其他网络问题),我建议您:

    1. 打印出任何例外
    2. 的详细信息
    3. 确保您知道失败所使用的连接方法 请求
    4. 如果您没有获得良好的返回代码,请将您的标题转储出来 找出哪个服务器实际上给了你返回代码
    5. 确保您正确编码(字符编码为字节) 您正在发送的数据(如果是,则会收到正确的解码字节 你将这些转换回字符)。
    6. 最后一件事。由于服务器为您提供500 - 我建议您在发送之前记录发布数据,如果发生故障,您可以检查它是否格式正确。