1
votes

I have made a class LocationFinder which gets the user's location.

I am instantiating the class and class and calling required methods to get the location.

Now after the location is found in LocationFinder class, I want to communicate with my MainActivity so that I can update the user's location on some TextView.

To do so, I have done this:

The constructor of my LocationFinder class looks like:

private Context context;
private OnLocationFoundListener onLocationFoundListener;

public LocationFinder(Context context) {
    this.context = context;
    onLocationFoundListener = (OnLocationFoundListener) context; // here is the exception is thrown
}

Where OnLocationFoundListener is an interface like:

public interface OnLocationFoundListener
{
    void setOnLocationFoundListener(String cityName, String stateName, String countryName);
}

After this on successful location found I am using onLocationFoundListener.setOnLocationFoundListener(cityName, stateName, countryName); to notify the MainActivity where I'm implementing the OnLocationFoundListener and overriding the required method.

The code sample is:

The LocationFinder class:

public class LocationFinder implements LocationListener {

    private Context context;
    private OnLocationFoundListener onLocationFoundListener;

    public LocationFinder(Context context) {
        this.context = context;
        onLocationFoundListener = (OnLocationFoundListener) context;
    }

    private static final int MY_PERMISSIONS_ACCESS_FINE_LOCATION = 1;

    private LocationManager locationManager;
    private ProgressDialog progressDialog;


    void getCityByLocation() {
        locationManager = (LocationManager) context.getSystemService(LOCATION_SERVICE);

        if (ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            if (ActivityCompat.shouldShowRequestPermissionRationale((Activity)context,
                    Manifest.permission.ACCESS_FINE_LOCATION)) {
                // Explanation not needed, since user requests this himself

            } else {
                ActivityCompat.requestPermissions((Activity)context,
                        new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
                        MY_PERMISSIONS_ACCESS_FINE_LOCATION);
            }

        } else if (locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER) ||
                locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
            progressDialog = new ProgressDialog(context);
            progressDialog.setMessage(context.getString(R.string.getting_location));
            progressDialog.setCancelable(false);
            progressDialog.setButton(DialogInterface.BUTTON_NEGATIVE, context.getString(R.string.dialog_cancel), new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialogInterface, int i) {
                    try {
                        locationManager.removeUpdates(LocationFinder.this);
                    } catch (SecurityException e) {
                        e.printStackTrace();
                    }
                }
            });
            progressDialog.show();
            if (locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) {
                locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, this);
            }
            if (locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
                locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this);
            }
        } else {
            showLocationSettingsDialog();
        }
    }




    @Override
    public void onLocationChanged(Location location) {

        progressDialog.hide();
        try {
            locationManager.removeUpdates(this);
        } catch (SecurityException e) {
            Log.e("LocationManager", "Error while trying to stop listening for location updates. This is probably a permissions issue", e);
        }
        Log.i("LOCATION (" + location.getProvider().toUpperCase() + ")", location.getLatitude() + ", " + location.getLongitude());
        double latitude = location.getLatitude();
        double longitude = location.getLongitude();
        getCityDetails(latitude, longitude);

    }

    @Override
    public void onStatusChanged(String s, int i, Bundle bundle) {

    }

    @Override
    public void onProviderEnabled(String s) {

    }

    @Override
    public void onProviderDisabled(String s) {

    }

    private void getCityDetails(double lat, double lon)
    {
        Geocoder geocoder = new Geocoder(context, Locale.getDefault());
        List<Address> addresses = null;
        try {
            addresses = geocoder.getFromLocation(lat, lon, 1);
        } catch (IOException e) {
            e.printStackTrace();
        }
        String cityName = addresses.get(0).getAddressLine(0);
        String stateName = addresses.get(0).getAddressLine(1);
        String countryName = addresses.get(0).getAddressLine(2);

        progressDialog.dismiss();
        onLocationFoundListener.setOnLocationFoundListener(cityName, stateName, countryName);

    }

    private void showLocationSettingsDialog() {
        AlertDialog.Builder alertDialog = new AlertDialog.Builder(context);
        alertDialog.setTitle(R.string.location_settings);
        alertDialog.setMessage(R.string.location_settings_message);
        alertDialog.setPositiveButton(R.string.location_settings_button, new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int which) {
                Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
                context.startActivity(intent);
            }
        });
        alertDialog.setNegativeButton(R.string.dialog_cancel, new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int which) {
                dialog.cancel();
            }
        });
        alertDialog.show();
    }

    public interface OnLocationFoundListener
    {
        void setOnLocationFoundListener(String cityName, String stateName, String countryName);
    }
}

The MainActivity :

public class MainActivity extends AppCompatActivity implements LocationFinder.OnLocationFoundListener {

    Button getCurrentLocation;
    TextView locationTextview;

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

        getCurrentLocation = (Button) findViewById(R.id.getCurrentCity);
        locationTextview = (TextView) findViewById(R.id.current_city);

        LocationFinder locationFinder = new LocationFinder(getApplicationContext());
        locationFinder.getCityByLocation();

    }

    @Override
    public void setOnLocationFoundListener(String cityName, String stateName, String countryName) {
        locationTextview.setText("City : "+cityName+", "+"\nState : "+stateName+", "+"\nCountry : "+countryName);
    }
}

Logcat:

Process: com.amitupadhyay.citybasedlocation, PID: 18474
                                                                                    java.lang.RuntimeException: Unable to start activity

ComponentInfo{com.amitupadhyay.citybasedlocation/com.amitupadhyay.citybasedlocation.MainActivity}: java.lang.ClassCastException: android.app.Application cannot be cast to com.amitupadhyay.citybasedlocation.LocationFinder$OnLocationFoundListener at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2456) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2523) at android.app.ActivityThread.access$900(ActivityThread.java:168) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1373) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:148) at android.app.ActivityThread.main(ActivityThread.java:5609) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:797) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:687) Caused by: java.lang.ClassCastException: android.app.Application cannot be cast to com.amitupadhyay.citybasedlocation.LocationFinder$OnLocationFoundListener at com.amitupadhyay.citybasedlocation.LocationFinder.(LocationFinder.java:38) at com.amitupadhyay.citybasedlocation.MainActivity.onCreate(MainActivity.java:21) at android.app.Activity.performCreate(Activity.java:6307) at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1118) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2409) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2523)  at android.app.ActivityThread.access$900(ActivityThread.java:168)  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1373)  at android.os.Handler.dispatchMessage(Handler.java:102)  at android.os.Looper.loop(Looper.java:148)  at android.app.ActivityThread.main(ActivityThread.java:5609)  at java.lang.reflect.Method.invoke(Native Method)  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:797)  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:687)

I don't understand why is this happening?

3
Add the exception pleaseJens
post logcat pleaseJaydeep Devda
u have to use activity context, not applicationStanislav Bondar

3 Answers

2
votes

try passing this as context instead of application context.

 LocationFinder locationFinder = new LocationFinder(this);
            locationFinder.getCityByLocation();

EDIT That is exactly what your logcat says. You are trying to pass a application context to activity.

1
votes

Change it like following,

public LocationFinder(Context context, OnLocationFoundListener listener) {
        this.context = context;
        onLocationFoundListener = listener;
}

And from Activity, initiate it like this,

LocationFinder locationFinder = new LocationFinder(getApplicationContext(), this);
0
votes

You Should Change OnLocationFoundListener Context parameter in constructor with OnLocationFoundListener

public LocationFinder(OnLocationFoundListener context) {
    this.context = context;
    onLocationFoundListener =  context; // here is the exception is thrown
}

And You should pass

MainActvity.this.



 LocationFinder locationFinder = new LocationFinder(MainActvity.this);