I am trying to implement tokenization in my Android app, and for that I always need to add the authorization header to my request anytime I make one to the server. The problem is that when I debug the server instance, even if the request is made, there is no Authorization header added in it that
Here is my code
private void syncDatabases()
{
String tag_json_obj = "json_obj_req";
String uri = "random_url";
final ProgressDialog pDialog = new ProgressDialog(this);
pDialog.setMessage("Please wait while syncing");
pDialog.show();
List<Plane> allPlane = service.gettAllPlane();
Gson gson = new Gson();
JSONArray jsArray = new JSONArray();
for (Plane p : allPlane)
{
String jsonString = gson.toJson(p);
try {
JSONObject obj = new JSONObject(jsonString);
obj.remove("ID");
jsArray.put(obj);
} catch (JSONException e) {
e.printStackTrace();
}
}
JsonArrayRequest jsonObjReq = new JsonArrayRequest(Request.Method.POST, uri, jsArray, new Response.Listener<JSONArray>()
{
#Override
public void onResponse(JSONArray response)
{
ArrayList<Plane> newList = new ArrayList<>();
try
{
for(int i=0;i<response.length();i++)
{
String planeName,planeEngine,planeProducer,planeCountry,planeYear,wikiLink,ID;
JSONObject pl = response.getJSONObject(i);
String p1 = pl.optString("ID");
if (pl != null && !p1.isEmpty())
ID = pl.getString("ID");
else
ID = "0";
String p2 = pl.optString("planeName");
if (p2 != null && !p2.isEmpty())
planeName = pl.getString("planeName");
else
planeName = "";
String p3 = pl.optString("planeEngine");
if (p3 != null && !p3.isEmpty())
planeEngine = pl.getString("planeEngine");
else
planeEngine = "";
String p4 = pl.optString("planeProducer");
if (p4 != null && !p4.isEmpty())
planeProducer = pl.getString("planeProducer");
else
planeProducer = "";
String p5 = pl.optString("planeCountry");
if (p5 != null && !p5.isEmpty())
planeCountry = pl.getString("planeCountry");
else
planeCountry = "";
String p6 = pl.optString("planeYear");
if (p6 != null && !p6.isEmpty())
planeYear = pl.getString("planeYear");
else
planeYear = "0";
String p7 = pl.optString("wikiLink");
if (p7 != null && !p7.isEmpty())
wikiLink = pl.getString("wikiLink");
else
wikiLink = "";
Plane plf = new Plane(Integer.parseInt(ID),planeName,planeEngine,planeProducer,planeCountry,Integer.parseInt(planeYear),wikiLink);
newList.add(plf);
}
}
catch (JSONException e)
{
e.printStackTrace();
}
service.deleteAllFromPlane();
for (Plane p : newList)
{
boolean ok = service.addNewPlane(p);
}
pDialog.dismiss();
tab1.onIorU();
}
}, new Response.ErrorListener()
{
#Override
public void onErrorResponse(VolleyError error)
{
Log.e("ERROR", "Error occurred ", error);
pDialog.dismiss();
}
})
{
#Override
public Map<String, String> getHeaders() throws AuthFailureError
{
SharedPreferences settings = PreferenceManager
.getDefaultSharedPreferences(MainActivity.this);
String auth_token_string = settings.getString("token", "");
Map<String, String> params = new HashMap<>();
params.put("Content-Type", "application/json; charset=UTF-8");
params.put("Authorization", auth_token_string);
return params;
}
};
I already verified if auth_token_string is null (it isn't). Here is what I see on the server side (C# Web API 2 server)
And here is how I get the header:
var authorization = request.Headers.Authorization;
In the pic you can see a part of the token I try to send in the headers field though. What am I doing wrong? Thank you.
In your authorization token you are missing Type of authorization. I am asuming that you are using Bacis auth, so try using this:
params.put("Authorization", "Basic " + auth_token_string);
Related
My JSON file that I host in my VPS is 2.2 MB and when I use OkHttp to create a request to retrieve it and then log the JSON I see that not all the JSON was requested.
My code:
public void sendJSONRequest() {
// init http client
mOkHttpClient = new OkHttpClient();
// init a request
mRequest = new okhttp3.Request.Builder().url(url).build();
// execute the request (async)
mOkHttpClient.newCall(mRequest).enqueue(new Callback() {
#Override
public void onFailure(Call call, IOException e) {
Log.i(TAG, e.getMessage());
}
#Override
public void onResponse(Call call, okhttp3.Response response) throws IOException {
Log.i(TAG, response.body().string());
parseGameJSONResponse(response.body().string());
}
});
}
The error that gets throw within parseGameJSONResponse:
java.lang.IllegalStateException: closed
at okio.RealBufferedSource.rangeEquals(RealBufferedSource.java:398)
at okio.RealBufferedSource.rangeEquals(RealBufferedSource.java:392)
at okhttp3.internal.Util.bomAwareCharset(Util.java:449)
at okhttp3.ResponseBody.string(ResponseBody.java:174)
The error is thrown because the JSON was cut
parse json method:
public ArrayList<Game> parseGameJSONResponse(String json) {
ArrayList<Game> upcomingGames = new ArrayList<>();
// Main JSON Object
JSONObject mainJsonObject = null;
try {
mainJsonObject = new JSONObject(json);
} catch (JSONException e) {
e.printStackTrace();
}
boolean removeDuplicates = mSettingsValue.getRemoveDuplicates();
if (mainJsonObject != null) {
// MAIN JSON Data Array
JSONArray jsonArray = null;
try {
jsonArray = mainJsonObject.getJSONArray("data");
} catch (JSONException e) {
e.printStackTrace();
}
if (jsonArray != null && jsonArray.length() > 0) {
try {
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject gameObject = jsonArray.getJSONObject(i);
Game game = new Game();
if (gameObject.has("id")) {
game.id = gameObject.getInt("id");
}
if (gameObject.has("name")) {
String name = gameObject.getString("name");
game.name = name;
if (name.endsWith("Edition") && removeDuplicates) {
// skip this iteration because it's a special edition and we don't want editions if setting is set to true
continue;
}
}
if (gameObject.has("slug")) {
// Creates the URL here
game.url = gameObject.getString("slug");
}
if (gameObject.has("updated_at")) {
game.updated_at = gameObject.getLong("updated_at");
}
if (gameObject.has("summary")) {
game.summary = gameObject.getString("summary");
}
if (gameObject.has("first_release_date")) {
game.first_release_date = gameObject.getLong("first_release_date");
}
// Game Release Dates
if (gameObject.has("release_dates")) {
JSONArray jsonReleaseDatesArray = gameObject.getJSONArray("release_dates");
ArrayList<ReleaseDate> releaseDates = new ArrayList<>();
for (int y = 0; y < jsonReleaseDatesArray.length(); y++) {
ReleaseDate releaseDate = new ReleaseDate();
JSONObject jsonReleaseDateObject = jsonReleaseDatesArray.getJSONObject(y);
if (jsonReleaseDateObject.has("category") && !jsonReleaseDateObject.isNull("category")) {
releaseDate.category = jsonReleaseDateObject.getInt("category");
}
if (jsonReleaseDateObject.has("platform") && !jsonReleaseDateObject.isNull("platform")) {
releaseDate.platform = jsonReleaseDateObject.getInt("platform");
}
if (jsonReleaseDateObject.has("date") && !jsonReleaseDateObject.isNull("date")) {
releaseDate.date = jsonReleaseDateObject.getLong("date");
}
if (jsonReleaseDateObject.has("region") && !jsonReleaseDateObject.isNull("region")) {
releaseDate.region = jsonReleaseDateObject.getInt("region");
// Toast.makeText(getContext(), releaseDate.region + ": Region", Toast.LENGTH_SHORT).show();
}
if (jsonReleaseDateObject.has("y") && !jsonReleaseDateObject.isNull("y")) {
releaseDate.year = jsonReleaseDateObject.getInt("y");
}
if (jsonReleaseDateObject.has("m") && !jsonReleaseDateObject.isNull("m")) {
releaseDate.month = jsonReleaseDateObject.getInt("m");
}
if (jsonReleaseDateObject.has("human") && !jsonReleaseDateObject.isNull("human")) {
releaseDate.human = jsonReleaseDateObject.getString("human");
}
releaseDates.add(releaseDate);
}
game.releaseDates = releaseDates;
}
// Screenshots
if (gameObject.has("screenshots")) {
JSONArray jsonScreenshotsArray = gameObject.getJSONArray("screenshots");
ArrayList<String> screenshots = new ArrayList<>();
for (int y = 0; y < jsonScreenshotsArray.length(); y++) {
JSONObject jsonScreenshotObject = jsonScreenshotsArray.getJSONObject(y);
screenshots.add(jsonScreenshotObject.getString("cloudinary_id"));
}
game.screenshots = screenshots;
}
// Videos
if (gameObject.has("videos")) {
ArrayList<String> videos = new ArrayList<>();
JSONArray jsonVideosArray = gameObject.getJSONArray("videos");
for (int y = 0; y < jsonVideosArray.length(); y++) {
JSONObject jsonVideoObject = jsonVideosArray.getJSONObject(y);
videos.add(jsonVideoObject.getString("video_id"));
}
game.videos = videos;
}
// Cover image
if (gameObject.has("cover")) {
JSONObject jsonCoverObject = gameObject.getJSONObject("cover");
game.cover = jsonCoverObject.getString("cloudinary_id");
}
// Websites
if (gameObject.has("websites")) {
JSONArray jsonWebsitesArray = gameObject.getJSONArray("websites");
ArrayList<Website> websites = new ArrayList<>();
for (int y = 0; y < jsonWebsitesArray.length(); y++) {
Website website = new Website();
JSONObject jsonWebsiteObject = jsonWebsitesArray.getJSONObject(y);
website.category = jsonWebsiteObject.getInt("category");
website.url = jsonWebsiteObject.getString("url");
websites.add(website);
}
game.websites = websites;
}
upcomingGames.add(game);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}
Toast.makeText(getContext(), "" + upcomingGames.size(), Toast.LENGTH_SHORT).show();
return upcomingGames;
}
Thank you guys. Really appreciate any kind of help so thanks
It seems it tries to read same InputStream twice (may not save in memory).
I think you should use just response.string() instead of response.body().string().
Also if you think it might be related to timing you can edit timeouts.
client = new OkHttpClient.Builder()
.connectTimeout(10, TimeUnit.SECONDS)
.writeTimeout(10, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS)
.build();
For more look at this.
https://github.com/square/okhttp/issues/1240
I'am trying to parse the 'Body' from a POST request with a Java Lambda.
I'am stuck on this error for a while.
org.json.simple.JSONObject cannot be cast to java.lang.String
But the Body when logged look like that :
{"body":{"email":"test#test.com"}}
Witch should work with the parsing i'am doing right ?
The weird thing is the insert is working on local with JUNIT but not online after on AWS.
#Override
public void handleRequest(InputStream inputStream, OutputStream outputStream, Context context) throws IOException {
logger = context.getLogger();
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
Number user_id = null;
String birthdate = null;
List<Number> company_id = new ArrayList<Number>();
String email = null;
String employment_status = null;
String firstname = null;
String lastname = null;
String login = null;
String profile = null;
List<Number> site_id = new ArrayList<Number>();
String validation_status = null;
JSONObject responseJson = new JSONObject();
Map<String, AttributeValue> expressionAttributeValues = new HashMap<String, AttributeValue>();
String filterExpression = "";
String RegionAWS = REGION.toString();
client = AmazonDynamoDBClientBuilder.standard().withRegion(RegionAWS).build();
DynamoDB dynamoDB = new DynamoDB(client);
Table table = dynamoDB.getTable("LI_user");
try {
JSONParser parser = new JSONParser();
JSONObject event = (JSONObject) parser.parse(reader);
logger.log(event.toJSONString());
if (event.get("body") != null) {
JSONObject bod = (JSONObject)parser.parse((String)event.get("body"));
// JSONObject bod = (JSONObject) event.get("body");
if ( bod.get("id") != null) {
user_id = (Number)bod.get("id");
}
if ( bod.get("birthdate") != null) {
birthdate = (String)bod.get("birthdate");
}
if ( bod.get("email") != null) {
email = (String) bod.get("email");
}
if ( bod.get("employment_status") != null) {
employment_status = (String) bod.get("employment_status");
}
if ( bod.get("firstname") != null) {
firstname = (String) bod.get("firstname");
}
if ( bod.get("lastname") != null) {
lastname = (String) bod.get("lastname");
}
if ( bod.get("login") != null) {
login = (String) bod.get("login");
}
if ( bod.get("profile") != null) {
profile = (String) bod.get("profile");
}
if ( bod.get("validation_status") != null) {
validation_status = (String) bod.get("validation_status");
}
}
Replace
JSONObject bod = (JSONObject)parser.parse((String)event.get("body"));
with
JSONObject bod = (JSONObject)event.get("body");
if event is always an instance of JSONObject (as it seems granted, otherwise you would get a ClassCast at JSONObject event = (JSONObject) parser.parse(reader);)
You see logged
{"body":{"email":"test#test.com"}}
just because of logger.log(event.toJSONString());
Yes thanks you i have progress.
But now its seem like when i send the data on JSON format with Postman, that he receive a stringified version of the body. I get this data on cloudwatch logs :
"resource": "/users",
"httpMethod": "POST",
"queryStringParameters": null,
"stageVariables": null,
"body": "{\n \"id\": 5,\n \"company_id\": [\n 1\n ],\n \"email\": \"test#test.com\",\n \"employment_status\": \"FULL-TIME\",\n \"firstname\": \"Sebastien\",\n \"lastname\": \"LALALLALA\",\n \"login\": \"test#test.com\",\n \"profile\": \"FULL-TIME\",\n \"site_id\": \"55\",\n \"birthdate\": \"1985.05.05\",\n \"validation_status\" : \"COMPLETE\"\n}\n"
}
And this error :
java.lang.ClassCastException: java.lang.String cannot be cast to org.json.simple.JSONObject
I want to make my code wait until there is a change anywhere in my class to the variable finaloutcomes. Is there any way to do this? I am carrying this out within an Asynctask, which I posted below.
public HashMap<String,String> checkbetoutcome() {
new LoadAllGamet().execute();
// INSERT CODE HERE
return finaloutcomes;
}
ASYNCTASK
class LoadAllGamet extends AsyncTask<String, String, String> {
#Override
protected void onPreExecute() {
super.onPreExecute();
}
protected String doInBackground(String... args) {
// HttpParams httpParameters = new BasicHttpParams();
// HttpConnectionParams.setConnectionTimeout(httpParameters, 250000);
//HttpConnectionParams.setSoTimeout(httpParameters, 250000);
HttpClient client = new DefaultHttpClient();
HttpPost post = new HttpPost(url_check_bet);
List<NameValuePair> params = new ArrayList<NameValuePair>();
params.add(new BasicNameValuePair("param", bet));
// Log.d("CURRENTITEM", currentitem);
try {
post.setEntity(new UrlEncodedFormEntity(params));
} catch (IOException ioe) {
ioe.printStackTrace();
}
try {
HttpResponse response = client.execute(post);
Log.d("Http Post Responsecxxx:", response.toString());
HttpEntity httpEntity = response.getEntity();
InputStream is = httpEntity.getContent();
JSONObject jObj = null;
String json = "";
client.getConnectionManager().closeExpiredConnections();
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(
is, "iso-8859-1"), 8);
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null) {
if (!line.startsWith("<", 0)) {
if (!line.startsWith("(", 0)) {
sb.append(line + "\n");
}
}
}
is.close();
json = sb.toString();
json = json.substring(json.indexOf('{'));
// Log.d("sbsssssssssss", json);
try {
jObj = new JSONObject(json);
} catch (JSONException e) {
Log.e("JSON Parser", "Error parsing data " + e.toString());
}
allgames = jObj.getJSONArray("bets");
// Log.d("WHAT IS MY ARRAY?", allgames.toString());
for (Integer i = 0; i < allgames.length(); i++) {
HashMap<String,String> statuses = new HashMap<>();
JSONObject c = allgames.getJSONObject(i);
JSONArray currentbet = c.getJSONArray("bet");
Log.d("Single array",currentbet.toString());
// Storing each json item in variable
for (Integer a = 0; a < currentbet.length();a++) {
JSONObject d = currentbet.getJSONObject(a);
String Result = d.getString("Result");
String id = d.getString("gid");
Log.d("RESULTS",Result);
statuses.put(id, Result);
}
allbetsmap.add(i, statuses);
Log.d("ddd", statuses.toString());
Log.d("AAA", allbetsmap.get(i).toString());
}
} catch (Exception e) {
Log.e("Buffer Error", "Error converting result " + e.toString());
}
}
catch (IOException e) {
e.printStackTrace();
}
return "";
}
#Override
protected void onPostExecute(String param) {
Log.d("SIZE",Integer.toString(allbetsmap.size()));
//ArrayList<Map<String,String>> allbetsmap = new ArrayList<>();
//ArrayList<Map<String,String>> passtocheck = new ArrayList<>();
if (allbetsmap.size() == passtocheck.size()) {
for (int i = 0; i < allbetsmap.size();i++) {
if (allbetsmap.get(i).size() == passtocheck.get(i).size()) {
String finaloutcome = "won";
for (String a : allbetsmap.get(i).keySet()) {
String f = allbetsmap.get(i).get(a);
if(f.equals("null")) {
finaloutcome = "open";
}
else if (! (f.equals(passtocheck.get(i).get(a)))) {
finaloutcome = "lost";
break;
}
}
finaloutcomes.put(Integer.toString(i),finaloutcome);
}
}
}
Log.d("Vital",finaloutcomes.toString());
}
}
Ok, forget what I wrote before. I didn't realize you were writing code for android. Here is an improved version of LoadAllGamet. There are two important things here. 1. define as much as possible locally i.e. inside a method or - if that's not possible - inside the class. 2. return the result instead of putting it into some variable.
class LoadAllGamet extends AsyncTask<String, Void, HashMap<String,String>> {
protected HashMap<String,String> doInBackground(String ... args) {
HashMap<String,String> finaloutcomes = new HashMap<>(),
HashMap<Integer, HashMap<String,String>> allbetsmap = new HashMap<>();
HttpClient client = new DefaultHttpClient();
...
Log.d("SIZE",Integer.toString(allbetsmap.size()));
if (allbetsmap.size() == passtocheck.size()) {
...
}
Log.d("Vital",finaloutcomes.toString());
return finaloutcomes;
}
}
Whenever you want to do something that might take some time you should not run
that in the UI thread of you App since it can block your UI.
Instead run it asynchronously. One way of doing this is to use AsyncTask.
Let's assume you want to do something and while that something is being processed
you also want to update the UI (e.g. progress bars) from time to time. And once you
are finished you want to do something else with the result.
Here is one way of writing this.
void doSomething() {
new AsyncTask<String, Progress, Result>() {
protected Result doInBackground(String... args) {
//some code
publishProgress(values);
//some more code
return result;
}
protected void onProgressUpdate(Progress ... values) {
updateProgessBars(values);
}
protected void onPostExecute(Result result) {
doSomethingElse(result);
}
}.execute();
}
The String in new AsyncTask<String, Progress, Result> is the type of the
arguments to doInBackground. Often however you don't really need that unless
you want to pass arguments into execute.
Progress is the type of the values you want to send to onProgressUpdate. That
one you only need if you want to update your UI while the background processing
is still going on.
Result is of course your result type. Whatever you want to happen after
the doInBackground is finished you write into onPostExecute.
I have a listview that is populated thru SQLite with cache data. After it finishes loading. in the background I check for new data and get a returned JSON result from a MySQL db.
In my onPostExecute of this background task, when this code is ran (the code below), and while it is being looped thru (a maximum of 50 loops), the UI thread is blocked and scrolling a ListView is not possible. Here is code:
if (result.length() != 0) {
JSONArray jArray = new JSONArray(result);
JSONObject json_data = null;
for (int ii = 0; ii < jArray.length(); ii++) {
json_data = jArray.getJSONObject(ii);
item = json_data.getString("item");
cat = json_data.getString("category");
user = json_data.getString("username");
userId = json_data.getLong("user_id");
review = json_data.getString("review");
reviewId = json_data.getLong("review_id");
itemId = json_data.getLong("item_id");
commentCount = json_data.getLong("commentCount");
url = json_data.getString("name");
url = pathUrl + url; // for profile icon
date = json_data.getString("date");
rating = json_data.getDouble("rating");
upVote = json_data.getLong("good");
wiki = json_data.getString("wiki");
watchItems.add(item);
watchCats.add(cat);
watchUsers.add(user);
watchReviews.add(review);
watchUrl.add(url);
watchDateList.add(date);
watchWikiList.add(wiki);
watchItemIdList.add(String.valueOf(itemId));
watchUserIds.add(String.valueOf(userId));
watchReviewId.add(String.valueOf(reviewId));
watchRating.add(String.valueOf(rating));
watchCommentCount.add(String.valueOf(commentCount));
watchUpVote.add(String.valueOf(upVote));
Rateit.haveFollowing = "1";
if (Rateit.isUserLoggedIn == true) {
boolean oldReview = datasource
.getReviewIds(reviewId);
if (!oldReview) {
// Cache Network Items
datasource.createTrendWatch(itemId, item,
review, reviewId, cat, user,
String.valueOf(userId), url, date,
commentCount, rating, upVote, 0,
wiki);
}
}
FollowingItems wti = new FollowingItems(
Long.valueOf(watchItemIdList.get(i)),
watchItems.get(i), watchCats.get(i),
watchReviews.get(i),
Long.valueOf(watchReviewId.get(i)),
watchUsers.get(i),
Long.valueOf(watchUserIds.get(i)),
watchUrl.get(i), watchDateList.get(i),
Long.valueOf(watchCommentCount.get(i)),
Double.valueOf(watchRating.get(i)),
Long.valueOf(watchUpVote.get(i)),
watchWikiList.get(i++));
watchingListObject.add(wti);
}
}
Why is this happening? And how can I prevent my code to prevent this? Are there any optimizations I can make?
Edit: Someone below requested full task code.
Below repeats the code above but in context with entire task.
public static class FollowingTask extends AsyncTask<String, String, Void> {
protected InputStream is = null;
protected String result = "";
protected String userId;
protected ArrayList<FollowingItems> watchingListObject;
protected Context mContext;
public FollowingTask(Context context) {
mContext = context;
}
#Override
protected void onPreExecute() {
if (mContext != null && (fromRefresh == false)) {
((MainFragmentActivity) mContext)
.setSupportProgressBarIndeterminateVisibility(true);
}
resetLists();
if (PrefActivity.getUserLoggedInStatus(mContext) == true) {
userId = PrefActivity.getLoggedInUserId(mContext);
} else {
userId = "-1";
}
super.onPreExecute();
}
#Override
protected Void doInBackground(String... params) {
datasource.purgeItemWatchingTable();
Log.d("1", "Back");
String url_select = "http://www.---.info/includes_mc_php/featured_watching.php";
HttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(url_select);
ArrayList<NameValuePair> param = new ArrayList<NameValuePair>();
param.add(new BasicNameValuePair("user_id", userId));
param.add(new BasicNameValuePair("v2", "true"));
try {
httpPost.setEntity(new UrlEncodedFormEntity(param));
HttpResponse httpResponse = httpClient.execute(httpPost);
HttpEntity httpEntity = httpResponse.getEntity();
// read content
is = httpEntity.getContent();
} catch (Exception e) {
e.printStackTrace();
}
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) {
e.printStackTrace();
}
return null;
}
protected void onPostExecute(Void v) {
String pathUrl = Rateit.PROFILE_PIC_URL;
String item, cat, user, review, url, date, following, wiki;
long itemId, reviewId, userId, commentCount, upVote;
double rating;
int i = 0;
watchingListObject = new ArrayList<FollowingItems>();
try {
String c = String.valueOf(result.charAt(0));
if (c.equals("{")) {
JSONObject jsonObject = new JSONObject(result);
following = jsonObject.getString("following");
if (following.equals("0")) {
Rateit.haveFollowing = "0";
}
} else {
if (result.length() != 0) {
JSONArray jArray = new JSONArray(result);
JSONObject json_data = null;
for (int ii = 0; ii < jArray.length(); ii++) {
json_data = jArray.getJSONObject(ii);
item = json_data.getString("item");
cat = json_data.getString("category");
user = json_data.getString("username");
userId = json_data.getLong("user_id");
review = json_data.getString("review");
reviewId = json_data.getLong("review_id");
itemId = json_data.getLong("item_id");
commentCount = json_data.getLong("commentCount");
url = json_data.getString("name");
url = pathUrl + url; // for profile icon
date = json_data.getString("date");
rating = json_data.getDouble("rating");
upVote = json_data.getLong("good");
wiki = json_data.getString("wiki");
watchItems.add(item);
watchCats.add(cat);
watchUsers.add(user);
watchReviews.add(review);
watchUrl.add(url);
watchDateList.add(date);
watchWikiList.add(wiki);
watchItemIdList.add(String.valueOf(itemId));
watchUserIds.add(String.valueOf(userId));
watchReviewId.add(String.valueOf(reviewId));
watchRating.add(String.valueOf(rating));
watchCommentCount.add(String.valueOf(commentCount));
watchUpVote.add(String.valueOf(upVote));
Rateit.haveFollowing = "1";
if (Rateit.isUserLoggedIn == true) {
boolean oldReview = datasource
.getReviewIds(reviewId);
if (!oldReview) {
// Cache Network Items
datasource.createTrendWatch(itemId, item,
review, reviewId, cat, user,
String.valueOf(userId), url, date,
commentCount, rating, upVote, 0,
wiki);
}
}
FollowingItems wti = new FollowingItems(
Long.valueOf(watchItemIdList.get(i)),
watchItems.get(i), watchCats.get(i),
watchReviews.get(i),
Long.valueOf(watchReviewId.get(i)),
watchUsers.get(i),
Long.valueOf(watchUserIds.get(i)),
watchUrl.get(i), watchDateList.get(i),
Long.valueOf(watchCommentCount.get(i)),
Double.valueOf(watchRating.get(i)),
Long.valueOf(watchUpVote.get(i)),
watchWikiList.get(i++));
watchingListObject.add(wti);
Log.d("1", "Post 2");
}
} else {
Rateit.haveFollowing = "2";
}
}
} catch (JSONException e1) {
e1.printStackTrace();
Rateit.haveFollowing = "2";
} catch (ParseException e1) {
e1.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
Log.d("1", "Post COMPLETE");
mPullRefreshListView.onRefreshComplete();
// Reset Trending List on Pull-to-Refresh
if (mContext != null) {
if (watchUsers.size() == 0) {
l.setVisibility(View.VISIBLE);
tv.setTypeface(TypeFace.get(mContext, Rateit.BPREPLAY));
} else {
l.setVisibility(View.GONE);
}
if (mContext != null) {
listView.setAdapter(null);
if (watchItems.size() > 0) {
wAdapter = new FollowingAdapter(mContext,
watchingListObject, TypeFace.get(mContext,
Rateit.BPREPLAY), TypeFace.get(
mContext, Rateit.ROBOTO_LIGHT),
TypeFace.get(mContext, Rateit.ROBOTO_THIN),
TypeFace.get(mContext, Rateit.ROBOTO_REGULAR));
listView.setAdapter(wAdapter);
}
}
}
if (mContext != null && (fromRefresh == false)) {
((MainFragmentActivity) mContext)
.setSupportProgressBarIndeterminateVisibility(false);
MainFragmentActivity.dismissDialog(mContext);
}
fromRefresh = false;
}
}
onPostExecute runs on the UI thread. It will block the UI. doInBackground runs in the background. You should perform heavy opertaions in the doInBackground (not in onPostExecute)
Solution: you should move the parsing etc. from the onPostExecute to doInBackground and use the onPostExecute just for binding the processed information to the UI.
I would suggest as first thing to profile that code and measure how much time exactly is spent to execute it. This way at least you understand if your problem is really here or somewhere else
I have such JSONparser class:
public class JSONParser {
static InputStream is = null;
static JSONObject jObj;
static String json = "";
// constructor
public JSONParser() {
}
public JSONObject getJSONFromUrl(String url) {
// Making HTTP request
try {
// defaultHttpClient
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpGet httpPost = new HttpGet(url);
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 {
BufferedReader reader = new BufferedReader(new InputStreamReader(
is, "UTF-8"), 8);
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null) {
sb.append(line + "\n");
}
is.close();
json = sb.toString();
} catch (Exception e) {
Log.e("Buffer Error", "Error converting result " + e.toString());
}
// try parse the string to a JSON object
try {
jObj = new JSONObject(json);
} catch (JSONException e) {
Log.e("JSON Parser", "Error parsing data " + e.toString());
}
// return JSON String
return jObj;
}
}
and such activity:
public class BankExchangersListActivity extends ExpandableListActivity {
private static String url;
// JSON Node names
private static final String TAG_Exchangers = "bank_exchangers";
private static final String TAG_ID = "id";
private static final String TAG_NAME = "name";
private static final String TAG_address = "address";
private static final String TAG_location_name = "location_name";
private static final String TAG_latitude = "latitude";
private static final String TAG_longitude = "longitude";
private static final String TAG_exchanger_type_name = "exchanger_type_name";
private static final String TAG_exchanger_curr_value = "value";
private static final String TAG_currency_list_name = "currency_list_name";
private static final String TAG_direction_of_exchange_name = "direction_of_exchange_name";
JSONArray banks = null;
JSONArray exc_currencies = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
String bank;
bank = this.getIntent().getStringExtra("Bank_id");
url = "****/**_**_***_list/"+bank+".json";
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_bank_exchangers_list);
// Hashmap for ListView
ArrayList<HashMap<String, String>> contactList = new ArrayList<HashMap<String, String>>();
// Creating JSON Parser instance
JSONParser jParser = new JSONParser();
// getting JSON string from URL
JSONObject json = jParser.getJSONFromUrl(url);
ArrayList result = new ArrayList();
try {
// Getting Array of Contacts
banks = json.getJSONArray(TAG_Exchangers);
// looping through All Contacts
for(int i = 0; i < banks.length(); i++){
JSONObject c = banks.getJSONObject(i);
exc_currencies = c.getJSONArray("currency_values");
HashMap<String, String> map2 = new HashMap<String, String>();
ArrayList secList = new ArrayList();
for(int k = 0; k < exc_currencies.length(); k++){
JSONObject m = exc_currencies.getJSONObject(k);
String currency = m.getString(TAG_exchanger_curr_value);
String currency_list_name = m.getString(TAG_currency_list_name);
String direction_of_exchange_name = m.getString(TAG_direction_of_exchange_name);
Log.e("wazzzup", currency); //here is trouble: how to do new array with linking to parent?
HashMap child = new HashMap();
child.put(TAG_exchanger_curr_value, currency );
child.put(TAG_currency_list_name, currency_list_name );
child.put(TAG_direction_of_exchange_name, direction_of_exchange_name );
secList.add(child);
}
// Storing each json item in variable
String id = c.getString(TAG_ID);
String name = c.getString(TAG_NAME);
Log.e("name", name); //here is trouble: how to do new array with linking to parent?
String address = c.getString(TAG_address);
String location_name = c.getString(TAG_location_name);
String latitude = c.getString(TAG_latitude);
String longitude = c.getString(TAG_longitude);
String exchanger_type_name = c.getString(TAG_exchanger_type_name);
HashMap<String, String> map = new HashMap<String, String>();
map.put(TAG_ID, id);
map.put(TAG_NAME, name);
map.put(TAG_address, address);
map.put(TAG_location_name, location_name);
map.put(TAG_latitude, latitude);
map.put(TAG_longitude, longitude);
map.put(TAG_exchanger_type_name, exchanger_type_name);
// adding HashList to ArrayList
contactList.add(map);
result.add(secList);
}
} catch (JSONException e) {
e.printStackTrace();
}
/*ListAdapter adapter = new SimpleAdapter(this, contactList,
R.layout.bank_exchanger_list_element,
new String[] { TAG_NAME, TAG_location_name, TAG_address, TAG_exchanger_type_name, TAG_latitude, TAG_longitude }, new int[] {
R.id.bank_e_n, R.id.nas_punkt_e_n , R.id.adress_obm_e_n , R.id.tip_obm_e_n , R.id.shirota_e_n , R.id.dolgota_e_n });
setListAdapter(adapter);*/
SimpleExpandableListAdapter expListAdapter =
new SimpleExpandableListAdapter(
this,
contactList,
R.layout.bank_exchanger_list_element,
new String[] { TAG_NAME, TAG_location_name, TAG_address, TAG_exchanger_type_name, TAG_latitude, TAG_longitude },
new int[] {
R.id.bank_e_n, R.id.nas_punkt_e_n , R.id.adress_obm_e_n , R.id.tip_obm_e_n , R.id.shirota_e_n , R.id.dolgota_e_n },
result, //something goes here
R.layout.exchanger_currencies,
new String[] {TAG_exchanger_curr_value, TAG_currency_list_name, TAG_direction_of_exchange_name},
new int[] { R.id.currencyvalue_e_n, R.id.currency_list_name_e_n, R.id.direction_of_exchange_e_n}
);
setListAdapter( expListAdapter );
ExpandableListView elv = (ExpandableListView) getExpandableListView();
for(int i=0; i < expListAdapter.getGroupCount(); i++)
elv.expandGroup(i);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.bank_exchangers_list, menu);
return true;
}
}
On android 2.3.3 it works properly. But on 4.x i see errors, after searching I understood that I need to use AsyncTask. Is it true?
But how do I use it here? If there are any useful examples, please let me know.
Just how to get it working on Android 4.x?
You should already use AsyncTask under Android 2.x. It greatly improves responsiveness. Here is a fragment from my MEGA API library (currently under development):
private class AsyncRequestConnection extends AsyncTask<Void, Void, String> {
private final Request request;
public AsyncRequestConnection(Request request) {
this.request = request;
}
#Override
protected String doInBackground(Void... params) {
try {
HttpPost p = createRequestHttpMessage(request);
String resp = new String(stripResponse(getRequestClient().execute(p)));
Log.v(TAG, resp);
return resp;
} catch (Exception e) {
Log.e(TAG, "Cannot complete API request", e);
cancel(false);
return null;
}
}
#Override
protected void onCancelled() {
request.backoff();
if (request.hasReachedMaxBackoff()) {
request.cancel(R.string.error_internal);
} else {
requestQueue.enqueue(request);
}
requestConnection = null;
nextRequest();
}
#Override
protected void onPostExecute(String result) {
if (result != null) {
request.attachResponse(result);
request.handleResponse();
requestConnection = null;
nextRequest();
} else {
request.cancel(R.string.error_internal);
}
}
}
doInBackgroud() is the only method that is run on a different thread. Here, all your costly operations should happen.
getRequestClient() returns a HttpClient (AndroidHttpClient.newInstance(AGENT_NAME) or reused object for multiple requests in a row).
Since you are running muliple threads here, make sure doInBackground() does not access any global data structure. In my example, get getRequestClient() is sure to be only called from this location and there is only one such AsyncTask at any time. Otherwise you need some kind of mutex. Also, the Request object is sure to used by this class exlusively. Event handling (call-back methods) is implemented in the Request object as well but for simpler tasks you could simply do everything you want to do in onCancel() and onPostExecute().
If you only want to download a JSON object and parse it, you probably won't even need a constructor and private member variables. Simply replace the first Void by String to pass the URL string to doInBackground() and replace String by JSONObject.