调用需要用户可能会拒绝的权限

32

我正在尝试制作一个应用程序,在每五分钟后发送用户位置更新。我认为我的代码运行良好,但是我收到有关应用程序使用的权限的错误。我非常确定已经在清单文件中添加了权限。有人能告译一下问题出在哪里吗?这是我的代码。

MainActivity.java

LocationManager locationManager ;
String provider;

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

    // Getting LocationManager object
    locationManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);

    // Creating an empty criteria object
    Criteria criteria = new Criteria();

    // Getting the name of the provider that meets the criteria
    provider = locationManager.getBestProvider(criteria, false);

    if(provider!=null && !provider.equals("")){

        // Get the location from the given provider
        Location location = locationManager.getLastKnownLocation(provider);
        locationManager.requestLocationUpdates(provider,5*60*1000,0,this);

        if(location!=null)
            onLocationChanged(location);
        else
            Toast.makeText(getBaseContext(), "Location can't be retrieved", Toast.LENGTH_SHORT).show();

    }else{
        Toast.makeText(getBaseContext(), "No Provider Found", Toast.LENGTH_SHORT).show();
    }
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.main, menu);
    return true;
}

@Override
public void onLocationChanged(Location location) {
    // Getting reference to TextView tv_longitude
    TextView tvLongitude = (TextView)findViewById(R.id.tv_longitude);

    // Getting reference to TextView tv_latitude
    TextView tvLatitude = (TextView)findViewById(R.id.tv_latitude);

    // Setting Current Longitude
    tvLongitude.setText("Longitude:" + location.getLongitude());

    // Setting Current Latitude
    tvLatitude.setText("Latitude:" + location.getLatitude() );
}

@Override
public void onProviderDisabled(String provider) {
    // TODO Auto-generated method stub
}

@Override
public void onProviderEnabled(String provider) {
    // TODO Auto-generated method stub
}

@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
    // TODO Auto-generated method stub
}

我在以下代码中收到一个错误,提示调用需要用户可能会拒绝的权限

Location location = locationManager.getLastKnownLocation(provider);
        locationManager.requestLocationUpdates(provider,5*60*1000,0,this);

我的 AndroidManifest 如下所示

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.INTERNET"/>

<application
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme" >
    <activity
        android:name=".MainActivity"
        android:label="@string/title_activity_main" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
</application>

4个回答

48

您使用哪个SDK?如果您使用的是Marshmallow,则需要检查用户是否已授予每个位置调用的权限。

请参阅此处

您应该像这样做:

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

如果您还没有权限,请请求权限。

有关更多信息,请查看上面的链接。


我正在使用Android 4.2及以上版本。 - Aman Verma
1
你必须使用SDK 23进行编译,没有其他的解释。请检查您的应用程序gradle文件中的设置。 - Shahar
是的,你说得对!它是使用SDK 23进行编译的。谢谢,这解决了问题。 - Aman Verma
6
这个 "MY_PERMISSION_ACCESS_COURSE_LOCATION" 是什么意思? - user3402040
一个常量整数,用于响应。 - Shahar
1
抱歉,但是只写了“问题已解决”,却没有说明如何解决的?应该修改哪个文件以及如何修改? - KansaiRobot

15

试一试我的代码:

public class MainActivity extends AppCompatActivity {

    /* GPS Constant Permission */
    private static final int MY_PERMISSION_ACCESS_COARSE_LOCATION = 11;
    private static final int MY_PERMISSION_ACCESS_FINE_LOCATION = 12;

    /* Position */
    private static final int MINIMUM_TIME = 10000;  // 10s
    private static final int MINIMUM_DISTANCE = 50; // 50m

    /* GPS */
    private String mProviderName;
    private LocationManager mLocationManager;
    private LocationListener mLocationListener;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        ...

        mLocationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);

        // Get the best provider between gps, network and passive
        Criteria criteria = new Criteria();
        mProviderName = mLocationManager.getBestProvider(criteria, true);

        // API 23: we have to check if ACCESS_FINE_LOCATION and/or ACCESS_COARSE_LOCATION permission are granted
        if (ContextCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED
                || ContextCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED) {

            // No one provider activated: prompt GPS
            if (mProviderName == null || mProviderName.equals("")) {
                startActivity(new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS));
            }

            // At least one provider activated. Get the coordinates
            switch (mProviderName) {
                case "passive":
                    mLocationManager.requestLocationUpdates(mProviderName, MINIMUM_TIME, MINIMUM_DISTANCE, this);
                    Location location = mLocationManager.getLastKnownLocation(mProviderName);
                    break;

                case "network":
                    break;

                case "gps":
                    break;

            }

        // One or both permissions are denied.
        } else {

            // The ACCESS_COARSE_LOCATION is denied, then I request it and manage the result in
            // onRequestPermissionsResult() using the constant MY_PERMISSION_ACCESS_FINE_LOCATION
            if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED ) {
                ActivityCompat.requestPermissions(this,
                        new String[]{Manifest.permission.ACCESS_COARSE_LOCATION},
                        MY_PERMISSION_ACCESS_COARSE_LOCATION);
            }
            // The ACCESS_FINE_LOCATION is denied, then I request it and manage the result in
            // onRequestPermissionsResult() using the constant MY_PERMISSION_ACCESS_FINE_LOCATION
            if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED ) {
                ActivityCompat.requestPermissions(this,
                        new String[] { Manifest.permission.ACCESS_FINE_LOCATION },
                        MY_PERMISSION_ACCESS_FINE_LOCATION);
            }

        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
        switch (requestCode) {
            case MY_PERMISSION_ACCESS_COARSE_LOCATION: {
                if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    // permission was granted
                } else {
                    // permission denied
                }
                break;

            case MY_PERMISSION_ACCESS_FINE_LOCATION: {
                if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    // permission was granted
                } else {
                    // permission denied
                }
                break;
            }

        }
    }
}

来源:链接


1
你可以调用 requestPermission 一次,将两个权限都传递到数组中。 - Fred Porciúncula
@ThiagoPorciúncula 我会尝试 :) 谢谢你的建议。 - eldivino87
1
这可能实际上没有任何区别,因为权限组的缘故。当您获取ACCESS_FINE_LOCATION权限时,自动获取ACCESS_COARSE_LOCATION权限,因为它们属于同一组(LOCATION)。在此处了解更多信息:http://developer.android.com/intl/pt-br/training/permissions/requesting.html。 - Fred Porciúncula

5

这对我很有帮助

if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
   Toast.makeText(YourService.this, "First enable LOCATION ACCESS in settings.", Toast.LENGTH_LONG).show();
   return;
}
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 100, 1, listener);

5
如果你请求定位时不使用这段精确的代码,即使你以其他自定义方式管理权限,安卓工作室会因任何原因报错。这是正确的做法。 - Sca09

3
Here are the bunch of steps you need to perform to fix this: 这是您需要执行的一系列步骤来解决此问题:
Main Activity .java: 主活动.java:
if (ContextCompat.checkSelfPermission(this,
 android.Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED
 || ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) 
 == PackageManager.PERMISSION_GRANTED) {         
locationManager.requestLocationUpdates
 (locationManager.requestLocationUpdates(provider,5*60*1000,0,this);
}//end of if

现在,您还需要更新您的 build.gradle
dependencies{
 ------------- //your pre-generated code
compile 'com.android.support:support-v4:23.0.1'
}

this 是Android开发者对它的评价。

如果您使用模拟器,请不要忘记从应用程序设置中授予权限,因为它可能不会提示您这样做。


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