How to download JSON data in android - java

I am developing an android application in which first I am sending request to Web service and getting the response status in 0 or 1 format if I get the response as 1 then complete JSON file is loaded.
My question is I want to make an offline app for which I want to download the JSON data from one activity and read that data in different activity with listview displaying title of every downloaded JSON file. After clicking the listview item, JSON data is displayed. And some of the JSON data items contains URL of images I also want to download them and display them in another activity.
I also want to encrypt the downloaded JSON data. Please Help me.
For reference I have attached the JSON file format.
{"test_time":7200,"time_taken":"0","time_left":"7200","score":null,"easy_score":null,"medium_score":null,"hard_score":null,"status":"n","sections":[{"section_id":"196498","section_name":"Reasoning Aptitude","section_no":1,"total_questions":"40","total_minutes":"24","questions":[{"question_id":"61562","question":{"1":{"text":"In a certain code GRANT is written as UOBSH and PRIDE is written as FEJSQ. How is SOLD written in that code?","image":"","imgHeight":"","imgWidth":""}},"correct_ans":{"1":{"text":"EMPT","image":"","imgHeight":"","imgWidth":""}},"rightOption":[],"rightOptionID":"246408","rightOptionNo":"2","anwer_explaination":{"1":{"text":"","image":"http://abc.com/testengine/images/questions/bankpower/image1.Jpeg","imgHeight":304,"imgWidth":212},"2":{"text":" ","image":"","imgHeight":"","imgWidth":""}},"question_time_taken":"10","marked":"0","skipped":"0","answer_id":"1395795","option_choose":"246407","question_status":1,"options":[{"OptionId":"246406","OptionDesc":{"1":{"text":"EPMT","image":"","imgHeight":"","imgWidth":""}}},{"OptionId":"246407","OptionDesc":{"1":{"text":"TPME","image":"","imgHeight":"","imgWidth":""}}},{"OptionId":"246408","OptionDesc":{"1":{"text":"EMPT","image":"","imgHeight":"","imgWidth":""}}},{"OptionId":"246409","OptionDesc":{"1":{"text":"CKNR","image":"","imgHeight":"","imgWidth":""}}},{"OptionId":"246410","OptionDesc":{"1":{"text":"ETPM","image":"","imgHeight":"","imgWidth":""}}}]},{"question_id":"61563","question":{"1":{"text":"Four of the following five are alike in a certain way and so form a group. Which is the one that does not belong to that group?","image":"","imgHeight":"","imgWidth":""}},"correct_ans":{"1":{"text":"27","image":"","imgHeight":"","imgWidth":""}},"rightOption":[],"rightOptionID":"246414","rightOptionNo":"3","anwer_explaination":{"1":{"text":"Mouse is odd rest are use for storage.","image":"","imgHeight":"","imgWidth":""}},"question_time_taken":"0","marked":"0","skipped":"1","answer_id":"","option_choose":"","question_status":3,"options":[{"OptionId":"246411","OptionDesc":{"1":{"text":"19","image":"","imgHeight":"","imgWidth":""}}},{"OptionId":"246412","OptionDesc":{"1":{"text":"17","image":"","imgHeight":"","imgWidth":""}}},{"OptionId":"246413","OptionDesc":{"1":{"text":"13","image":"","imgHeight":"","imgWidth":""}}},{"OptionId":"246414","OptionDesc":{"1":{"text":"27","image":"","imgHeight":"","imgWidth":""}}},{"OptionId":"246415","OptionDesc":{"1":{"text":"37","image":"","imgHeight":"","imgWidth":""}}}]}

parse all the data using the parser detailed in that link
http://www.androidhive.info/2012/01/android-json-parsing-tutorial/
then Write all the data into a file using the method below , this way ur data is downloaded and saved as a file
public void appendData(String text)
{
File myFile = new File("sdcard/myfile.file");
if (!myFile.exists())
{
try
{
myFile.createNewFile();
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
try
{
//BufferedWriter for performance, true to set append to file flag
BufferedWriter buf = new BufferedWriter(new FileWriter(myFile, true));
buf.append(text);
buf.newLine();
buf.close();
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}

You need to do something like this:
private class PrepareMapTask extends AsyncTask<String, Integer, Boolean>
{
// Initialize with invalid value
private int mPrepareResult = -1;
private String mJsonString = null;
protected Boolean doInBackground(String... urls)
{
mJsonString = downloadFileFromInternet(urls[0]);
if(mJsonString == null /*|| mJsonString.isEmpty()*/)
return false;
JSONObject jObject = null;
try {
jObject = new JSONObject(mJsonString);
JSONArray jsonImageArray = jObject.getJSONArray("imageTarget");
JSONArray jsonUrlArray = jObject.getJSONArray("videoUrls");
JSONArray jsonVideoOrUrlArray = jObject.getJSONArray("videoOrUrl");
if (jsonImageArray == null || jsonUrlArray == null)
return false;
for (int i = 0; i<jsonImageArray.length(); i++){
mapTargetUrl.put(jsonImageArray.get(i).toString(), jsonUrlArray.get(i).toString());
mVideoOrUrl.add(jsonVideoOrUrlArray.get(i).toString());
}
} catch (JSONException e) {
e.printStackTrace();
return false;
}
return true;
}
protected void onPostExecute(Boolean result)
{
}
private String downloadFileFromInternet(String url)
{
if(url == null /*|| url.isEmpty() == true*/)
new IllegalArgumentException("url is empty/null");
StringBuilder sb = new StringBuilder();
InputStream inStream = null;
try
{
url = urlEncode(url);
URL link = new URL(url);
inStream = link.openStream();
int i;
int total = 0;
byte[] buffer = new byte[8 * 1024];
while((i=inStream.read(buffer)) != -1)
{
if(total >= (1024 * 1024))
{
return "";
}
total += i;
sb.append(new String(buffer,0,i));
}
}catch(Exception e )
{
e.printStackTrace();
return null;
}catch(OutOfMemoryError e)
{
e.printStackTrace();
return null;
}
return sb.toString();
}
private String urlEncode(String url)
{
if(url == null /*|| url.isEmpty() == true*/)
return null;
url = url.replace("[","");
url = url.replace("]","");
url = url.replaceAll(" ","%20");
return url;
}
}
Take the data structures as per your json and modify the code.

try {
DefaultHttpClient httpclient = new DefaultHttpClient();
HttpPost httpPostRequest = new HttpPost(URL);
// Set HTTP parameters
/*StringEntity se;
se = new StringEntity(jsonObjSend.toString());*/
jsonObjSend.length();
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(jsonObjSend.length());
nameValuePairs.add(new BasicNameValuePair("data", jsonObjSend.toString()));
// Log.i("jsonObjSend.toString()","jsonObjSend.toString()"+jsonObjSend.toString());
Log.i("HTTPPOST","URL: "+URL);
Log.i("HTTPPOST","Request: "+jsonObjSend.toString());
UrlEncodedFormEntity en=new UrlEncodedFormEntity(nameValuePairs);
en.getContent();
httpPostRequest.getParams().setParameter("http.socket.timeout", new Integer(600000));
httpPostRequest.setEntity(en);
long t = System.currentTimeMillis();
HttpResponse response = (HttpResponse) httpclient.execute(httpPostRequest);
Log.i(TAG, "HTTPResponse received in [" + (System.currentTimeMillis()-t) + "ms]");
Log.i(TAG, httpPostRequest.getRequestLine().getProtocolVersion().toString());
responses = convertEntityToString(response.getEntity(), "UTF-8");
Log.i("HTTPPOST","Responce: "+responses);
Log.i("HTTPPOST","******************");
//Log.i("Encoding",response.getEntity().getContentEncoding().getName());
if (response.equalsIgnoreCase("")) {
webresponse = 1;
} else {
webresponse = 0;
}
} catch (IOException e) {
h.post(new Runnable() {
#Override
public void run() {
pd.dismiss();
AlertNullWebserviceResponce();
}
});
e.printStackTrace();
}

Related

Show progress bar while downloading JSON - Android

I am downloading a very huge JSON and it takes a lot of time.
I want to show the percentage of data I have downloaded.
I searched and found how to display progress if downloading a file but not JSON.
Here is how I am downloading JSON
private String getStringFromURL(String url) {
String string = null;
try {
HttpClient client = new DefaultHttpClient();
url = url.replace(" ", "%20");
url = url.replace("|", "%7C");
HttpGet get = new HttpGet(url);
HttpResponse response = client.execute(get);
if (response.getStatusLine().getStatusCode() == 200) {
String result = EntityUtils.toString(response.getEntity(),
HTTP.UTF_8);
if (result.toLowerCase().contains("invalid"))
return null;
result = result.replace("\r", "");
result = result.replace("\n", "").replace("\t", "\\t")
.replace("\b", "\\b").replace("\f", "\\f")
.replace("&", "\\&").replace("\'", "\\'")
.replace(";", "\\;").replace("?", "\\?")
.replace("*", "\\*");
string = result;
}
} catch (Exception e) {
e.printStackTrace();
}
return string;
}
You better to use AsyncTask to download data. There is a sample code below. I did not test it but it should work.
private class FetchJsonTask extends AsyncTask<Void, Void, String> {
private ProgressDialog progressDialog;
private Context context;
public FetchJsonTask(Context context) {
this.context = context;
}
#Override
protected void onPreExecute() {
// set up progress dialog
progressDialog = new ProgressDialog(context);
progressDialog.setIndeterminate(true);
progressDialog.setMessage("Please wait...");
// show it
progressDialog.show();
}
#Override
protected String doInBackground(Void... params) {
// These two need to be declared outside the try/catch
// so that they can be closed in the finally block.
HttpURLConnection urlConnection = null;
BufferedReader reader = null;
// Will contain the raw JSON response as a string.
String jsonStr = null;
try {
// Construct the URL somehow
URL url = createURL();
// Create the request to MuslimSalat.com, and open the connection
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.connect();
// Read the input stream into a String
InputStream inputStream = urlConnection.getInputStream();
StringBuffer buffer = new StringBuffer();
if (inputStream == null) {
// Nothing to do.
return null;
}
reader = new BufferedReader(new InputStreamReader(inputStream));
String line;
while ((line = reader.readLine()) != null) {
// Since it's JSON, adding a newline isn't necessary (it won't affect parsing)
// But it does make debugging a *lot* easier if you print out the completed
// buffer for debugging.
buffer.append(line + "\n");
}
if (buffer.length() == 0) {
// Stream was empty. No point in parsing.
return null;
}
jsonStr = buffer.toString();
} catch (IOException e) {
Log.e(LOG_TAG, "Error ", e);
// If the code didn't successfully get the data, there's no point in attemping
// to parse it.
return null;
} finally{
if (urlConnection != null) {
urlConnection.disconnect();
}
if (reader != null) {
try {
reader.close();
} catch (final IOException e) {
Log.e(LOG_TAG, "Error closing stream", e);
}
}
}
return jsonStr;
}
#Override
protected void onPostExecute(String jsonString) {
// jsonString is your result use it somehow.
Log.d(LOG_TAG, "Json result: " + jsonString);
// dismiss the progress because downloading process is finished.
progressDialog.dismiss();
}
}
You can call it from your activity, fragment etc.
FetchJsonTask fetchJsonTask = new FetchJsonTask(context);
fetchJsonTask.execute();

Get Json data from the Url below(Url returns json data)

This is the URL which returns me the json object Link.
Now I need to get the json data to my code. When I try to access the link I get the html script. How do I get the json data from the above URL to my code. Here is my code.
class task extends AsyncTask<String, String, Void>
{
private ProgressDialog progressDialog = new
`ProgressDialog(MainActivity.this);`
InputStream is = null ;
String result = "";
protected void onPreExecute() {
progressDialog.setMessage("Fetching data...");
progressDialog.show();
progressDialog.setOnCancelListener(new OnCancelListener() {
#Override
public void onCancel(DialogInterface arg0) {
task.this.cancel(true);
}
});
}
#Override
protected Void doInBackground(String... params) {
String url_select1 = "http://andpermission.byethost5.com/PermissionList.php";
HttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(url_select1);
ArrayList<NameValuePair> param = new ArrayList<NameValuePair>();
try {
httpPost.setEntity(new UrlEncodedFormEntity(param));
HttpResponse httpResponse = httpClient.execute(httpPost);
HttpEntity httpEntity = httpResponse.getEntity();
//read content
is = httpEntity.getContent();
} catch (Exception e) {
Log.e("log_tag", "Error in http connection "+e.toString());
//Toast.makeText(MainActivity.this, "Please Try Again", Toast.LENGTH_LONG).show();
}
try {
BufferedReader br = new BufferedReader(new InputStreamReader(is));
StringBuilder sb = new StringBuilder();
String line = "";
while((line=br.readLine())!=null)
{
sb.append(line+"\n");
}
is.close();
result=sb.toString();
} catch (Exception e) {
// TODO: handle exception
Log.e("log_tag", "Error converting result "+e.toString());
}
return null;
}
protected void onPostExecute(Void v) {
// ambil data dari Json database
try {
JSONArray Jarray = new JSONArray(result);
for(int i=0;i<Jarray.length();i++)
{
JSONObject Jasonobject = null;
//text_1 = (TextView)findViewById(R.id.txt1);
Jasonobject = Jarray.getJSONObject(i);
//get an output on the screen
//String id = Jasonobject.getString("id");
String name = Jasonobject.getString("name");
String db_detail="";
if(et.getText().toString().equalsIgnoreCase(name)) {
db_detail = Jasonobject.getString("detail");
text.setText(db_detail);
break;
}
//text_1.append(id+"\t\t"+name+"\t\t"+password+"\t\t"+"\n");
}
this.progressDialog.dismiss();
} catch (Exception e) {
// TODO: handle exception
Log.e("log_tag", "Error parsing data "+e.toString());
}
}
}
Using string builder I append the content and I find only the java script and I don't find the json data. How to I get the json data from the above URL.
In string "Result" in my code I get the below output.
<html>
<body>
<script type="text/javascript" src="/aes.js"></script>
<script>
function toNumbers(d) {
var e = [];
d.replace(/(..)/g, function(d) {
e.push(parseInt(d, 16))
});
return e
}
function toHex() {
for (var d = [], d = 1 == arguments.length && arguments[0].constructor == Array ? arguments[0] : arguments, e = "", f = 0; f < d.length; f++) e += (16 > d[f] ? "0" : "") + d[f].toString(16);
return e.toLowerCase()
}
var a = toNumbers("f655ba9d09a112d4968c63579db590b4"),
b = toNumbers("98344c2eee86c3994890592585b49f80"),
c = toNumbers("b8eeb5e790c4a5395d01cde6b8230fdd");
document.cookie = "__test=" + toHex(slowAES.decrypt(c, 2, a, b)) + "; expires=Thu, 31-Dec-37 23:55:55 GMT; path=/";
location.href = "http://andpermission.byethost5.com/PermissionList.php?ckattempt=1";
</script>
<noscript>This site requires Javascript to work, please enable Javascript in your browser or use a browser with Javascript support</noscript>
How do I get only the json data from the URL instead the java script.
Try the full URL: http://andpermission.byethost5.com/PermissionList.php?ckattempt=1.
And also make sure you are using GET instead of POST, because that's what the URL refers to.
Here a good example: http://www.learn2crack.com/2013/10/android-json-parsing-url-example.html
On the other hand, there are some libraries like Aquery, Okhttp and Volley, that do this job very good.

uploading and downloading a encoded bitmap image to and from server using mysql and php

I have a small project in which I have to upload and save 3 images in a table, on a remote mysql database. After that I have to fetch those images from the table and display in imageViews in my android application. Upload and downloads is done in two separate android applications.
I want to upload images with good quality but low size, so I'm compressing the images with bitmap compress technique and then encode it to string using base64, and then upload it to server.
In the server I have written a php file which receives the encoded string and saves it into the table(using longBlob).
my issues:
1.if I try to decode and save the image into the table in the php, I'm getting an error.
2.I directly saved the encoded image and retrieved it using json, but when I try to create a json object(to get the image) in the android code, its giving error like JSONException:value[{"imagePhoto":"/4AAQS....etc" and JSON.typemismatch and caused by:java.lang.nullpointerexception
I really don't know how to do this and I don't know whether my approach is right or wrong. Basically I just want the image to upload with less size and good quality, get saved and retrieved with good quality.
please help....thank you
code:
encoding the image
public String getImage(String path){
try {
ByteArrayOutputStream stream=new ByteArrayOutputStream();
Bitmap photo = BitmapFactory.decodeFile(techFolder.getPath() + File.separator + path);
photo.compress(Bitmap.CompressFormat.JPEG, 0,stream);
byte[] byte_arr=stream.toByteArray();
// Encode Image to String
String encodedString=Base64.encodeToString(byte_arr, Base64.DEFAULT);
return encodedString;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
php file
<?php
//i skipped the login and db selection details
$imagePhoto=$_POST["imagePhoto"];
$imageAddress=$_POST["imageAddress"];
$imageSignature=$_POST["imageSignature"];
//$imagePhotoa=base64_decode($imagePhoto);
//$imageAddressa=base64_decode($imageAddress);
//$imageSignaturea=base64_decode($imageSignature);
$query="INSERT INTO `a1597402_semapho` VALUES ('$imagePhoto', '$imageAddress', '$imageSignature')";
//executing query
$result=mysql_query($query) or die(mysql_error());
//$row = mysql_fetch_array($result);
if ($result) {
$response["success"] = 1;
$response["message"] = "Succesfully submitted";
die(json_encode($response));
} else{
$response["success"] = 0;
$response["message"] = "Failed to submit the details ";
die(json_encode($response));
}
mysql_close();
?>
code for retrieving the image:
public class JSONParser {
static InputStream is = null;
static JSONObject jObj = null;
static String json = "";
public static String getJSONFromUrl(String url,Boolean isParam,List<NameValuePair> params ) {
// make HTTP request
try {
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(url);
//checking for parameters to send to server
if(isParam)
httpPost.setEntity(new UrlEncodedFormEntity(params));
HttpResponse httpResponse = httpClient.execute(httpPost);
HttpEntity httpEntity = httpResponse.getEntity();
is = httpEntity.getContent();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
try {
BufferedInputStream bis = new BufferedInputStream(is, 8190);
ByteArrayBuffer baf = new ByteArrayBuffer(50);
int current = 0;
while ((current = bis.read()) != -1)
{
baf.append((byte)current);
}
byte[] imageData = baf.toByteArray();
// BufferedReader reader = new BufferedReader(new InputStreamReader(is, "iso-8859-1"), 8);
// StringBuilder sb = new StringBuilder();
// String line = null;
// while ((line = reader.readLine()) != null) {
// //Log.d("stringff",line);
// sb.append(line + "\n");
// }
is.close();
//json = sb.toString();
json=new String(imageData);
Log.d("stringff",json);
} catch (Exception e) {
}
// return JSON String
return json;
}
}
background task which calls jsonParser class
#Override
protected Void doInBackground(Void... arg0) {
json = JSONParser.getJSONFromUrl(STATE_URL,false,params);
Log.d("image", json);
//parsing json string
try {
jsonObj = new JSONObject(json);
} catch (JSONException e) {
// TODO Auto-generated catch block
Log.d("BREAK1","break1");
e.printStackTrace();
}
String image;
try {
image = jsonObj.getString("imagePhoto");
byte[] imageAsBytes = Base64.decode(image.getBytes(), 0);
Bitmap bp = BitmapFactory.decodeByteArray(imageAsBytes, 0, imageAsBytes.length);
i.setImageBitmap(bp);
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//byte[] decodedByte = Base64.decode(json, Base64.DEFAULT);
return null;
}

How to send variables to PHP from Android to do a SELECT ... WHERE in PHP

I already got a method to read data from mysql and display it into my android app in textview's. The problem is that now I just retrieve all data from the database without doing a select ... where , just a select. I want to do a select ... where using the variables sent from my android app. I already use the folowing code in my login to send username and pass
nameValuePairs=new ArrayList<NameValuePair>(2);
nameValuePairs.add(new BasicNameValuePair("utilizator",utilizator.getText().toString().trim()));
nameValuePairs.add(new BasicNameValuePair("parola",parola.getText().toString().trim()));
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
In the method I use I have 2 java files. I really don't understand them much ... so I don't know where to add the code to send variables to php.
httprequest.java
public class httprequest {
static int TIMEOUT = 5000;
public String read_url_resource(String _s_url)
{
String s_response_ = "";
BufferedReader br_reader=null;
StringBuilder sb_builder = new StringBuilder();
URL u_url = null;
try {
if ( _s_url==null || _s_url.length()==0)
return "";
//this.log_message("Downloading from "+_s_url, false);
u_url = new URL(_s_url);
HttpURLConnection huc_urlConnection = null;
huc_urlConnection = (HttpURLConnection)u_url.openConnection();
if ( huc_urlConnection!=null){
huc_urlConnection.setConnectTimeout(TIMEOUT);
huc_urlConnection.setReadTimeout(TIMEOUT);
huc_urlConnection.setUseCaches(false);
huc_urlConnection.setDoOutput(false);
InputStream is_input_stream = huc_urlConnection.getInputStream();
#SuppressWarnings("unused")
URL oURL = huc_urlConnection.getURL();
int i_response_code=huc_urlConnection.getResponseCode();
if ( i_response_code==200){
br_reader = new BufferedReader(new InputStreamReader(is_input_stream));
String line="";
while ((line = br_reader.readLine()) != null)
sb_builder.append(line);
is_input_stream.close();
s_response_ = sb_builder.toString();
String s_auth= huc_urlConnection.getURL().getAuthority();
}
}
} catch (Exception e) {
if ( e!=null )
Log.e("URL PROBLEM", e.toString());
s_response_ = "[\"error\": \"No connection\"]";
}
return s_response_;
}
}
and ReadJSONData.java
public class ReadJSONData extends AsyncTask<String, Integer, Integer> {
private String server = "http://asociatia-online.esy.es/cote.php?hc_location=ufi";
private ReadJSONListener jsonListener;
private String json ="";
private int internal_categ;
httprequest request;
public interface ReadJSONListener
{
void onTaskFinished(String s_json, int _i_internal_category);
}
public ReadJSONData (ReadJSONListener _jsonListener, int _i_internal_category)
{
this.jsonListener=_jsonListener;
this.internal_categ =_i_internal_category;
}
#Override
protected Integer doInBackground(String... strings) {
request = new httprequest();
this.downloadResource();
return null;
}
private void downloadResource() {
switch (this.internal_categ) {
case 1:
this.json = request.read_url_resource(server);
break;
}
}
#Override
protected void onPostExecute(Integer result)
{
this.jsonListener.onTaskFinished(this.json, this.internal_categ);
}
}
So, where to add the 4 lines code to send variables? In which file and where. Thanks !
With this code you can send variables to PHP and get some data back and store it in strings to use as you want.
private class ObtinereInformatii extends AsyncTask<String, Void, String>{
#Override
protected String doInBackground(String... params) {
//http post
try {
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost("http://asociatia-online.esy.es/rezumat.php");
nameValuePairs = new ArrayList<NameValuePair>(2);
nameValuePairs.add(new BasicNameValuePair("luna_rezumat",spinner_luna.getSelectedItem().toString().trim()));
nameValuePairs.add(new BasicNameValuePair("an_rezumat",spinner_an.getSelectedItem().toString().trim()));
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
HttpResponse response = httpclient.execute(httppost);
HttpEntity entity = response.getEntity();
is = entity.getContent();
} catch (Exception e) {
Log.e("log_tag", "Error in http connection" + e.toString());
}
//convert response to string
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(is, "iso-8859-1"), 8);
sb = new StringBuilder();
sb.append(reader.readLine() + "\n");
String line = "0";
while ((line = reader.readLine()) != null) {
sb.append(line + "\n");
}
is.close();
result = sb.toString();
Log.e("-------",result);
} catch (Exception e) {
Log.e("log_tag", "Error converting result " + e.toString());
}
return result;
}
protected void onPostExecute(String result){
try{
jArray = new JSONArray(result);
readJson(jArray);
} catch (JSONException e) {
e.printStackTrace();
}
}
}
private void readJson(JSONArray ja_data) throws JSONException {
if (ja_data!=null)
{
for (int i = 0; i<ja_data.length(); i++)
{
JSONObject jo = ja_data.getJSONObject(i);
if (jo.has("data_rezumat"))
{
if (jo.getString("data_rezumat")!=null)
{
z_data_rezumat= jo.getString("data_rezumat");
}
}
}
}
}

Perform AsyncTask on Android / Posting JSON

I am working on an android app, and am running into some troubles with registering users. I want to post a JSON object to my server and receive one back. I can successfully create a JSON object with the right information but when I go to post it I get a NetworkOnMainThreadException or my HttpClient class returns null when it should be returning a JSONObject and I am very confident that my web server works correctly. I understand that you cannot connect to the network on the main thread and have created an HttpClient class that uses AsnycTask (although probably not correctly). I have been working on this for quite a while and would appreciate any guidance in the right direction.
//Main activity
#Override
public void onClick(View arg0) {
if(!(isEmpty(name) || isEmpty(username) || isEmpty(password) || isEmpty(email))) {
user = new JSONObject();
try {
user.put("username", username.getText().toString());
user.put("name", name.getText().toString());
user.put("email", email.getText().toString());
user.put("password", password.getText().toString());
} catch (JSONException e) {
e.printStackTrace();
}
jRegister = new JSONObject();
try {
jRegister.put("apiToken", Utilities.apiToken);
jRegister.put("user", user);
Log.i("MainActivity", jRegister.toString(2));
} catch (JSONException e) {
e.printStackTrace();
}
//
HttpClient client = new HttpClient(url, jRegister);
result = client.getJSONFromUrl();
try {
if(result != null)
tv.setText(result.toString(2));
else
tv.setText("null");
} catch (JSONException e) {
e.printStackTrace();
}
}else {
tv.setText("");
}
}
HttpClient Class
public class HttpClient extends AsyncTask<Void, Void, JSONObject>{
private final String TAG = "HttpClient";
private String URL;
private JSONObject jsonObjSend;
private JSONObject result = null;
public HttpClient(String URL, JSONObject jsonObjSend) {
this.URL = URL;
this.jsonObjSend = jsonObjSend;
}
public JSONObject getJSONFromUrl() {
this.execute();
return result;
}
#Override
protected JSONObject doInBackground(Void... params) {
try {
DefaultHttpClient httpclient = new DefaultHttpClient();
HttpPost httpPostRequest = new HttpPost(URL);
StringEntity se;
se = new StringEntity(jsonObjSend.toString());
// Set HTTP parameters
httpPostRequest.setEntity(se);
httpPostRequest.setHeader("Accept", "application/json");
httpPostRequest.setHeader("Content-type", "application/json");
long t = System.currentTimeMillis();
HttpResponse response = (HttpResponse) httpclient.execute(httpPostRequest);
Log.i(TAG, "HTTPResponse received in [" + (System.currentTimeMillis()-t) + "ms]");
HttpEntity entity = response.getEntity();
if (entity != null) {
// Read the content stream
InputStream instream = entity.getContent();
// convert content stream to a String
String resultString= convertStreamToString(instream);
instream.close();
resultString = resultString.substring(1,resultString.length()-1); // remove wrapping "[" and "]"
JSONObject jsonObjRecv = new JSONObject(resultString);
// Raw DEBUG output of our received JSON object:
Log.i(TAG,"<JSONObject>\n"+jsonObjRecv.toString()+"\n</JSONObject>");
return jsonObjRecv;
}
}
catch (Exception e) {
e.printStackTrace();
}
return null;
}
protected void onPostExecute(JSONObject jObject) {
result = jObject;
}
private static String convertStreamToString(InputStream is) {
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
StringBuilder sb = new StringBuilder();
String line = null;
try {
while ((line = reader.readLine()) != null) {
sb.append(line + "\n");
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return sb.toString();
}
}
I understand that you cannot connect to the network on the main thread
and have created an HttpClient class that uses AsnycTask (although
probably not correctly).
You are right you have not implemented it the right way.
In your onClick events (still on Main thread) you performed a network activity causing the error:
HttpClient client = new HttpClient(url, jRegister);
result = client.getJSONFromUrl();
Instead you should run the network operation inside of the AsnycTask
public class GetJsonTask extends AsyncTask<Void, Void, JSONObject >{
private String URL;
private JSONObject jsonObjSend;
public GetJsonTask(String URL, JSONObject jsonObjSend) {
this.URL = URL;
this.jsonObjSend = jsonObjSend;
}
#Override
protected JSONObject doInBackground(Void... params) {
JSONObject jsonObjRecv;
try {
DefaultHttpClient httpclient = new DefaultHttpClient();
HttpPost httpPostRequest = new HttpPost(URL);
StringEntity se;
se = new StringEntity(jsonObjSend.toString());
// Set HTTP parameters
httpPostRequest.setEntity(se);
httpPostRequest.setHeader("Accept", "application/json");
httpPostRequest.setHeader("Content-type", "application/json");
long t = System.currentTimeMillis();
HttpResponse response = (HttpResponse) httpclient.execute(httpPostRequest);
Log.i(TAG, "HTTPResponse received in [" + (System.currentTimeMillis()-t) + "ms]");
HttpEntity entity = response.getEntity();
if (entity != null) {
// Read the content stream
InputStream instream = entity.getContent();
// convert content stream to a String
String resultString= convertStreamToString(instream);
instream.close();
resultString = resultString.substring(1,resultString.length()-1); // remove wrapping "[" and "]"
jsonObjRecv = new JSONObject(resultString);
// Raw DEBUG output of our received JSON object:
Log.i(TAG,"<JSONObject>\n"+jsonObjRecv.toString()+"\n</JSONObject>");
}
}
catch (Exception e) {
e.printStackTrace();
}
return jsonObjRecv;
}
protected void onPostExecute(JSONObject result) {
try {
if(result != null)
tv.setText(result.toString(2));
else
tv.setText("null");
} catch (JSONException e) {
e.printStackTrace();
}
}else {
tv.setText("");
}
}
}
Then you call your async in onclik method like this:
public void onClick(View arg0) {
//.......
GetJsonTask client = new GetJsonTask(url, jRegister);
client.execute();
}
One problem in your code is that your expectations of AsyncTask aren't quite right. In particular this function:
public JSONObject getJSONFromUrl() {
this.execute();
return result;
}
AsyncTask runs the code in the doInBackground() function in a separate thread. This means that once you call execute() you have two parallel lines of execution. You end up with what's called a Race Condition. When you reach the return result line, a couple of things can be happening:
doInBackground() hasn't run and therefore result is still has the default value. In this case null.
doInBackground() can be in the middle of the code. In your particular case because it doesn't modify result then this doesn't affect you much. But it could be on any line (or middle of a line sometimes if operations aren't atomic) when that return happens.
doInBackground() could've finished, but since onPostExecute() runs on the UI thread it has to wait until your onClick handler is finished. By the time onPostExecute() has a chance to run onClick already tried to update tv with whatever it was that getJSONFromUrl returned, most likely null.
The way to set up tasks with AsyncTask is to give it the information it needs to do it's work, start it up with execute, and since you can't know how long it will take to complete, let it handle the finishing steps of the task.
This means that after calling execute you don't wait around for it's result to update views (like in your case), but rather rely on the AsyncTask's onPostExecute or related methods to take over the next steps.
For your case this would mean that your onPostExecute should look something like:
protected void onPostExecute(JSONObject result) {
try {
if(result != null)
tv.setText(result.toString(2));
else
tv.setText("null");
} catch (JSONException e) {
e.printStackTrace();
}
}

Categories