Я получаю следующее исключение, когда пытаюсь использовать LocationManager в пользовательском классе, работающем во внешней службе:
*** Uncaught remote exception! (Exceptions are not yet supported across processes.)
java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
at android.os.Handler.<init>(Handler.java:200)
at android.os.Handler.<init>(Handler.java:114)
at android.location.LocationManager$GpsStatusListenerTransport$1.<init>(LocationManager.java:1464)
at android.location.LocationManager$GpsStatusListenerTransport.<init>(LocationManager.java:1464)
at android.location.LocationManager.addGpsStatusListener(LocationManager.java:1503)
at org.poseidon_project.contexts.hardware.GPSIndoorOutdoorContext.start(GPSIndoorOutdoorContext.java:97)
at org.poseidon_project.context.management.ContextManager.addObserverRequirement(ContextManager.java:97)
at org.poseidon_project.context.reasoner.ContextMapper.registerIndoorOutdoorsContext(ContextMapper.java:260)
at org.poseidon_project.context.reasoner.ContextMapper.registerContext(ContextMapper.java:197)
at org.poseidon_project.context.ContextReasonerCore.addContextRequirement(ContextReasonerCore.java:70)
at org.poseidon_project.context.ContextReasonerService$1.addContextRequirement(ContextReasonerService.java:74)
at org.poseidon_project.context.IContextReasoner$Stub.onTransact(IContextReasoner.java:74)
at android.os.Binder.execTransact(Binder.java:446)
Теперь я прочитал много ответов, касающихся использования Looper, с такими вещами, как:
Looper.prepare;
mLocationManager.requestLocationUpdates(mProvider, mMinTime, mMinDistance, this, Looper.getMainLooper);
Но в конечном итоге это не приводит к вызову обратного вызова (onLocationChanged (местоположение)) при обновлении?
Класс реализует LocationListener, который также вызывает методы LocatioManager:
public abstract class LocationContext extends ContextObserver implements LocationListener {
protected LocationManager mLocationManager;
private int mMinTime = 3000;
private int mMinDistance = 10;
private String mProvider = LocationManager.GPS_PROVIDER;
private String mIdealProvider = LocationManager.GPS_PROVIDER;
public LocationContext (Context c) {
super(c);
mLocationManager = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
}
public LocationContext (Context c, ContextReceiver cr) {
super(c, cr);
mLocationManager = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
}
public LocationContext (Context c, ContextReceiver cr, int minTime, int minDistance, String name) {
super(c, cr, name);
mMinTime = minTime;
mMinDistance = minDistance;
mLocationManager = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
}
public LocationContext (Context c, ContextReceiver cr, int minTime, int minDistance, String provider, String name) {
super(c, cr, name);
mMinTime = minTime;
mMinDistance = minDistance;
mProvider = provider;
mIdealProvider = provider;
mLocationManager = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
}
@Override
public boolean start() {
//new Thread(new Runnable() {
// @Override
// public void run() {
//Looper.prepare();
mLocationManager.requestLocationUpdates(mProvider, mMinTime, mMinDistance, this);
//handler.sendEmptyMessage(0);
//Looper.loop();
// }
//}).start();
mIsRunning = true;
//Looper.loop();
return true;
}
@Override
public boolean pause() {
return stop();
}
@Override
public boolean resume() {
return start();
}
@Override
public boolean stop() {
mLocationManager.removeUpdates(this);
mIsRunning = false;
return true;
}
@Override
public void onLocationChanged(Location location) {
checkContext(location);
}
protected abstract void checkContext(Location location);
@Override
public void onProviderDisabled(String provider) {
if (provider.equals(mIdealProvider)) {
mProvider = LocationManager.GPS_PROVIDER;
if (! mLocationManager.isProviderEnabled(mProvider)) {
Intent gpsOptionIntent = new Intent (android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS);
mContext.startActivity(gpsOptionIntent);
}
}
}
@Override
public void onProviderEnabled(String provider) {
if ((provider.equals(mIdealProvider)) && (! provider.equals(mProvider))) {
mLocationManager.removeUpdates(this);
mProvider = provider;
mLocationManager.requestLocationUpdates(mProvider, mMinTime, mMinDistance, this);
}
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
// TODO Auto-generated method stub
}
public int getMinTime() {
return mMinTime;
}
public void setMinTime(int mMinTime) {
this.mMinTime = mMinTime;
}
public int getMinDistance() {
return mMinDistance;
}
public void setMinDistance(int mMinDistance) {
this.mMinDistance = mMinDistance;
}
Я не очень понимаю, как использовать Looper в моей ситуации. Кто-нибудь может помочь? Я понимаю ответ «запустить в потоке пользовательского интерфейса», но это одно сервисное приложение, пользовательского интерфейса нет, поэтому я не думаю, что смогу сделать это в потоке пользовательского интерфейса?
****ОБНОВЛЕНИЕ******Решение найдено******
Я считаю, что нашел решение. Рассматриваемый класс был абстрактным классом, который я расширил несколькими классами, которые выполняли различные операции на основе местоположения.
В абстрактном классе LocationContext я использовал:
mLocationManager.requestLocationUpdates(mProvider, mMinTime, mMinDistance,this, Looper.getMainLooper());
И в классе реализации (например, для анализа состояния спутников GPS) я поместил его в новую тему:
new Thread(new Runnable() {
@Override
public void run() {
Looper.prepare();
GPSIndoorOutdoorContext.super.start();
mLocationManager.addGpsStatusListener(gpsListener);
Looper.loop();
}
}).start();