Reputation: 7391
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?
Upvotes: 1
Views: 1877
Reputation: 6704
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);
Upvotes: 1
Reputation: 5711
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);
Upvotes: 0
Reputation: 2162
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.
Upvotes: 2