我一直试图从我公司的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;
}
}
答案 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错误:
编码可能是500返回代码的关键。当您告诉服务器您正在发送JSON数据时,它可能希望数据将是UTF-8编码的。但是,您发送的数据似乎不是。如果您只使用标准的Latin-1字符,那么这将不是问题。如果您的JSON数据包含该字符集中未包含的字符,则数据将无法正确编码,这可能是您的服务器无法理解的原因。
为了安全起见,在发送JSON数据时,我建议您对UTF-8进行编码(并记住生成的字节数不一定与字符串中的字符数相同)。
关于500错误代码(实际上是任何错误代码),我建议您在收到的响应中转储标题。他们可能会识别实际返回请求的服务器。它可能不是您的服务器 - 在通过移动网络进行处理时,因为涉及其他网关可以拒绝请求。
总之,为了调查此问题(或任何其他网络问题),我建议您:
最后一件事。由于服务器为您提供500 - 我建议您在发送之前记录发布数据,如果发生故障,您可以检查它是否格式正确。