java.lang.NullPointerException Can't set text from class to activity [duplicate] - java

This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 2 years ago.
I'm rather new to coding and my long term goal is to create an android weather app. I've created the main activity and a class, plus I'm using Weatherlib to make things a bit easier.
The main activity asks for permission and grabs the location using GPS. Those coords are sent to the getweather method which grabs the information using OpenWeatherMap. When the data is retrieved, in this case, cloud percentage, what I want it to do is pass that to the main activity to setText for the TextView clouds. My issue is that it's throwing a NullPointerException when I try to do that from onWeatherRetrieved.
public class MainActivity extends AppCompatActivity {
private double latitude;
private double longitude;
private FusedLocationProviderClient fusedLocationClient;
private String response;
private TextView clouds;
private Context context;
private Context x;
private WeatherOWM weatherOWM;
//Get location
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
clouds = findViewById(R.id.clouds);
x = this;
context = getApplicationContext();
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
requestPermissions();
fusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
if (ActivityCompat.checkSelfPermission(this, ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED){
return;
}
fusedLocationClient.getLastLocation().addOnSuccessListener (this, new OnSuccessListener<Location>() {
#Override
public void onSuccess(Location location) {
if (location != null){
double latitude = location.getLatitude();
double longitude = location.getLongitude();
System.out.println(latitude + " " + longitude);
WeatherOWM loc = new WeatherOWM(latitude, longitude, context);
loc.getWeather();
}
}
});
}
public void setClouds(Integer cloud) {
clouds.setText(cloud);
}
private void requestPermissions(){
ActivityCompat.requestPermissions(this, new String[]{ACCESS_FINE_LOCATION}, 1);
}
}
public class WeatherOWM{
private double latitude;
private double longitude;
private Context ma;
WeatherConfig config = new WeatherConfig();
private Object WeatherConfig;
private Object hourForecast;
private Object MainActivity;
private MainActivity mainActivity;
public WeatherOWM(double latitude, double longitude, Context ma){
this.latitude = latitude;
this.longitude = longitude;
this.ma = ma;
}
public void getWeather() {
TextView clouds = new TextView(ma);
//Init client
WeatherClient client = null;
config.ApiKey = "REDACTED";
try {
client = (new WeatherClient.ClientBuilder()).attach(ma)
.httpClient(WeatherDefaultClient.class)
.provider(new OpenweathermapProviderType())
.config(config)
.build();
} catch (WeatherProviderInstantiationException e) {
e.printStackTrace();
}
client.getHourForecastWeather(new WeatherRequest(latitude, longitude), new WeatherClient.HourForecastWeatherEventListener() {
#Override
public void onWeatherRetrieved(WeatherHourForecast weatherHourForecast) {
List<HourForecast> hourList = weatherHourForecast.getHourForecast();
for (HourForecast hourForecast: hourList) {
Weather weather = hourForecast.weather;
long timestamp = hourForecast.timestamp;
mainActivity.setClouds(hourForecast.weather.clouds.getPerc());
System.out.println(hourForecast.weather.clouds.getPerc());
}
}
#Override
public void onWeatherError(WeatherLibException wle) {
System.out.println("ERROR");
}
#Override
public void onConnectionError(Throwable t) {
System.out.println("ERROR");
}
});
}
}

In the WeatherOWM class , you have created an instance of MainActivity as here :
private MainActivity mainActivity;
and in the method , you have written :
mainActivity.setClouds(hourForecast.weather.clouds.getPerc());
the problem is that the variable "mainActivity" has no value and is empty so you have to give value to it.
so in the WeatherOWM class , write this code :
mainActivity = new MainActivity();
please reply is solved your problem

Related

Current Location with Geocoder not working for non activities

I am currently building an Android app and my main problem is that I have a class that retrieves the current latitude and longitude of my current location.
Whenever I make an activity out of it, it works fine. However, now that I;m trying to make it a class that will just retrieve the latitude and longitude and will set it to a setter, it doesn't work.
Namely, I am using FusedLocationProviderClient and Geocoder in order to retrieve those two elements.
The problem is that both of them won't take the current object as an argument (context, since it's a non activity class), whereas they work just fine with activities. In other words, this doesn't apply whenever I apply this for the context. Below is my class, with the problems that I am facing.
I would appreciate some help here thank you in advance.
public class CurrentLocationFinder {
FusedLocationProviderClient fusedLocationProviderClient;
double lagitudeValue, longitudeValue;
private final static int REQUEST_CODE = 100;
public CurrentLocationFinder() {
fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this);//*******doesn't accept 'this' in method
getLastLocation();
}
private void getLastLocation() { //doesn't accept 'this'
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
fusedLocationProviderClient.getLastLocation().addOnSuccessListener(location -> {
if (location != null) {
Geocoder geocoder = new Geocoder(this, Locale.getDefault()); //doesn't accept 'this'
List<Address> addressList = null;
try {
addressList = geocoder.getFromLocation(location.getLatitude(), location.getLongitude(), 1);
System.out.println("********************" + addressList.get(0).getLatitude());
setLagitude(addressList.get(0).getLatitude());
setLongitude(addressList.get(0).getLongitude());
System.out.println("=====================" + addressList.get(0).getLatitude());
} catch (IOException e) {
e.printStackTrace();
}
}
});
} else {
//askPermission();
}
}
public double getLagitude() {
return this.lagitudeValue;
}
public double getLongitude() {
return this.longitudeValue;
}
public void setLagitude(double lagitude) {
this.lagitudeValue = lagitude;
}
public void setLongitude(double longitude) {
this.longitudeValue = longitude;
}
}

Android: String array becomes null when I pass it back to MapsActivity from a class which uses an async task

I am fairly new to Android development and am creating an application which uses a Google map fragment. I am querying the Google Directions Api and retrieving JSON data using an AsyncTask method. I then decode the polyline and in turn gain a string array of LatLon pairs. I now would now like to use this string array back in my MainActivity. I have tried many ways to do this, however every single way has made the string array null.
Method tried = 1) using a static field 2) using Intent objects to transfer data 3) creating an interface.
Could someone please tell me as to how I should go around this and why it keeps becoming null in my MainActivity? Snippets of my code are below, thanks.
public class GetDirectionsData extends AsyncTask<Object, String,
String>
{
private GoogleMap mMap;
private Context context;
private String url , googleDirectionsData;
private String distance,duration;
private LatLng destinationLatLng;
private String[] directionsList;
public GetDirectionsData(Context context)
{
this.context = context;
}
#Override
protected String doInBackground(Object... objects)
{
mMap = (GoogleMap)objects[0];
url = (String)objects[1];
destinationLatLng = (LatLng)objects[2];
DownloadUrl downloadURL = new DownloadUrl();
try
{
googleDirectionsData = downloadURL.readUrl(url);
}
catch (IOException e)
{
e.printStackTrace();
}
return googleDirectionsData;
}
#Override
protected void onPostExecute(String s)
{
// uses other class DataParser to extract relevant JSONdata and
// displays polyline
DataParser directionParser = new DataParser();
directionsList = directionParser.parseDirections(s);
displayDirection(directionsList);
}
public void displayDirection(String[] directionsList)
{
int count = directionsList.length;
for(int i = 0; i < count; i++)
{
PolylineOptions options = new PolylineOptions();
options.color(Color.BLUE);
options.width(10);
options.addAll(PolyUtil.decode(directionsList[i])); // decode polylines
mMap.addPolyline(options);
}
}
I now want to pass directionsList string array back to MapsActivity Below
public class MapsActivity extends FragmentActivity
{
public void onClick(View v)
{
Object directionDataTransfer[];
// DIRECTIONS BUTTON
switch(v.getId())
{
case R.id.IB_search:
directionDataTransfer = new Object[3];
GetDirectionsData getDirectionsData = new GetDirectionsData(this);
String directionsUrl = getDirectionsUrl();
directionDataTransfer[0] = mMap;
directionDataTransfer[1] = directionsUrl;
directionDataTransfer[2] = new LatLng(//destination LatLon)
getDirectionsData.execute(directionDataTransfer);
Toast.makeText(MapsActivity.this, "Fetching directions", Toast.LENGTH_LONG).show();
}
}
private String getDirectionsUrl()
{
StringBuilder googleDirectionsUrl = new StringBuilder("https://maps.googleapis.com/maps/api/directions/json?");
googleDirectionsUrl.append("origin=" + originLat + "," + originLon);
googleDirectionsUrl.append("&destination=" + destinationLat + "," + destinationLon);
googleDirectionsUrl.append("&mode=" + modeOfTransport);
googleDirectionsUrl.append("&waypoints=via:" + waypointsLat + "," + waypointsLon);
googleDirectionsUrl.append("&key=" + googleApiKey);
return( googleDirectionsUrl.toString() );
}
}
Here is one of the example using Interface - hope this helps.
DummyAsyncTask.java
import android.os.AsyncTask;
public class DummyAsyncTask extends AsyncTask<Void, Void, String> {
private DummyInterface mListener = null;
DummyAsyncTask(DummyInterface listener) {
mListener = listener;
}
#Override
protected String doInBackground(Void... voids) {
return s; // return your string from doInBackground(it will be available as a parameter in onPostExecute())
}
#Override
protected void onPostExecute(String s) {
if(mListener != null) {
mListener.onCallback(s); // sending string s back to activity which registered for callback
}
}
}
DummyInterface.java
public interface DummyInterface {
void onCallback(String s); // callback API
}
DummyActivity.java
import android.app.Activity;
import android.os.Bundle;
public class DummyActivity extends Activity implements DummyInterface{
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
new DummyAsyncTask(this).execute();
}
#Override
public void onCallback(String s) {
System.out.println("String s = " + s);
}
}

requestLocationUpdates throws error

sorry, I know such questions happened here, but I cannot action them in my code, I am a beginner...
So, I am trying to get a GPS coordinates read from LocationManager and my code is throwing a "Can't create handler inside thread that has not called Looper.prepare()".
So my code works this way. I used a Timer and Timertask classes to create a scheduled task from which my coordinates are being read.
This is a timer class:
public class GeoLocationTimer extends Timer {
private List coords;
private Context context;
public GeoLocationTimer(Context context){
this.context = context;
this.coords = new ArrayList<Double>();
//Log.e("cont timer","content" + context);
}
public void addPosition(Double pos) {
this.coords.add(pos);
}
public void scheduleTasks(long interval) {
//Log.e("z schedule","cont"+context);
this.schedule(new GeoLocationTask(this, context), 0, interval);
}
public void cancelTasks() {
this.cancel();
}
public List getList(){
return coords;
}
This is task:
public class GeoLocationTask extends TimerTask{
private final GeoLocationTimer timerContext;
private final Context context;
private Pair<Double, Double> coordsSet;
public GeoLocationTask(GeoLocationTimer timerContext, Context context){
this.timerContext = timerContext;
this.context = context;
}
#Override
public void run() {
// TODO Auto-generated method stub
GeoActivity tracker = new GeoActivity(context);
coordsSet = tracker.getLocation();
Log.e("first","timertask");
if (coordsSet != null){
Log.e("first","a tu wartosc" + coordsSet.first);
Log.e("second","a tu wartosc" + coordsSet.second);
timerContext.addPosition(coordsSet.first);
timerContext.addPosition(coordsSet.second);
//context.addPosition(tracker.getLocationNow().get(1));
}
}
public boolean cancel() {
return false;
}
}
Here is context from which I am trying to run this task:
package com.example.gpstracking;
public class GeoActivity extends ContextWrapper {
Context context;
public GeoActivity(Context base) {
super(base);
this.context = base;
}
public Pair<Double, Double> getLocation(){
Tracking track = new Tracking(context);
return track.getLocation();
}
And tracking now:
public class Tracking extends Service implements LocationListener{
private final Context mContext;
Location location; // location
double latitude; // latitude
double longitude; // longitude
// The minimum distance to change Updates in meters
private static final long MIN_DISTANCE_CHANGE_FOR_UPDATES = 10; // 10 meters
// The minimum time between updates in milliseconds
private static final long MIN_TIME_BW_UPDATES = 1000 * 30 * 1; // 0.5 minute
// flag for GPS status
boolean isGPSEnabled = false;
// flag for network status
boolean isNetworkEnabled = false;
boolean canGetLocation = false;
protected LocationManager locationManager;
public Tracking(Context context) {
this.mContext = context;
}
public Pair<Double, Double> getLocation() {
try {
locationManager = (LocationManager) mContext.getSystemService(LOCATION_SERVICE);
// getting GPS status
isGPSEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
// getting network status
isNetworkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
if (!isGPSEnabled && !isNetworkEnabled) {
// no network provider is enabled
Log.e("no provider","turn it on man!");
} else {
this.canGetLocation = true;
// First get location from Network Provider
if (isNetworkEnabled) {
Log.e("Network", "Network");
location = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
latitude = location.getLatitude();
longitude = location.getLongitude();
Log.e("latitude","latitude"+latitude);
Log.e("longitude","longitude"+longitude);
locationManager.requestLocationUpdates(
LocationManager.NETWORK_PROVIDER,
MIN_TIME_BW_UPDATES,
MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
return new Pair(latitude,longitude);
}
// if GPS Enabled get lat/long using GPS Services
if (isGPSEnabled) {
Log.e("GPS", "GPS");
locationManager.requestLocationUpdates(
LocationManager.GPS_PROVIDER,
MIN_TIME_BW_UPDATES,
MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
longitude = location.getLongitude();
return new Pair(latitude,longitude);
}
}
} catch (Exception e) {
Log.e("excepton:","exp" + e.getMessage());
e.printStackTrace();
e.getMessage();
}
return new Pair(0.0,0.0);
}
#Override
public void onLocationChanged(Location location) {
// TODO Auto-generated method stub
}
So, sorry for being stupid. Could someone help me with this?
Cheers
A
I probably found the issue: I really should not call requestlocationupdates in here, as I am calling for updates in the timer class. Need to go and test it outside :)
Cheers!

Android Asynctask return value in onCreate of Activity

Here in for loop i want to call Async return value. i want to call that value in snippet after title.
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_show_full_map);
Intent i = getIntent();
lat = i.getStringArrayListExtra("L");
longi = i.getStringArrayListExtra("Longitude");
len=lat.size();
for(;j<len;j++){
LatLng location = new LatLng(Double.valueOf(lat.get(j)).doubleValue(),
Double.valueOf(longi.get(j)).doubleValue()) ;
new ReverseGeocodingTask(getBaseContext()).execute(location);
googlemap.addMarker(new MarkerOptions()
.title(plat.get(j).toString())
.snippet(snippet)
.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_CYAN))
.position(location)
);
}
}
Here Below is my AsyncTask code where i am returning the values. please some take a look and explain me my silly mistake....
private class ReverseGeocodingTask extends AsyncTask<LatLng, Void, String>
{
Context mContext;
public ReverseGeocodingTask(Context context){
super();
mContext = context;
}
// Finding address using reverse geocoding
#Override
protected String doInBackground(LatLng... params) {
Geocoder geocoder = new Geocoder(mContext);
double latitude = params[0].latitude;
double longitude = params[0].longitude;
List<Address> addresses = null;
try {
addresses = geocoder.getFromLocation(latitude, longitude,1);
} catch (IOException e) {
e.printStackTrace();
}
if(addresses != null && addresses.size() > 0 ){
Address address = addresses.get(0);
addressText = String.format("%s, %s, %s",
address.getMaxAddressLineIndex() > 0 ? address.getAddressLine(0) : "",
address.getLocality(),
address.getCountryName());
}
return addressText;
}
#Override
protected void onPostExecute(String addressResult) {
// Setting the title for the marker.
// This will be displayed on taping the marker
snippet = addressResult;
super.onPostExecute(snippet);
//Toast.makeText(Show_full_map.this,addressText,Toast.LENGTH_LONG).show();
}
}
I guess you want snippet immediately after calling execute. This is not how AsyncTask works. You can pass location in constructor of AsyncTask and access it from onPostExecute().
Just move the following code from your for loop to onPostExecute():
#Override
protected void onPostExecute(String snippet) {
super.onPostExecute(snippet);
googlemap.addMarker(new MarkerOptions()
.title(plat.get(j).toString())
.snippet(snippet)
.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_CYAN))
.position(location)
);
}

How to move HTTPClient to async Task

I am having trouble with an method I am moving to an AsyncTask. I have the doInBackground complete but I need to move the rest of the method into onPostExecute...I Just don't know how to.
Here is my original Method.
private void ShowFuelStopAndRoute(String location) throws IOException {
Geocoder geocoder = new Geocoder(this, Locale.getDefault());
List<Address> addresses;
addresses = geocoder.getFromLocationName(location, 1);
if(addresses.size() > 0) {
BitmapDescriptor subwayBitmapDescriptor = BitmapDescriptorFactory.fromResource(R.drawable.fillingstation);
currentFuelLat= addresses.get(0).getLatitude();
currentFuellong= addresses.get(0).getLongitude();
LatLng toPostion = new LatLng(currentFuelLat, currentFuellong);
GMapV2Direction md = new GMapV2Direction();
AsyncDoc asyncDoc = new AsyncDoc(MapViewActivity.this, currentLocation, toPostion, GMapV2Direction.MODE_DRIVING);
ArrayList<LatLng> directionPoint = md.getDirection(doc);
PolylineOptions rectLine = new PolylineOptions().width(5).color(Color.BLUE);
for(int i = 0 ; i < directionPoint.size() ; i++) {
rectLine.add(directionPoint.get(i));
}
map.addPolyline(rectLine);
Marker fuelMarker = map.addMarker(new MarkerOptions().position(toPostion).icon(subwayBitmapDescriptor).title("Fueling Station, " + location));
}
}
I move the following line into a different class and a Async Class
Document doc = md.getDocument(currentLocation, toPostion, GMapV2Direction.MODE_DRIVING);
And this has been replaced with :
return DALController.sharedInstance().getDocument(startLoc, endLoc, mode);
I have this much of the AsyncTask Complete as shown below:
private class AsyncDoc extends AsyncTask<Void, Void, Document > {
public String mode;
public LatLng startLoc;
public LatLng endLoc;
public AsyncDoc (Activity activity, LatLng startLoc, LatLng endLoc, String mode){
this.startLoc = startLoc;
this.endLoc = endLoc;
this.mode = mode;
dialog = new ProgressDialog(activity);
}
private Activity activity;
private ProgressDialog dialog;
protected void onPreExecute() {
this.dialog.setMessage("Progress start");
if (! (activity).isFinishing()) {
this.dialog.show();
}
}
#Override
protected Document doInBackground(Void... params) {
return DALController.sharedInstance().getDocument(startLoc, endLoc, mode);
}
#Override
protected void onPostExecute(Document result) {
if (dialog.isShowing()) {
dialog.dismiss();
}
}
}
But I need to make sure the rest of the code doesn't run until the doInBackground is complete:
ArrayList<LatLng> directionPoint = md.getDirection(doc);
PolylineOptions rectLine = new PolylineOptions().width(5).color(Color.BLUE);
for(int i = 0 ; i < directionPoint.size() ; i++) {
rectLine.add(directionPoint.get(i));
}
map.addPolyline(rectLine);
Marker fuelMarker = map.addMarker(new MarkerOptions().position(toPostion).icon(subwayBitmapDescriptor).title("Fueling Station, " + location));
How can I ensure the doInBackground completes before the rest of my showfuelstopandroute method completes?
How can I ensure the doInBackground completes before the rest of my
showfuelstopandroute method completes?
you should need to move all code inside onPostExecute which you want to execute after doInBackground execution complete. as:
#Override
protected void onPostExecute(Document result) {
if (dialog.isShowing()) {
dialog.dismiss();
}
// do your work here after doInBackground execution
ArrayList<LatLng> directionPoint = md.getDirection(result);
....
}
In an AsyncTask, the method onPostExecute() runs only after doInBackground() has completed. What is the issue you are facing?
As mentioned by others you can move the whole code which should be executed after the task in its postExecute-method.
Another method would be to let your activity have a Method for hat which the task can call in its onPostExecute()

Categories

Resources