#android #android-activity #service
#Android #android-активность #Обслуживание
Вопрос:
В моем приложении для Android я использую ‘LocationService’ в классе ‘Service’. Несколько руководств рекомендуют эту практику, чтобы иметь постоянную проверку местоположения во всех действиях. Однако, несмотря на наличие хорошей документации, у меня все еще есть вопрос, касающийся связи между activity и моим сервисом.
Это мой класс 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());
}
}
Я чувствую, что это не элегантный способ, возможно, даже неправильный. Я получаю хорошее местоположение, но мне кажется, что я не получаю доступа к службе, но
скорее относитесь к нему как к статическому классу. Я еще не знаком с концепцией привязки сервисов к activities, поэтому мне интересно, действительно ли мне нужно
чтобы сделать это.
РЕДАКТИРОВАТЬ 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 некоторое время равен нулю. Таким образом, подключение к службе занимает некоторое время. Как я узнаю, когда служба подключена?
И если предположить, что я хотел бы реализовать LocalBroadcast
, будет ли это дополнением к реализации сервиса? У вас есть подсказка о том, как с этого начать? Потому что, если я отправлю LocationUpdates, как только они появятся, я бы не стал беспокоиться о том, чтобы ждать подключения службы.
Комментарии:
1. Я бы не хотел отвечать здесь о связанных службах, потому что вопрос по SO должен касаться одной темы. В общем, вы не должны использовать службу, пока не был вызван
onServiceConnected()
обратный вызов. В вашем случае вы могли быlocationService.requestBackgroundLocation();
ввестиonServiceConnected()
и посмотреть, что произойдет.2. Ну ладно. Я не видел такой зависимости с функцией onServiceConnected (). Да, тогда это звучит неплохо. Тогда я позабочусь о трансляциях в другой раз. На данный момент все работает так, как я хочу. Спасибо!
Ответ №1:
То, что у вас есть, на самом деле не очень хороший дизайн. Подумайте вот о чем: обычно вы хотели бы не просто получить местоположение, но и постоянно обновлять его. Это означает, что ваша активность должна быть уведомлена о появлении таких обновлений.
Здесь у вас есть несколько вариантов:
- Привяжите службу и выполните обычные вызовы методов для нее (получите местоположение, зарегистрируйте / отмените регистрацию слушателей)
- Используется
LocalBroadcastManager
для трансляции обновлений местоположения из службы в Activities - Используйте какую-нибудь шину событий (мою любимую — EventBus от GreenRobot), чтобы транслировать обновления местоположения из сервиса в мероприятия
Я лично использую последний подход: служба отправляет «липкие» события в Event Bus при обновлении местоположения, и действия запрашивают эти события в onResume()
, а также подписываются на обновления. Таким образом, вашему Service
не нужно будет постоянно работать — запустите его, когда вам нужно местоположение, получите местоположение с желаемой точностью и остановите службу, чтобы не расходовать заряд батареи.
Комментарии:
1. Спасибо, это было начало. Я привязал службу, но теперь моя служба равна нулю, пока она не подключена. Я отредактировал свой вопрос и был бы благодарен за еще несколько советов 🙂
Ответ №2:
Да, не делайте этого — это не только неэлегантно, но и приведет к утечке памяти. Служба Android может быть привязана к любому другому компоненту, см.:https://developer.android.com/guide/components/bound-services.html . Ваша активность или другая служба будут привязаны к вашей службе определения местоположения и использовать интерфейс, предоставляемый этой службой. Обратите внимание, служба будет запущена, когда останется хотя бы одно соединение. Запустите и привяжитесь к службе, а затем она будет выполняться до тех пор, пока вы ее не остановите, и вы сможете использовать явный интерфейс из этой службы с помощью Binder. Еще одна хорошая технология — использование EventBus (greenRobot) для передачи фиксированных событий между Activity и сервисом. Событие будет ждать, пока другой компонент не будет инициализирован и получит это событие. Вы можете подписаться на это событие и отказаться от подписки с помощью методов onPause и onResume.