我创建了一个类LocationFinder
来获取用户的位置。
我正在实例化类和类并调用所需的方法来获取位置。
现在,在 LocationFinder
类中找到位置后,我想与我的 MainActivity
进行通信,以便我可以在某些 TextView 上更新用户的位置。
为此,我这样做了:
我的 LocationFinder
类的构造函数如下所示:
private Context context;
private OnLocationFoundListener onLocationFoundListener;
public LocationFinder(Context context) {
this.context = context;
onLocationFoundListener = (OnLocationFoundListener) context; // here is the exception is thrown
}
其中 OnLocationFoundListener
是一个类似以下的接口(interface):
public interface OnLocationFoundListener
{
void setOnLocationFoundListener(String cityName, String stateName, String countryName);
}
在成功定位后,我正在使用 onLocationFoundListener.setOnLocationFoundListener(cityName, stateName, CountryName);
来通知 MainActivity
我正在其中实现 OnLocationFoundListener
并重写所需的方法。
代码示例是:
LocationFinder
类:
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);
}
}
主要 Activity :
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);
}
}
日志猫:
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)
我不明白为什么会发生这种情况?
最佳答案
尝试将其作为上下文而不是应用程序上下文传递。
LocationFinder locationFinder = new LocationFinder(this);
locationFinder.getCityByLocation();
编辑 这正是您的 logcat 所说的。您正在尝试将应用程序上下文传递给 Activity 。
关于java - 将 Activity 上下文转换为接口(interface)会抛出 ClassCastException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42834878/