如何从 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.