如何从 activity 执行在启动服务上定义的方法并取回结果?
How can I execute a method that's defined on a started service from an activity and get the result back?
如果我有此服务,我需要创建一个方法 getCoordinates(),因为我想从该服务进行广播,但我希望这些坐标可在需要时从活动中使用。假设我有一个方法 getCoordinates(),这是为活动创建一个可访问的方法来调用它的最佳方法?在想要消费它的活动中,该调用将如何进行?是否需要进行任何检查以防服务未正常运行而不会使应用程序崩溃?下面提供了我当前的代码。非常感谢。
@SuppressWarnings("MissingPermission")
public class GPSService extends Service {
private LocationListener listener;
private LocationManager locationManager;
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate() {
super.onCreate();
listener= new LocationListener() {
@Override
public void onLocationChanged(Location location) {
//To transfer the data to the main activity I use broadcast receiver in the main activity, using an intent filter location_update
Intent intentSendLocationMainActivity = new Intent("location_update");
Log.d("Location-update",location.getLongitude()+" "+location.getLongitude());
intentSendLocationMainActivity.putExtra("coordinates",location.getLongitude()+" "+location.getLongitude());
//I need to differentiate here if the app is killed or not to send the location to main activity or to a server
sendBroadcast(intentSendLocationMainActivity);
}
@Override
public void onStatusChanged(String s, int i, Bundle bundle) {
}
@Override
public void onProviderEnabled(String s) {
}
@Override
public void onProviderDisabled(String s) {
Intent activateGPSIntent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
activateGPSIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(activateGPSIntent);
}
};
locationManager = (LocationManager) getApplicationContext().getSystemService(Context.LOCATION_SERVICE);
//noinspection MissingPermission, listen for updates every 3 seconds
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,3000,0,listener);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d("ClearFromRecentService", "Service Started");
return START_STICKY;
}
@Override
public void onDestroy() {
super.onDestroy();
Log.d("ClearFromRecentService", "Service Destroyed, Removing update location listener");
//unregistering the listener
/*if(locationManager != null){
locationManager.removeUpdates(listener);
}*/
}
public void onTaskRemoved(Intent rootIntent) {
Log.e("ClearFromRecentService", "END");
//here you can call a background network request to post you location to server when app is killed
Toast.makeText(getApplicationContext(), "Warning: App killed", Toast.LENGTH_LONG).show();
//stopSelf(); //call this method to stop the service
}
public void getCoordinate(){
//return coordinates to the user
}
}
在您的服务中创建一个扩展 Binder 的 class,并在此 class 中创建一个函数,该函数 return 是指向服务本身的指针。还要创建一个与 Binder class 相同类型的成员变量,并在 onBind()
中创建 return 这个对象...所有这些都在你的服务中
private final IBinder mBinder = new GPSBinder();
public class GPSBinder extends Binder {
public GPSService getService() {
return GPSService.this;
}
}
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
在您的 activity 中,您需要添加一个 GPSServie 类型的变量,并绑定到该服务,可能在您的 onResume()
中,并添加一个将被通知的 ServiceConnection
对象绑定完成后,您将获得 Binder 的一个实例,您可以使用它来获取服务的实例
GPSService mService;
bindService(intent, mConnection, Context.BIND_AUTO_CREATE); // Put this in onResume()
private ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName className, IBinder service) {
// We've bound to LocalService, cast the IBinder and get LocalService instance
GPSService.GPSBinder binder = (GPSService.GPSBinder)service;
myService = binder.getService();
}
@Override
public void onServiceDisconnected(ComponentName arg0) {
mService = null;
}
};
最后,无论何时需要调用 getCoordinate(),只需使用服务变量
if (myService!=null)
myService.getCoordinate(); // YEAH!!!!!
不要忘记在 onPause()
上与服务解除绑定
您可以定义 getCoordinates() 方法如何使用静态方法:
public static void getCoordinate(){
//return coordinates to the user
}
有了这个解决方案,您可以随时随地调用它。
NOTE: you have defined getCoordinates() how void, it can't return nothing.
如果我有此服务,我需要创建一个方法 getCoordinates(),因为我想从该服务进行广播,但我希望这些坐标可在需要时从活动中使用。假设我有一个方法 getCoordinates(),这是为活动创建一个可访问的方法来调用它的最佳方法?在想要消费它的活动中,该调用将如何进行?是否需要进行任何检查以防服务未正常运行而不会使应用程序崩溃?下面提供了我当前的代码。非常感谢。
@SuppressWarnings("MissingPermission")
public class GPSService extends Service {
private LocationListener listener;
private LocationManager locationManager;
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate() {
super.onCreate();
listener= new LocationListener() {
@Override
public void onLocationChanged(Location location) {
//To transfer the data to the main activity I use broadcast receiver in the main activity, using an intent filter location_update
Intent intentSendLocationMainActivity = new Intent("location_update");
Log.d("Location-update",location.getLongitude()+" "+location.getLongitude());
intentSendLocationMainActivity.putExtra("coordinates",location.getLongitude()+" "+location.getLongitude());
//I need to differentiate here if the app is killed or not to send the location to main activity or to a server
sendBroadcast(intentSendLocationMainActivity);
}
@Override
public void onStatusChanged(String s, int i, Bundle bundle) {
}
@Override
public void onProviderEnabled(String s) {
}
@Override
public void onProviderDisabled(String s) {
Intent activateGPSIntent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
activateGPSIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(activateGPSIntent);
}
};
locationManager = (LocationManager) getApplicationContext().getSystemService(Context.LOCATION_SERVICE);
//noinspection MissingPermission, listen for updates every 3 seconds
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,3000,0,listener);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d("ClearFromRecentService", "Service Started");
return START_STICKY;
}
@Override
public void onDestroy() {
super.onDestroy();
Log.d("ClearFromRecentService", "Service Destroyed, Removing update location listener");
//unregistering the listener
/*if(locationManager != null){
locationManager.removeUpdates(listener);
}*/
}
public void onTaskRemoved(Intent rootIntent) {
Log.e("ClearFromRecentService", "END");
//here you can call a background network request to post you location to server when app is killed
Toast.makeText(getApplicationContext(), "Warning: App killed", Toast.LENGTH_LONG).show();
//stopSelf(); //call this method to stop the service
}
public void getCoordinate(){
//return coordinates to the user
}
}
在您的服务中创建一个扩展 Binder 的 class,并在此 class 中创建一个函数,该函数 return 是指向服务本身的指针。还要创建一个与 Binder class 相同类型的成员变量,并在 onBind()
中创建 return 这个对象...所有这些都在你的服务中
private final IBinder mBinder = new GPSBinder();
public class GPSBinder extends Binder {
public GPSService getService() {
return GPSService.this;
}
}
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
在您的 activity 中,您需要添加一个 GPSServie 类型的变量,并绑定到该服务,可能在您的 onResume()
中,并添加一个将被通知的 ServiceConnection
对象绑定完成后,您将获得 Binder 的一个实例,您可以使用它来获取服务的实例
GPSService mService;
bindService(intent, mConnection, Context.BIND_AUTO_CREATE); // Put this in onResume()
private ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName className, IBinder service) {
// We've bound to LocalService, cast the IBinder and get LocalService instance
GPSService.GPSBinder binder = (GPSService.GPSBinder)service;
myService = binder.getService();
}
@Override
public void onServiceDisconnected(ComponentName arg0) {
mService = null;
}
};
最后,无论何时需要调用 getCoordinate(),只需使用服务变量
if (myService!=null)
myService.getCoordinate(); // YEAH!!!!!
不要忘记在 onPause()
您可以定义 getCoordinates() 方法如何使用静态方法:
public static void getCoordinate(){
//return coordinates to the user
}
有了这个解决方案,您可以随时随地调用它。
NOTE: you have defined getCoordinates() how void, it can't return nothing.