NullPointerException when using Aysnctask in android - android

I am writing an android application, I use Aysnctask to get the current weather using openWeatherAPI. but it gives me a NullPointerException at this line :
results[0]=t;
this is the Aysnctask class I wrote:
private class GetWeather extends AsyncTask<String[], Void, String[]>{
#Override
protected String[] doInBackground(String... params) {
// TODO Auto-generated method stub
try {
params[0]=currentLatitude;
params[1]=currentLongitude;
String Url1="http://api.openweathermap.org/data/2.5/weather?lat="+currentLatitude+"&lon="+currentLongitude;
s1=getJson(Url1);
//Toast.makeText(getApplicationContext(), "the ss = "+s1, Toast.LENGTH_LONG).show();
Log.d("yes","yes");
if(s1!=null){
JSONObject jObj1 = new JSONObject(s1);
Log.d("jsonOOO","jsonOOO");
Tem= jObj1.getJSONObject("main").getDouble("temp");
Log.d("temmm","temmm="+String.valueOf(Tem));
pressure=jObj1.getJSONObject("main").getDouble("pressure");
humm=jObj1.getJSONObject("main").getDouble("humidity");
wind=jObj1.getJSONObject("wind").getDouble("speed");
desc=jObj1.getJSONObject("weather").getDouble("description");
double tem_c=Tem-273.15;
Log.d("tem11","tem11="+String.valueOf(tem_c));
String t=Double.toString(tem_c);
String t=String.valueOf(tem_c);
Log.d("tem22","tem22="+t);
results[0]=t;
Log.d("results[0]=","results[0]"+results[0]);
results[1]=String.valueOf(pressure);
results[2]=String.valueOf(humm);
results[3]=String.valueOf(wind);
results[4]=String.valueOf(desc);
}
} catch (Exception e) {
// TODO: handle exception
}
return results;
}//do in background
#Override
protected void onPostExecute(String[] results) {
temp.setText(results[0]+"°C");
hum.setText(results[1]+ "%");
press.setText(results[2]+ " hPa");
windSpeed.setText(results[3]+ " mps");
condDescr.setText(results[4]);
}
}
the value of temp,pressure, etc.. is not null. I tried to print them in logCat and they were printed.

The results array needs to be declared and initialized (probably as a local variable in the doInBackground(String) method):
String[] results = new String[5];

It seems like you did not initialize String[] results before you called it.
Hence causing the NullPointerException.

You have to initialize your String Array like this : String[] results = new String[5];

results must be null. Null-check and initialize as below:
Log.d("tem22","tem22="+t);
if (results == null ) { //null-check
results = new String[5]; //initialize
}
results[0]=t;
Log.d("results[0]=","results[0]"+results[0]);
results[1]=String.valueOf(pressure);
results[2]=String.valueOf(humm);
results[3]=String.valueOf(wind);
results[4]=String.valueOf(desc);
To avoid such exceptions, it is better to configure your IDE to warn you about potential null de-referencing
(e.g in Eclipse -> Preferences -> Java -> Compiler -> Errors -> Warnings ->Null analysis)

Related

Search query in android studio not workng properly

Okay so I made module for searching medicines and display items in a listview, I am using JDBC here. The main issue is when I place an underscore_ in the searchview, It kind of makes a bug where the listview items duplicate themselves.
Based on my observation; this bug only occurs when the underscore is inserted simultaneously, but if pressed at slower interval, It doesn't duplicate items anyway.
Here is what it looks without anything on the SearchView:
This is when underscores are placed at slower interval
And even if underscores doesn't exist in the listview it still displays it, but when I add even more underscores, they started to disappear one by one starting from the bottom.
And here's the main problem; when Underscores are placed simultaneously
Here are my code for the search in AsyncTask
private class searchUnfiltered extends AsyncTask<String, String, String> {
String z = "";
String fromSearchView = sv.getQuery().toString().trim();
boolean isSuccess = false;
String about;
#Override
protected void onPreExecute() {
myArrayList2.clear();
myArrayList.clear();
super.onPreExecute();
}
#Override
protected String doInBackground(String... params) {
try {
Connection con = connectionClass.CONN();
if (con == null) {
z = "Please check your internet connection";
} else {
String querySearch = "select name from medicines where name like '%"+ fromSearchView +"%' order by name ASC";
Statement stmt1 = con.createStatement();
ResultSet rs1 = stmt1.executeQuery(querySearch);
if(rs1 != null) {
while (rs1.next()) {
myArrayList2.add(rs1.getString("name"));
}
}
}
} catch (Exception ex) {
isSuccess = false;
z = "Exceptions" + ex;
}
return z;
}
#Override
protected void onPostExecute(String s) {
if(!isSuccess && !z.equals("")) {
Toast.makeText(getBaseContext(), z, Toast.LENGTH_LONG).show();
}
ListAdapter listAdapter = new ArrayAdapter<>(MedicineSearch.this, android.R.layout.simple_list_item_1, myArrayList2);
lv.setAdapter(listAdapter);
}
}
Whenever value is changed in search view the searchUnfiltered will be triggered, please tell me if what I'm doing is efficient or if you have any better suggestions, it would be very helpful.
That is a race condition reason you are clearing the data onPreExecute then doInBackground is working typing 5 _ at a fast pace will clear 5 times before you get any results back.
as a Solution move:
myArrayList2.clear();// if this didn't work try myArrayList2 = new ArrayList<>();
from onPreExecute to doInBackground.

Arraylist of strings into one comma separated string

Trying to convert a Arraylist of strings into one big comma separated string.
However when I use the
String joined = TextUtils.join(", ", participants);
Debugger shows me size of 4 for participants however the joined value as "" therefore empty
private ArrayList<String> participants;
Not sure what is going wrong?
UPDATE:
List<String> list = new ArrayList<>();
list.add("Philip");
list.add("Paul Smith");
list.add("Raja");
list.add("Ez");
String s = TextUtils.join(", ", list);
This works when I have a list that I manually populate however below is how the code is working right now.
In the onCreate()
callApi(type);
String s = TextUtils.join(", ", participants);
getSupportActionBar().setTitle(s);
In callAPI():
JSONArray participantsR = sub.getJSONArray("referralParticipants");
Log.e("Participants length ", String.valueOf(participantsR.length()));
for (int i = 0; i < participantsR.length(); i++)
{
JSONObject object = participantsR.getJSONObject(i);
String firstname = (String) object.get("fullName");
participants.add(firstname);
Log.e("Times", String.valueOf(i));
}
I'm trying to reproduce your error and am unable to. Here is my code:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_temp);
List<String> list = new ArrayList<>();
list.add("Philip Johnson");
list.add("Paul Smith");
list.add("Raja P");
list.add("Ezhu Malai");
String s = TextUtils.join(", ", list);
Log.d(LOGTAG, s);
}
My output is Philip Johnson, Paul Smith, Raja P, Ezhu Malai as expected.
Are you importing the correct TextUtils class?
android.text.TextUtils;
Given the new information, here is my approach:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_temp);
callApi(type, new OnResponseListener<List<String>>() {
#Override public void onResponse(List<String> list) {
getSupportActionBar().setTitle(TextUtils.join(", ", list));
}
});
}
I don't know what networking library you're using, but you may have to define OnResponseListener as an interface. It's very easy:
public interface OnResponseListener<T> {
public void onResponse(T response);
}
You will then need to modify your callApi function to take an instance of OnResponseListener> and call it's onResponse method after completing the call.
I would recommend looking into the Volley library, and reading the Android documentation about simple network calls.
I use StringUtils.join from Apache Common Utilities.
The code is super-simple just the way you wanted,
StringUtils.join(participants,", ");
Works flawlessly for me.
EDIT
As requested, here is the StringUtils.java file for those who just want to use this single utility class and not the entire library.
I don't know what TextUtils does. This will do it.
StringBuffer sb = new StringBuffer();
for (String x : participants) {
sb.append(x);
sb.append(", ");
}
return sb.toString();
Easy enough, just use that.
Try with kotlin
val commaSeperatedString = listOfStringColumn.joinToString { it ->
"\'${it.nameOfStringVariable}\'" }
// output: 'One', 'Two', 'Three', 'Four', 'Five'

how to call Aysnctask in android

I am writing an android application, I use Aysnctask to get the current weather using openWeatherAPI. How could I call the Aysnctask class.
this is the Aysnctask class I wrote:
private class getWeather extends AsyncTask<String[], Void, String[]>{
#Override
protected String[] doInBackground(String[]... params) {
// TODO Auto-generated method stub
try {
String Url1="http://api.openweathermap.org/data/2.5/weather?lat="+currentLatitude+"&lon="+currentLongitude;
s1=getJson(Url1);
if(s1!=null){
JSONObject jObj1 = new JSONObject(s1);
Tem= jObj1.getJSONObject("main").getDouble("temp");
pressure=jObj1.getJSONObject("main").getDouble("pressure");
humm=jObj1.getJSONObject("main").getDouble("humidity");
wind=jObj1.getJSONObject("wind").getDouble("speed");
desc=jObj1.getJSONObject("weather").getDouble("description");
double tem_c=Tem-273.15;
String t=Double.toString(tem_c);
results[0]=t;
results[1]=Double.toString(pressure);
results[2]=Double.toString(humm);
results[3]=Double.toString(wind);
results[4]=Double.toString(desc);
}
} catch (Exception e) {
// TODO: handle exception
}
return results;
}//do in background
#Override
protected void onPostExecute(String[] results) {
temp.setText(results[0]+"°C");
hum.setText(results[1]+ "%");
press.setText(results[2]+ " hPa");
windSpeed.setText(results[3]+ " mps");
condDescr.setText(results[4]);
}
}
when I press a button, I want to get the weather of current latitude and longitude, but I don't know how to execute the class
try this
getWeather gt= new getWeather();
gt.execute(new String{currentLatitude,currentLongitude});
Per the android docs here, which have plenty of examples, you would do:
new GetWeather().execute(currentLatitude,currentLongitude);
I would personally shy away from holding a reference to it but rather send in what you need or use a listener. Also, please capitalize you classes :)
You access both of them like so in doInBackGround
String latitutde= params[0];
String longitude = params[1];
An example on the docs which you can look at is:
new DownloadFilesTask().execute(url1, url2, url3);
As you can see, pass however many parameters you need and it'll just be accessible in the array from the first generic parameter you mention. In your case its a String array, so you'd send only Strings.
Try this..
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
new getWeather(currentLatitude,currentLongitude).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, new String[]{null});
else
new getWeather(currentLatitude,currentLongitude).execute(new String[]{null});
and also add constructor to your async task
String currentLatitude;
String currentLongitude;
// constructor
#SuppressWarnings("rawtypes")
public getWeather(String currentLatitude, String currentLongitude) {
this.currentLatitude = currentLatitude;
this.currentLongitude = currentLongitude;
}
EDIT 1:
You cannot parse double to string like this String t=Double.toString(tem_c);
you need to parse like below codes.
String t = String.valueOf(tem_c);
results[0] = t;
results[1] = String.valueOf(pressure);
results[2] = String.valueOf(humm);
results[3] = String.valueOf(wind);
results[4] = String.valueOf(desc);

Pulling data from a remote mySQL database, using AsyncTask; only displaying very last table row

As the title says really. I have two columns. I want to put them into textviews so I did it. However only the bottom two results, one from each column gets shown. Very odd. Here is my code: http://pastebin.com/qNgfHfT3
The parsing/onPostExecute is towards the bottom where the issue is.
One thing to note: The logs labeled "work" & "dontwork" show all my results, however the logs in the onPostExecute (Google & Google1) only show the last result so I presume the error is in the transfer from parsing to displaying.
Would really appreciate any help here. Thanks.
If you are receiving a JSON response I'd suggest you to parse it by using Gson. It's strongly recommendable as long as you can parse the whole thing in a pair of lines.
Note that creating a proper object it is as easy as doing the following:
YourObject object = gson.fromJson(responseReader, YourObject.class);
or even if you are retrieving a list of items:
Type listType = new TypeToken<List<YourObject>>() {}.getType();
List<YourObject> objects = gson.fromJson(responseReader, listType);
Here's an example that fits exactly your needs
After the process is done you'll have your object (or list of objects) available in an accesible variable.
EDIT:
First your Asynctask should have the following params:
public class HttpTask extends AsyncTask<Void, Void, ArrayList<Driver>> {
and your doInBackground method will need to pass that array to your onPostExecute:
#Override
protected ArrayList<Driver> doInBackground(Void... params) {
For the rest, I take it when the JSon parsing starts.
//PARSING JSON DATA
try {
JSONObject json_data;
Driver d;
jArray = new JSONArray(result);
int l = jArray.length();
if(l>0){
ArrayList<Driver> drivers = newArrayListList<Driver>();
for (int i = 0; i < l; i++) {
json_data = jArray.getJSONObject(i);
d = new Driver(json_data.optString("Driver_full_name"), json_data.optString("Drives_for"));
drivers.add(d);
Log.i("work", returnString);
Log.i("dontwork", somethingelse);
}
} catch (JSONException e1) {
Log.d("DB", "Error somewhere");
CurrentSeasonDrivers_DriverName.this.runOnUiThread(new Runnable() {
public void run() {
Toast.makeText(CurrentSeasonDrivers_DriversName, "Could not parse data so shut up", Toast.LENGTH_LONG).show();
}
});
}
return drivers;
}
protected void onPostExecute(ArrayList<Drivers>... drivers) {
Log.i("Google", returnString);
Log.i("Google1", somethingelse);
String firstDriverName = drivers.get(0).name;
String firstDriverDrivesFor = drivers.get(0).drivesfor;
String secondDriverName = drivers.get(1).name;
TextView drivername = (TextView) findViewById(R.id.DriverName);
drivername.setText(firstDriverName);
TextView drivesfor = (TextView) findViewById(R.id.DrivesFor);
drivesfor.setText(firstDriverDrivesFor);
}
With this and an object for your driver will complete the circle.
public class Driver{
public String name;
public String drivesfor;
public Driver(String _name, String _drivesfor){
name = _name;
drivesfor = _drivesfor;
}
}
I guess you can take over from here.
Let me know about your progress.

Android, Null Pointer Exception to Data that isn't null

I'm writing an app for android that needs to parse data from an XML file. I've never come across an error like this that is so impossibly hard to track down. Or maybe my brain just stopped working. That happens. XML file is of the form:
<?xml version="1.0" encoding="iso-8859-1"?>
<memberRoster>
<agent>
<agentInfo1>...</agentInfo1>
<agentInfo2>...</agentInfo2>
...
</agent>
<agent>
...
</agent>
...
</memberRoster>
So far it's working well, except for some random bits of fun!
Every now and then it will throw a NullPointerException. I did some more digging and found out that there are THREE "agents" (out of 800) with "supposedly" null data. I checked the XML file and the data is there, there are no illegal characters, etc. It is the same three "agents" every time. The program parses other entries before and after these "null" "agents". Also of note is that not all "agentInfo" fields in the ArrayList come up null; example, one of the entries has 7 of the 8 entries as null, with the 8th one non-null, another has only one null with the last 7 non-null.
I'm parsing the data in to an ArrayList from the XML file, and like I mentioned before, it works flawlessly until it comes to those three specific entries in the XML file.
I'm sorry I can't give much more info than that, the data is sensitive to our members.
EDIT:
Sorry! I knew I was forgetting something! :)
Some code from my XMLHandler.java class:
public void characters(char[] ch, int start, int length)
if(this.in_mr_agentNrdsId) {
agent[0] = ch.toString();
}
else if(this.in_mr_agentFirstName) {
agent[1] = ch.toString();
}
else if(this.in_mr_agentLastName) {
agent[2] = ch.toString();
}
else if(this.in_mr_agentPhone) {
agent[3] = ch.toString();
}
else if(this.in_mr_agentEmail) {
agent[4] = ch.toString();
}
else if(this.in_mr_agentOfficeName) {
agent[5] = ch.toString();
}
else if(this.in_mr_agentOfficePhone) {
agent[6] = ch.toString();
}
else if(this.in_mr_agentType) {
agent[7] = ch.toString();
pds.setMemberRoster(agent);
agent = new String[8];
}
PDS is an object of type ParsedDataSet, which is just a simple class containing the ArrayList objects and a few getter and setter methods:
public class ParsedDataSet {
private ArrayList agentOpenHouses = new ArrayList();
private ArrayList calendarOfEvents = new ArrayList();
private ArrayList latestStatistics = new ArrayList();
private ArrayList memberRoster = new ArrayList();
public ArrayList<String[]> getAgentOpenHouses() {
return agentOpenHouses;
}
public ArrayList<String[]> getCalendarOfEvents() {
return calendarOfEvents;
}
public ArrayList<String[]> getLatestStatistics() {
return latestStatistics;
}
public ArrayList<String[]> getMemberRoster() {
return memberRoster;
}
public void setAgentOpenHouses(String[] agentOpenHousesItem) {
this.agentOpenHouses.add(agentOpenHousesItem);
}
public void setCalendarOfEvents(String[] calendarOfEventsItem) {
this.calendarOfEvents.add(calendarOfEventsItem);
}
public void setLatestStatistics(String[] latestStatisticsItem) {
this.latestStatistics.add(latestStatisticsItem);
}
public void setMemberRoster(String[] memberRosterItem) {
this.memberRoster.add(memberRosterItem);
}
} // end class ParsedDataSet
You could throw an if statement into your assignements and reassign any caught 'NULL' or empty strings into a zero value or just reassign as variable = "" in your code.
For example:
if (agentInfo1 == NULL) {
agentInfo1 = "" || agentInfo1 = 0; //Depending on what your variables are
}
Try putting try catch loop in code to find where the error is happening, then, pinpoint the exact part of code that is giving this error, there do null checks before proceeding. This is based on best practices of software development, rather than a fix for you.
Alternatively, you can makes sure on server side that there are no "null" values, maybe by giving dummy value like "EMPTY_STRING". This is especially relevant if your app is already shipped and you cant make any client code changes.

Categories

Resources