NullPointerException with StringBuilder - android

I get a very common crash below from the code below.
I thought my try, catches will have handled that.
java.lang.RuntimeException: An error occured while executing doInBackground()
at android.os.AsyncTask$3.done(AsyncTask.java:200)
at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:273)
at java.util.concurrent.FutureTask.setException(FutureTask.java:124)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:307)
at java.util.concurrent.FutureTask.run(FutureTask.java:137)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1068)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:561)
at java.lang.Thread.run(Thread.java:1102)
Caused by: java.lang.NullPointerException
at java.io.Reader.<init>(Reader.java:65)
at java.io.InputStreamReader.<init>(InputStreamReader.java:65)
at com.test.test.FinderMain.grabPlaneRoute(FinderMain.java:759)
at com.test.test.FinderMain.access$7(FinderMain.java:729)
at com.test.test.FinderMain$GetRouteTask.doInBackground(FinderMain.java:684)
at com.test.test.FinderMain$GetRouteTask.doInBackground(FinderMain.java:1)
at android.os.AsyncTask$2.call(AsyncTask.java:185)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
Line 759 is within grabPlaneRoute and is the line containing the "StringBuilder total = new StringBuilder();"
Can someone help with this, it is driving me crazy! :-)
private void grabPlaneRoute(String adshex) {
List<GeoPoint> localList = new ArrayList<GeoPoint>();
HttpURLConnection con = null;
URL url;
InputStream is=null;
try {
url = new URL("http://www.testurl.com&test=" + adshex);
con = (HttpURLConnection) url.openConnection();
con.setReadTimeout(20000 /* milliseconds */);
con.setConnectTimeout(60000 /* milliseconds */);
con.setRequestMethod("GET");
con.setDoInput(true);
// Start the query
con.connect();
is = con.getInputStream();
}catch (IOException e) {
//handle the exception !
e.printStackTrace();
return;
}
//localList = decodePoly(convertStreamToString(is));
//Log.i("HTTP DUMP", convertStreamToString(is));
BufferedReader r = new BufferedReader(new InputStreamReader(is),8024);
StringBuilder total = new StringBuilder();
String line;
try {
while ((line = r.readLine()) != null) {
String[] separated = line.split(",");
GeoPoint p = getPoint(Double.valueOf(separated[0]),Double.valueOf(separated[1]));
localList.add(p);
}
}catch (IOException e) {
//handle the exception !
e.printStackTrace();
}
drawPlaneRoute(localList);
}

Line 759 is actually the line that begins with BufferedReader r = new ....
The variable is is null.
What happens when con.GetInputStream returns a null, and doesn't throw an exception? You're not handling that case, and that's likely what's happening here.
In addition, I don't see a need for the either try/catch block at all. Just let the exception percolate up the call stack. You're hiding the IOException now, preventing anyone calling grabPlaneRoute from discovering that an error occurred.

It's fairly impossible for StringBuilder total = new StringBuilder(); to cause a NullPointerException. On the other hand, the nearest cause of the Exception is in the logtrace:
at java.io.Reader.<init>(Reader.java:65)
at java.io.InputStreamReader.<init>(InputStreamReader.java:65)
Which makes me think that it's caused by:
BufferedReader r = new BufferedReader(new InputStreamReader(is),8024);
In that case, the only thing that could be null is is.

Related

Can't read from buffered reader in android

I am trying to get data by using API. I get data in bufferedreader which contains multiple lines. But I am not able to extract that in a String. I do know that bufferedreader has data, i have checked by displaying it using multiple .readLine(); but the loop doesn't work.
protected String[][] doInBackground(Cursor[] cursors)
{
String list[][] = new String[cursors[0].getCount()][2];
//while(cursors[0].moveToNext())
{
String DATA="",temp;
String baseAddress="http://www.alphavantage.co/query?function=TIME_SERIES_INTRADAY";
String apiKey="J63P";
Uri Url = Uri.parse(baseAddress)
.buildUpon()
.appendQueryParameter("symbol","SBIN")
.appendQueryParameter("interval","1min")
.appendQueryParameter("apikey",apiKey)
.build();
Log.d("built URL",Url.toString());
try
{
url= new URL(Url.toString());
urlconnection= (HttpURLConnection) url.openConnection();
urlconnection.setRequestMethod("GET");
urlconnection.connect();
InputStream inputStream = urlconnection.getInputStream();
if (inputStream==null)
{
Log.d("inputstream","empty");
return null;
}
BufferedReader reader= new BufferedReader(new InputStreamReader(inputStream));
while((temp = reader.readLine())!=null)
{
DATA.concat(temp);
}
Log.d("unedited",DATA);
}
catch(IOException e)
{
Log.e("createList", "Error in url ", e);
return null;
}
try {
String List = "Time Series (1min)";
JSONObject full = new JSONObject(DATA);
JSONArray permin = full.getJSONArray(List);
for (int i=0;i<permin.length();i++)
{
String open,high,low,close;
JSONObject current = permin.getJSONObject(i);
open = current.getString("1. open");
high = current.getString("2. high");
low = current.getString("3. low");
close = current.getString("4. close");
Log.d("Extracted ",open + " " + high + " " + low + " " + close +"\n");
}
}
catch (JSONException e)
{
Log.e("createList","Error in json",e);
}
}
return list;
}
and Log is:
04-24 14:34:52.009 3574-3619/lcukerd.com.stocknotifier D/built URL: http://www.alphavantage.co/query?function=TIME_SERIES_INTRADAY&symbol=SBIN&interval=1min&apikey=J63P
04-24 14:34:53.723 3574-3619/lcukerd.com.stocknotifier E/createList: Error in json
org.json.JSONException: End of input at character 0 of
at org.json.JSONTokener.syntaxError(JSONTokener.java:450)
at org.json.JSONTokener.nextValue(JSONTokener.java:97)
at org.json.JSONObject.<init>(JSONObject.java:156)
at org.json.JSONObject.<init>(JSONObject.java:173)
at lcukerd.com.stocknotifier.MainActivity$createList$override.doInBackground(MainActivity.java:123)
at lcukerd.com.stocknotifier.MainActivity$createList$override.access$dispatch(MainActivity.java)
at lcukerd.com.stocknotifier.MainActivity$createList.doInBackground(MainActivity.java:0)
at lcukerd.com.stocknotifier.MainActivity$createList.doInBackground(MainActivity.java:69)
at android.os.AsyncTask$2.call(AsyncTask.java:288)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
at java.lang.Thread.run(Thread.java:818)
Also, note that "Log" statement after inner while loop is also not working.
Pls, Help me Solve it.
You got exception in the Json data, it is very clear from the log, it says:
04-24 14:34:53.723 3574-3619/lcukerd.com.stocknotifier E/createList:
Error in json
Oh yeah:
Change this line:
DATA.concat(temp);
To
data = DATA.concat(temp);
Also in java it's better to write it this way:
data += temp;

android- Intentional '%' in string throws IllegalArgumentException

I am making a http call to an api for a string response.
The result contains intentional % signs in a sentence like:
"This land is 95% fertail and 5% contaminated"
Android throws IllegalArgumentException: Invalid % sequence at 1756 which corresponds to the "95%" part.
EDIT: StackTrace:
java.lang.RuntimeException: An error occured while executing doInBackground()
at android.os.AsyncTask$3.done(AsyncTask.java:300)
at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:355)
at java.util.concurrent.FutureTask.setException(FutureTask.java:222)
at java.util.concurrent.FutureTask.run(FutureTask.java:242)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
at java.lang.Thread.run(Thread.java:818)
Caused by: java.lang.IllegalArgumentException: Invalid % sequence at 1756: [{"address":{"addressComponen...
My httpGet method:
public String makeHttpGetRequestUtf8(String urlStr) throws IOException {
String result = "";
try {
URL url = new URL(urlStr);
BufferedReader brIn = new BufferedReader(new InputStreamReader(url.openStream(), "UTF-8"));
String line = "";
while ((line = brIn.readLine()) != null)
result += line;
}catch (Exception e){
Log.e("HTT_GET", "Failed to make httpGetRequestUtf8: " + e);
}
String afterDecode = URLDecoder.decode(result, "UTF-8");
return afterDecode;
}
Android throws IllegalArgumentException: Invalid % sequence at 1756 which corresponds to the "95%" part.
Server writes this data with this metod and so I believe the encoding should be fine?
File file = new File(path/filename.txt);
String content = writeMeToFile;
Writer out;
try{
out = new BufferedWriter(new OutputStreamWriter(
new FileOutputStream(file), "UTF8"));
if(!file.exists()){
file.createNewFile();
}else{
FileUtils.copyFile(file, dest);
out.write(content);
out.close();
}
} catch (IOException e) {
Logger.getLogger(UpdateAds.class.getName()).log(Level.SEVERE, null, e);
}
Side question/note: Somehow characters like 'ä', 'ö', 'ü', 'õ' are fine in the browser but show up as � in android.
I don't understand at which side am I encoding the string wrong. Since the text is fine in the browser I am thinking it's android, but the httpGet method is done by the book.
Thanks!

Unknown error while calling Web API from Android

i am trying to send a JSONObject as input parameter for a C# Web API with the following code
protected String doInBackground(JSONObject... companyInfo) {
try {
URL url;
URLConnection urlConn;
url = new URL(HOST_NAME + WEB_API_METHOD);
urlConn = url.openConnection();
urlConn.setDoInput(true);
urlConn.setDoOutput(true);
urlConn.setUseCaches(false);
urlConn.setRequestProperty("Content-Type", "application/json");
urlConn.setRequestProperty("Host", HOST_NAME);
urlConn.connect();
PrintWriter out = new PrintWriter(urlConn.getOutputStream());
out.print(companyInfo[0]);
out.close();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(urlConn.getInputStream()));
StringBuilder stringBuilder = new StringBuilder();
String line;
while ((line = bufferedReader.readLine()) != null) {
stringBuilder.append(line).append("\n");
}
bufferedReader.close();
Log.i("companyInfo > ", stringBuilder.toString());
}
catch (Exception ex)
{
Log.e("Exception", ex.getLocalizedMessage());
}
return null;
}
When this is called, the method doesn't execute and when i try to catch the error, i don't get a meaningful message. it shows the URL name and thats it.
I am unable to find the issue and any help would be appreciated.
this is the error i got
java.io.FileNotFoundException: http://MY_FULL_URL
at com.android.okhttp.internal.huc.HttpURLConnectionImpl.getInputStream(HttpURLConnectionImpl.java:238)
at com.fourtyninetons.NewCompanyActivity$saveCompanyProfile.doInBackground(NewCompanyActivity.java:103)
at com.fourtyninetons.NewCompanyActivity$saveCompanyProfile.doInBackground(NewCompanyActivity.java:70)
at android.os.AsyncTask$2.call(AsyncTask.java:295)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:234)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
at java.lang.Thread.run(Thread.java:818)
Lakshman.
As mentioned in the solution of this question, the problem is with the web api method and the backend database. Fiddler helped me solve the issue and the above code is working fine.
Useful Tip: When anyone gets this FileNotFoundExceptionuser POSTMAN or FIDDLER to execute the method and find for the errors.
Thank you everyone who attempted to solve this.

Android API error / httpget NetworkOnMainThreadException [duplicate]

This question already has answers here:
How can I fix 'android.os.NetworkOnMainThreadException'?
(66 answers)
Closed 8 years ago.
This is my error message:
08-17 07:58:14.286 32620-32620/xxx.dk.xxx E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: xxx.dk.xxx, PID: 32620
android.os.NetworkOnMainThreadException
at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1239)
at java.net.InetAddress.lookupHostByName(InetAddress.java:388)
at java.net.InetAddress.getAllByNameImpl(InetAddress.java:239)
at java.net.InetAddress.getAllByName(InetAddress.java:214)
at com.android.okhttp.internal.Dns$1.getAllByName(Dns.java:28)
at com.android.okhttp.internal.http.RouteSelector.resetNextInetSocketAddress(RouteSelector.java:216)
at com.android.okhttp.internal.http.RouteSelector.next(RouteSelector.java:122)
at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:292)
at com.android.okhttp.internal.http.HttpEngine.sendSocketRequest(HttpEngine.java:255)
at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:206)
at com.android.okhttp.internal.http.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:345)
at com.android.okhttp.internal.http.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:89)
at xxx.dk.xxx.DAL.JsonConnection.checkSecret(JsonConnection.java:42)
at xxx.dk.xxx.BLL.CheckCarrierData.checkSecret(CheckCarrierData.java:14)
at xxx.dk.xxx.GUI.Login.onClick(Login.java:49)
at android.view.View.performClick(View.java:4480)
at android.view.View$PerformClick.run(View.java:18686)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:157)
at android.app.ActivityThread.main(ActivityThread.java:5872)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:858)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:674)
at dalvik.system.NativeStart.main(Native Method)
Im trying to use a httpGet method, which is working on API10, but it fails when im using it on an unit with 4.4.2 -> i need the support from API10 and up.
The code:
public class JsonConnection
{
private String secretJsonStr = null;
private String nameOfCarrier = "";
public String checkSecret(String secret)
{
HttpURLConnection urlConnection = null;
BufferedReader reader = null;
final String QueryParam = "secret";
try
{
final String httpUrl = "***SOMEURL***?";
Uri builtUri = Uri.parse(httpUrl).buildUpon().
appendQueryParameter(QueryParam, secret.toString()).build();
URL url = new URL(builtUri.toString());
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.connect();
// Read the input stream into a String
InputStream inputStream = urlConnection.getInputStream();
StringBuffer buffer = new StringBuffer();
if (inputStream == null)
{
// Nothing to do.
return null;
}
reader = new BufferedReader(new InputStreamReader(inputStream));
String line;
while ((line = reader.readLine()) != null)
{
buffer.append(line + "\n");
}
if (buffer.length() == 0)
{
// Stream was empty. No point in parsing.
return null;
}
secretJsonStr = buffer.toString();
} catch (IOException e)
{
Log.e("Login", "Error", e);
return null;
} finally
{
if (urlConnection != null)
{
urlConnection.disconnect();
}
if (reader != null)
{
try
{
reader.close();
} catch (final IOException e)
{
Log.e("Login", "Error closing stream", e);
}
}
}
try
{
JSONObject secretJson = new JSONObject(secretJsonStr);
nameOfCarrier = getCarrierInfoFromJson(secretJson);
}
catch (JSONException e)
{
e.printStackTrace();
}
return nameOfCarrier;
}
private String getCarrierInfoFromJson(JSONObject secretJson)
throws JSONException
{
final String CARRIER_NAME = "Name";
String nameOfCarrier2 = secretJson.getString(CARRIER_NAME);
return nameOfCarrier2;
}
}
Due to some protection, i cannot show you the URL, but everything is working like a charm when running in API 10 2.3.6 units..
I though there where complete backwards compatibility on all android devices.
Hope you have the knowledge to help me on, I for sure cannot see how. :-(
Kindest regards
Rasmus
The problem is that the http requests are executed on the main thread (NetworkOnMainThreadException), so you need to move the calls into a Thread. More info here.
update: actually, possible duplicate of this.
As error say you can't execute an HTTP connection on the MainThread that would froze the screen. which is not appropriate.
You can get that permission as the following:
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
But, this is not a good practice. you must run the http connection on a background thread and display a loading msg to the user.
new Thread(new Runnable() {
#Override
public void run() {
// code goes here ...
}
}).start();
As other answers are suggesting, you are getting this error because you are running network operation on main thread. I would suggest to use AsyncTask.
This link shows you structure of AsyncTask.
To call the AsyncTask, use
//getData() is name of class
new getData().execute();
More reference on Android Developer site.

Android Unit Tests

I am trying to write a AndroidTestCase for one of my classes that make connection to a server and parse the returned JSONObject. When I test the functionality in the UI, the file works fine and the correct information are parsed and displayed. When I input the URL into my browser, I get the correct JSONObject back. However, when I try to get the JSONObject through a AndroidTestCase and simply verifying that it's not null, I get IOException when it tries to get the corresponding JSONObject for an url. I verified that the url it's using is correct. Here's the stack trace.
java.net.UnknownHostException: api.penncoursereview.com
at java.net.InetAddress.lookupHostByName(InetAddress.java:506)
at java.net.InetAddress.getAllByNameImpl(InetAddress.java:294)
at java.net.InetAddress.getAllByName(InetAddress.java:256)
at org.apache.harmony.luni.internal.net.www.protocol.http.HttpConnection.<init>(HttpConnection.java:69)
at org.apache.harmony.luni.internal.net.www.protocol.http.HttpConnection.<init>(HttpConnection.java:48)
at org.apache.harmony.luni.internal.net.www.protocol.http.HttpConnection$Address.connect(HttpConnection.java:322)
at org.apache.harmony.luni.internal.net.www.protocol.http.HttpConnectionPool.get(HttpConnectionPool.java:89)
at org.apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnectionImpl.getHttpConnection(HttpURLConnectionImpl.java:285)
at org.apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnectionImpl.makeConnection(HttpURLConnectionImpl.java:267)
at org.apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnectionImpl.retrieveResponse(HttpURLConnectionImpl.java:1018)
at org.apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnectionImpl.getInputStream(HttpURLConnectionImpl.java:512)
at edu.upenn.cis.cis350.backend.Parser.retrieveJSONObject(Parser.java:34)
at edu.upenn.cis.cis350.test.ParserTest.test_retrieveJSONObject(ParserTest.java:22)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:507)
at junit.framework.TestCase.runTest(TestCase.java:154)
at junit.framework.TestCase.runBare(TestCase.java:127)
at junit.framework.TestResult$1.protect(TestResult.java:106)
at junit.framework.TestResult.runProtected(TestResult.java:124)
at junit.framework.TestResult.run(TestResult.java:109)
at junit.framework.TestCase.run(TestCase.java:118)
at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:169)
at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:154)
at android.test.InstrumentationTestRunner.onStart(InstrumentationTestRunner.java:529)
at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1448)
Any idea why the code works in simulator but not in test?
Thanks in advance for the help!
edit:
Here is the relevant method:
public JSONObject retrieveJSONObject(String path){
try{
URL url = new URL(path);
Log.w("Parser: retrieveJSONObject", "url=" + url);
URLConnection connection = url.openConnection();
String line;
StringBuilder builder = new StringBuilder();
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
while ((line = reader.readLine()) != null) {
builder.append(line);
}
Log.v("Length",builder.toString());
return new JSONObject(builder.toString());
}
catch(IOException e) {
Log.w("Parser: retrieveJSONObject", "IOException: Bad Url");
e.printStackTrace();
return null;
} catch (JSONException e) {
Log.w("Parser: retrieveJSONObject", "JSONException: mis-formatted JSON");
e.printStackTrace();
return null;
}
}
Line 34 is the line initializing the BufferedReader.
I guess what you are missing is the INTERNET permission.
Considering that your method is defined static in Utils class, the following test works.
public void testRetrieveJSONObjectWithUrl() {
final String url = "http://www.bom.gov.au/fwo/IDV60901/IDV60901.94868.json";
assertNotNull(Utils.retrieveJSONObject(url));
}

Categories

Resources