简体   繁体   中英

Android Location object returns null when I pass it to asyncTask

I am sending android user location lat and longitude to server together with registration ID and other parameters as json object in Asynctask(a nested class of the activity). But the Location object(that had values at the start of the app) instantiated in the activity as such

location = LocationServices.FusedLocationApi
                    .getLastLocation(mgoogleapiclient);

is returning null in the Asynctask Class. Can someone explain to me why? Do I have to use separate class to get user location and send it in another asynctask or service(which doesn't make sense from architectural standpoint)?

Location mLastLocation = LocationServices.FusedLocationApi.getLastLocation(
                mGoogleApiClient);
        if (mLastLocation != null) {
            PostData pdata = new PostData();
            double latitude = mLastLocation.getLatitude();
            double longitude = mLastLocation.getLongitude();
            pdata.execute(String.valueOf(latitude), String.valueOf(longitude));
        }

I am retrieving this from the AsyncTask class as such:

json.put("latitude", String.valueOf(args[1]));
                    json.put("longitude", String.valueOf(args[2]));

But when I debug it, I am getting the getting the registration ID which I sent to the AsyncTask class from another method. I hope I am making myself clear.

@Override
        protected String doInBackground(String... args) {   
            try {
                try {
                    URL url;
                    HttpURLConnection urlConn;
                    url = new URL ("myphp.php");
                    urlConn = (HttpURLConnection)url.openConnection();
                    urlConn.setDoInput (true);
                    urlConn.setDoOutput (true);
                    urlConn.setUseCaches (false);
                    urlConn.setRequestProperty("Content-Type","application/json");   
                    urlConn.setRequestProperty("Accept", "application/json");
                    urlConn.setChunkedStreamingMode(0);
                    urlConn.setRequestMethod("POST");
                    urlConn.connect();                  
                    //get google account
                    AccountManager am = AccountManager.get(getBaseContext()); // "this" references the current Context
                    Account[] accounts = am.getAccountsByType("com.google");

                    //Create JSONObject here
                    JSONObject json = new JSONObject();
                    json.put("regID", String.valueOf(args[0]));
                    json.put("Google account", accounts[0].name);
                    json.put("name", "Amanda");
                    json.put("tel", "2069994444");
                    json.put("latitude", String.valueOf(args[1]));
                    json.put("longitude", String.valueOf(args[2]));

                    String postData=json.toString();

                    // Send POST output.
                    OutputStreamWriter os = new OutputStreamWriter(urlConn.getOutputStream(), "UTF-8");
                      os.write(postData);
                      Log.i("NOTIFICATION", "Data Sent");
                      os.close();

                    BufferedReader reader = new BufferedReader(new InputStreamReader(urlConn.getInputStream())); 
                    String msg=""; 
                    String line = ""; 
                    while ((line = reader.readLine()) != null) {
                        msg += line; } 
                    Log.i("msg=",""+msg);
                } catch (MalformedURLException muex) {
                    // TODO Auto-generated catch block
                    muex.printStackTrace();
                } catch (IOException ioex){
                    ioex.printStackTrace();
                } 
            } catch (Exception e) {
                e.printStackTrace();
                Log.e("ERROR", "There is error in this code");

            }
            return null;

        }

The following is how I sent the registration ID

gcm = GoogleCloudMessaging.getInstance(this);
            regid = getRegistrationId(context);
            if (!regid.isEmpty()) {
                PostData pd = new PostData();               
                pd.execute(regid); 
            } else {
                //register
                registerInBackground();
            }

The problem is that you are sending two separate sets of varargs to the AsyncTask at different times.

You should be sending all necessary data to the AsyncTask when you call execute() in order for it to have the data is needs.

So, you need to get all of the data ready, and send it in one call to execute() , something like this:

Location mLastLocation = LocationServices.FusedLocationApi.getLastLocation(
        mGoogleApiClient);

gcm = GoogleCloudMessaging.getInstance(this);
regid = getRegistrationId(context);
if (!regid.isEmpty() && mLastLocation != null) {
    double latitude = mLastLocation.getLatitude();
    double longitude = mLastLocation.getLongitude();
    PostData pd = new PostData();
    pd.execute(regid, String.valueOf(latitude), String.valueOf(longitude));
} else {
    //register if regid is empty
    if (regid.isEmpty()){
       registerInBackground();
    }
}

Also, there is no need to call String.valueOf() on your String arguments that are passed in to doInBackground() , so you can remove those calls:

@Override
protected String doInBackground(String... args) {
    try {
        try {
            URL url;
            HttpURLConnection urlConn;
            url = new URL ("myphp.php");
            urlConn = (HttpURLConnection)url.openConnection();
            urlConn.setDoInput (true);
            urlConn.setDoOutput (true);
            urlConn.setUseCaches (false);
            urlConn.setRequestProperty("Content-Type","application/json");
            urlConn.setRequestProperty("Accept", "application/json");
            urlConn.setChunkedStreamingMode(0);
            urlConn.setRequestMethod("POST");
            urlConn.connect();
            //get google account
            AccountManager am = AccountManager.get(getBaseContext()); // "this" references the current Context
            Account[] accounts = am.getAccountsByType("com.google");

            //Create JSONObject here
            JSONObject json = new JSONObject();
            json.put("regID", args[0]); //modified
            json.put("Google account", accounts[0].name);
            json.put("name", "Amanda");
            json.put("tel", "2069994444");
            json.put("latitude", args[1]); //modified
            json.put("longitude", args[2]); //modified

            String postData=json.toString();

            // Send POST output.
            OutputStreamWriter os = new OutputStreamWriter(urlConn.getOutputStream(), "UTF-8");
            os.write(postData);
            Log.i("NOTIFICATION", "Data Sent");
            os.close();

            BufferedReader reader = new BufferedReader(new InputStreamReader(urlConn.getInputStream()));
            String msg="";
            String line = "";
            while ((line = reader.readLine()) != null) {
                msg += line; }
            Log.i("msg=",""+msg);
        } catch (MalformedURLException muex) {
            // TODO Auto-generated catch block
            muex.printStackTrace();
        } catch (IOException ioex){
            ioex.printStackTrace();
        }
    } catch (Exception e) {
        e.printStackTrace();
        Log.e("ERROR", "There is error in this code");

    }
    return null;

}

Edit: It sounds like you should register a location listener in order to explicitly request a location. Here is sample code that you can use as a reference in order to register a location listener in your code:

public class MainActivity extends Activity implements
        GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener {

    LocationRequest mLocationRequest;
    GoogleApiClient mGoogleApiClient;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        buildGoogleApiClient();
        mGoogleApiClient.connect();
    }

    @Override
    protected void onPause(){
        super.onPause();
        if (mGoogleApiClient != null) {
            LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
        }
    }

    protected synchronized void buildGoogleApiClient() {
        Toast.makeText(this,"buildGoogleApiClient",Toast.LENGTH_SHORT).show();
        mGoogleApiClient = new GoogleApiClient.Builder(this)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .addApi(LocationServices.API)
                .build();
    }

    @Override
    public void onConnected(Bundle bundle) {
        Toast.makeText(this,"onConnected",Toast.LENGTH_SHORT).show();

        mLocationRequest = new LocationRequest();
        mLocationRequest.setInterval(10);
        mLocationRequest.setFastestInterval(10);
        mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
        //mLocationRequest.setPriority(LocationRequest.PRIORITY_LOW_POWER);
        //mLocationRequest.setSmallestDisplacement(0.1F);

        LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
    }

    @Override
    public void onConnectionSuspended(int i) {
        Toast.makeText(this,"onConnectionSuspended",Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onConnectionFailed(ConnectionResult connectionResult) {
        Toast.makeText(this,"onConnectionFailed",Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onLocationChanged(Location location) {

        Log.d("locationtesting", "accuracy: " + location.getAccuracy() + " lat: " + location.getLatitude() + " lon: " + location.getLongitude());

        Toast.makeText(this,"Location Changed",Toast.LENGTH_SHORT).show();


        //unregister here if you only need one location update:
        if (mGoogleApiClient != null) {
            LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
        }
    }
}
private void startReceivingLocationUpdates() {
        if (locationManager == null) {
            locationManager = (android.location.LocationManager)context.getSystemService(Context.LOCATION_SERVICE);
        }

        if (locationManager != null) {
            try {locationManager.requestLocationUpdates(android.location.LocationManager.NETWORK_PROVIDER, 1000, 0F, 
                    (android.location.LocationListener) listener);
            } 
         catch (SecurityException ex) 
             {
                Log.i(TAG, "fail to request location update, ignore", ex);
            } 

           catch (IllegalArgumentException ex)
           {
                Log.d(TAG, "provider does not exist " + ex.getMessage());
            }

            try {
                locationManager.requestLocationUpdates(android.location.LocationManager.GPS_PROVIDER, 1000, 0F, 
                        (android.location.LocationListener) listener);
                //if (listener != null) listener.showGpsOnScreenIndicator(false);
            }
           catch (SecurityException ex) {
                Log.i(TAG, "fail to request location update, ignore", ex); 
                } 

            catch (IllegalArgumentException ex) {
                Log.d(TAG, "provider does not exist " + ex.getMessage());  
                }

            Log.d(TAG, "startReceivingLocationUpdates");
        }
    }

This solved the null pointer exception on my Location object, I got it from here

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM