I'm trying to parse a Large JSON file that contains 24,000 lines(it contains regular Expressions to detect sms from sms provider) , the file is locally stored in assets folder here's the code of my class
public class SmsActivity extends AppCompatActivity {
ListView lv;
ArrayList<String> msg;
ArrayAdapter<String> adapter;
JSONObject obj;
JSONArray rules_array;
JSONObject rule_object = null;
String body, address, smsDate;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sms);
lv = (ListView) findViewById(R.id.list);
permission();
}
void permission() {
// first check for permissions
if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_SMS) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_SMS},
10);
} else {
adapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, Inbox());
lv.setAdapter(adapter);
}
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String permissions[], #NonNull int[] grantResults) {
switch (requestCode) {
case 10: {
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
ArrayAdapter<String> adapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, Inbox());
lv.setAdapter(adapter);
Toast.makeText(this, "Permission is granted",
Toast.LENGTH_SHORT).show();
} else {//If permission is not granted,then it will ask for permission .
permission();
}
}
}
}
public String loadJSONFromAsset() {
String json = null;
try {
InputStream is = getAssets().open("sms_formats.json");
int size = is.available();
byte[] buffer = new byte[size];
is.read(buffer);
is.close();
json = new String(buffer, "UTF-8");
} catch (IOException ex) {
ex.printStackTrace();
return null;
}
return json;
}
//Arraylist is used to create dynamic array.The size can be varried .
public ArrayList<String> Inbox() {
msg = new ArrayList<>();
try {
//A Uri object is usually used to tell a ContentProvider what we want to access by reference.In this ,we are accessing inbox.
Uri uri = Uri.parse("content://sms/inbox");
//ContentResolver is used to request the content.
//cursor object gets the data.
Cursor cursor = getContentResolver().query(uri, new String[]{"_id", "address", "date", "body"}, null, null, null);
obj = new JSONObject(loadJSONFromAsset());
if (!obj.isNull("rules")) {
rules_array = obj.getJSONArray("rules");
//It checks whether there is any messages in inbox.If there is no message then the following if statement will not be executed.
if (cursor != null) {
while (cursor.moveToNext()) {
address = cursor.getString(1);
body = cursor.getString(3);
String date = cursor.getString(cursor.getColumnIndex("date"));
Long timestamp = Long.parseLong(date);
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(timestamp);
Date finaldate = calendar.getTime();
smsDate = finaldate.toString();
for (int i = 0; i < rules_array.length(); i++) {
rule_object = rules_array.getJSONObject(i);
if (!rule_object.isNull("name")) {
// you have a name for the rule
Log.e("NO", "error");
}
if (!rule_object.isNull("patterns")) {
JSONArray pattern_array = rule_object.getJSONArray("patterns");
for (int j = 0; j < pattern_array.length(); j++) {
JSONObject pattern_obj = pattern_array.getJSONObject(j);
if (!pattern_obj.isNull("regex")) {
String type = pattern_obj.getString("sms_type");
if (type.equals("transaction")) {
String regex = pattern_obj.getString("regex");
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(body);
if (matcher.find()) {
msg.add("\nSender=>" + address + "\n" + "Message=>" + body + "\n" + "Date and Time=>" + smsDate + "\n");
}
}
}
}
}
}
}
cursor.close();
}
}
} catch (JSONException e) {
e.printStackTrace();
}
return msg;
}
}
The problem here is when i use Android studio debugger i can see that all JSON objects and JSONArrays have the values they are supposed to have.But when i run the app on the phone it gives me black screen with no output.
I tried to implement AsyncTask cause I thought the black screen was due the large amount of data it was processing on the main thread from the JSON file, but it didn't help either. Can Someone please point me in the right direction.
Ps-I'm a beginner in Android Development
edit added AsyncTask.
public class LoadData extends AsyncTask<String, Void, JSONObject> {
String bodyData;
#Override
protected JSONObject doInBackground(String... body) {
bodyData = body.toString();
if (!obj.isNull("rules")) {
try {
rules_array = obj.getJSONArray("rules");
for (int i = 0; i < rules_array.length(); i++) {
rule_object = rules_array.getJSONObject(i);
if (!rule_object.isNull("name")) {
// you have a name for the rule
Log.e("NO", "error");
}
if (!rule_object.isNull("patterns")) {
JSONArray pattern_array = rule_object.getJSONArray("patterns");
for (int j = 0; j < pattern_array.length(); j++) {
JSONObject pattern_obj = pattern_array.getJSONObject(j);
if (!pattern_obj.isNull("regex")) {
return pattern_obj;
}
}
}
}
} catch (JSONException e) {
e.printStackTrace();
}
}
return null;
}
#Override
protected void onPostExecute(JSONObject pattern_obj) {
super.onPostExecute(pattern_obj);
String type = null;
try {
type = pattern_obj.getString("sms_type");
if (type.equals("transaction")) {
String regex = pattern_obj.getString("regex");
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(bodyData);
if (matcher.find()) {
msg.add("\nSender=>" + address + "\n" + "Message=>" + body + "\n" + "Date and Time=>" + smsDate + "\n");
}
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}
Parsing a large JSON file that contains 24,000 lines is complex work. Using AsynTask to perform that stuff in worker thread, then publish result in UI thread
When your app performs intensive work in response to user interaction, this single thread model can yield poor performance unless you implement your application properly. Specifically, if everything is happening in the UI thread, performing long operations such as network access or database queries will block the whole UI. When the thread is blocked, no events can be dispatched, including drawing events. From the user's perspective, the application appears to hang. Even worse, if the UI thread is blocked for more than a few seconds (about 5 seconds currently) the user is presented with the infamous "application not responding" (ANR) dialog. The user might then decide to quit your application and uninstall it if they are unhappy.
This stuff below could be done in worker thread, so you don't have to put it into onPostExecute() which runs on UI thread (That's the reason your UI had been blocking)
String type = null;
try {
type = pattern_obj.getString("sms_type");
if (type.equals("transaction")) {
String regex = pattern_obj.getString("regex");
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(bodyData);
if (matcher.find()) {
msg.add("\nSender=>" + address + "\n" + "Message=>" + body + "\n" + "Date and Time=>" + smsDate + "\n");
}
}
} catch (JSONException e) {
e.printStackTrace();
}
So it could be something like this
public class LoadData extends AsyncTask<String, Void, JSONObject> {
#Override
protected JSONObject doInBackground(String... body) {
// do your complex work
// This run on Worker Thread
return aJsonObject;
}
#Override
protected void onPostExecute(JSONObject jsonObject) {
super.onPostExecute(jsonObject);
// Doing anything with your view
// This run on UI Thread
}
}
Related
I am storing the data that I parsed from the JSON that is returned by my API request into the Firebase database.
submitButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String APIURL = "https://api.github.com/users/" + idInput.getText().toString();
String repoURL = "https://api.github.com/users/" + idInput.getText().toString() + "/repos";
new JSONTask().execute(APIURL);
//new JSONTask().execute(repoURL);
String parsedUserID = idInput.getText().toString();
SM.sendDataToProfile(parsedUserID);
viewPager.setCurrentItem(1);
//addUser(parsedUserID);
}
});
When the button is clicked, it calls a new JSONTask (asynctask) on the APIURL.
JSONTask
public class JSONTask extends AsyncTask<String, String, String> {
#Override
// Any non-UI thread process is running in this method. After completion, it sends the result to OnPostExecute
protected String doInBackground(String... params) {
HttpURLConnection connection = null;
BufferedReader reader = null;
try {
// Pass in a String and convert to URL
URL url = new URL(params[0]);
connection = (HttpURLConnection) url.openConnection();
connection.connect();
InputStream stream = connection.getInputStream();
// Reads the data line by line
reader = new BufferedReader(new InputStreamReader(stream));
StringBuffer strBuffer = new StringBuffer();
String line = "";
while ((line = reader.readLine()) != null) {
strBuffer.append(line);
}
// If we are able to get the data do below :
String retreivedJson = strBuffer.toString();
return retreivedJson;
// When we are not able to retreive the Data
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (connection != null) {
// close both connection and the reader
connection.disconnect();
}
try {
if (reader != null) {
reader.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
And it does parsing in another function.
My question is, as you can see on my setOnClickListener, I tried to make two JSONTask on two different URLs because the first URL gives me the information of the user and the second URL (repoURL) gives me the information of the user's repositories. I tried to fetch the repo info of the user and store it into the DB, but it seems like this is a wrong approach.
What is a right way to call two separate AsyncTasks on two different URLs?
EDIT
private void addUserRepo(final String githubID, final String[] repoList) {
DatabaseReference users = databaseReference.child("users");
users.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
List list = new ArrayList<String>(Arrays.asList(repoList));
databaseReference.child("users").child(githubID).child("Repos").setValue(list);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
Using data parsed from
public void formatJSONArray(String results){
try {
JSONArray jsonArray = new JSONArray(results);
RepoInfo[] repoList = new RepoInfo[jsonArray.length()];
for(int i = 0; i < jsonArray.length(); i++){
JSONObject jsonObject=jsonArray.getJSONObject(i);
if(jsonObject.optString("name") != null) {
repoList[i].setRepoName(jsonObject.getString("name"));
//repoNameList.add(jsonObject.getString("name"));
}
if(jsonObject.optString("description") != null) {
repoList[i].setDescription(jsonObject.getString("description"));
//descriptionList.add(jsonObject.getString("description"));
}
if(jsonObject.optJSONObject("owner") != null){
JSONObject ownerObject=jsonObject.getJSONObject("owner");
if(ownerObject.optString("login")!=null) {
repoList[i].setOwner(ownerObject.getString("login"));
//userNameList.add(ownerObject.getString("login"));
}
}
}
} catch (JSONException jsonException){
}
}
The response of two different URLs will surely not be similar. So you need different parse methods for them.
One lazy way would be to use two different AsyncTasks subclasses for two different urls.
Another way would be to store a flag inside the asynctask indicating whether it is dealing with user or repo.
public class JSONTask extends AsyncTask <String , String , String> {
boolean fetchingRepo;
#Override
protected String doInBackground (String... params) {
fetchingRepo = params[0].endsWith("/repos");
//other statements
}
Now inside onPostExecute:
if(fetchingRepo){
//parse one way
} else {
//parse another way
}
I am loading some json into a list view and want to delete items from the list on click and for the item to be deleted from the json. The delete functionality seems to be working. The method delete is called, the items are removed on click and debugging shows the item being removed. However after going to another activity and viewing the list again, the deleted items come back. what am i doing wrong? This is my class:
public class edit extends AppCompatActivity
{
public ListView pizzaList;
ListView addicList;
ArrayAdapter<String> arrayAdapter;
String appreciations;
String currentPizza;
ArrayList<String> list = new ArrayList<String>();
private String name;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.edit_activity);
pizzaList = (ListView) findViewById(R.id.pizzas);
registerForContextMenu(pizzaList);
arrayAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, list);
pizzaList.setAdapter(arrayAdapter);
pizzaList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
delete(view,position);
arrayAdapter.notifyDataSetChanged();
}
});
try {
FileManager fileManager = new FileManager();
String str = fileManager.ReadFile(this);
if (str != null) {
JSONArray jarray = new JSONArray(str);
String outputText = "";
for (int i = 0; i < jarray.length(); i++) {
JSONObject jsonObject = jarray.getJSONObject(i);
String pizzaName = jsonObject.getString("name");
int price = jsonObject.getInt("price");
outputText = outputText + " " + pizzaName + " " + " $" + price + "\n";
appreciations = outputText;
list.add(appreciations);
arrayAdapter.notifyDataSetChanged();
outputText = "";
}
} else {
Toast to = Toast.makeText(getApplicationContext(), "No saved Pizzas", Toast.LENGTH_LONG);
to.show();
}
} catch (JSONException e) {
e.printStackTrace();
}
}
public void delete(View view, int pos)
{
try {
FileManager fileManager = new FileManager();
String str = fileManager.ReadFile(this);
if (str != null)
{
JSONArray jarray = new JSONArray(str);
JSONObject jsonObject = jarray.getJSONObject(pos);
jarray.remove(pos);
list.remove(pos);
arrayAdapter.notifyDataSetChanged();
JSONArray jsArray = new JSONArray(jarray);
arrayAdapter.notifyDataSetChanged();
} else {
Toast to = Toast.makeText(getApplicationContext(), "No saved Pizzas", Toast.LENGTH_LONG);
to.show();
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}
You would need to remove the item from the database, use asynchronous request such as volley or robospice for it. Then instead of making the request when coming back you would use the data stored on the cache the second time and only make the request again when data has been changed. You can create your cache logic in your application class to make it visible throughout your app.
First and foremost, I am an android newbie.
I am creating a simple app which pulls some data from the server through a PHP script and showing them in a ListView in the next Activity. However, I find that if the script returns nothing, the app crashes. So I kept a check that only if the script returns some data, the app would switch to the next activity.This is my code.
public class HomeScreen extends ActionBarActivity {
String message3;
String message_short;
String[] items;
String[] short_items;
int check = 0;
private ProgressDialog dialog;
public String readJSONFeed(String URL)
{
StringBuilder sb = new StringBuilder();
HttpClient client = new DefaultHttpClient();
HttpGet hg = new HttpGet(URL);
try
{
HttpResponse response = client.execute(hg);
StatusLine statusLine = response.getStatusLine();
int statusCode = statusLine.getStatusCode();
if(statusCode == 200)
{
HttpEntity en = response.getEntity();
InputStream content = en.getContent();
BufferedReader reader = new BufferedReader(new InputStreamReader(content));
String line;
while((line = reader.readLine()) != null)
{
sb.append(line);
}
}
else
{
Log.e("JSON", "Failed to download File");
}
}
catch(ClientProtocolException e)
{
e.printStackTrace();
}
catch(IOException e)
{
e.printStackTrace();
}
return sb.toString();
}
private class ReadJSONFeedTask extends AsyncTask<String, Void, String>
{
protected void onPreExecute()
{
super.onPreExecute();
dialog = new ProgressDialog(HomeScreen.this);
dialog.setMessage("Downloading Notifications. Please wait . . .");
dialog.setIndeterminate(false);
dialog.setCancelable(false);
dialog.show();
}
protected String doInBackground(String...urls)
{
return readJSONFeed(urls[0]);
}
protected void onPostExecute(String result)
{
dialog.dismiss();
try
{
JSONArray jsonArray = new JSONArray(result);
items = new String[jsonArray.length()];
short_items = new String[jsonArray.length()];
for(int i = 0; i < jsonArray.length(); i++)
{
JSONObject jobj = jsonArray.getJSONObject(i);
message3 = "SUBJECT : " + jobj.getString("subject") + "\n\n" +
"DATE : " + jobj.getString("date") + "\n" + jobj.getString("time") + "\n\n"
+ "NOTICE : " + jobj.getString("notice");
message_short = "SUBJECT : " + jobj.getString("subject") + "\n"
+ "NOTICE : " + jobj.getString("notice").substring(0, 20) + "..."
+ "\n" + jobj.getString("time");
items[i] = message3;
short_items[i] = message_short;
check += 1;
}
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home_screen);
}
public void notificationPane(View view)
{
String localhost = "http://10.0.2.2/example/json/notification.php";
new ReadJSONFeedTask().execute(localhost);
if(check != 0)
{
Intent i = new Intent(HomeScreen.this, NotificationPanel.class);
i.putExtra("items", items);
i.putExtra("short_items", short_items);
startActivity(i);
}
else
{
Toast.makeText(getBaseContext(), "Either there is no notification to display or there might be a problem with your internet connection.", Toast.LENGTH_SHORT).show();
}
}
public void recentNotice(View view)
{
String localhost = "http://10.0.2.2/example/json/recent_notification.php";
new ReadJSONFeedTask().execute(localhost);
if(check != 0)
{
Intent i = new Intent(HomeScreen.this, NotificationPanel.class);
i.putExtra("items", items);
i.putExtra("short_items", short_items);
startActivity(i);
}
else
{
Toast.makeText(getBaseContext(), "Either there is no notification to display or there might be a problem with your internet connection.", Toast.LENGTH_SHORT).show();
}
}
}
The int check is where I check whether the server has returned any JSON data. If the check is not 0, it does not switch to the next activity.But problem with this code is that when I click the button, it shows me the TOAST Either there is no notification to display or there might be a problem with your internet connection. even before it has pulled data from the server, thus it never goes to the next Activity NotificationPanel.class. I understand this is due to the AsyncTask. What is more weird is if I keep clicking the button several times, the app suddenly switches to the next activity showing the data in ListView. But it doesn't always work. Is there a work around to this problem?Please help.Thank you in advance.
Move your code with if else to the last in onPostExecute. AsyncTask is still in execution when you check the result.
You should put this piece of code in the onPostExecute method:
if(check != 0)
{
Intent i = new Intent(HomeScreen.this, NotificationPanel.class);
i.putExtra("items", items);
i.putExtra("short_items", short_items);
startActivity(i);
}
else
{
Toast.makeText(getBaseContext(), "Either there is no notification to display or there might be a problem with your internet connection.", Toast.LENGTH_SHORT).show();
}
Put them after your current code and tell me if it worked.
"What is more weird is if I keep clicking the button several times, the app suddenly switches to the next activity showing the data in ListView. But it doesn't always work. Is there a work around to this problem?"
What you are saying here is prety clear. You cannot run your intent at first, because json is not yet fetched, when you click the button first few times. But if you continue clicking it, it will eventually fetch JSON and be able to go to next activity.
SO I'm prety sure what I said is what needs to be done.
EDIT
I'm prety sure your async task should looklike this:
private class ReadJSONFeedTask extends AsyncTask<Void, Void, Void>
{
#Override
protected void onPreExecute()
{
super.onPreExecute();
dialog = new ProgressDialog(HomeScreen.this);
dialog.setMessage("Downloading Notifications. Please wait . . .");
dialog.setIndeterminate(false);
dialog.setCancelable(false);
dialog.show();
}
//no need a return statment
#Override
protected Void doInBackground(Void... params)
{
try
{
JSONArray jsonArray = new JSONArray(readJSONFeed(urls[0]));
items = new String[jsonArray.length()];
short_items = new String[jsonArray.length()];
for(int i = 0; i < jsonArray.length(); i++)
{
JSONObject jobj = jsonArray.getJSONObject(i);
message3 = "SUBJECT : " + jobj.getString("subject") + "\n\n" +
"DATE : " + jobj.getString("date") + "\n" + jobj.getString("time") + "\n\n"
+ "NOTICE : " + jobj.getString("notice");
message_short = "SUBJECT : " + jobj.getString("subject") + "\n"
+ "NOTICE : " + jobj.getString("notice").substring(0, 20) + "..."
+ "\n" + jobj.getString("time");
items[i] = message3;
short_items[i] = message_short;
check += 1;
}
}
catch(Exception e)
{
e.printStackTrace();
}
}
#Override
protected void onPostExecute(String result)
{
if(check != 0)
{
Intent i = new Intent(HomeScreen.this, NotificationPanel.class);
i.putExtra("items", items);
i.putExtra("short_items", short_items);
startActivity(i);
}
else
{
Toast.makeText(getBaseContext(), "Either there is no notification to display or there might be a problem with your internet connection.", Toast.LENGTH_SHORT).show();
}
dialog.dismiss();
}
}
Hello every one i am working on app which is similar to the facebook.In that currently i am stuck in one point like we have posts in facebook which shows on our wall in that all the post is shows in bulk like 20 20 fashion that same thing i want to apply in my app. For that thing i use listview which get value form server and create view according to that i also get all value but the problem is that when i add 1st 20 value then it work fine but when i add another 20 value it will delete the previous data in listview.
any idea how i can do this thing in my app and thanks in advance....
my function get value from the server
private void getPostnew(String start) {
String URL = start;
System.out.println("start value new :" + start);
final String usernamefor = "";
aq = new AQuery(getParent());
listitem = new ArrayList<BeanTop>();
aq.ajax(URL, JSONObject.class, 10 * 1000,
new AjaxCallback<JSONObject>() {
#Override
public void callback(String url, JSONObject json1,
AjaxStatus status) {
System.out.println("json " + json1);
if (json1 == null) {
} else {
try {
JSONArray jarray = json1
.getJSONArray("subject");
for (int j = 0; j < jarray.length(); j++) {
try {
JSONObject j1 = jarray.getJSONObject(j);
try {
listcount = j1
.getString("likecount");
} catch (Exception e) {
listcount = "0";
}
AddObject(j1.getString("text"),
j1.getString("leftpic"),
j1.getString("rightpic"),
j1.getString("rightvotecount"),
j1.getString("leftvotecount"),
j1.getString("textleft"),
j1.getString("textright"),
j1.getString("date_created"),
j1.getString("voteid"),
j1.getString("user"),
j1.getString("dom"),
j1.getString("Isvoted"),
j1.getString("Islike"),
j1.getString("profilepic"),
listcount,
j1.getString("commentcount"));
} catch (Exception e) {
e.printStackTrace();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
FriendlistAdapter ad = new FriendlistAdapter(Top.this,
listitem);
subjectlist.setAdapter(ad);
ad.notifyDataSetChanged();
}
});
}
method for save the data in bean class
private void AddObject(String string1, String string2, String string3,
String string5, String string6, String string7, String string8,
String string9, String string10, String string11,
String usernamefor, String isvoted, String isliked,
String profilepic, String likecount, String commentcount) {
BeanTop ib = new BeanTop();
Date date = null;
try {
System.out.println("date " + string9);
date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(string9);
} catch (Exception e) {
e.printStackTrace();
}
ib.setText(string1);
ib.setLeftpic(string2);
ib.setRightpic(string3);
ib.setRightVote(string5);
ib.setLeftVote(string6);
ib.setLefttext(string7);
ib.setRighttext(string8);
ib.setDate(string9);
ib.setDate1(date);
ib.setVoteid(string10);
ib.setUsername(string11);
ib.setDom(usernamefor);
ib.setIsvoted(isvoted);
ib.setIsliked(isliked);
ib.setProfilepic(profilepic);
ib.setLikecount(likecount);
ib.setCommentcount(commentcount);
List<BeanTop> bookingList = new ArrayList<BeanTop>();
bookingList.addAll(listitem);
Collections.sort(bookingList, new Comparator<BeanTop>() {
public int compare(BeanTop m1, BeanTop m2) {
return m1.getDate().compareTo(m2.getDate());
}
});
Collections.reverse(bookingList);
try {
listitem.clear();
} catch (Exception e) {
e.printStackTrace();
}
listitem.addAll(bookingList);
try {
bookingList.clear();
} catch (Exception e) {
e.printStackTrace();
}
listitem.add(ib);
}
Cant say without seeing your code, but I can show you general way of doing this...
First you should maintain a list, say at class level like...
List<MyPost> posts = ArrayList<MyPost>();
Then you can create you adapter by passing 'posts' list in it.
And just call '.addAll(xxx)' to you 'posts' list everytime you get items from server like,
posts.addAll(newItems);
and right after that, call yourAdapter.notifyDatasetChanged(); so that list can redraw/update its views...
And in you code...use,
if (listitem == null) {
listitem = new ArrayList<BeanTop>();
}
in you getPostnew() instead of only listitem = new ArrayList<BeanTop>();.
Hope this helps...
You are re-initializing listitem = new ArrayList<BeanTop>(); eveytime the getPostnew methood is called. This is why your old posts are lost. Try change that line to:
if (listitem == null) {
listitem = new ArrayList<BeanTop>();
}
you should use a global variable to store the data which you get from server ,in your method
getPostnew(String start) every time you execute it ,the listitem will be recreated;so the last data will be lost.
The only thing that's guaranteed to always be there is the messagesByDate obj.
The array and objects named such as "15 MAY 2012" are generated by a server(no control) based on rather or not messages are present for that date.
If u notice the first date represented is an array while the other dates are objects containing other objects that have been numbered.
QUESTION 1: how do i parse this without knowing what dates will be present?
QUESTION 2: Some messages are in an array instead of an object. how do I put them all together in one ArrayList. Rather its in an array or not because the array will not always been there.
Please any help would be appreciated as I'm down to my last hair
Thanks.
{
"messagesByDate":{
"15 May 2012":[
{
"id":"1383483367",
"conversation_id":"274618561",
"user_id":"4318264",
"message":"ok will do",
"date_sent":"1337133515",
"date_sent_ago":"7 mins ago"
},
{
"id":"1380222533",
"conversation_id":"274618561",
"user_id":"5159567",
"message":"ok well hmu",
"date_sent":"1337085122",
"date_sent_ago":"13 hrs ago"
},
{
"id":"1380172978",
"conversation_id":"274618561",
"user_id":"5159567",
"message":"superhead",
"date_sent":"1337083910",
"date_sent_ago":"13 hrs ago"
},
{
"id":"1380130860",
"conversation_id":"274618561",
"user_id":"5159567",
"message":"you ready B",
"date_sent":"1337082797",
"date_sent_ago":"14 hrs ago"
},
{
"id":"1378841432",
"conversation_id":"274618561",
"user_id":"5159567",
"message":"hit my cell tho",
"date_sent":"1337054524",
"date_sent_ago":"22 hrs ago"
},
{
"id":"1378836763",
"conversation_id":"274618561",
"user_id":"5159567",
"message":"whats up baby",
"date_sent":"1337054475",
"date_sent_ago":"22 hrs ago"
}
],
"12 May 2012":{
"6":{
"id":"1362948558",
"conversation_id":"274618561",
"user_id":"4318264",
"message":"ok ima text u",
"date_sent":"1336819668",
"date_sent_ago":"3 days ago"
}
},
"11 May 2012":{
"7":{
"id":"1361356267",
"conversation_id":"274618561",
"user_id":"5159567",
"message":"yea thats cool",
"date_sent":"1336790738",
"date_sent_ago":"3 days ago"
},
"8":{
"id":"1357783913",
"conversation_id":"274618561",
"user_id":"5159567",
"message":"sorry im here. would u like to exchange numebers instead?",
"date_sent":"1336722533",
"date_sent_ago":"4 days ago"
},
"9":{
"id":"1357759262",
"conversation_id":"274618561",
"user_id":"5159567",
"message":"hello?",
"date_sent":"1336721851",
"date_sent_ago":"4 days ago"
}
}
}
}
THE ANSWER SORTA-KINDA
JSONObject dateHolder = r.getJSONObject("messagesByDate");
Iterator holderItr = dateHolder.keys();
while(holderItr.hasNext()){
String thisdate = holderItr.next().toString();
Object date = dateHolder.get(thisdate);
if (date instanceof JSONArray) {
System.out.println(thisdate+" is an ARRAY.");
JSONArray jarray = (JSONArray) date;
for(int x=0;x<jarray.length();x++){
String msgId = jarray.getJSONObject(x).getString("id");
String msgConvoId = jarray.getJSONObject(x).getString("conversation_id");
String msgUserId = jarray.getJSONObject(x).getString("user_id");
String msgBody = jarray.getJSONObject(x).getString("message");
String msgDateSent = jarray.getJSONObject(x).getString("date_sent");
String msgDateSentAgo = jarray.getJSONObject(x).getString("date_sent_ago");
HashMap<String,String> temp = new HashMap<String,String>();
temp.put("msgId",msgId);
temp.put("msgUserId", msgUserId);
temp.put("msgBody", msgBody);
temp.put("msgDateSent", msgDateSent);
temp.put("msgDateSentAgo", msgDateSentAgo);
messages.add(temp);
}
} else {
System.out.println(thisdate+" is an OBJECT.");
JSONObject jobj = (JSONObject) date;
Iterator insideDate = jobj.keys();
while(insideDate.hasNext()){
String number = insideDate.next().toString();
System.out.println(number);
String msgId = jobj.getJSONObject(number).getString("id");
String msgConvoId = jobj.getJSONObject(number).getString("conversation_id");
String msgUserId =jobj.getJSONObject(number).getString("user_id");
String msgBody = jobj.getJSONObject(number).getString("message");
String msgDateSent = jobj.getJSONObject(number).getString("date_sent");
String msgDateSentAgo = jobj.getJSONObject(number).getString("date_sent_ago");
HashMap<String,String> temp = new HashMap<String,String>();
temp.put("msgId",msgId);
temp.put("msgUserId", msgUserId);
temp.put("msgBody", msgBody);
temp.put("msgDateSent", msgDateSent);
temp.put("msgDateSentAgo", msgDateSentAgo);
messages.add(temp);
}
}
}
This gives me all the messages in a HashMap and adds it to an ArrayList called messages like I want but its out of order by date. the json is listed by date...anyone know if there is a way to direct json reading? OR are my WHILE and FOR loops out of order? can i sort hashmaps by a key? I'll google that...
First create a class like this:
import java.util.LinkedList;
import android.util.Log;
public class Message{
private LinkedList<String> id = new LinkedList<String>();
private LinkedList<String> conversation_id = new LinkedList<String>();
private LinkedList<String> user_id = new LinkedList<String>();
private LinkedList<String> message = new LinkedList<String>();
private LinkedList<String> date_sent = new LinkedList<String>();
private LinkedList<String> date_sent_ago = new LinkedList<String>();
public LinkedList<String> getId() {
return id;
}
public void setId(String id) {
this.id.add(id);
}
.
.
.
// For checking response after you get info from server
public void printContent() {
for(String str : id)
Log.i("Id>>>", str);
.
.
.
}
}
Then you need to call server in onCreate() add this code:
if(Manager.isOnline(this)) // Check Internet connection and if you find it then
new MyAsyncTask().execute();
Now, you should add this class:
public class MyAsyncTask extends AsyncTask<Void, Void, Boolean> {
#Override
protected void onPreExecute() {
Log.i(TAG, "MyAsyncTask is about to start...");
showProgressBar();
}
#Override
protected Boolean doInBackground(Void... params) {
boolean status = false;
// Get News items in json format
msg = getMessageItems(); // msg is an instance of Message class define it as global variable.
msg.printContent(); // Check result in logcat
if(msg != null)
status = true;
return status;
}
#Override
protected void onPostExecute(Boolean result) {
Log.i(TAG, "MyAsyncTask finished its task. Data returned to caller.");
if(result)
displayData();
hideProgressBar();
}
}
Here we will connect to server, get Json data and parse it.
private Menu getMenuItems() {
Message mMessage = new Message ();
String response = null;
String connection = **YOUR_URL**;
try {
URL url = new URL(connection);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
int responseCode = conn.getResponseCode();
Log.i(TAG, "Try to open: " + connection);
Log.i(TAG, "Response code is: " + responseCode);
if (responseCode == HttpURLConnection.HTTP_OK) {
BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
if (in != null) {
StringBuilder strBuilder = new StringBuilder();
// Read character by character
int ch = 0;
while ((ch = in.read()) != -1)
strBuilder.append((char) ch);
// get returned message and show it
response = strBuilder.toString();
Log.i("JSON returned by server:", response);
JSONObject jObject = new JSONObject(response);
JSONArray contestantObjects = jObject.getJSONArray("**messagesByDate**");
for(int i=0; i<contestantObjects.length(); i++){
mMessage .setId(contestantObjects.getJSONObject(i).getString("id").toString());
// Repeat this to get all of other items
}
}
in.close();
} else
Log.e(TAG, "Couldn't open connection in getMenuItems()");
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
return mMessage;
}
Now you have an object that each of its item is a list. You can do whatever you want in display method. you can pass it as an object to adapter to show its data.
private void displayData() {
messageAdapter.setData(msg);
listView.setAdapter(messageAdapter);
}
JSONObject json = service.getJunk();
JSONObject msgJson = json.getJSONObject("messagesByDate");
for( Iterator it = msgJson.keys(); it.hasNext(); ) {
Object obj = msgJson.get( (String)it.next() );
if( obj instanceof JSONObject ) {
JSONObject jobj = (JSONObject)obj;
// process json object
} else {
JSONArray arry = (JSONArray)obj;
// process array
}
}