"android.os.NetworkOnMainThreadException" even when running in AsyncTask - java

I'm getting the android.os.NetworkOnMainThreadException error even when I'm running the code inside AsyncTask thread. This is basically just a chunk of code that should return me a value from a website.
package com.jasperhonkasalo.merenpinnankorkeusvsa;
import android.os.AsyncTask;
import android.util.Log;
import org.w3c.dom.Document;
import org.xml.sax.InputSource;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.StringReader;
import java.net.URL;
import java.util.Iterator;
import javax.xml.namespace.NamespaceContext;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathFactory;
public class NewBackgroundTask {
public static class BackgroundTask extends AsyncTask<String, Void, String> {
String value = "presetvalue";
#Override
protected String doInBackground(String... urls) {
class NamespaceResolver implements NamespaceContext {
private Document document;
public NamespaceResolver(Document doc) {
document = doc;
}
public String getNamespaceURI(String prefix) {
if (prefix.equals("")) {
return document.lookupNamespaceURI(null);
} else {
return document.lookupNamespaceURI(prefix);
}
}
public String getPrefix(String namespaceURI) {
return document.lookupPrefix(namespaceURI);
}
public Iterator<String> getPrefixes(String namespaceURI) {
return null;
}
}
try {
String url = "http://opendata.fmi.fi/wfs/fin?service=WFS&version=2.0.0&request=GetFeature&storedquery_id=fmi::observations::mareograph::timevaluepair&fmisid=134223&";
StringBuilder sb = new StringBuilder();
try (BufferedReader r = new BufferedReader(new InputStreamReader(new URL(url).openStream(), "UTF-8"))) {
String line;
while ((line = r.readLine()) != null) {
sb.append(line + "\n");
}
}
String xml = sb.toString();
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
Document document = factory.newDocumentBuilder().parse(new InputSource(new StringReader(xml)));
XPath xpath = XPathFactory.newInstance().newXPath();
xpath.setNamespaceContext(new NamespaceResolver(document));
String time = xpath.evaluate("//wml2:MeasurementTimeseries[#gml:id='obs-obs-1-1-WATLEV']/wml2:point[last()]//wml2:time", document);
value = xpath.evaluate("//wml2:MeasurementTimeseries[#gml:id='obs-obs-1-1-WATLEV']/wml2:point[last()]//wml2:value", document);
System.out.format("time = %s; value = %s\n", time, value);
return value;
} catch (Exception e) {
Log.d("EXCEPTIONFAIL", e.toString());
return "FAIL: " + e.toString();
}
}
#Override
protected void onPostExecute(String feed) {
// TODO: do something with the feed
}
}
}
I'm getting the value with:
static String eeee = new NewBackgroundTask.BackgroundTask().value;
The value of "value"- variable is staying the same (presetvalue) and also giving me a android.os.NetworkOnMainThreadException error. I'm really new to any java programming and would appreciate any help.

You need to execute the AsyncTask, you cannot simply access a static field of it and expect it to give you any result. You need to do something like that:
new BackgroundTask().execute();
Since this is an asynchronous call, it cannot return a result directly (that's what asynchronous means). Instead, you get the result in the onPostExecute() method, which is executed in the main thread.
If you are really completely new to Java programming, you should perhaps not start with asynchronous method calls. That's something, even experienced developers have sometimes problems with.

Related

How to turn a java Json data Fetching class into a method?

I got a method that fetch data from a web service, so Im looking for a way to call it as a method.
How can I turn this code into a method? or can I call a class in a method? because it has a protected method and extended from a class, but if I implemented the extended class AsyncTask to the class I need to use the Json fetching protected method doInBackground it says "Interface expexted here".
Here's my code that I need to convert it to a method or a way to add it to the class I want to use it in:
Notice: I already extended AppCompatActivity to the class I want to call doInBackground in so I cannot extend FetchData class.
Thanks a lot :D
package com.example.wordspuzzlejsontest;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.AsyncTask;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
public class FetchData extends AsyncTask<Void, Void, Void> {
final String update = "4";
String data = "";
int currentLevel;
Context context;
FetchData(Context context) {
this.context = context;
}
#Override
protected Void doInBackground(Void... voids) {
try {
URL url = new URL("https://api.jsonbin.io/b/5e42776dd18e4016617690ce/" + update);
HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
InputStream inputStream = httpURLConnection.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
String line = "";
while (line != null) {
line = bufferedReader.readLine();
data = data + line;
}
JSONArray JA = new JSONArray(data);
SharedPreferences sharedPreferences = context.getSharedPreferences("SHARED_PREFS", Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPreferences.edit();
currentLevel = sharedPreferences.getInt("currentLevel", 0);
for (int i = 0; i < JA.length();) {
i = currentLevel;
JSONObject JO = (JSONObject) JA.get(i);
String id = (String) JO.get("id");
String img = (String) JO.get("img");
String w1 = (String) JO.get("w1");
String w2 = (String) JO.get("w2");
String w3 = (String) JO.get("w3");
String w4 = (String) JO.get("w4");
editor.putString("id" + i, id);
editor.putString("img" + i, img);
editor.putString("w1" + i, w1);
editor.putString("w2" + i, w2);
editor.putString("w3" + i, w3);
editor.putString("w4" + i, w4);
editor.apply();
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
return null;
}
}
```
Summing up my comments:
Create a new class called NewClass.java
class NewClass extends FetchData{
public Void fetchData(Void... voids){ return this.doInBackground(voids);}
}
Since doInBackground in a protected method, you will have private access inside NewClass.java

How to fix android.os.NetworkOnMainThread [duplicate]

This question already has answers here:
How can I fix 'android.os.NetworkOnMainThreadException'?
(66 answers)
Closed 3 years ago.
I'm getting the "android.os.NetworkOnMainThreadException" even though I'm not running anything network related in my main thread. How can I fix this?
I actually tried the code inside Eclipse and it worked just fine, but not in Android Studio where I'm developing the app itself.
Testclass.java:
package com.*****.*****;
import android.graphics.Bitmap;
import android.os.AsyncTask;
import android.view.View;
import java.io.*;
import java.net.*;
import java.util.*;
import javax.xml.xpath.*;
import javax.xml.namespace.*;
import org.xml.sax.InputSource;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
abstract class Testclass {
public static class NamespaceResolver implements NamespaceContext {
private Document document;
public NamespaceResolver(Document doc) {
document = doc;
}
public String getNamespaceURI(String prefix) {
if (prefix.equals("")) {
return document.lookupNamespaceURI(null);
} else {
return document.lookupNamespaceURI(prefix);
}
}
public String getPrefix(String namespaceURI) {
return document.lookupPrefix(namespaceURI);
}
public Iterator<String> getPrefixes(String namespaceURI) {
return null;
}
}
public static String downloadString(String url) throws Exception {
StringBuilder sb = new StringBuilder();
try (BufferedReader r = new BufferedReader(new InputStreamReader(new URL(url).openStream(), "UTF-8"))) {
String line;
while ((line = r.readLine()) != null) {
sb.append(line + "\n");
}
}
return sb.toString();
}
public static Document createDocumentFromString(String xml) throws Exception {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
return factory.newDocumentBuilder().parse(new InputSource(new StringReader(xml)));
}
static String value;
public static String result() {
try {
String url = "http://opendata.fmi.fi/wfs/fin?service=WFS&version=2.0.0&request=GetFeature&storedquery_id=fmi::observations::mareograph::timevaluepair&fmisid=134223&";
String xml = downloadString(url);
Document document = createDocumentFromString(xml);
XPath xpath = XPathFactory.newInstance().newXPath();
xpath.setNamespaceContext(new NamespaceResolver(document));
String time = xpath.evaluate("//wml2:MeasurementTimeseries[#gml:id='obs-obs-1-1-WATLEV']/wml2:point[last()]//wml2:time", document);
value = xpath.evaluate("//wml2:MeasurementTimeseries[#gml:id='obs-obs-1-1-WATLEV']/wml2:point[last()]//wml2:value", document);
System.out.format("time = %s; value = %s\n", time, value);
return value;
} catch (Exception e) {
return "FAIL: " + e.toString();
}
}
}
Output when run in android studio: "null" and also throws "android.os.NetworkOnMainThreadException"
Output when run in Eclipse: "-97.0" (correct output)
You need to run network related tasks on another thread, something like this:
Thread mThread = new Thread(new Runnable() {
#Override
public void run() {
try {
//Put your code that you want to run in here
} catch (Exception e) {
e.printStackTrace();
}
}
Now, if you are not sure what causing this you can check your error log, it will guid you to the line that caused this problem.
Another thing that you can do is to add custom logs/prints with the error description, later on, you can check those logs to see if any of them called (if yes this means that you were getting error)
You need to use Asyn Task for networking purposes.
A simple example is given in below link
Async task in android

Asynchronous HTTP call doesn't work

I am working on an Android app (min API 8) and I want to make an activity where there is a preloader GIF running while some tasks are executed in the background.
These tasks involve connection to a database and queries. So in some way, I want to achieve something that involves techniques like you would use to make a progress bar.
I know I can't make a connection in the main thread in Java so I made a class that does this in another thread. The connection works fine, but I can't make the whole behaviour work properly. More precisely, if I use thread.join()then the main thread is blocked (which is the opposite of what I want) and if I don't use it, the code of the main thread goes on and finishes before the background process has terminated.
Can someone help me with this please ?
This is the class I created to manage POST queries to an URL :
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.concurrent.atomic.AtomicReference;
public class Request
{
private URL m_url;
private StringBuilder m_parameters;
private HttpURLConnection m_connection;
public Request(String url)
{
try
{
m_url = new URL(url);
}
catch(MalformedURLException exception)
{
System.exit(1);
}
m_connection = null;
m_parameters = new StringBuilder();
}
public void put(String key, String value)
{
if(m_parameters.length() != 0)
m_parameters.append('&');
try
{
m_parameters.append(URLEncoder.encode(key, "UTF-8"));
m_parameters.append('=');
m_parameters.append(URLEncoder.encode(value, "UTF-8"));
}
catch(UnsupportedEncodingException exception)
{
System.exit(1);
}
}
private void sendRequest()
{
try
{
byte[] data = m_parameters.toString().getBytes("UTF-8");
m_connection = (HttpURLConnection) m_url.openConnection();
m_connection.setAllowUserInteraction(true);
m_connection.setRequestMethod("POST");
m_connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded;charset=utf-8");
m_connection.setRequestProperty("Content-Length", String.valueOf(data.length));
m_connection.setDoOutput(true);
m_connection.getOutputStream().write(data);
}
catch(Exception exception)
{
System.exit(1);
}
}
private String getResponse()
{
String response = "";
try
{
if(m_connection.getResponseCode() == HttpURLConnection.HTTP_OK)
{
Reader reader = new BufferedReader(new InputStreamReader(m_connection.getInputStream(), "UTF-8"));
int c;
do {
c = reader.read();
response += (char) c;
}
while (c >= 0);
}
}
catch(IOException exception)
{
System.exit(1);
}
m_connection.disconnect();
return response;
}
public String get()
{
final AtomicReference<String> response = new AtomicReference<>();
Thread thread = new Thread(new Runnable()
{
public void run()
{
sendRequest();
response.set(getResponse());
}
});
thread.start();
/*
try
{
thread.join();
}
catch(InterruptedException exception)
{
System.exit(1);
}
*/
return response.get();
}
}
And this is how I use it in the main thread (the activity) :
Request request = new Request("http://posttestserver.com/post.php?dump&html&sleep=5");
request.put("name", "bob");
String response = request.get();
Thanks.
Okay, I finally solved that problem using standard IntentServiceof Android :
https://developer.android.com/training/run-background-service/create-service.html
This tutorial helped a lot too :
http://code.tutsplus.com/tutorials/android-fundamentals-intentservice-basics--mobile-6183
Here is my new class Request:
import android.app.IntentService;
import android.content.Intent;
import android.os.Bundle;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.Set;
public class Request extends IntentService
{
private URL m_url;
private StringBuilder m_parameters;
private HttpURLConnection m_connection;
public Request()
{
super("Request");
m_url = null;
m_connection = null;
m_parameters = new StringBuilder();
}
public void put(String key, String value)
{
if(m_parameters.length() != 0)
m_parameters.append('&');
try
{
m_parameters.append(URLEncoder.encode(key, "UTF-8"));
m_parameters.append('=');
m_parameters.append(URLEncoder.encode(value, "UTF-8"));
}
catch(UnsupportedEncodingException exception)
{
System.exit(1);
}
}
private void sendRequest()
{
try
{
byte[] data = m_parameters.toString().getBytes("UTF-8");
m_connection = (HttpURLConnection) m_url.openConnection();
m_connection.setAllowUserInteraction(true);
m_connection.setRequestMethod("POST");
m_connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded;charset=utf-8");
m_connection.setRequestProperty("Content-Length", String.valueOf(data.length));
m_connection.setDoOutput(true);
m_connection.getOutputStream().write(data);
}
catch(Exception exception)
{
System.exit(1);
}
}
private String getResponse()
{
String response = "";
try
{
if(m_connection.getResponseCode() == HttpURLConnection.HTTP_OK)
{
Reader reader = new BufferedReader(new InputStreamReader(m_connection.getInputStream(), "UTF-8"));
int c;
do {
c = reader.read();
response += (char) c;
}
while (c >= 0);
}
}
catch(IOException exception)
{
System.exit(1);
}
m_connection.disconnect();
return response;
}
protected void onHandleIntent(Intent intent)
{
Bundle bundle = intent.getExtras();
Set<String> keys = bundle.keySet();
for(String key : keys)
put(key, bundle.getString(key));
try
{
m_url = new URL(bundle.getString("url"));
}
catch(MalformedURLException exception)
{
System.exit(1);
}
sendRequest();
String response = getResponse();
Intent broadcast = new Intent();
broadcast.setAction(ReadyActivity.ResponseReceiver.m_broadcastKey);
broadcast.putExtra("response", response);
sendBroadcast(broadcast);
}
}
Here is the ResponseReceiversubclass of my main activity :
public class ResponseReceiver extends BroadcastReceiver
{
public static final String m_broadcastKey = "Uz258e3wZm77Z3Tdebn7PqgW3CLBJ8";
public void onReceive(Context context, Intent intent)
{
String response = intent.getStringExtra("response");
clear();
((TextView) m_widgets.get("text")).setText("Finally found someone !" + response);
show(m_widgets.get("text"));
((Button) m_widgets.get("button1")).setText("OK let's do this !");
show(m_widgets.get("button1"));
((Button) m_widgets.get("button2")).setText("Later ?");
show(m_widgets.get("button2"));
unregisterReceiver(m_receiver);
}
}
Then I also had to instantiate the ResponseReceiver in the activity:
private ResponseReceiver m_receiver;
...
IntentFilter filter = new IntentFilter(ResponseReceiver.m_broadcastKey);
m_receiver = new ResponseReceiver();
registerReceiver(m_receiver, filter);
And finally call the service :
Intent service = new Intent(this, Request.class);
ArrayList<CharSequence> parameters = new ArrayList<>();
service.putExtra("url", "http://posttestserver.com/post.php?dump&html&sleep=10");
service.putExtra("username", "bob");
service.putExtra("age", "20");
startService(service);
Maybe it will help someone in the future.

why i am getting the following exception

this is my nodefinder.java file
package com.acme.web.action.executer;
import java.sql.ResultSet;
import java.util.Map;
import org.alfresco.web.bean.repository.Node;
import org.alfresco.web.bean.repository.Repository;
import org.alfresco.web.ui.common.component.UIActionLink;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
import org.alfresco.service.cmr.model.FileFolderService;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.cmr.search.SearchParameters;
import org.alfresco.service.cmr.search.SearchService;
public class NodeFinder {
// private static final String = null;
SearchParameters sp = new SearchParameters();
private NodeService nodeService;
private FileFolderService fileFolderService;
//geting the filefolder service
public FileFolderService getFileFolderService() {
return fileFolderService;
}
// setting the file folder service
public void setFileFolderService(FileFolderService fileFolderService) {
this.fileFolderService = fileFolderService;
}
// getting the node servise
public NodeService getNodeService() {
return nodeService;
}
// setting the node server
public void setNodeService(NodeService nodeService) {
this.nodeService = nodeService;
}
public void execute(ActionEvent event) {
ResultSet resultSet_s = null;
UIActionLink comp = (UIActionLink) event.getComponent();
Map<String, String> params = comp.getParameterMap();
String id = params.get("id1");
System.out.println("1");
NodeRef actionedUponNodeRef = new NodeRef(Repository.getStoreRef(), id);
String qry_s = "#cm\\:name:train";
System.out.println("2");
SearchParameters sp_s = new SearchParameters();
System.out.println("3");
sp_s.addStore(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE);
sp_s.setLanguage(SearchService.LANGUAGE_LUCENE);
sp_s.setQuery(qry_s);
System.out.println( "4" );
Node node = new Node(actionedUponNodeRef);
System.out.println("5");
resultSet_s = (ResultSet) Repository.getServiceRegistry(
FacesContext.getCurrentInstance()).getSearchService().query(
sp_s);
System.out.println("5.1");
if (resultSet_s != null) {
System.out.println("6");
System.out.println("Node value is::::" + node.getName());
}
}
}
Because you imported java.sql.ResultSet instead of an alfresco class/interface compatible to org.alfresco.repo.search.impl.lucene.PagingLuceneResultSet
Look at that line ...(ResultSet) Repository.getServiceRegistry(..., then look at your exception and finally at your imports. There you will see that ResultSet is actually java.sql.ResultSet (which is indicated by your ClassCastException's message).
If you then look at the super classes or interfaces of org.alfresco.repo.search.impl.lucene.PagingLuceneResultSet I'd say you won't find any java.sql.ResultSet. That's why you get that exception.

How to parse GPX files with SAXReader?

I'm trying to parse a GPX file. I tried it with JDOM, but it does not work very well.
SAXBuilder builder = new SAXBuilder();
Document document = builder.build(filename);
Element root = document.getRootElement();
System.out.println("Root:\t" + root.getName());
List<Element> listTrks = root.getChildren("trk");
System.out.println("Count trk:\t" + listTrks.size());
for (Element tmpTrk : listTrks) {
List<Element> listTrkpts = tmpTrk.getChildren("trkpt");
System.out.println("Count pts:\t" + listTrkpts.size());
for (Element tmpTrkpt : listTrkpts) {
System.out.println(tmpTrkpt.getAttributeValue("lat") + ":" + tmpTrkpt.getAttributeValue("lat"));
}
}
I opened the example file (CC-BY-SA OpenStreetMap) and the output is just:
Root: gpx
Count trk: 0
What can I do? Should I us a SAXParserFactory (javax.xml.parsers.SAXParserFactory) and implement a Handler class?
Here is my gpx reader. It ignores some of the tags but I hope it will help.
package ch.perry.rando.geocode;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
/**
*
* #author perrym
*/
public class GpxReader extends DefaultHandler {
private static final DateFormat TIME_FORMAT
= new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
private List<Trackpoint> track = new ArrayList<Trackpoint>();
private StringBuffer buf = new StringBuffer();
private double lat;
private double lon;
private double ele;
private Date time;
public static Trackpoint[] readTrack(InputStream in) throws IOException {
try {
SAXParserFactory factory = SAXParserFactory.newInstance();
factory.setValidating(true);
SAXParser parser = factory.newSAXParser();
GpxReader reader = new GpxReader();
parser.parse(in, reader);
return reader.getTrack();
} catch (ParserConfigurationException e) {
throw new IOException(e.getMessage());
} catch (SAXException e) {
throw new IOException(e.getMessage());
}
}
public static Trackpoint[] readTrack(File file) throws IOException {
InputStream in = new FileInputStream(file);
try {
return readTrack(in);
} finally {
in.close();
}
}
#Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
buf.setLength(0);
if (qName.equals("trkpt")) {
lat = Double.parseDouble(attributes.getValue("lat"));
lon = Double.parseDouble(attributes.getValue("lon"));
}
}
#Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
if (qName.equals("trkpt")) {
track.add(Trackpoint.fromWGS84(lat, lon, ele, time));
} else if (qName.equals("ele")) {
ele = Double.parseDouble(buf.toString());
} else if (qName.equals("")) {
try {
time = TIME_FORMAT.parse(buf.toString());
} catch (ParseException e) {
throw new SAXException("Invalid time " + buf.toString());
}
}
}
#Override
public void characters(char[] chars, int start, int length)
throws SAXException {
buf.append(chars, start, length);
}
private Trackpoint[] getTrack() {
return track.toArray(new Trackpoint[track.size()]);
}
}
To read GPX files easily in Java see: http://sourceforge.net/p/gpsanalysis/wiki/Home/
example:
//gets points from a GPX file
final List points= GpxFileDataAccess.getPoints(new File("/path/toGpxFile.gpx"));
Ready to use, open source, and fully functional java GpxParser (and much more) here
https://sourceforge.net/projects/geokarambola/
Details here
https://plus.google.com/u/0/communities/110606810455751902142
With the above library parsing a GPX file is a one liner:
Gpx gpx = GpxFileIo.parseIn( "SomeGeoCollection.gpx" ) ;
Getting its points, routes or tracks trivial too:
for(Point pt: gpx.getPoints( ))
Location loc = new Location( pt.getLatitude( ), pt.getLongitude( ) ) ;

Categories

Resources