在我的Android应用程序中,我在'Service'类中使用'LocationService'。有几个教程推荐这种做法 跨活动的永久位置检查。然而,尽管有一些很好的文档,我仍然有一个问题 活动与我的服务之间的沟通。
这是我的LocationService类:
public class LocationService extends Service {
public static LocationManager locationManager;
public static LocationListener listener;
private static Location currentLocation = null;
@Override
public void onCreate() {
super.onCreate();
}
@Override
public void onStart(Intent intent, int startId) {
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
listener = new LocationListener() {
@Override
public void onLocationChanged(Location location) {
currentLocation = location;
System.out.println("Current Location: " + currentLocation);
}
@Override
public void onStatusChanged(String s, int i, Bundle bundle) {
}
@Override
public void onProviderEnabled(String s) {
}
@Override
public void onProviderDisabled(String s) {
}
};
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onDestroy() {
locationManager.removeUpdates(listener);
}
public static Location getCurrentLocation() {
return currentLocation;
}
这是我全球课程的一部分:
...
@Override
public void onCreate() {
super.onCreate();
if(!LocationService.isRunning()) {
Intent intent = new Intent(this, LocationService.class);
startService(intent);
}
}
...
这是我的Activity类:
public class ScreenActivity extends FragmentActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.screen);
}
if (usesPosition) {
Location tLoc = LocationService.getCurrentLocation();
TextView t = (TextView) findViewById(R.id.tv);
t.setText(tLoc.toString());
}
}
我觉得这不是一种优雅的方式,甚至可能是错误的。我确实得到了一个好位置,但我觉得我没有访问该服务,但是 而是像静态类一样对待它。我还不熟悉将活动绑定到活动的概念,所以我想知道我是否确实需要 这样做。
编辑1
感谢您的第一个答案!这对我有点帮助了。这是我的Activity类的一部分:
private ServiceConnection locationServiceConnection = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
locationServiceBound = false;
System.out.println("Service disconnected");
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
com.ma.sainz.geoobserver.Tools.Services.LocationService.MyBinder myBinder = (com.ma.sainz.geoobserver.Tools.Services.LocationService.MyBinder) service;
locationService = myBinder.getService();
locationServiceBound = true;
System.out.println("Service bound");
}
};
其中myBinder
是LocationService
中定义的类。
这是我的新onStart() - 我的活动方法:
@Override
protected void onStart() {
super.onStart();
Intent locationServiceIntent = new Intent(this, com.ma.sainz.geoobserver.Tools.Services.LocationService.class);
bindService(locationServiceIntent, locationServiceConnection, Context.BIND_AUTO_CREATE);
locationService.requestBackgroundLocation();
System.out.println("onStart");
}
startService(locationServiceIntent)
已在之前的活动中完成。
但是,locationService暂时为null。所以服务连接需要一些时间。我如何知道服务何时连接?
假设我想实现LocalBroadcast
,那么除了服务实现之外还会这样吗?你有关于如何开始的提示吗?因为如果我们在他们出现的时候立即发送locationUpdates,我就不会费心等待服务连接。
答案 0 :(得分:1)
你所拥有的并不是一个非常好的设计。想一想:通常你不仅要获得一个位置,还要保持更新。这意味着在发生此类更新时应通知您的活动。
你在这里有几个选择:
LocalBroadcastManager
以便从“服务转移到活动”广播位置更新我个人使用后一种方法:服务在位置更新时将“粘性”事件发布到事件总线,活动在onResume()
中查询这些事件并订阅更新。这样您的Service
就不需要一直运行 - 在需要位置时启动它,获得所需精度的位置,并停止服务以免耗电。
答案 1 :(得分:0)
是的,不要这样做 - 它不是没有优雅,但也会导致内存泄漏。 Android服务可以绑定到其他组件,请参阅:https://developer.android.com/guide/components/bound-services.html。 您的actvity或其他服务将绑定到您的位置服务并使用ServiceProvides接口。请注意,当至少保留一个连接时,服务将运行。启动并绑定到服务,然后它将一直运行,直到你停止它,你将能够使用Binder的该服务的显式接口。 另一个很好的技术 - 使用EventBus(greenRobot)在Activity和Service之间传递粘性事件。事件将等到另一个组件初始化并接收该事件。您可以订阅该事件并在onPause和onResume方法中取消订阅。