im试图使用android拥有的Geocoder来获取城市我们创建的应用程序作为作业。我正在尝试在AsyncTask内执行此操作,但出现此异常:
Can't create handler inside thread that has not called Looper.prepare()
AsyncTask代码:
public class GeocoderTask extends AsyncTask<Void, Void, String> {
LocationManager locationManager;
Location location;
Context context;
String city;
public GeocoderTask(Context context) {
this.context = context;
locationManager = (LocationManager)context.getSystemService(Context.LOCATION_SERVICE);
}
@SuppressLint("MissingPermission")
@Override
protected String doInBackground(Void... voids) {
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, new LocationListener() {
@Override
public void onLocationChanged(Location location) {
GeocoderTask.this.location = location;
Geocoder geocoder = new Geocoder(context, Locale.getDefault());
List<Address> addresses;
try {
addresses = geocoder.getFromLocation(GeocoderTask.this.location.getLatitude(), GeocoderTask.this.location.getLongitude(), 3);
city = addresses.get(0).getLocality();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e){
e.getMessage();
}
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
@Override
public void onProviderEnabled(String provider) {
}
@Override
public void onProviderDisabled(String provider) {
}
});
return city;
}
@Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
FrgPersonInfo frgPersonInfo = new FrgPersonInfo();
System.out.println(s);
frgPersonInfo.saveUserToTable(s);
}
}
我正在从片段调用AsyncTask片段中的调用:
view.findViewById(R.id.btnRegister).setOnClickListener(new View.OnClickListener() {
@SuppressLint("MissingPermission")
@Override
public void onClick(View v) {
checkPermissions();
GeocoderTask geocoderTask = new GeocoderTask(context);
geocoderTask.execute();
}
});
我在AsyncTask中的onPostExecute中调用的方法:
public void saveUserToTable(String city) {
String age = uAge.getText().toString();
String name = fName.getText().toString();
UserInfo userInfo = new UserInfo();
userInfo.setIsConnected(true);
userInfo.setUserImage(imageUrl);
userInfo.setAge(Integer.valueOf(age));
userInfo.setName(name);
userInfo.setCity(city);
Backendless.Data.of(UserInfo.class).save(userInfo, new AsyncCallback<UserInfo>() {
@Override
public void handleResponse(UserInfo response) {
System.out.println("Bitch, im here again!");
((TextView)parentView.findViewById(R.id.loginFrgBtn)).setTextColor(Color.BLUE);
((TextView)parentView.findViewById(R.id.registerFrgBtn)).setTextColor(Color.BLACK);
FragmentTransaction ft = fm.beginTransaction();
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
FrgLogin frgLogin = new FrgLogin();
ft.replace(R.id.container, frgLogin);
ft.commit();
TastyToast.makeText(context, "Welcome!", TastyToast.LENGTH_LONG, TastyToast.SUCCESS).show();
}
@Override
public void handleFault(BackendlessFault fault) {
TastyToast.makeText(context, fault.getMessage(), TastyToast.LENGTH_LONG, TastyToast.ERROR).show();
}
});
}
checkPermission:
private void checkPermissions() {
List<String> neededPerms = new ArrayList<>();
int fineGpsPerm = context.checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION);
int coarseGpsPerm = context.checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION);
if (fineGpsPerm != PackageManager.PERMISSION_GRANTED || coarseGpsPerm != PackageManager.PERMISSION_GRANTED) {
neededPerms.add(Manifest.permission.ACCESS_FINE_LOCATION);
neededPerms.add(Manifest.permission.ACCESS_COARSE_LOCATION);
}
if (!neededPerms.isEmpty()) {
ActivityCompat.requestPermissions( getActivity(), neededPerms.toArray(new String[neededPerms.size()]), GPS_PERM_CODE);
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode){
case GPS_PERM_CODE:
if (grantResults[0] != PackageManager.PERMISSION_GRANTED|| grantResults[1] != PackageManager.PERMISSION_GRANTED) {
Toast.makeText(context, "Need to Allow perms First", Toast.LENGTH_SHORT).show();
checkPermissions();
}
break;
}
}
片段类:
public class FrgPersonInfo extends Fragment{
public static final int GPS_PERM_CODE = 103;
Context context;
EditText fName, uAge, uCity;
String imageUrl = "";
FragmentManager fm;
View parentView;
LocationManager locationManager;
Location location;
boolean isLocEnabled = false;
String cityAddress = "";
@Override
public void onAttach(@NonNull Context context) {
super.onAttach(context);
this.context = context;
System.out.println("in person onattach");
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@SuppressLint("MissingPermission")
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
//inflating the wanted fragmentView
View myView = inflater.inflate(R.layout.frg_person_info, container, false);
// init the fields
fName = myView.findViewById(R.id.fName);
uAge = myView.findViewById(R.id.userAge);
uCity = myView.findViewById(R.id.userCity);
fm = getActivity().getSupportFragmentManager();
locationManager = (LocationManager)context.getSystemService(Context.LOCATION_SERVICE);
return myView;
}
@SuppressLint("MissingPermission")
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
parentView = view.getRootView();
//creating a bundle so we can (in this case) get data
Bundle bundle = getArguments();
//use the get.. method to get data by key
// imageUrl = bundle.getString(FrgRegister.IMAGE_KEY);
checkPermissions();
if (isLocEnabled) {
} else {
Toast.makeText(context, "dont have perms", Toast.LENGTH_SHORT).show();
}
view.findViewById(R.id.btnRegister).setOnClickListener(new View.OnClickListener() {
@SuppressLint("MissingPermission")
@Override
public void onClick(View v) {
checkPermissions();
GeocoderTask geocoderTask = new GeocoderTask(context);
geocoderTask.getUpdate();
}
});
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
}
@Override
public void onDetach() {
super.onDetach();
this.fName = null;
this.uAge = null;
this.uCity = null;
this.fm = null;
this.imageUrl = null;
}
public void saveUserToTable(String city) {
String age = uAge.getText().toString();
String name = fName.getText().toString();
UserInfo userInfo = new UserInfo();
userInfo.setIsConnected(true);
userInfo.setUserImage(imageUrl);
userInfo.setAge(Integer.valueOf(age));
userInfo.setName(name);
userInfo.setCity(city);
Backendless.Data.of(UserInfo.class).save(userInfo, new AsyncCallback<UserInfo>() {
@Override
public void handleResponse(UserInfo response) {
System.out.println("Bitch, im here again!");
((TextView)parentView.findViewById(R.id.loginFrgBtn)).setTextColor(Color.BLUE);
((TextView)parentView.findViewById(R.id.registerFrgBtn)).setTextColor(Color.BLACK);
FragmentTransaction ft = fm.beginTransaction();
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
FrgLogin frgLogin = new FrgLogin();
ft.replace(R.id.container, frgLogin);
ft.commit();
TastyToast.makeText(context, "Welcome!", TastyToast.LENGTH_LONG, TastyToast.SUCCESS).show();
}
@Override
public void handleFault(BackendlessFault fault) {
TastyToast.makeText(context, fault.getMessage(), TastyToast.LENGTH_LONG, TastyToast.ERROR).show();
}
});
}
private void checkPermissions() {
List<String> neededPerms = new ArrayList<>();
int fineGpsPerm = context.checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION);
int coarseGpsPerm = context.checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION);
if (fineGpsPerm != PackageManager.PERMISSION_GRANTED || coarseGpsPerm != PackageManager.PERMISSION_GRANTED) {
neededPerms.add(Manifest.permission.ACCESS_FINE_LOCATION);
neededPerms.add(Manifest.permission.ACCESS_COARSE_LOCATION);
}
if (!neededPerms.isEmpty()) {
ActivityCompat.requestPermissions( getActivity(), neededPerms.toArray(new String[neededPerms.size()]), GPS_PERM_CODE);
} else {
isLocEnabled = true;
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode){
case GPS_PERM_CODE:
if (grantResults[0] != PackageManager.PERMISSION_GRANTED || grantResults[1] != PackageManager.PERMISSION_GRANTED) {
checkPermissions();
} else {
isLocEnabled = true;
}
break;
}
}
}
Asynctask是一个线程,它仅执行应该执行的任务,不需要Looper,尽管没有为该线程调用Looper。 Locationlistener
的工作方式不同于您尝试的。只要不停止侦听器,就会调用OnLocationchanged
get,但这是异步发生的,您不能只在asynctask
内部等待该操作完成。您必须从主线程启动locationlistener
,并且每当您的位置更改时,都会调用函数onLocationChanged
。例如,您可以将onPostExecution放在locationlistener内。
@Override
public void onLocationChanged(Location location) {
GeocoderTask.this.location = location;
Geocoder geocoder = new Geocoder(context, Locale.getDefault());
List<Address> addresses;
try {
addresses = geocoder.getFromLocation(GeocoderTask.this.location.getLatitude(), GeocoderTask.this.location.getLongitude(), 3);
city = addresses.get(0).getLocality();
FrgPersonInfo frgPersonInfo = new FrgPersonInfo();
System.out.println(city);
frgPersonInfo.saveUserToTable(s);
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e){
e.getMessage();
}
}
创建locationListener以保留对其的引用。
创建一个类以触发LocationUpdates
public class GeocoderTask {
LocationManager locationManager;
Location location;
Context context;
String city;
LocationListener locationListener = new LocationListener(){
@Override
public void onLocationChanged(Location location) {
GeocoderTask.this.location = location;
Geocoder geocoder = new Geocoder(context, Locale.getDefault());
List<Address> addresses;
FrgPersonInfo frgPersonInfo = new FrgPersonInfo();
System.out.println(city);
frgPersonInfo.saveUserToTable(s);
try {
addresses = geocoder.getFromLocation(GeocoderTask.this.location.getLatitude(), GeocoderTask.this.location.getLongitude(), 3);
city = addresses.get(0).getLocality();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e){
e.getMessage();
}
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {}
@Override
public void onProviderEnabled(String provider) {}
@Override
public void onProviderDisabled(String provider) {}
}
public GeocoderTask(Context context) {
this.context = context;
locationManager = (LocationManager)context.getSystemService(Context.LOCATION_SERVICE);
}
public void getUpdate(){
locationManager.requestSingleUpdate(LocationManager.GPS_PROVIDER,locationListener,null
}
您只需要创建类并使用locationListener调用Function getUpdate,这将调用一次Update。如果需要更多更新,也可以使用requestUpdates并创建一个函数来删除侦听器。