在我的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;
}
这是我的Global类的一部分:
...
@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
中定义的类。这就是我的Activity的新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暂时为空。所以服务连接需要一些时间。我如何知道服务何时已连接?
假设我想实现一个LocalBroadcast
,它会是服务实现之外的吗?你能告诉我怎么开始吗?因为如果我一有locationUpdates就发送,我就不用等待服务连接了
你的设计真的不是很好。想想看:通常你不仅想获得一个位置,还想保持它的更新。这意味着当此类更新发生时,应该通知您的Activity。
你有几个选择:
- 绑定服务并对其执行常规方法调用(获取位置,注册/取消注册侦听器)
- 使用
LocalBroadcastManager
来广播从服务到活动的位置更新 - 使用一些事件总线(我最喜欢的- GreenRobot的EventBus),以便从服务广播位置更新到活动
我个人使用后一种方法:服务在位置更新时将"粘性"事件发布到事件总线,活动在onResume()
中查询这些事件并订阅更新。这样你的Service
就不需要一直运行-当你需要位置时启动它,获得所需的精确位置,并停止服务,以不消耗电池。
是的,不要这样做——这不仅不美观,而且还会导致内存泄漏。Android Service可以绑定到任何其他组件,参见:https://developer.android.com/guide/components/bound-services.html。您的活动或其他服务将绑定到您的位置服务并使用这些服务提供的接口。注意,当至少有一个连接保留时,服务将运行。启动并绑定到服务,然后它将运行,直到你停止它,你将能够使用Binder从该服务的显式接口。另一个好技术——使用EventBus (greenRobot)在Activity和Service之间传递粘性事件。事件将等待,直到另一个组件初始化并接收该事件。你可以在onPause和onResume方法中订阅和取消订阅该事件