Now I'm working on an Android SDK project, the code is too old and I tried to collect data from server using okhttp3. By using the following function I'm able to collect the response from server.
String json = requestGetString(url);
public String requestGetString(String uri) throws IOException {
Response res = null;
try {
res = getStringHttp(host+uri);
System.out.println(res.body().string());
return res.body().string();
}catch (NullPointerException e) {
//body = null ??
throw new IOException(e);
} catch (IOException e) {
throw new IOException(e);
}finally {
if(res != null){
try{
res.close();
}catch (NullPointerException e){
//body = null ??
throw new IOException(e);
}
}
}
}
I'm receiving the Json but I'cant parse it with my data class.
like the following
AuthAppResponse result = parseJson(path, json, AuthAppResponse.class);
You can look my parser function
private <TResponse> TResponse parseJson(String path, String json, Class<TResponse> responseClass) throws IOException
{
return parseJson(getGson(), path, json, responseClass);
}
and this,
private <TResponse> TResponse parseJson(Gson gson, String path, String json, Class<TResponse> responseClass) throws IOException
{
try
{
return gson.fromJson(json, responseClass);
}
catch (JsonSyntaxException e)
{
throw new IOException("The response from '" + path + "' failed to be parsed as JSON.\ncontent = " + json, e);
}
}
Nothing happen.
And the same SDK with latest code base it works fine with the same code. Anyone have an idea to figure out the possible solution for this.
please share your comment.
You can consume an okhttp response body only once. You're consuming it twice. First in:
System.out.println(res.body().string());
and then in
return res.body().string();
Finally i fount the missing part in my code, I miss to add a proguard file in the old project, that's why the Gson does not parse the response
Related
onResponse is called.
But response.isSuccessful() is false.
I want to watch error massage.
#Override
public void onResponse(Call<UserInfo> call, Response<UserInfo> response) {
if (!response.isSuccessful()) {
try {
Log.d("Success false", response.errorBody().string()); // letter broken!!
} catch (IOException e) {
e.printStackTrace();
}
return;
}
}
print :
{"error":"\ub85c\uadf8\uc778\uc774 \ud544\uc694\ud569\ub2c8\ub2e4."}
Why letter is broken?
I think the error message is UTF8 encoded string. You could decode it by URLDecoder.decode(s, s)
I fixed it!
I think of json data as a string data.
error massage is json data.
json data need convert.
Try this :
JSONObject jsonobject = new JSONObject ( response.errorBody().string());
Log.d("error",jsonobject.getString("error");
I have a question about the proper syntax and order of code in regards to accessing a REST API.
I am trying to access a database that I made on an mBaas called backendless.com. (The following data information is specific to this mBaas but my question is more about the general process of accessing REST API's in Android)
According to their tutorial to bulk delete (https://backendless.com/documentation/data/rest/data_deleting_data_objects.htm) I need a URL that queries my database for a specific value and then deletes it. I have that value. They also need 3 request headers (application-id, secret key, application type).I have those as well.
I utilized all of this information in an ASyncTask class that technically should open the url, set the request headers, and make the call to the REST API. My only issue is, I have no idea if I'm missing some kind of code here? Is my current code in proper order? Every time my class is executed, nothing happens.
I also get a log cat exception in regards to my URL: java.io.FileNotFoundException: api.backendless.com/v1/data/bulk/...
The URL does not lead to anything when I place it in my browser but I'm told that it shouldn't since the browser sends it as a GET request.
Anyway, here is my ASyncTask Class with all of the info. Does anyone know if this code looks correct or am I missing something here? I'm new to making these type of calls and don't really understand the roll that request-headers play in accessing REST APIs. Please let me know. Thank you!
class DeleteBulkFromBackEnd extends AsyncTask<Void,Void,String>{
final String API_URL = "https://api.backendless.com/v1/data/bulk/LocalPhoneNum?where%3DuserEmailID%3Dmark#gmail.com";
#Override
protected String doInBackground(Void... params) {
HttpURLConnection urlConnection = null;
try {
URL url = new URL(API_URL);
urlConnection = (HttpURLConnection)url.openConnection();
urlConnection.setRequestProperty( "application-id","12345678" );
urlConnection.setRequestProperty( "secret-key","12345678" );
urlConnection.setRequestProperty( "application-type", "REST" );
urlConnection.connect();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
Log.d("Contact","ERROR " + e.toString() );//IO Exception Prints in log cat not recognizing URL
e.printStackTrace();
}finally {
urlConnection.disconnect();
}
return null;
}
}
I recommend you to use okhttp for easy network access.
And check the response code and response body.
In your build.gradle:
compile 'com.squareup.okhttp3:okhttp:3.4.1'
Your AsyncTask will be like this:
class DeleteBulkFromBackEnd extends AsyncTask<Void, Void, String> {
final String API_URL = "https://api.backendless.com/v1/data/bulk/LocalPhoneNum?where%3DuserEmailID%3Dmark#gmail.com";
final OkHttpClient mClient;
public DeleteBulkFromBackEnd(OkHttpClient client) {
mClient = client;
}
#Override
protected String doInBackground(Void... params) {
try {
Request request = new Request.Builder()
.url(API_URL)
.delete()
.header("application-id", "12345678")
.header("secret-key", "12345678")
.header("application-type", "REST")
.build();
Response response = mClient.newCall(request).execute();
Log.d("DeleteBulkFromBackEnd", "Code: " + response.code());
Log.d("DeleteBulkFromBackEnd", "Body: " + response.body().string());
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
Execute the AsyncTask like this:
OkHttpClient client = new OkHttpClient();
void someMethod() {
...
new DeleteBulkFromBackEnd(client).execute();
...
}
As I've commented, here's the solution:
class DeleteBulkFromBackEnd extends AsyncTask<Void,Void,String>{
final String API_URL = "https://api.backendless.com/v1/data/bulk/LocalPhoneNum?where%3DuserEmailID%3Dmark#gmail.com";
#Override
protected String doInBackground(Void... params) {
HttpURLConnection urlConnection = null;
try {
URL url = new URL(API_URL);
urlConnection = (HttpURLConnection)url.openConnection();
urlConnection.setRequestProperty( "application-id","12345678" );
urlConnection.setRequestProperty( "secret-key","12345678" );
urlConnection.setRequestProperty( "application-type", "REST" );
urlConnection.setRequestMethod("DELETE");
urlConnection.connect();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
Log.d("Contact","ERROR " + e.toString() );//IO Exception Prints in log cat not recognizing URL
e.printStackTrace();
}finally {
urlConnection.disconnect();
}
return null;
}
}
I'm trying to send custom exceptions from ASP.NET Web API , but when I consume these WebService from Android I'm always getting a different message:
This how I read the webservice in Android:
public Object doRequest(String url) {
String charset = Charset.defaultCharset().displayName();
try {
if (mFormBody != null) {
// Form data to post
mConnection
.setRequestProperty("Content-Type",
"application/json; charset="
+ charset);
mConnection.setFixedLengthStreamingMode(mFormBody.length());
}
mConnection.connect();
if (mFormBody != null) {
OutputStream out = mConnection.getOutputStream();
writeFormData(charset, out);
}
// Get response data
int status = mConnection.getResponseCode();
if (status >= 300) {
String message = mConnection.getResponseMessage();
return new HttpResponseException(status, message);
}
InputStream in = mConnection.getInputStream();
String enconding = mConnection.getContentEncoding();
if (enconding == null) {
enconding = "UTF-8";
}
BufferedReader reader = new BufferedReader(new InputStreamReader(
in, enconding));
StringBuilder sb = new StringBuilder();
String line=null;
while ((line=reader.readLine()) != null) {
sb.append(line);
}
return sb.toString().trim();
} catch (Exception e) {
return e;
}
finally{
if(mConnection!=null){
mConnection.disconnect();
}
}
}
As you can see, I check the value returned by getResponseCode() and if it's equal or greater than 300 I throw an Exception. Everything works except for the fact that getResponseMessage() doesn't return the string I used when I created the exception in WebApi. Instead I get this error:
From WebApi,all I'm doing in the catch block is to throw the exception:
try
{
}
catch (Exception ex)
{
throw ex;
}
Using fiddler realized I was getting this message:
{"Message":"Error."}
Well, looking for a solution on Internet, I found that I could do something like this:
try
{
}
catch (Exception ex)
{
throw new HttpResponseException(Request.CreateErrorResponse(HttpStatusCode.NotFound, ex.Message));
//throw (ex);
}
But unfortunately this didn't work either. Although fiddler now shows the message I used to create the Exception.
When I read the value of getResponseMessage() is returns this string : "Not Found".
Do you know what I need to do so that the message that is being sent from WebApi through the Exception make its way to Android, specifically to the getResponseMessage() property?
Thanks in advance.
Well, I think you need to create a HttpResponseMessage object first, and based on that object create the HttpResponseException that you're going to throw.
Setting a HttpResponseMessage object is pretty easy. Most of the time you only need to set two properties: Content and ReasonPhrase.
try
{
}
catch (Exception ex)
{
HttpResponseMessage msg = new HttpResponseMessage(HttpStatusCode.NotFound)
{
Content = new StringContent(string.Format("Excepción")),
ReasonPhrase = ex.Message
};
throw new HttpResponseException(msg);
}
As you can see is ReasonPhrase where we passed the exception message.
Hope it helps.
I try to get some Data from a WebService using KSoap2.
The WebService responses a very large XML-File so while I'm doing the HttpTransportSE.call() I get an ouOfMemory Exception.
Is it possible to get a snipped response from a Soap Webservice?
Or is there a way to write it directly in a file on the device?
This is my Class to get the Data:
public static SoapObject GetItemData()
{
SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME_ITEM_DATA);
request.addProperty("Company", company);
request.addProperty("SerialNumber", serialId);
itemEnvelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
itemEnvelope.dotNet = true;
itemEnvelope.setOutputSoapObject(request);
AndroidHttpTransportSE androidHttpTransport = new AndroidHttpTransportSE(URL);
androidHttpTransport.debug = true;
Log.d("==ITEM_URL==", URL);
try
{
androidHttpTransport.call(SOAP_ACTION_ITEM_DATA, itemEnvelope);
Log.d("==ItemVerbindung==", "Verbindung aufgebaut");
}
catch (Exception e)
{
e.printStackTrace();
Log.d("==ItemVerbindung==", "HTTPCALL nicht ausgeführt");
}
try
{
itemResult = (SoapObject)itemEnvelope.getResponse();
Log.d("==ItemResponse==", "PropertyCount: "+itemResult.getPropertyCount());
}
catch(ClassCastException e)
{
itemResult = (SoapObject)itemEnvelope.bodyIn;
}
catch (SoapFault e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
if(itemResult != null)
{
return itemResult;
}
return null;
}
I have also coppied the HttpTransportSE.java and manipulated it to write directly in a file. But there I get an unvalid Token error.
I remember to have seen this problem before:
Two Recommendations:
1) Save your SOAP XML stream directly to disk as you download it. Don't store it in memory.
2) Parse it using a SAX-style parser, where you don't load the whole DOM in memory, but rather parse it in chunks.
EDIT: Check this -> Very large SOAP response - Android- out of memory error
I found a solution without using the KSoap2 Library.
Here is the code:
try {
java.net.URL url = new java.net.URL(URL);
HttpURLConnection rc = (HttpURLConnection) url.openConnection();
rc.setRequestMethod("POST");
rc.setDoOutput(true);
rc.setDoInput(true);
rc.setRequestProperty("Content-Type", "text/xml; charset=utf-8");
rc.addRequestProperty("User-Agent", HTTP.USER_AGENT);
rc.setRequestProperty("SOAPAction", SOAP_ACTION_ITEM_DATA);
OutputStream out = rc.getOutputStream();
Writer wout;
wout = new OutputStreamWriter(out);
wout.write("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
wout.write("<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">");
wout.write("<soap:Body>");
wout.write("<GetItemData2 xmlns=\"http://localhost/HSWebBL\">");
wout.write("<Company>" + company + "</Company>");
wout.write("<SerialNumber>" + serialId + "</SerialNumber>");
wout.write("</GetItemData2>");
wout.write("</soap:Body>");
wout.write("</soap:Envelope>");
wout.flush();
wout.close();
rc.connect();
Log.d("==CLIENT==", "responsecode: " + rc.getResponseCode() + " " + rc.getResponseMessage());
InputStream in = new BufferedInputStream(rc.getInputStream(), BUFFER_SIZE);
} catch (ProtocolException e) {
e.printStackTrace();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
I use a SAXParser to parse the InputStream.
In that way I don't get an outOfMemoryException and no parsing error anymore.
I got a valid Json string(at least every onlinevalidator I tried says so) which contains some chinese characters.
The json string is the following:
{"title":"\u8981\u805e--\u83ef\u723e\u8857\u65e5\u5831","url":"http://cn.wsj.com","desc":"\u300a\u83ef\u723e\u8857\u65e5\u5831\u300b\u4e2d\u6587\u7db2\u7d61\u7248\u6700\u65b0\u8ca1\u7d93\u8981\u805e","imageUrl":null,"lastUpdate":"1327588937","items":[{"title":"\u4e16\u8cbf\u7d44\u7e54\u7e3d\u5e79\u4e8b\ufe55\u4eba\u6c11\u5e63\u5e63\u503c\u88ab\u4f4e\u4f30\ufe50\u4f46\u4f4e\u4f30\u7a0b\u5ea6\u4e0d\u660e","desc":"\u4e16\u754c\u8cbf\u6613\u7d44\u7e54\u7e3d\u5e79\u4e8b\u5e15\u65af\u5361\u723e\uff0e\u62c9\u7c73\u9031\u56db\u8868\u793a\ufe50\u4eba\u6c11\u5e63\u532f\u7387\u88ab\u660e\u986f\u4f4e\u4f30\ufe50\u4f46\u4f4e\u4f30\u7a0b\u5ea6\u9084\u4e0d\u6e05\u695a\u3002","url":"http://cn.wsj.com/big5/20120126/BCHc-20120126WR182711424.asp?source=rss","pubdate":null}]}
Now when i Parse the JsonString in Android via new JsonObject(jsonString) I only got some squares instead of characters.
Why cant android handle this json string?
Any help would be apreciated.
If anyone would like to have the server Ressource, it can be found under:
// edit
url removed
public static String test(){
String testResult= "";
try {
HttpGet get = new HttpGet("http://xxxxx");//edit url removed.
DefaultHttpClient httpclient = new DefaultHttpClient();
HttpResponse response = httpclient.execute(get);
String result = EntityUtils.toString(response.getEntity());
JSONObject obj = new JSONObject(result);
if(!obj.isNull("title")){
testResult= obj.getString("title");
Log.d("Test","Test1:"+ testResult);
}
} catch (JSONException e) {
e.printStackTrace();
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return testResult;//
}
and Then TextView.setText(testResult);
It works for me.
it's Traditional Chinese String:"要聞--華爾街日報"
May be your ROM has no Traditional Chinese font????
When you receive your JSON, you may have to decode the UTF-8 result when you're building your result. Have a look at utf8 decoding. Something similar to this, but with JSON