在Android API 23中获取用户位置

4

我可以编写代码获取用户的位置,在 API < 23 中可以正常工作。但在 API 23 及以上版本中,我的代码在日志中没有返回任何内容。

更多细节:
我手动启用了设备的 GPS。 在第一次运行应用程序时,应用程序请求权限,但没有日志返回。
在下一次运行时,应用程序返回我的准备好的 Toast(检查您的提供者)。

这是我编写的代码:

public class MainActivity extends AppCompatActivity implements LocationListener {

private static final int MY_PERMISSIONS_REQUEST_COARSE_LOCATION = 124;
private static final int MY_PERMISSIONS_REQUEST_FINE_LOCATION = 123;

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

    // Here, thisActivity is the current activity
    if (ContextCompat.checkSelfPermission(this,
            Manifest.permission.ACCESS_FINE_LOCATION)
            != PackageManager.PERMISSION_GRANTED) {

        // Should we show an explanation?
        if (ActivityCompat.shouldShowRequestPermissionRationale(this,
                Manifest.permission.ACCESS_FINE_LOCATION)) {

        } else {

            ActivityCompat.requestPermissions(this,
                    new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
                    MY_PERMISSIONS_REQUEST_FINE_LOCATION);
        }
    }
    if (ContextCompat.checkSelfPermission(this,
            Manifest.permission.ACCESS_COARSE_LOCATION)
            != PackageManager.PERMISSION_GRANTED) {

        if (ActivityCompat.shouldShowRequestPermissionRationale(this,
                Manifest.permission.ACCESS_COARSE_LOCATION)) {

        } else {
            ActivityCompat.requestPermissions(this,
                    new String[]{Manifest.permission.ACCESS_COARSE_LOCATION},
                    MY_PERMISSIONS_REQUEST_COARSE_LOCATION);

        }
    }

    if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
        // TODO: Consider calling
        //    ActivityCompat#requestPermissions
        // here to request the missing permissions, and then overriding
        //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
        //                                          int[] grantResults)
        // to handle the case where the user grants the permission. See the documentation
        // for ActivityCompat#requestPermissions for more details.
        return;
    }
    LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
    String provider = locationManager.getBestProvider(new Criteria(), false);
    Location location = locationManager.getLastKnownLocation(provider);
    if (location == null) {
        Toast.makeText(this, "Check your provider", Toast.LENGTH_SHORT).show();
    } else {
        Log.i("New Location", "lat: " + location.getLatitude());
        Log.i("New Location", "lng: " + location.getLongitude());
    }
}

@Override
public void onLocationChanged(Location location) {
    Log.i("Location", "lat: " + location.getLatitude());
    Log.i("Location", "lng: " + location.getLongitude());
}

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

}

@Override
public void onProviderEnabled(String provider) {

}

@Override
public void onProviderDisabled(String provider) {

}

}


在你的方法 getBestProvider() 中,你只检查已启用的提供程序,如果提供程序未启用,则位置将始终返回 null。在这种情况下,您需要检查提供程序是否已启用,如果未启用,则让用户启用它。 - Sandeep Londhe
我将 true 改为了 false,但并没有解决问题。如何进行第二步?我在 Android 开发方面几乎是新手。 - DrMorteza
1个回答

6
在Android API 23+中,有一种新的处理被视为“危险”的权限的方法,比如android.permission.ACCESS_FINE_LOCATIONandroid.permission.ACCESS_COARSE_LOCATION等。
如果您正在使用android.permission.ACCESS_FINE_LOCATION,则无需处理android.permission.ACCESS_COARSE_LOCATION
请查看官方文档中的此链接,了解如何在Android API 23+中在运行时处理权限。 https://developer.android.com/training/permissions/requesting.html 这个链接也可能会对您有所帮助。 https://developer.android.com/guide/topics/location/strategies.html 如何检查权限:
int permissionCheck = ContextCompat.checkSelfPermission(thisActivity,
    Manifest.permission.ACCESS_FINE_LOCATION);

如何请求权限:

if (ContextCompat.checkSelfPermission(thisActivity,
            Manifest.permission.ACCESS_FINE_LOCATION)
    != PackageManager.PERMISSION_GRANTED) {

    // Should we show an explanation?
    if (ActivityCompat.shouldShowRequestPermissionRationale(thisActivity,
        Manifest.permission.ACCESS_FINE_LOCATION)) {

        // Show an expanation to the user *asynchronously* -- don't block
        // this thread waiting for the user's response! After the user
        // sees the explanation, try again to request the permission.

    } else {

        // No explanation needed, we can request the permission.

        ActivityCompat.requestPermissions(thisActivity,
            new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
            MY_PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION);

        // MY_PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION is an
        // app-defined int constant. The callback method gets the
        // result of the request.
    }
}

请注意,即使您在运行时请求权限,仍必须像这样在Android清单中保留权限条目:
<manifest ... >
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    ...
    <!-- Needed only if your app targets Android 5.0 (API level 21) or higher. -->
    <uses-feature android:name="android.hardware.location.gps" />
    ...
</manifest>

在检查和授权权限后,您应该根据上面的位置策略审查链接,您可以在那里找到您缺少的详细信息。

基本上您没有注册侦听器以接收位置更新。 在onCreate()方法的末尾添加此行后,您应该开始在日志中看到位置更新。

// Register the listener with the Location Manager to receive location updates
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, this);

没有解决问题。我认为问题不在权限上,因为会再次返回 Toast。而且 Toast 是在“location == null”时出现的。 - DrMorteza
请检查更新后的答案。现在应该可以了。 - Alejandro Casanova
谢谢。你的回答解决了问题。但是,它运行了一个加载locationUpdate方法的方式(有些取巧)。我的 onCreate()方法里的位置获取器没有获取到位置(返回我预先准备的Toast)。这并不是一个解决方案吗?或者我应该移除这些代码行吗? - DrMorteza

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接