客户必须具有ACCESS_FINE_LOCATION权限才能请求PRIORITY_HIGH_ACCURACY位置运行时错误

时间:2017-10-24 11:58:37

标签: java android android-permissions google-location-services

有很多类似的问题,但似乎都没有解决我的问题。

我已经应用了文档中提到的运行时权限,但我仍然在行上遇到运行时错误

LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);

这是我的完整代码。

public class MainActivity extends AppCompatActivity implements GoogleApiClient.ConnectionCallbacks,
    GoogleApiClient.OnConnectionFailedListener,LocationListener {

private static final String TAG ="hello" ;
private GoogleApiClient mGoogleApiClient;
private LocationRequest mLocationRequest;


public Location mLastLocation=null;


public final int MY_PERMISSIONS_REQUEST_COARSE_LOCATION=0;

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

    if (mGoogleApiClient==null){
        mGoogleApiClient= new GoogleApiClient.Builder(this)

                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .addApi(LocationServices.API)
                .build();
    }

    mLocationRequest = LocationRequest.create()
            .setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
            .setInterval(10 * 100)        // 10 seconds, in milliseconds
            .setFastestInterval( 1* 100); // 1 second, in milliseconds

    }









@Override
public void onConnected(@Nullable Bundle bundle) {


    int permissionCheck = ContextCompat.checkSelfPermission(this,
            Manifest.permission.ACCESS_FINE_LOCATION);
    int permissionCheck1 = ContextCompat.checkSelfPermission(this,
            Manifest.permission.ACCESS_COARSE_LOCATION);
    if (permissionCheck != PackageManager
            .PERMISSION_GRANTED && permissionCheck1 != PackageManager.PERMISSION_GRANTED) {

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

            // Show an explanation 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(this,
                    new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
                    MY_PERMISSIONS_REQUEST_COARSE_LOCATION);


        }
    }


    mLastLocation=LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
    if (mLastLocation != null) {
        TextView mLatitudeText =(TextView)findViewById(R.id.textView);
        TextView mLongitudeText =(TextView)findViewById(R.id.textView2);

        mLatitudeText.setText(String.valueOf(mLastLocation.getLatitude()));
        mLongitudeText.setText(String.valueOf(mLastLocation.getLongitude()));

        Log.i("Location Info", "Location achieved!");

    } else {



        Log.i("Location Info", "No location :(");

    }


    LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);//error here!!






}



@Override
public void onConnectionSuspended(int i) {

}

@Override
public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {

}

@Override
protected void onResume() {
    mGoogleApiClient.connect();
    super.onResume();

}

@Override
protected void onPause() {
    mGoogleApiClient.disconnect();
    super.onPause();
}



@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    switch (requestCode) {
        case  MY_PERMISSIONS_REQUEST_COARSE_LOCATION :{
            // If request is cancelled, the result arrays are empty.
            if (grantResults.length > 0
                    && grantResults[0] == PackageManager.PERMISSION_GRANTED) {

                Log.i("Message","Got full permission");



            } else {

                // permission denied, boo! Disable the
                // functionality that depends on this permission.
            }
            return;
        }

        // other 'case' lines to check for other
        // permissions this app might request
    }



}


@Override
public void onLocationChanged(Location location)
{
    Log.i("Location Info", "Location is changed Bitchh :(");
    handleNewLocation(location);
}

private void handleNewLocation(Location location) {
    Log.d(TAG, location.toString());
}

}

此外,已在清单文件中授予权限。

因此,这是运行时的错误堆栈跟踪

  

10-24 17:13:02.857 2224-2379 / com.example.ashutosh.location E / AbstractTracker:无法在未调用Looper.prepare()的线程内创建处理程序   0-24 17:13:03.184 2224-2224 / com.example.ashutosh.location E / AndroidRuntime:FATAL EXCEPTION:main                                                                                处理:com.example.ashutosh.location,PID:2224                                                                                java.lang.SecurityException:客户端必须具有ACCESS_FINE_LOCATION权限才能请求PRIORITY_HIGH_ACCURACY位置。                                                                                    在android.os.Parcel.readException(Parcel.java:1620)                                                                                    在android.os.Parcel.readException(Parcel.java:1573)                                                                                    在com.google.android.gms.internal.zzed.zzb(未知来源)                                                                                    在com.google.android.gms.internal.zzcda.zza(未知来源)                                                                                    在com.google.android.gms.internal.zzcdd.zza(未知来源)                                                                                    在com.google.android.gms.internal.zzcdj.zza(未知来源)                                                                                    在com.google.android.gms.internal.zzccc.zza(未知来源)                                                                                    在com.google.android.gms.internal.zzbay.zzb(未知来源)                                                                                    在com.google.android.gms.internal.zzbca.zze(未知来源)                                                                                    在com.google.android.gms.internal.zzbcx.zze(未知来源)                                                                                    在com.google.android.gms.internal.zzbcp.zze(未知来源)                                                                                    在com.google.android.gms.internal.zzccb.requestLocationUpdates(未知来源)                                                                                    在com.example.ashutosh.location.MainActivity.onConnected(MainActivity.java:122)                                                                                    在com.google.android.gms.common.internal.zzac.zzn(未知来源)                                                                                    在com.google.android.gms.internal.zzbcp.zzm(未知来源)                                                                                    在com.google.android.gms.internal.zzbcd.zzpY(未知来源)                                                                                    在com.google.android.gms.internal.zzbcd.onConnected(未知来源)                                                                                    在com.google.android.gms.internal.zzbcx.onConnected(未知来源)                                                                                    在com.google.android.gms.internal.zzbbi.onConnected(未知来源)                                                                                    在com.google.android.gms.common.internal.zzaa.onConnected(未知来源)                                                                                    在com.google.android.gms.common.internal.zzn.zzrj(未知来源)                                                                                    在com.google.android.gms.common.internal.zze.zzs(未知来源)                                                                                    在com.google.android.gms.common.internal.zzi.zzrk(未知来源)                                                                                    在com.google.android.gms.common.internal.zzh.handleMessage(未知来源)                                                                                    在android.os.Handler.dispatchMessage(Handler.java:102)                                                                                    在android.os.Looper.loop(Looper.java:152)                                                                                    在android.app.ActivityThread.main(ActivityThread.java:5497)                                                                                    at java.lang.reflect.Method.invoke(Native Method)                                                                                    在com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run(ZygoteInit.java:726)                                                                                    在com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)

3 个答案:

答案 0 :(得分:2)

requestPermissions() 异步。返回时,您还没有权限。用户甚至没有询问有关权限。

您需要在两个地方执行您的位置逻辑:

  • 如果您已经获得许可,请事先预先

  • onRequestPermissionResult()中,如果您请求了权限并且用户授予了权限

This sample appthis sample app说明了如何请求运行时权限并将其与LocationClient一起使用。

答案 1 :(得分:0)

尝试此序列,

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


int permissionCheck = ContextCompat.checkSelfPermission(this,
        Manifest.permission.ACCESS_FINE_LOCATION);
int permissionCheck1 = ContextCompat.checkSelfPermission(this,
        Manifest.permission.ACCESS_COARSE_LOCATION);
if (permissionCheck != PackageManager
        .PERMISSION_GRANTED && permissionCheck1 != PackageManager.PERMISSION_GRANTED) {

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

        // Show an explanation 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(this,
                new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
                MY_PERMISSIONS_REQUEST_COARSE_LOCATION);


    }
} else {

if (mGoogleApiClient==null){
    mGoogleApiClient= new GoogleApiClient.Builder(this)

            .addConnectionCallbacks(this)
            .addOnConnectionFailedListener(this)
            .addApi(LocationServices.API)
            .build();
}

mLocationRequest = LocationRequest.create()
        .setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
        .setInterval(10 * 100)        // 10 seconds, in milliseconds
        .setFastestInterval( 1* 100); // 1 second, in milliseconds
        }
}



@Override public void onConnected(@Nullable Bundle bundle) {
mLastLocation=LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
if (mLastLocation != null) {
    TextView mLatitudeText =(TextView)findViewById(R.id.textView);
    TextView mLongitudeText =(TextView)findViewById(R.id.textView2);
    mLatitudeText.setText(String.valueOf(mLastLocation.getLatitude()));
    mLongitudeText.setText(String.valueOf(mLastLocation.getLongitude()));
    Log.i("Location Info", "Location achieved!");
} else {
    Log.i("Location Info", "No location :(");
}

LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);//error here!!
}


@Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
switch (requestCode) {
    case  MY_PERMISSIONS_REQUEST_COARSE_LOCATION :{
        // If request is cancelled, the result arrays are empty.
        if (grantResults.length > 0
                && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            Log.i("Message","Got full permission");
        if (mGoogleApiClient==null){
         mGoogleApiClient= new GoogleApiClient.Builder(this)
            .addConnectionCallbacks(this)
            .addOnConnectionFailedListener(this)
            .addApi(LocationServices.API)
            .build();
        }
        mLocationRequest = LocationRequest.create()
        .setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
        .setInterval(10 * 100)        // 10 seconds, in milliseconds
        .setFastestInterval( 1* 100); // 1 second, in milliseconds
        } else {

            // permission denied, boo! Disable the
            // functionality that depends on this permission.
        }
        return;
    }
    // other 'case' lines to check for other
    // permissions this app might request
}

}

答案 2 :(得分:0)

我讨厌以下解决方案,但我没有找到更好的方法。 如果您从Google API请求位置API并执行:.addApi(LocationServices.API),则需要在连接GoogleAPI之前获得位置。

因此,

fun checkPermission(context:Context, permission:Name) : Boolean =
    ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED

fun isLocationPermissionGranted() = checkPermission(context, Manifest.permission.ACCESS_FINE_LOCATION)

if (isLocationPermissionGranted()) {
     googleApiBuilder.connect()
} else {
     MyPermissionChangeRegistrar().instance.register { 
          if (isLocationPermissionGranted()) {
               googleApiBuilder.connect()
          }
     } 
}

当权限注册商是一个在权限更改时调用回调的类

class SomeActivity: Activity() {
    override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) {
        MyPermissionChangeRegistrar.callCallbacks()
    }
}

IMMHO,Google应该在内部防范这种情况。但他们没有。