update ui from background thread Android - android

I need to update UI from onPostExecute method in may async task. What I am trying is I am parsing an xml and take texts from there.. I need to create textView dynamically from onPostExecute() for each xml node it contain text and add it to my layout..
when I try to do this a got NetworkOnMainThreadException..
me tried handler to solve this issue, but didn't get working properly.
please check my code.
protected void onPostExecute(final InputStream stream) {
// dismiss the dialog after getting all albums
pDialog.dismiss();
try {
XmlPullParser xpp = Xml.newPullParser();
xpp.setInput(stream, null);
xpp.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false);
xpp.next();
int eventType = xpp.getEventType();
System.out.println("eventType : " + eventType);
String tagname = null;
String type = null;
String link = null;
String content = null;
while (eventType != XmlPullParser.END_DOCUMENT)
{
if(eventType == XmlPullParser.START_DOCUMENT){
// str += "\nXML Parsing Starting...\n";
eventType = xpp.next();
continue;
}
else if(eventType == XmlPullParser.START_TAG)
{
// str += "\nroot tag: "+xpp.getName();
tagname = xpp.getName();
if(xpp.getName().equals("text")){
if(xpp.getAttributeCount()>0){
type = xpp.getAttributeValue(null, "type");
// str += "\nroot attr: "+type;
}
}
else if((xpp.getName().equals("image")) || (xpp.getName().equals("audio")) || (xpp.getName().equals("video")) ){
if(xpp.getAttributeCount()>0){
link = xpp.getAttributeValue(null, "src");
// str += "\nroot attr: "+link;
}
}
}
else if(eventType == XmlPullParser.TEXT)
{
content = xpp.getText();
// str += "\nvalue : "+xpp.getText();
}
else if(eventType == XmlPullParser.END_TAG)
{
// str += "\nending tag: "+xpp.getName();
eventType = xpp.next();
continue;
}
System.out.println("content : " + content);
System.out.println("tagname : " + tagname);
if(content != null ){
if((tagname.equals("text") || tagname.equals("preview")) ){
// UPDATE_TEXT =1;
// TextView text = new TextView(ContentView.this);
text = new TextView(getBaseContext());
text.setText(content);
if(type != null){
if(type.equals("heading1"))
text.setTextAppearance(ContentView.this, R.style.heading1);
else if(type.equals("heading2"))
text.setTextAppearance(ContentView.this, R.style.heading2);
else if(type.equals("heading3"))
text.setTextAppearance(ContentView.this, R.style.heading3);
else if(type.equals("heading4"))
text.setTextAppearance(ContentView.this, R.style.heading4);
type = null;
}
if (text != null && layout != null){
Log.e(getPackageName(), text.toString());
runOnUiThread(new Runnable() {
public void run() {
Message message = handler.obtainMessage();
message.what = 1;
handler.sendMessage(message);
// handler.sendEmptyMessage(1);
// layout.addView(text);
}
});
}
content = null;
}
else if((tagname.equals("image"))){
text = new TextView(ContentView.this);
text.setText(content);
if(link != null){
link = null;
}
runOnUiThread(new Runnable() {
public void run() {
handler.sendEmptyMessage(1);
// layout.addView(text);
}
});
content = null;
}
}
eventType = xpp.next();
}
// str += "\n\nXML parsing Ending......";
} catch (XmlPullParserException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
check my handler class in activity class..
protected Handler handler = new Handler() {
#Override
public void handleMessage(Message msg) {
switch (msg.what) {
case 1:
layout.addView(text);
break;
case 2:
layout.addView(text);
break;
}
}
};
still am getting same error.

you need Object Model for data infos and setter and can used this:
private ProgressDialog progressBar;
class MyTask extends AsyncTask<String, Void, String> {
#Override
protected void onPreExecute() {
super.onPreExecute();
progressBar = new ProgressDialog(getApplicationContext());
progressBar.setMessage("please, waiting ...");
progressBar.setCancelable(false);
progressBar.show();
}
#Override
protected String doInBackground(String... params) {
try {
// parsing xml and get data
// get info and set them in my model ...
} catch (Exception e) {
e.printStackTrace();
}
return params[0];
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
if (null != progressBar && progressBar.isShowing()) {
progressBar.dismiss();
}
// do work in UI and set getter informations and set layout ...
switch(select) {
case 1:
layout.addView(text);
break;
case 2:
layout.addView(text);
break;
}
}
}

You failed to post the entire AsyncTask, forcing everyone to have to guess.
My guess is that you did the HTTP connection in doInBackground(), then passed the resulting InputStream to onPostExecute(). This will not work, as that InputStream is tied to a network socket.
Move your InputStream and XML parsing into doInBackground().

Related

Rss Reader Android not working

I want to make a simple Rss Reader app and it doesn't working. More exactly, it doesn't show nothing, almost nothing. For example, for this feed http://feeds.feedburner.com/telefoane-mobilissimo, I get "https://www.mobilissimo.ro/telefoane/" and "Telefoane mobile: specificații, galerii foto, video, benchmark-uri, teste".
Here is the code:
public List<FeedModel> parseFeed(InputStream inputStream) throws XmlPullParserException,
IOException {
String title = null;
String description = null;
String link=null;
String content=null;
String pubDate=null;
Bitmap bitmap=null;
URL url;
boolean isItem = false;
List<FeedModel> items = new ArrayList<>();
try {
XmlPullParser xmlPullParser = Xml.newPullParser();
xmlPullParser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false);
xmlPullParser.setInput(inputStream, null);
xmlPullParser.nextTag();
while (xmlPullParser.next() != XmlPullParser.END_DOCUMENT) {
int eventType = xmlPullParser.getEventType();
String name = xmlPullParser.getName();
if(name == null)
continue;
if(eventType == XmlPullParser.END_TAG) {
if(name.equalsIgnoreCase("item")) {
isItem = false;
}
continue;
}
if (eventType == XmlPullParser.START_TAG) {
if(name.equalsIgnoreCase("item")) {
isItem = true;
continue;
}
}
String result = "";
if (xmlPullParser.next() == XmlPullParser.TEXT) {
result = xmlPullParser.getText();
xmlPullParser.nextTag();
}
System.out.println(result);
System.out.println(isItem);
if (name.equalsIgnoreCase("title")) {
title = result;
} else if (name.equalsIgnoreCase("description")) {
description = result.substring(result.indexOf("<img"));
}
else if (name.equalsIgnoreCase("pubDate"))
pubDate=result;
else if (name.equalsIgnoreCase("link"))
link = result;
else if (name.equalsIgnoreCase("content:encoded"))
content=result.substring(result.indexOf("<div"),result.indexOf("]]")-1);
if (description!=null&&description.startsWith("<img"))
{
System.out.println(description.substring(10,74));
url=new URL(description.substring(10,74));
description=description.substring(description.indexOf("/>")+2);
bitmap = BitmapFactory.decodeStream(url.openConnection().getInputStream());
}
if (title != null && description != null && bitmap!=null && link!=null) {
if(isItem) {
FeedModel item = new FeedModel(title, description, pubDate, content, bitmap, feed, link);
items.add(item);
}
title = null;
description = null;
pubDate=null;
link=null;
content=null;
bitmap=null;
isItem = false;
}
}
return items;
} finally {
inputStream.close();
}
}
public class FeedTask extends AsyncTask<Void,Void,Void>{
private String feedTask;
public FeedTask(String feed)
{
this.feedTask=feed;
}
#Override
protected void onPreExecute() {
if (anInt==1)
{
MainActivity.this.anInt=0;
centerError.animate().alpha(0f).setDuration(getResources().getInteger(android.R.integer.config_mediumAnimTime)).setListener(new AnimatorListenerAdapter() {
#Override
public void onAnimationEnd(Animator animation) {
centerError.setVisibility(View.GONE);
super.onAnimationStart(animation);
}
});
}
swipeRefreshLayout.setRefreshing(true);
recyclerView.animate().alpha(0f).setDuration(getResources().getInteger(android.R.integer.config_mediumAnimTime));
super.onPreExecute();
}
#Override
protected Void doInBackground(Void... params) {
try {
URL url = new URL(feedTask);
InputStream inputStream = url.openConnection().getInputStream();
feedModelList = parseFeed(inputStream);
}
catch (Exception e){}
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
if (feedModelList!=null) {
recyclerView.setAdapter(new FeedAdapter(feedModelList, MainActivity.this));
recyclerView.animate().alpha(1f).setDuration(getResources().getInteger(android.R.integer.config_mediumAnimTime));
}
else System.out.println("heeey");
swipeRefreshLayout.setRefreshing(false);
super.onPostExecute(aVoid);
}
}

Parsing XML fron URL and stuck in loop

I'm trying to parse XML from URL and not getting any data, when I debug I see that I'm stuck in the while() loop. The variable i came up to 160 before I gave up. I don't get why I'm stuck in the while loop and not getting into any of the if statements in the loop.
public class Task extends AsyncTask<Void,Void,Void> {
private List<Task> tasks;
public Task()
{
}
#Override
protected Void doInBackground(Void... params) {
makeTask();
return null;
}
public Task(String title){
mTitle = title;
}
private List<Task> makeTask(){
int i = 0;
tasks = new ArrayList<>();
try {
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
factory.setNamespaceAware(true);
XmlPullParser xpp = factory.newPullParser();
URL url = new URL("http://xxx");
InputStream stream = url.openStream();
xpp.setInput(stream, null);
int eventType = xpp.getEventType();
while (eventType != XmlPullParser.END_DOCUMENT) {
if (eventType == XmlPullParser.START_DOCUMENT) {
}
else if (eventType == XmlPullParser.END_DOCUMENT) {
}
else if (eventType == XmlPullParser.START_TAG) {
if (xpp.getName().equalsIgnoreCase("Task")) {
tasks.add(new Task(xpp.nextText()));
Log.d("Task: ", xpp.nextText());
}
else if (eventType == XmlPullParser.END_TAG) {
}
else if (eventType == XmlPullParser.TEXT) {
}
eventType = xpp.next();
}
i++;
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (XmlPullParserException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return tasks;
}
Edit:
This is the new while() loop and working thanks to #imsiso
while (eventType != XmlPullParser.END_DOCUMENT) {
if (eventType == XmlPullParser.START_TAG) {
if (xpp.getName().equalsIgnoreCase("name")) {
tasks.add(new Task(xpp.nextText()));
}
eventType = xpp.next();
}
else
eventType = xpp.next();
The line below in the code List<Task> tasks = task.getTasks(); is giving error:
java.lang.NullPointerException: Attempt to invoke interface method 'int java.util.List.size()' on a null object reference
I'm think that I'm getting that error because I'm not waiting for the AsyncTask to finish and don't know how I should do that.
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
/*Removed irrelevant code here*/
Task task = new Task();
new Task().execute();
List<Task> tasks = task.getTasks();
mAdapter = new TaskAdapter(tasks);
mTaskRV.setAdapter(mAdapter);
return view;
}
Here's an example TaskLoader and Callback for Loader.
private LoaderManager.LoaderCallbacks<List<TaskModel>> mLoaderCallbacks = new LoaderManager.LoaderCallbacks<List<TaskModel>>()
{
#Override
public Loader<List<TaskModel>> onCreateLoader(int id, Bundle args)
{
return new TaskLoader(getContext());
}
#Override
public void onLoadFinished(Loader<List<TaskModel>> loader, List<TaskModel> data)
{
mTaskRV.setAdapter(new TaskAdapter(data));
}
#Override
public void onLoaderReset(Loader<List<TaskModel>> loader)
{
//
}
};
And the TaskLoader.
private static class TaskLoader extends AsyncTaskLoader<List<TaskModel>>
{
private static final String TAG = TaskLoader.class.getSimpleName();
private List<TaskModel> mData = null;
public TaskLoader(Context context)
{
super(context);
}
#Override
protected void onStartLoading()
{
super.onStartLoading();
if(mData != null){
deliverResult(mData);
}
if(takeContentChanged() || mData == null){
forceLoad();
}
}
#Override
public void deliverResult(List<TaskModel> data)
{
mData = data;
super.deliverResult(data);
}
#Override
public List<TaskModel> loadInBackground()
{
try{
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
factory.setNamespaceAware(true);
XmlPullParser xpp = factory.newPullParser();
URL url = new URL("http://xxx");
InputStream in = null;
try{
in = url.openStream();
xpp.setInput(in, "UTF-8");
return parseTasks(xpp);
}
finally{
if(in != null){
in.close();
}
}
}
catch(MalformedURLException e){
Log.e(TAG, "loadInBackground", e);
}
catch(XmlPullParserException e){
Log.e(TAG, "loadInBackground", e);
}
catch(IOException e){
Log.e(TAG, "loadInBackground", e);
}
return null;
}
private List<TaskModel> parseTasks(XmlPullParser xpp)
throws XmlPullParserException, IOException
{
ArrayList<TaskModel> tasks = new ArrayList<>();
int eventType = xpp.getEventType();
while(eventType != XmlPullParser.END_DOCUMENT){
if(eventType == XmlPullParser.START_TAG){
if(xpp.getName().equalsIgnoreCase("description")){
tasks.add(new TaskModel(xpp.nextText()));
}
}
eventType = xpp.next();
}
return tasks;
}
}
You should provide a listener to the async task that will be triggered when the doInBackground() completes. For instance:
public interface TaskListener{
public void onTaskDone(List<Task> results);
}
public class Task extends AsyncTask<Void,Void,Void> {
private List<Task> tasks;
private TaskListener mListener;
public Task(TaskListener listener)
{
this.mListener = listener;
}
protected Void doInBackground(Void... params) {
.... xml parsing...
if (mListener != null){
mListener.onTaskDone(tasks);
}
}
}
and when you create the task:
Task task = new Task(this);
letting the class implementing the TaskListener interface.
In this method you provide the task's result to the adapter.
public void onTaskDone(final List<Task> tasks){
runOnUiThread(new Runnable() {
#Override
public void run() {
mAdapter = new TaskAdapter(tasks);
mTaskRV.setAdapter(mAdapter);
}
});
}
First let's use this for while which is more clear. And using get text should be better cause it can avoid jumping over a tag or such in other cases.
while (eventType != XmlPullParser.END_DOCUMENT) {
if (eventType == XmlPullParser.START_TAG) {
if (xpp.getName().equalsIgnoreCase("name")) {
tasks.add(new Task(xpp.getText()));
}
}
eventType = xpp.next();
}
And a out that error in List<Task> tasks = task.getTasks(); This should help https://stackoverflow.com/a/218510/2226796
Also I didn't get this part :
Task task = new Task();
new Task().execute();

how to consume data in rest api that returns xml data in android

please can anybody tell how to consume rest API in android that returns xml data.there are so many example with JSON.but I need to response in xml format ...can anybody tell how to do that please help me thanks in advance.
You can try something like this
private class CallAPI extends AsyncTask<String, String, String> {
#Override
protected String doInBackground(String... params) {
String urlString=params[0]; // URL to call
String schid="";
String resultToDisplay = "";
InputStream in = null;
Result result = null ;
// HTTP Get
try {
URL url = new URL(urlString);
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
in = new BufferedInputStream(urlConnection.getInputStream());
//resultToDisplay +="&" + URLEncoder.encode("data", "UTF-8") ;
} catch (Exception e ) {
System.out.println(e.getMessage());
return e.getMessage();
}
// Parse XML
XmlPullParserFactory pullParserFactory;
try {
pullParserFactory = XmlPullParserFactory.newInstance();
XmlPullParser parser = pullParserFactory.newPullParser();
parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false);
parser.setInput(in, null);
result = parseXML(parser);
} catch (XmlPullParserException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
// Simple logic to determine if the email is dangerous, invalid, or valid
if (result != null ) {
if( result.hygieneResult.equals("Spam Trap")) {
resultToDisplay = "Dangerous, please correct";
}
else if( Integer.parseInt(result.statusNbr) >= 300) {
resultToDisplay = "Invalid, please re-enter";
}
else {
resultToDisplay = "Thank you for your submission";
}
}
else {
resultToDisplay = "Exception Occured";
}
return resultToDisplay;
}
protected void onPostExecute(String schid) {
if(schid == null) {
schid = "THERE WAS AN ERROR";
}
Intent intent = new Intent(getApplicationContext(), ResultActivity.class);
intent.putExtra(EXTRA_MESSAGE, schid);
startActivity(intent);
}
private Result parseXML( XmlPullParser parser ) throws XmlPullParserException, IOException {
int eventType = parser.getEventType();
Result result = new Result();
while( eventType!= XmlPullParser.END_DOCUMENT) {
String strid = null;
switch(eventType)
{
case XmlPullParser.START_TAG:
strid = parser.toString();
//name=parser.getName();
if( strid.equals("Error")) {
System.out.println("Web API Error!");
}
else if ( strid.equals("StatusNbr")) {
result.statusNbr = parser.nextText();
}
else if (strid.equals("HygieneResult")) {
result.hygieneResult = parser.nextText();
}
break;
case XmlPullParser.END_TAG:
break;
} // end switch
eventType = parser.next();
} // end while
return result;
}
} // end CallAPI
Now in your activity
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
// This is the method that is called when the submit button is clicked
public void verifyDetails(View view) {
EditText schidEditText = (EditText) findViewById(R.id.sch_id);
String schid = schidEditText.getText().toString();
if( schid != null && !schid.isEmpty()) {
String urlString = apiURL + "schid:" + schid.toString();
//String urlString = apiURL + "LicenseInfo.RegisteredUser.UserID=" + strikeIronUserName + "&LicenseInfo.RegisteredUser.Password=" + strikeIronPassword + "&VerifyEmail.Email=" + email + "&VerifyEmail.Timeout=30";
new CallAPI().execute(urlString);
}
}
}
You need to use DocumentBuilderFactory for Parsing XML using Java
You can find a good tutorial for this on that place XML and Java - Parsing XML using Java
Check Xml Parsing Tuotorial using DOM parser
also Xml Parsing Tuotorial using XML pull parser

Activity Indicator does not work with async task

When i use asynctask method, activity indicator does not work. AsyncTask method is used to download the image from URL and put on phone memory. Below is my code
btnSubmit.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
AsyncCallWS aws = new AsyncCallWS();
try {
retData = aws.execute().get();
Log.d(TAG, "STATUS is " + retData);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// Close the window and go back to login page
Intent intent = new Intent(launchar.this, arcamera.class);
intent.putExtra("url", url_);
intent.putExtra(Strings.USERNAME, mUsername);
intent.putExtra(Strings.PASSWORD, mPassword);
intent.putExtra(Strings.COMP_ID, mCompId);
startActivity(intent);
}
});
My Async Method is below :
private class AsyncCallWS extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... params) {
// Call the service
HttpConnectionHelper helper = new HttpConnectionHelper(
Constants.SERVICE_GETAR_URL);
final String REQUEST_DATA = String.format(
"<ReqData xmlns=\"http://www.ceolution.com/phone\"> "
+ "<key>%s|%s|%s</key>" + "</ReqData>", mUsername,
mPassword, mCompId);
try {
helper.setRequestMethod(HttpPost.METHOD_NAME);
helper.setPostData(REQUEST_DATA);
helper.setHeader("Content-Type", "application/xml");
int code = helper.getResponseCode();
if (Constants.LOG_ENABLED) {
Log.i(TAG, "Response code = " + code);
}
if (code == HttpURLConnection.HTTP_OK) {
String data = helper.getResponseData();
if (Constants.LOG_ENABLED) {
Log.v(TAG, "Response Data - " + data);
}
ARParser par = new ARParser();
String data_ = par.ParseAR(data);
Log.i(TAG, "RETURN DATA IS " + data_);
// Get Object
BufferedReader br = new BufferedReader(new StringReader(
data_));
InputSource is = new InputSource(br);
// Create XML Parser
ARXMLFormatter parser = new ARXMLFormatter();
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser sp = factory.newSAXParser();
XMLReader reader = sp.getXMLReader();
reader.setContentHandler(parser);
reader.parse(is);
myData = parser.itemList;
if (myData != null) {
String OutputData = "";
Location itemLocation = null;
for (Item item : myData) {
if (item != null) {
itemLocation = new Location("");
itemLocation.setLatitude(Double
.parseDouble(item.getLat()));
itemLocation.setLongitude(Double
.parseDouble(item.getLg()));
if (location != null) {
float distanceInMeters = itemLocation
.distanceTo(location);
Log.d(TAG, "distanceInMeters is "
+ distanceInMeters);
if (distanceInMeters <= Double
.parseDouble(item.getR())) {
// Must have to clean the directory
// before
// writing data
File savefilepath1 = new File(
COURSE_ZIP_FILE_PATH);
cleanDirectory(savefilepath1);
Image realData = null;
String imageName = "";
for (int k = 0; k < 8; k++) {
realData = null;
imageName = "";
switch (k) {
case 0: {
realData = item.getN();
imageName = "n.png";
break;
}
case 1: {
realData = item.getE();
imageName = "e.png";
break;
}
case 2: {
realData = item.getS();
imageName = "s.png";
break;
}
case 3: {
realData = item.getW();
imageName = "w.png";
break;
}
case 4: {
realData = item.getNe();
imageName = "ne.png";
break;
}
case 5: {
realData = item.getNw();
imageName = "nw.png";
break;
}
case 6: {
realData = item.getSe();
imageName = "se.png";
break;
}
case 7: {
realData = item.getSw();
imageName = "sw.png";
break;
}
}
url_[k] = realData.getL();
boolean status = false;
if (realData.getU() != ""
&& realData.getU() != null)
status = DownloadFile(
realData.getU()
.replace(
"http",
"https"),
imageName);
Log.d(TAG, "Download status is "
+ status);
}
Log.d(TAG,
"This is the item to processed");
return "SUCCESS";
}
OutputData = OutputData + item.toString();
} else
return "GPSISSUE";
} else
Log.e("Items", "No details");
}
Log.d(TAG, "OutputData data is " + OutputData);
}
return "NODATA";
}
} catch (Exception ex) {
ex.printStackTrace();
return "ERROR";
}
return "NODATA";
}
The XML file is below
<FrameLayout
android:id="#+id/laucnh_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true" >
<ImageView
android:id="#+id/btnSubmit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:background="#drawable/launch"
android:onClick="#string/onClick"
android:scaleType="center" />
</FrameLayout>
Even i tried to put the activity indicator in onPreExecute() and onPostExecute() also does not work.
I am not sure what may be reason .
Please help.
You will have to publish updates from your asyncTask to the UI. Here is an example of it. So in the onProgressUpdate Function you can update the UI. I hope this helps.
private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
protected Long doInBackground(URL... urls) {
int count = urls.length;
long totalSize = 0;
for (int i = 0; i < count; i++) {
totalSize += Downloader.downloadFile(urls[i]);
publishProgress((int) ((i / (float) count) * 100));
// Escape early if cancel() is called
if (isCancelled()) break;
}
return totalSize;
}
protected void onProgressUpdate(Integer... progress) {
setProgressPercent(progress[0]);
}
protected void onPostExecute(Long result) {
showDialog("Downloaded " + result + " bytes");
}
}

Android 3.0 Honeycomb problem in parsing RSS feed

I am trying to parse rss feed in honeycomb 3.0 but it gives error as follows.
ERROR/AndroidNews::PullFeedParser(444): android.os.NetworkOnMainThreadException
I tried same code in android lower version it works but it doesn't work in Honeycomb.
Please suggest some help
This is in main activity
try{
FeedParser parser = new XmlPullFeedParser(feedUrl);
messages = parser.parse();
titles = new ArrayList<String>(messages.size());
String description ="";//= new ArrayList<String>(messages.size());
for (Message msg : messages){
description = msg.getDescription().toString();
Log.v("Desc", description);
titles.add(description);
}
} catch (Throwable t){
Log.e("AndroidNews",t.getMessage(),t);
}
I am using XmlPullFeedParser which extends BaseFeedParser
public class XmlPullFeedParser extends BaseFeedParser {
public XmlPullFeedParser(String feedUrl) {
super(feedUrl);
}
public List<Message> parse() {
List<Message> messages = null;
XmlPullParser parser = Xml.newPullParser();
try {
// auto-detect the encoding from the stream
parser.setInput(this.getInputStream(), null);
int eventType = parser.getEventType();
Message currentMessage = null;
boolean done = false;
while (eventType != XmlPullParser.END_DOCUMENT && !done){
String name = null;
switch (eventType){
case XmlPullParser.START_DOCUMENT:
messages = new ArrayList<Message>();
break;
case XmlPullParser.START_TAG:
name = parser.getName();
if (name.equalsIgnoreCase(ITEM)){
currentMessage = new Message();
} else if (currentMessage != null){
if (name.equalsIgnoreCase(LINK)){
currentMessage.setLink(parser.nextText());
} else if (name.equalsIgnoreCase(DESCRIPTION)){
currentMessage.setDescription(parser.nextText());
} else if (name.equalsIgnoreCase(PUB_DATE)){
currentMessage.setDate(parser.nextText());
} else if (name.equalsIgnoreCase(TITLE)){
currentMessage.setTitle(parser.nextText());
}
}
break;
case XmlPullParser.END_TAG:
name = parser.getName();
if (name.equalsIgnoreCase(ITEM) && currentMessage != null){
messages.add(currentMessage);
} else if (name.equalsIgnoreCase(CHANNEL)){
done = true;
}
break;
}
eventType = parser.next();
}
} catch (Exception e) {
Log.e("AndroidNews::PullFeedParser", e.getMessage(), e);
throw new RuntimeException(e);
}
return messages;
}
}
This is BaseFeedParser:
public class BaseFeedParser implements FeedParser {
// names of the XML tags
static final String CHANNEL = "channel";
static final String PUB_DATE = "pubDate";
static final String DESCRIPTION = "description";
static final String LINK = "link";
static final String TITLE = "title";
static final String ITEM = "item";
static final String BODY = "body";
private final URL feedUrl;
protected BaseFeedParser(String feedUrl){
try {
this.feedUrl = new URL(feedUrl);
} catch (MalformedURLException e) {
throw new RuntimeException(e);
}
}
protected InputStream getInputStream() {
try {
return feedUrl.openConnection().getInputStream();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public List<Message> parse() {
// TODO Auto-generated method stub
return null;
}
}
This is FeedParser:
public interface FeedParser {
List<Message> parse();
}
This is message class:
public class Message implements Comparable<Message>{
static SimpleDateFormat FORMATTER =
new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss Z");
private String title;
private URL link;
private String description;
private Date date;
private String body;
public String getTitle() {
return title;
}
public String getBody() {
return body;
}
public void setTitle(String title) {
this.title = title.trim();
}
// getters and setters omitted for brevity
public URL getLink() {
return link;
}
public void setLink(String link) {
try {
this.link = new URL(link);
} catch (MalformedURLException e) {
throw new RuntimeException(e);
}
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description.trim();
}
public String getDate() {
return FORMATTER.format(this.date);
}
public void setDate(String date) {
// pad the date if necessary
while (!date.endsWith("00")){
date += "0";
}
try {
this.date = FORMATTER.parse(date.trim());
} catch (ParseException e) {
throw new RuntimeException(e);
}
}
public Message copy(){
Message copy = new Message();
copy.title = title;
copy.link = link;
copy.description = description;
copy.date = date;
copy.body = body;
return copy;
}
#Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("Title: ");
sb.append(title);
sb.append("Body: ");
sb.append(body);
sb.append('\n');
sb.append("Date: ");
sb.append(this.getDate());
sb.append('\n');
sb.append("Link: ");
sb.append(link);
sb.append('\n');
sb.append("Description: ");
sb.append(description);
return sb.toString();
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((date == null) ? 0 : date.hashCode());
result = prime * result
+ ((description == null) ? 0 : description.hashCode());
result = prime * result + ((link == null) ? 0 : link.hashCode());
result = prime * result + ((title == null) ? 0 : title.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Message other = (Message) obj;
if (date == null) {
if (other.date != null)
return false;
} else if (!date.equals(other.date))
return false;
if (description == null) {
if (other.description != null)
return false;
} else if (!description.equals(other.description))
return false;
if (link == null) {
if (other.link != null)
return false;
} else if (!link.equals(other.link))
return false;
if (title == null) {
if (other.title != null)
return false;
} else if (!title.equals(other.title)){
return false;
} else if (!body.equals(other.body))
return false;
return true;
}
public int compareTo(Message another) {
if (another == null) return 1;
// sort descending, most recent first
return another.date.compareTo(date);
}
}
The error message here pretty much tells you what is going on -- you are trying to access the network on tthe main thread. You really shouldn't do that on any version of android, because it can (read: will) cause your UI to hang while the connection is processing.
There are ways to turn the error off, but I won't get into tthem: you shouodnt do it.
instead, you want to do this work in aa background thread and post a minimal handler back to the UI thread. I don't have an example handy (on my tablet now) but let me know if you cannot find one.
..edit..
OK, here's a simple example. This requires an activity with a text view (id "text") and, of course, INTERNET permissions. Let me know if you have any questions!
public class MainActivity extends Activity {
private TextView mTextView;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mTextView = (TextView) findViewById(R.id.text);
// start our call in a new thread
(new Thread(new Runnable() {
#Override
public void run() {
fetchPage();
}
})).start();
}
private void fetchPage() {
try {
URL url = new URL("http://stackoverflow.com/feeds");
HttpURLConnection c = (HttpURLConnection) url.openConnection();
c.setRequestMethod("GET");
c.setDoOutput(true);
c.connect();
ByteArrayOutputStream bos = new ByteArrayOutputStream();
InputStream is = c.getInputStream();
byte[] buffer = new byte[1024];
int len1 = 0;
while ((len1 = is.read(buffer)) != -1) {
bos.write(buffer, 0, len1);
}
bos.close();
is.close();
// Remember, all UI things must occur back on the UI thread!
final String text = bos.toString();
this.runOnUiThread(new Runnable() {
#Override
public void run() {
mTextView.setText(text);
}
});
} catch (final IOException ioe) {
this.runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(MainActivity.this, ioe.getMessage(), Toast.LENGTH_LONG).show();
}
});
}
}
thanks,
--randy

Categories

Resources