thread exiting error in android - android

Please help with this error .... In the following code the get info function works correctly but it gives an error saying the thread caught an exception at exiting.... I am trying to use a tab host and the first tab page is the following... In this i show a progress dialog until i get my data and then show it in a list view
public class History extends Activity implements OnItemClickListener
{
/** Called when the activity is first created. */
ListView list;
//LIST OF ARRAY STRINGS WHICH WILL SERVE AS LIST ITEMS
ArrayList<String> listItems;
//DEFINING STRING ADAPTER WHICH WILL HANDLE DATA OF LISTVIEW
ArrayAdapter<String> adapter;
private String resDriver,resPassenger,ID;
private ProgressDialog dialog;
ArrayList<HashMap<String, Object>> listInfo = new ArrayList<HashMap<String, Object>>();
HashMap<String, Object> item;
JSONObject jDriver;
//JSONObject jPassenger;
// Make strings for logging
private final String TAG = this.getClass().getSimpleName();
private final String RESTORE = ", can restore state";
private final String state = "Home Screen taking care of all the tabs";
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
Intent loginIntent = getIntent();
ID = loginIntent.getStringExtra("ID");
listItems = new ArrayList<String>();
Log.i(TAG, "Started view active rides");
setContentView(R.layout.searchresults);
list = (ListView)findViewById(R.id.ListView01);
list.setOnItemClickListener(this);
adapter=new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1,listItems);
list.setAdapter(adapter);
getInfo();
}
The function getInfo is used to start a thread which shows a dialog box and starts a http request to get some data ...
public void getInfo(){
GetInfoThread checkUpdate = new GetInfoThread();
checkUpdate.start();
dialog = ProgressDialog.show(History.this, "Retrieving Info","Please Wait ...", true);
}
private class GetInfoThread extends Thread
{
public void run() {
jDriver = new JSONObject();
try {
jDriver.put("ID", ID);
jDriver.put("task", "GET DATES");
} catch (JSONException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
listItems = new ArrayList<String>();
Log.i(TAG,"Sending data for the driver rides");
resDriver = HTTPPoster.sendJson(jDriver,"http://dsadsada"); // Any Server URL
JSONObject driver;
try {
driver = new JSONObject(resDriver);
Log.i(TAG,"Recieved Driver details");
listItems.add(array[0]);
handler.sendEmptyMessage(0);
}
}
} catch (JSONException e) {
// TODO Auto-generated catch block
listItems.add("No driver rides created");
handler.sendEmptyMessage(0);
}
}
private Handler handler = new Handler() {
#Override
public void handleMessage(Message msg) {
dialog.dismiss();
Log.i(TAG,"hello 123");
adapter.notifyDataSetChanged();
}
};
}

I am not sure exactly what is causing your error but I suspect it has to do with UI changes not running on the actual UI thread. In Android there is a class called AsyncTask that will do the threading for you and handle the passing of data between the background thread an the UI thread. I would suggest rewriting your code to utilize the AsyncTask class.

Related

How to use listview from different xml layout file

I am working on android ListView and i am getting one issue.I created one list view into the XML file installation.xml and i want to use that list view into my Searchdata.java. so basically what i want that when i click on searchdata button than data is fetched from web service and after parsing, it will saved into the listview.and when i click on Installation View button than new window will be appear where i could see that list data.
SearchData.java
public class SearchData extends Activity {
EditText Keyword;
JSONParser jsonparser = new JSONParser();
ListView Datalist;
HorizontalScrollView VideoDatalist;
ArrayList<HashMap<String, String>> DataList;
ArrayList<HashMap<String, String>> VideoDataList;
JSONArray contacts = null;
private ProgressDialog pDialog;
ImageButton searchdata,InstallationView;
String Keyvalue = new String();
private static final String TAG_InnerText = "InnerText";
private static final String TAG_Title = "Title";
private static final String TAG_URL = "URL";
private static final String TAG_VIDEO_URL = "URL";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_search_data);
InstallationView=(ImageButton)findViewById(R.id.InstallationView);
Keyword = (EditText) findViewById(R.id.KeyData);
Datalist=(ListView)findViewById(R.layout.activity_installation);
VideoDatalist=(HorizontalScrollView)findViewById(R.id.Horizontallist);
searchdata=(ImageButton)findViewById(R.id.searchicon);
String Keyvalue = new String();
DataList = new ArrayList<HashMap<String, String>>();
VideoDataList = new ArrayList<HashMap<String, String>>();
searchdata.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
new ReadData().execute();
}
});
InstallationView.setOnClickListener(new View.OnClickListener(){
public void onClick(View v)
{
startActivity(new Intent(SearchData.this, Installation.class));
}
});
}
public class ReadData extends AsyncTask<Void, Void, Void>
{
#Override
protected void onPreExecute() {
super.onPreExecute();
pDialog = new ProgressDialog(SearchData.this);
pDialog.setMessage("Please wait...");
pDialog.setCancelable(false);
pDialog.show();
}
protected Void doInBackground(Void... arg0) {
try{
Keyvalue=Keyword.getText().toString();
String Jsonstr = jsonparser.makeHttpRequest("http://10.47.93.26:8080/Search/api/Search/"+Keyvalue);
try {
if (Jsonstr != null) {
JSONArray jsonObj = new JSONArray (Jsonstr);
for (int i = 0; i < jsonObj.length(); i++) {
JSONObject c = jsonObj.getJSONObject(i);
String name = c.optString(TAG_Title);
String url = c.optString(TAG_URL);
HashMap<String, String> info = new HashMap<String, String>();
if( !name.isEmpty() )
{
info.put(TAG_Title, name);
}
else
{
info.put(TAG_Title,"User Manual");
}
if(url.contains("youtube"))
{
info.put(TAG_URL, url);
VideoDataList.add(info);
}
else
{
info.put(TAG_URL, url);
DataList.add(info);
}
}
}
else {
Log.e("ServiceHandler", "Couldn't get any data from the url");
}
}
catch (JSONException e) {
e.printStackTrace();
}
}
catch(Exception ex)
{
ex.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
if (pDialog.isShowing())
pDialog.dismiss();
SimpleAdapter adapter = new SimpleAdapter(
SearchData.this, DataList,
R.layout.list_item, new String[]
{
TAG_Title
}, new int[] {
R.id.InnerText });
Datalist.setAdapter(adapter);
}
}
}
web service running and parsing code is running correctly. i am getting error at post method,so can you help me on this.
Error
Call your Installation activity in onClick() method:
And pass your ArrayList data through intent,
InstallationView.setOnClickListener(new View.OnClickListener(){
public void onClick(View v)
{
Intent intent= new Intent(SearchData.this, Installation.class);
intent.putParcelableArrayListExtra("HASH_MAP",DataList);
startActivity(intent);
}
});
In your Installation activity class,set the view in onCreate() and initialize listview from xml file:
setContentView(R.layout.activity_installation);
ListView listView = (ListView)findViwById(R.id.listview);
And try to get the data from intent:
ArrayList<HashMap<String,String>> hashmap_dataList = getIntent.getParcelableArrayListExtra("HASH_MAP");
then do whatever you want with listview and hashmap.
In the onCreate(...) method of your SearchData Activity, the following can never work and will always return 'null' (hence your NullPointerException)...
Datalist=(ListView)findViewById(R.layout.activity_installation);
Calling findViewById(...) will only work for any UI elements which have been inflated when you called setContentView(...). In this case you used R.layout.activity_search_data for your layout file which doesn't contain a ListView with an id of R.layout.activity_installation which is, by the way, a resource id of a layout file and not a resource id of a UI element.
The only way you can do what you need is to put your data as an extra into the Intent you use when you call...
startActivity(new Intent(SearchData.this, Installation.class));
...when the Installation Activity is created it will then need to get the data and create its own adapter.
EDIT: HashMap is Serializable and can be passed as an Intent extra. Pass your DataList HashMap as follows...
Intent i = new Intent(SearchData.this, Installation.class);
i.putExtra("data_list", DataList);
startActivity(i);
In the Installation Activity you can then use...
getIntent().getSerializableExtra("data_list");

Async Task in android not working

This is a follow up question from my question thread exiting error in android
I created an async task but the values do not show up in the list view....
public class History extends Activity implements OnItemClickListener
{
/** Called when the activity is first created. */
ListView list;
//LIST OF ARRAY STRINGS WHICH WILL SERVE AS LIST ITEMS
ArrayList<String> listItems;
//DEFINING STRING ADAPTER WHICH WILL HANDLE DATA OF LISTVIEW
ArrayAdapter<String> adapter;
private String resDriver,resPassenger,ID;
private ProgressDialog dialog;
ArrayList<HashMap<String, Object>> listInfo = new ArrayList<HashMap<String, Object>>();
HashMap<String, Object> item;
JSONObject jDriver;
//JSONObject jPassenger;
// Make strings for logging
private final String TAG = this.getClass().getSimpleName();
private final String RESTORE = ", can restore state";
private final String state = "Home Screen taking care of all the tabs";
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
Intent loginIntent = getIntent();
ID = loginIntent.getStringExtra("ID");
listItems = new ArrayList<String>();
Log.i(TAG, "Started view active rides");
setContentView(R.layout.searchresults);
list = (ListView)findViewById(R.id.ListView01);
list.setOnItemClickListener(this);
adapter=new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1,listItems);
list.setAdapter(adapter);
getInfo();
}
#Override
public void onItemClick(AdapterView<?> arg0, View v, int position, long arg3)
{
// TODO Auto-generated method stub
Toast.makeText(this, "u clicked " + listItems.get(position) ,Toast.LENGTH_LONG).show();
}
public void getInfo(){
DownloadInfo task = new DownloadInfo();
task.execute(new String[] { "http://www.vogella.de" });
}
private class DownloadInfo extends AsyncTask<String, Void , ArrayList<String>>{
#Override
protected ArrayList<String> doInBackground(String ... strings) {
ArrayList<String> listItems1;
jDriver = new JSONObject();
try {
jDriver.put("ID", ID);
jDriver.put("task", "GET DATES");
} catch (JSONException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
listItems1 = new ArrayList<String>();
Log.i(TAG,"Sending data for the driver rides");
resDriver = HTTPPoster.sendJson(jDriver,"URL"); // Any Server URL
JSONObject driver;
try {
driver = new JSONObject(resDriver);
Log.i(TAG,"Recieved Driver details");
if ( driver.getString("DATABASE ERROR").equals("False")){
int length = Integer.parseInt( driver.getString("length"));
Log.i(TAG,"length is " + length);
for( int i =0 ; i< length ; i++){
String info = driver.getString(Integer.toString(i));
String[] array = info.split(",");
Log.i(TAG,"array is " + Arrays.toString(array));
Log.i(TAG,"Date "+ array.length);
Log.i(TAG,"DONE WITH THE LOOP");
//listInfo.add(item);
Log.i(TAG,"Date is"+array[0]);
listItems1.add(array[0]);
}
}
} catch (JSONException e) {
// TODO Auto-generated catch block
listItems1.add("No driver rides created");
}
return listItems1;
}
#Override
protected void onPostExecute(ArrayList<String> result) {
listItems = result;
adapter.notifyDataSetChanged();
}
}
}
The problem is that the values in the adapter do not get modified...
You initialize your adapter with a empty listItems, after your fill your listItems in AsyncTask. onPostExecute(), your adapter is not get updated, try this:
protected void onPostExecute(ArrayList<String> result) {
listItems = result;
adapter.addAll(ListItems);
adapter.notifyDataSetChanged();
}
Hope that help.
listItems = result; won't work, you need to use :
listItems.clear();
listItems.addAll(result);
If you create another list, your adapter won't know it, because it keeps a reference to the old list (which remains the same).

Android progressdialog thread exception

My app uses the CallLog to collect data and put it into a listview. As this takes time, I tried to use progressdialog to show the user the status of the loading. Unfortunately (I have used progressdialog before) eclipse throws me an error: ERROR/AndroidRuntime(771): android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
public class Calls extends Activity {
//declaring variables
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.calls);
lv1 = (ListView) findViewById(R.id.ListView01);
pd = new ProgressDialog(Calls.this);
pd.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
pd.setMessage("Loading contacts");
pd.show();
//Thread thread = new Thread() {
//public void run() {
Calls.this.runOnUiThread(new Runnable() {
#Override
public void run() {
//collecting data from CallLog, putting data into an array
//Here comes the hard part, which is the root of the problem:
final ArrayList<SearchResults> results = new ArrayList<SearchResults>();
SearchResults sr1 = new SearchResults();
for (int b=0; b<storage.length; b++)
{
for (int e=0; e<storage[b].length; e++)
{
if (e+3 < storage[b].length)
{
arr_split_all.add(storage[b][e] + " " + storage[b][e+1] + " " + storage[b][e+2] + " " + storage[b][e+3]);
sr1 = new SearchResults();
sr1.setData1(storage[b][e+2]);
sr1.setData2(storage[b][e]);
sr1.setData3(storage[b][e+1]);
sr1.setData4(storage[b][e+3]);
sr1.setBitmap2(bitmaparray[b]); //bitmaparray has the same size as storage, and there is no problem with this
results.add(sr1);
}
}
}
lv1.setAdapter(new MyCustomBaseAdapter(Calls.this, results)); //problematic row
handler.sendEmptyMessage(0);
}
};
thread.start();
}
}//end of onCreate
private Handler handler = new Handler() {
#Override
public void handleMessage(Message msg) {
pd.dismiss();
}
}); //ADDED a )
}//end of class
// SearchResults is another class:
public class SearchResults extends Application{
private String data1 = "";
private String data2 = "";
private String data3 = "";
private String data4 = "";
private String bitmap = "";
private Bitmap bitmap2;
public void setData1(String data1) {
this.data1 = data1;
}
public String getData1() {
return data1;
}
//etc...
}
And I am using a BaseAdapter class to put the data into the appropriate places of the listview (which consists of an imageview and four textviews), but I don't think that is relevant now.
According to Logcat, the problem is with the lv1.setAdapter(new MyCustomBaseAdapter(Calls.this, results)); row. If I attach an arraylist to the listview, it is working fine. Without the progressdialog all textviews and the imageview of each row of the listview is loaded properly.
The problem is your findViewById() call to your ListView01 (and later on, the setAdapter() call). You cannot modify (or access) views from a custom thread. This has to be done on the UI thread, either via runOnUiThread() or in a place where the UI thread runs.

Handler will not bind to main thread

So my code seems to run just fine until it hits this line
adapter.notifyDataSetChanged();
The error that pops up in the logcat is CalledFromWrongThreadException. The debug also shows the handler being run in the Background thread. How do I get the handler to bind to the main thread, and not the background one? I thought I just had to create the handler in the main thread, but I guess I am wrong, quite possible I am new to andriod. How do I fix this?
//Imports are included
public class DirectoryActivity extends ListActivity {
private ProgressDialog ProgressDialog = null;
private ArrayList<DirectoryListing> listing = null;
private DirectoryAdapter adapter;
private Runnable viewOrders;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.directory);
final Handler handler = new Handler() {
#Override
public void handleMessage(Message msg) {
if (listing != null && listing.size() > 0) {
adapter.notifyDataSetChanged();
for (int i = 0; i < listing.size(); i++)
adapter.add(listing.get(i));
Log.e("log_tag", "\nStill running\n");
}
ProgressDialog.dismiss();
adapter.notifyDataSetChanged();
}
};
listing = new ArrayList<DirectoryListing>();
adapter = new DirectoryAdapter(this, R.layout.rows, listing);
setListAdapter(adapter);
ProgressDialog = ProgressDialog.show(DirectoryActivity.this, "Please wait...", "Retrieving data ...", true);
viewOrders = new Runnable() {
#Override
public void run() {
listing = PreparePage.getArrayList();
handler.handleMessage(null);
}
};
Thread thread = new Thread(null, viewOrders, "Background");
thread.start();
}
private static class PreparePage {
protected static ArrayList<DirectoryListing> getArrayList() {
ArrayList<DirectoryListing> listings = new ArrayList<DirectoryListing>();
JSONObject information = GetPageData.getJSONFromURL(url);
Iterator key = information.keys();
while (key.hasNext()) {
String id = (String) key.next();
JSONObject info = null;
try {
info = information.getJSONObject(id);
} catch (JSONException e) {
e.printStackTrace();
}
String name = "", title = "", photo = "";
try {
name = info.get("firstName") + " " + info.get("lastName");
title = info.getJSONObject("position").getString("name");
photo = info.optString("photoPath", "none");
} catch (JSONException e) {
e.printStackTrace();
}
listings.add(new DirectoryListing(name, title, photo));
}
return listings;
}
}
}
Try calling handler.sendEmptyMessage(0); instead of handler.handleMessage(null);
I don't know why this would cause the errors you are seeing, but this is how I have it set up when I use handler and thread instead of AsyncTask. And I have have never seen that error doing it this way.
#Nguyen is right though AsyncTask is the preferred way to handle these types of things now. And it actually makes it much easier to do.
AsyncTask docs
AsyncTask Example
In my experience, you should create your own class that extends AsyncTask class to do something at background. This is a simpler and more effectively than using thread + handler.

Android: How do I make a ListView update itself periodically?

I never got this working in a straightforward manner. Sorry if I'm being a little vague. I'll try to elaborate on what I'm trying to do. I am trying to build a listview that grabs its data from a webservice. Once I initialize a listview, I want to keep polling the webserver periodically and update the contents of the listview. For this I am doing something like this:
public class SampleAutoUpdateList extends Activity {
//Autoupdate handler
private Handler handler = new Handler();
private Runnable updater = new Runnable() {
public void run() {
/*
* Update the list
*/
try {
Log.i("UPDATE", "Handler called");
searchAdapter = getFeed(URL);
searchAdapter.notifyDataSetChanged();
handler.postDelayed(this, Configuration.REFRESH_INTERVAL);
} catch(Exception e) {
Log.e("UPDATE ERROR", e.getMessage());
}
}
};
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.linearmode);
this.context = this;
searchAdapter = getFeed(URL);
LinearLayout l2 = (LinearLayout) findViewById(R.id.secondaryLayout);
ListView list = new ListView(context);
l2.addView(list);
// display UI
UpdateDisplay(list);
updater.run();
}
private SearchAdapter getFeed(String URL) {
try
{
SearchHandler handler = new SearchHandler();
URL url = new URL(URL);
String data = convertStreamToString(url.openStream());
data = data.substring(data.indexOf('['), data.length()-1);
handler.parseJSON(data);
return handler.getFeed();
}
catch (Exception ee)
{
// if we have a problem, simply return null
Log.e("getFeed", ee.getMessage());
return null;
}
}
private void UpdateDisplay(View searchView) {
// TODO Auto-generated method stub
// TODO Auto-generated method stub
searchList = (ListView) searchView;
myProgressDialog = ProgressDialog.show(this,
"Please wait...", "Loading search....", true);
new Thread() {
public void run() {
try{
Thread.sleep(2000);
} catch (Exception e) { }
runOnUiThread(new Runnable() {
#Override
public void run() {
if (searchAdapter == null)
{
Log.e("ERROR", "No Feed Available");
return;
}
searchAdapter.setContext(context);
searchList.setAdapter(searchAdapter);
searchList.setSelection(0);
}
});
// Dismiss the Dialog
myProgressDialog.dismiss();
}
}.start();
}
}
And the SearchHandler class is simple:
public class SearchHandler extends DefaultHandler {
SearchAdapter _adapter;
SearchItem _item;
public SearchHandler()
{
}
public SearchAdapter getFeed()
{
return _adapter;
}
public void parseJSON(String data) {
// TODO Auto-generated method stub
_adapter = new SearchAdapter();
JSONArray parseArray;
try {
parseArray = new JSONArray(data);
for (int i=0; i < parseArray.length(); i++) {
SearchItem item = new SearchItem();
JSONObject jsonUser = parseArray.getJSONObject(i);
item.set_from(jsonUser.getString ("from"));
item.set_msg(jsonUser.getString("msg"));
}
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
No matter what I do, the handler gets called and the new items are fetched, but the list is never refreshed... Any ideas on what could be going wrong?
Well, it is a little bit difficult to follow your code, since you only have a fragment of it, and few of the really relevant bits. For example, based on your available code, your list should be forever empty, since you never associate the searchAdapter with a ListView...at least in the code you have shown.
That being said, the following lines seem particularly odd:
searchAdapter = getFeed(URL);
searchAdapter.notifyDataSetChanged();
I am going to assume that getFeed() (not shown) creates a new ListAdapter of some sort. If getFeed() is creating a new ListAdapter, there is no need to call notifyDataSetChanged() on it, as its data set hasn't changed -- it's brand new. Moreover, unless you are associating this new ListAdapter to your ListView, the new ListAdapter will have no effect.
If I'm barking up the wrong tree, consider adding lines to your sample showing the implementation of getFeed() and where you are using searchAdapter.

Categories

Resources