Android - 跨多个活动实现LocationListener的最佳方式

d37*_*3ur 40 android locationlistener

我已经坚持这个问题很长一段时间了.我正在开发一个在几个不同的活动中广泛使用位置的应用程序.我发现的每个示例都在每个Activity中使用单独的LocationListener.这在我的情况下是不可行的.

我想知道在多个活动中跟踪用户位置的最有效方法是什么.现在我已经创建了一个实现LocationListener的服务,并使用广播来更新Activity基类中的静态lat和long字段.这意味着该服务始终在运行,这并不理想.但是,如果我关闭服务并仅在需要时重新启动它,那么获得一个好位置需要时间.我需要Activity的onCreate()中的位置数据.如果我尝试在activity基类中实现它,它也是一样的.如果我经常在onResume/onCreate中注册监听器并在onPause()中注销它,则开始接收更新需要花费太多时间.我还试图创建一个我可以绑定的服务,所以它只在我需要一个位置时启动.但是我遇到了同样的问题,绑定到服务并开始获取更新需要很长时间.

我现在使用的服务是有效的,但是从我读过的所有内容中,我不应该使用不断运行的服务来处理这样的琐碎事情.但该应用程序的重点是根据用户的当前位置提供相关数据.所以我有一个只在后台运行的服务,并定期提供更新.导致我在这一点上重新检查设计的一个主要问题是,我最近发现如果用户在没有打开GPS的情况下启动应用程序然后启用它,则不会调用onProviderEnabled().在这种情况下,应用程序无法识别GPS已启用,因此它可以开始侦听更新.

我认为我从查看示例中了解了LocationManager和LocationListener,但我似乎无法将其应用于我需要多个活动中的位置数据的情况.任何帮助或建议将不胜感激.

Dev*_*red 43

我通常实现此要求的方式是使用绑定的Service实现,如SDK文档中的本地服务示例中的实现.显然,您熟悉服务的优势,只允许您创建一次所有位置代码.

通过Bindings访问服务允许服务启动和停止,以便当您的应用程序不在前台时它不会运行(只要不再绑定任何活动就会死亡).使IMO工作良好的关键是将服务绑定到onStart()UNBIND中onStop(),因为当你从一个Activity移动到另一个Activity时,这两个调用会重叠(第二个Activity在第一个Activity停止之前开始).这使得服务在应用程序内部移动时不会死亡,并且只有当整个应用程序(或至少任何对位置感兴趣的部分)离开前台时服务才会死亡.

使用Bindings,您不必在Broadcast中传递Location数据,因为Activity可以直接在Service上调用方法来获取最新位置.然而,广播作为一种指示何时有新的更新可用的方法仍然是有利的......但是这只会成为监听活动的通知,以便getLocation()在服务上调用该方法.

我的0.02美元.希望有帮助!

  • @Grantland有效点,因为活动仍然是服务将存在的前景.如果服务需要在这些实例中重新调整自己,我会保持绑定相同,但让它为`Intent.ACTION_SCREEN_ON`和`Intent.ACTION_SCREEN_OFF`注册一个`BroadcastReceiver`来关闭像GPS这样的重组件.将绑定机制移动到onPause()/ onResume()会导致服务在整个应用程序的使用过程中经常停止/重新启动,因为这些回调从不重叠,让服务经常陷入未绑定状态. (2认同)

Spi*_*pau 17

我遇到了同样的问题,我试图用Devunwired的好答案来解决它,但我遇到了一些麻烦.我找不到停止服务的方法,当我完成我的应用程序时,GPS模块仍在运行.所以我发现了另一种方式:

我写了一个GPS.java类:

public class GPS {

    private IGPSActivity main;

    // Helper for GPS-Position
    private LocationListener mlocListener;
    private LocationManager mlocManager;

    private boolean isRunning;

    public GPS(IGPSActivity main) {
        this.main = main;

        // GPS Position
        mlocManager = (LocationManager) ((Activity) this.main).getSystemService(Context.LOCATION_SERVICE);
        mlocListener = new MyLocationListener();
        mlocManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, mlocListener);
        // GPS Position END
        this.isRunning = true;
    }

    public void stopGPS() {
        if(isRunning) {
            mlocManager.removeUpdates(mlocListener);
            this.isRunning = false;
        }
    }

    public void resumeGPS() {
        mlocManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, mlocListener);
        this.isRunning = true;
    }

    public boolean isRunning() {
        return this.isRunning;
    }

    public class MyLocationListener implements LocationListener {

        private final String TAG = MyLocationListener.class.getSimpleName();

        @Override
        public void onLocationChanged(Location loc) {
            GPS.this.main.locationChanged(loc.getLongitude(), loc.getLatitude());
        }

        @Override
        public void onProviderDisabled(String provider) {
            GPS.this.main.displayGPSSettingsDialog();
        }

        @Override
        public void onProviderEnabled(String provider) {

        }

        @Override
        public void onStatusChanged(String provider, int status, Bundle extras) {

        }

    }

}
Run Code Online (Sandbox Code Playgroud)

此类用于需要GPS坐标的每个Activity.每个Activity都必须实现以下接口(通信所需):

public interface IGPSActivity {
    public void locationChanged(double longitude, double latitude);
    public void displayGPSSettingsDialog();
}
Run Code Online (Sandbox Code Playgroud)

现在我的主要活动看起来像这样:

public class MainActivity extends Activity implements IGPSActivity {

    private GPS gps;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        gps = new GPS(this);
    }


    @Override
    protected void onResume() { 
        if(!gps.isRunning()) gps.resumeGPS();   
        super.onResume();
    }

    @Override
    protected void onStop() {
        gps.stopGPS();
        super.onStop();
    }


    public void locationChanged(double longitude, double latitude) {
        Log.d(TAG, "Main-Longitude: " + longitude);
        Log.d(TAG, "Main-Latitude: " + latitude);
    }


    @Override
    public void displayGPSSettingsDialog() {
                Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
                startActivity(intent);
    }
}
Run Code Online (Sandbox Code Playgroud)

第二个是这样的:

public class TEST4GPS extends Activity implements IGPSActivity{

    private GPS gps;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        this.gps = new GPS(this);
    }

    @Override
    public void locationChanged(double longitude, double latitude) {
        Log.d("TEST", "Test-Longitude: " + longitude);
        Log.d("TEST", "Test-Latitude: " + latitude);

    }

    @Override
    protected void onResume() { 
        if(!gps.isRunning()) gps.resumeGPS();   
        super. onResume();
    }

    @Override
    protected void onStop() {
        gps.stopGPS();
        super.onStop();
    }

    @Override
    public void displayGPSSettingsDialog() {
                Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
                startActivity(intent);

    }
}
Run Code Online (Sandbox Code Playgroud)

它不如Devunwired的解决方案那么漂亮,但它对我有用.CYA

  • @MrGibbage很抱歉,但我必须重新创建整个事情.我的答案现在已经3年了,如果我不得不再次在我的应用程序中实现全球GPS信号,那么它看起来会完全不同.将跟踪代码放在您的应用程序中,并使用LocalBroadcastManager将位置发送到您选择的活动/片段.https://developer.android.com/reference/android/support/v4/content/LocalBroadcastManager.html (2认同)