【问题标题】:Android Location API does not show mock locations onLocationChangedAndroid Location API 不显示模拟位置 onLocationChanged
【发布时间】:2014-06-18 04:22:58
【问题描述】:

我正在努力使用 android location api 不断更新我的设备当前位置。我在这里做错了什么?

import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.util.Log;
import android.widget.Toast;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesClient;
import com.google.android.gms.common.GooglePlayServicesUtil;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.GoogleMapOptions;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.LatLng;

public class ViewMapActivity extends FragmentActivity implements LocationListener,
        GooglePlayServicesClient.ConnectionCallbacks, GooglePlayServicesClient.OnConnectionFailedListener {

    public static final Long LOCATION_MIN_TIME = 1000L;
    public static final float LOCATION_MIN_DISTANCE = 10f;

    private static GoogleMap googleMap;
    private LocationManager locationManager;
    private  Criteria criteria;
    private String provider;


    public ViewMapActivity() {
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.i("ViewMap"," Map created");
        setContentView(R.layout.map);
        GooglePlayServicesUtil.isGooglePlayServicesAvailable(getApplicationContext());
        GoogleMapOptions mapOptions = new GoogleMapOptions();
        mapOptions.mapType(GoogleMap.MAP_TYPE_NORMAL);
        mapOptions.zoomGesturesEnabled(true);
        mapOptions.zoomControlsEnabled(true);
        googleMap = ((SupportMapFragment)  getSupportFragmentManager().findFragmentById(R.id.mapfragment))
                .getMap();
        googleMap.setMyLocationEnabled(true);

        locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
        criteria = new Criteria();
        provider = locationManager.getBestProvider(criteria,  false);
        //Log.d("ViewMap", provider.toString());

        Location location = locationManager.getLastKnownLocation(provider);

        if(location != null) {
            onLocationChanged(location);
        } else {
            Log.d("ViewMap", "Location found onCreate."+location.toString());
        }
    }

    @Override
    protected void onPause() {
        super.onPause();
        Log.d("ViewMap", "Paused");
        locationManager.removeUpdates(this);
    }

    @Override
    protected void onResume() {
        super.onResume();
        Log.d("ViewMap", "Resume");
        locationManager.requestLocationUpdates(provider, 400, 1, this);
    }

    @Override
    public void onLocationChanged(Location location) {
        Log.i("ViewMap", "location changed");
        LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude());
        //googleMap.moveCamera(CameraUpdateFactory.newLatLng(latLng));
        //googleMap.animateCamera(CameraUpdateFactory.zoomBy(15)); //TODO: move this to static config
        String loc = "Lat:"+latLng.latitude+" long:"+latLng.longitude;
        Toast.makeText(getBaseContext(), loc, Toast.LENGTH_SHORT).show();
        Log.d("ViewMap", latLng.toString());
    }

    @Override
    public void onStatusChanged(String s, int i, Bundle bundle) {
        Log.d("ViewMap", "Status Changed: "+s);
    }

    @Override
    public void onProviderEnabled(String s) {
        if(locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)){
            Log.d("ViewMap", "GPS Provider");
            locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 400, 1, this);
        } else {
            Log.d("ViewMap", "Network Provider");
            locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, this);
        }
    }

    @Override
    public void onProviderDisabled(String s) {
        if(locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)){
            locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this);
        } else {
            locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, this);
        }
    }

    @Override
    public void onConnected(Bundle bundle) {
        // TODO may be add some logs
        Log.i("ViewMap", "GPS can work now");
        locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 0, this);
        locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 1000, 0, this);
    }

    @Override
    public void onDisconnected() {
        // TODO may be add some logs
        Log.i("ViewMap", "GPS is disconnected");
    }

    @Override
    public void onConnectionFailed(ConnectionResult connectionResult) {
       // TODO may be add some logs
        Log.e("ViewMap", "Google play connection failed. GPS might not work");
    }
}

这里是 AndroidManifest.xml

 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
           package="com.sample.activity"
           android:versionCode="1"
          android:versionName="1.0">
    <uses-sdk android:minSdkVersion="18"/>

    <permission
            android:name="com.sample.activity.permissions.MAP_RECEIVE"
            android:protectionLevel="signature" />

    <uses-feature
            android:glEsVersion="0x00020000"
            android:required="true" />

    <uses-permission android:name="android.permission.ACCESS_GPS" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission 
android:name="com.google.android.providers.gsf.permission.READ_GSERVICES"
/>
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION" />


    <application android:label="@string/app_name" android:icon="@drawable/ic_launcher">
        <activity android:name="SplashScreenStartActivity"
                  android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>

        <activity android:name=".ViewMapActivity"/>



        <meta-data android:name="com.google.android.maps.v2.API_KEY" 
android:value="@string/google_map_api_key" />
         <meta-data android:name="com.google.android.gms.version" android:value="@integer/google_play_services_version" />
     </application> </manifest>

作为后续问题,我如何通过传递模拟位置来测试此活动。我正在使用来自 http://developer.android.com/training/location/location-testing.html 的模拟位置示例。标记确实显示模拟位置,但 onLocation 始终显示当前位置

【问题讨论】:

  • 标记确实显示了模拟位置,但 onLocation 总是显示当前位置——那么到底是什么问题?
  • 问题是当前位置显示的是真实的当前位置,而不是developer.android.com/training/location/location-testing.html提供的测试应用提供的位置。我可以看到当前标记在不同的模拟位置移动,但 onLocationChanged 始终显示我的真实位置,而不是模拟位置。

标签: java android google-maps


【解决方案1】:

模拟位置仅适用于 GPS,不会伪造任何其他提供商。具体来说,它不会伪造 NETWORK 位置提供程序。不要使用标准来选择最佳提供商,请指定 GPS 提供商。

一般来说,我认为标准没有用。您编写了您的应用程序,您知道您是否需要 GPS 的准确性或想要通过网络节省电池电量。指定你想要的,而不是让操作系统为你挑选一个。

【讨论】:

  • 您的意思是,如果获得 GPS_PROVIDER,我将能够收听模拟位置。我想我早先尝试过,但没有奏效。让我再试一次,我会告诉你的。
  • 这个答案没有任何意义。您可以使用任何提供者名称作为模拟位置提供者。使用标准是一个好主意,因为它将您想要可用 分开。 (如果你直接指定 GPS 并且它被关闭,你就是 SOL)
  • @RobertLiberatore 标准过于复杂并提供 0 额外价值。您知道您需要什么,如果您需要 GPS,只需请求即可。如果没有,不要。我从来没有写过一个应用程序,我想使用它没有打开的非 GPS,我宁愿失败并要求打开它。我需要这种准确性,或者我不需要,我使用网络。今天的模拟提供者可能可以用于任何提供者,我已经有几年没有使用位置了。写这个答案时绝对不是真的。
  • 我刚刚在 API 18 上成功运行了一个虚构的模拟提供程序。/shrug 您对位置提供程序的态度是 Android 不再允许开发人员直接选择提供程序的原因(请参阅“融合位置提供程序” )。除了准确性之外,还有更多的因素需要衡量,坦率地说,依赖单一的提供者类型只是一个糟糕的建议。
  • 不,使用标准而不理解您要解决的问题并为其使用正确的提供程序是懒惰的编程,并且不必要地侵犯了您的用户隐私。如果您不是绝对需要 GPS,则应该请求网络。总是使用最不准确的,会给你可接受的结果。做任何其他事情都是低俗的。 FusedProvider 的事情是锁定试图迫使人们使用 Google Play 服务并杀死几个正在形成的分支,比如 Fire。这就是他们制作它的主要原因(以及为什么它不在平台上)。
【解决方案2】:

您能否使用您的活动的导入集更新问题,如果答案不正确,将编辑/删除我的答案。
为什么总是看到当前位置可能是因为onCreate()中的googleMap.setMyLocationEnabled(true);

坦率地说,有问题的代码似乎是从多个来源复制粘贴的,没有太多了解,或者细节被忽略了,不是那么温和。

代码包含两种获取用户位置的混合方法。
1.使用LocationClientRetrieving the Current Location
这实现了来自GooglePlayServicesClient
的接口 包裹是com.google.android.gms.location.LocationClient 所以这是LocationListener.
Testing Using Mock Locations的链接上,这个已经用过了。

2. 使用LocationManager
您可以使用requestLocationUpdates() 方法。这里的包是android.location 所以这是LocationListener.

这对您的代码意味着什么:
1.1您已经实现了第一个监听器方法,但您从未设置、调用或使用locationClient.connect(),因此永远不会调用以下代码部分。

@Override
    public void onConnected(Bundle bundle) {
        // TODO may be add some logs
        Log.i("ViewMap", "GPS can work now");
        locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 0, this);
        locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 1000, 0, this);
    }

    @Override
    public void onDisconnected() {
        // TODO may be add some logs
        Log.i("ViewMap", "GPS is disconnected");
    }

    @Override
    public void onConnectionFailed(ConnectionResult connectionResult) {
       // TODO may be add some logs
        Log.e("ViewMap", "Google play connection failed. GPS might not work");
    }  

无论如何,您都应该使用这种方法,因为您正在使用 Google Play 服务。

2.1 locationManager.requestLocationUpdates(provider, 400, 1, this);
如果您导入了正确的 LocationListener,这就是您获得位置的原因。您可以检查导入,如果它不是 android.location 包,我认为代码不会到达那里。

【讨论】:

  • 添加了一些导入语句。是的,你是对的,代码只是从不同来源复制粘贴代码。我对这些概念不熟悉。
猜你喜欢
  • 2016-12-09
  • 1970-01-01
  • 1970-01-01
  • 2021-03-22
  • 1970-01-01
  • 2016-09-02
  • 2012-03-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多