融合位置 API 运行时权限错误

Posted

技术标签:

【中文标题】融合位置 API 运行时权限错误【英文标题】:Fused location API runtime permissions error 【发布时间】:2017-04-30 10:47:32 【问题描述】:

我正在尝试获得访问该位置的权限并使用适用于 androidFusedlocation 提供程序 API,但是,我的应用在打开时崩溃。我查看了 Google 开发人员文档并对相应的方法进行了适当的更改。

当我得到一个位置时,我会传递坐标并使用 SharedPreferences 存储它们。能否请您告诉我我在程序中没有处理什么或处理不正确?

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

private final String TAG = "LocationActivity";

private GoogleApiClient mGoogleApiClient;
private LocationRequest mLocationRequest;

String lat, lon;
Location mLastLocation;
GridView androidGridView;
String[] gridViewString = 


@Override
protected void onCreate(Bundle savedInstanceState) 
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    //checkAppPermission();
    Log.d(TAG, "Test location ..............");
    //setup GoogleApiclient
    buildGoogleApiClient();
    Log.d(TAG, "After build api client");

public void checkAppPermission()
    if (checkPermission()) 
        Toast.makeText(this, "Permission already granted.", Toast.LENGTH_LONG).show();
     else 
        requestPermission();
        Toast.makeText(this, "Please request permission.", Toast.LENGTH_LONG).show();
    

private boolean checkPermission() 
    int result = ContextCompat.checkSelfPermission(getApplicationContext(), ACCESS_FINE_LOCATION);
    Log.d(TAG, "Test location 2..............");
    return result == PackageManager.PERMISSION_GRANTED;


private void requestPermission() 

    ActivityCompat.requestPermissions(this, new String[]ACCESS_FINE_LOCATION, 1);
    Log.d(TAG, "requestPermissions..............");

//This method will be called when the user will tap on allow or deny
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) 
    //Checking the request code of our request
    Log.d(TAG, "onRequestPermissionsResult..............");

    if (requestCode == 1) 

        //If permission is granted
        if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) 

            //Displaying a toast
            Toast.makeText(this, "Permission granted now you can read the storage", Toast.LENGTH_LONG).show();
         else 
            //Displaying another toast if permission is not granted
            Toast.makeText(this, "Oops you just denied the permission", Toast.LENGTH_LONG).show();
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) 
                if (shouldShowRequestPermissionRationale(android.Manifest.permission.ACCESS_FINE_LOCATION)) 
                    showMessageOKCancel("You need to allow access to both the permissions",
                            new DialogInterface.OnClickListener() 
                                @Override
                                public void onClick(DialogInterface dialog, int which) 
                                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) 
                                        requestPermissions(new String[]ACCESS_FINE_LOCATION,,
                                                1);
                                    
                                
                            );
                    return;
                
            
        
    



private void showMessageOKCancel(String message, DialogInterface.OnClickListener okListener) 
    new AlertDialog.Builder(MainActivity.this)
            .setMessage(message)
            .setPositiveButton("OK", okListener)
            .setNegativeButton("Cancel", null)
            .create()
            .show();


protected synchronized void buildGoogleApiClient() 
    mGoogleApiClient = new GoogleApiClient.Builder(this)
            .addApi(LocationServices.API)
            .addConnectionCallbacks(this)
            .addOnConnectionFailedListener(this)
            .build();
    Log.d(TAG, "GoogleAPIclient init ..............");



@Override
protected void onStart() 
    super.onStart();
    // Connect the client.
    Log.d(TAG, "onStart fired ..............");
    mGoogleApiClient.connect();



@Override
protected void onStop() 
    // Disconnecting the client invalidates it.
    mGoogleApiClient.disconnect();
    Log.d(TAG, "onStop fired ..............");
    super.onStop();


@Override
public void onConnected(Bundle bundle) 
    checkAppPermission();
    Log.d(TAG, "inside onconnected");
    mLocationRequest = LocationRequest.create();
    mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
    mLocationRequest.setInterval(1000); // Update location every 10 seconds
    LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
    mLastLocation = LocationServices.FusedLocationApi.getLastLocation(
            mGoogleApiClient);
    if (mLastLocation != null) 
        lat = String.valueOf(mLastLocation.getLatitude());
        lon = String.valueOf(mLastLocation.getLongitude());
    
    Log.d(TAG,"" +lat);
    Log.d(TAG,""+ lon);
    Log.d(TAG, "calling storeprefs inside onconnected");
    storeprefs(lat,lon);


@Override
public void onConnectionSuspended(int i) 
    Log.i(TAG, "GoogleApiClient connection has been suspend");


@Override
public void onConnectionFailed(ConnectionResult connectionResult) 
    Log.i(TAG, "GoogleApiClient connection has failed");

@Override
protected void onPause() 
    super.onPause();


@Override
public void onLocationChanged(Location location) 
    // New location has now been determined
    String lat = Double.toString(location.getLatitude());
    String lon = Double.toString(location.getLongitude());
    Log.i(TAG, lat);
    Log.i(TAG, lon);
    storeprefs(lat,lon);
    // You can now create a LatLng Object for use with maps
    //LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude());


错误:

 FATAL EXCEPTION: main
                                               Process: com.example.android.wesport, PID: 11572
                                               java.lang.RuntimeException: Unable to start activity ComponentInfocom.example.android.wesport/com.example.android.wesport.MainActivity: java.lang.IllegalStateException: GoogleApiClient is not connected yet.
                                                   at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2646)
                                                   at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2707)
                                                   at android.app.ActivityThread.-wrap12(ActivityThread.java)
                                                   at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1460)
                                                   at android.os.Handler.dispatchMessage(Handler.java:102)
                                                   at android.os.Looper.loop(Looper.java:154)
                                                   at android.app.ActivityThread.main(ActivityThread.java:6077)
                                                   at java.lang.reflect.Method.invoke(Native Method)
                                                   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:865)
                                                   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755)
                                                Caused by: java.lang.IllegalStateException: GoogleApiClient is not connected yet.
                                                   at com.google.android.gms.internal.zzof.zzd(Unknown Source)
                                                   at com.google.android.gms.location.internal.zzd.requestLocationUpdates(Unknown Source)
                                                   at com.example.android.wesport.MainActivity.onCreate(MainActivity.java:82)
                                                   at android.app.Activity.performCreate(Activity.java:6662)
                                                   at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1118)
                                                   at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2599)
                                                   at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2707) 
                                                   at android.app.ActivityThread.-wrap12(ActivityThread.java) 
                                                   at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1460) 
                                                   at android.os.Handler.dispatchMessage(Handler.java:102) 
                                                   at android.os.Looper.loop(Looper.java:154) 
                                                   at android.app.ActivityThread.main(ActivityThread.java:6077) 
                                                   at java.lang.reflect.Method.invoke(Native Method) 
                                                   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:865) 
                                                   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755) 

堆栈跟踪 2

FATAL EXCEPTION: main
              Process: com.example.android.wesport, PID: 5763
              java.lang.SecurityException: Client must have ACCESS_FINE_LOCATION permission to request PRIORITY_HIGH_ACCURACY locations.
                  at android.os.Parcel.readException(Parcel.java:1683)
                  at android.os.Parcel.readException(Parcel.java:1636)
                  at com.google.android.gms.location.internal.zzi$zza$zza.zza(Unknown Source)
                  at com.google.android.gms.location.internal.zzk.zza(Unknown Source)
                  at com.google.android.gms.location.internal.zzl.zza(Unknown Source)
                  at com.google.android.gms.location.internal.zzd$1.zza(Unknown Source)
                  at com.google.android.gms.location.internal.zzd$1.zza(Unknown Source)
                  at com.google.android.gms.internal.zznt$zza.zzb(Unknown Source)
                  at com.google.android.gms.internal.zzoc.zzf(Unknown Source)
                  at com.google.android.gms.internal.zzoc.zzd(Unknown Source)
                  at com.google.android.gms.internal.zzoh.zzd(Unknown Source)
                  at com.google.android.gms.internal.zzof.zzd(Unknown Source)
                  at com.google.android.gms.location.internal.zzd.requestLocationUpdates(Unknown Source)
                  at com.example.android.wesport.MainActivity.onConnected(MainActivity.java:171)
                  at com.google.android.gms.common.internal.zzl.zzm(Unknown Source)
                  at com.google.android.gms.internal.zzof.zzk(Unknown Source)
                  at com.google.android.gms.internal.zzod.zzsb(Unknown Source)
                  at com.google.android.gms.internal.zzod.onConnected(Unknown Source)
                  at com.google.android.gms.internal.zzoh.onConnected(Unknown Source)
                  at com.google.android.gms.internal.zznw.onConnected(Unknown Source)
                  at com.google.android.gms.common.internal.zzk$1.onConnected(Unknown Source)
                  at com.google.android.gms.common.internal.zzd$zzj.zztp(Unknown Source)
                  at com.google.android.gms.common.internal.zzd$zza.zzc(Unknown Source)
                  at com.google.android.gms.common.internal.zzd$zza.zzw(Unknown Source)
                  at com.google.android.gms.common.internal.zzd$zze.zztr(Unknown Source)
                  at com.google.android.gms.common.internal.zzd$zzd.handleMessage(Unknown Source)
                  at android.os.Handler.dispatchMessage(Handler.java:102)
                  at android.os.Looper.loop(Looper.java:154)
                  at android.app.ActivityThread.main(ActivityThread.java:6077)
                  at java.lang.reflect.Method.invoke(Native Method)
                  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:865)
                  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755)

【问题讨论】:

我现在已将堆栈跟踪添加到报告的问题中 我可以从错误中看到,客户端必须具有 ACCESS_FINE_LOCATION 权限才能请求 PRIORITY_HIGH_ACCURACY 位置,但是在我调用的 onConnected() 方法中,检查权限()验证了 ACCESS_FINE_LOCATION 权限?我错过了什么吗? 【参考方案1】:
Caused by: java.lang.IllegalStateException: GoogleApiClient is not connected yet.

在调用onConnected() 之前,您不能调用requestLocationUpdates()。但是,如果您确定自己拥有运行时权限,那么您已经在 onCreate() 中调用了 requestLocationUpdates()

【讨论】:

你是对的。我已修复它,但仍然出现错误。我已经在上面发布了我的新堆栈跟踪并更新了程序,以便只维护位置上下文 @MaheshN:只有在 两个 onConnected() 被调用 并且 你有权限之前,你才能调用 requestLocationUpdates()。现在,您在获得权限之前调用buildGoogleApiClient(),然后从onConnected() 调用requestLocationUpdates()(同样,在您获得权限之前)。 This sample app 演示了如何做到这一点。 你的 github 链接有帮助。我能够正确包含运行时权限。感谢您的帮助

以上是关于融合位置 API 运行时权限错误的主要内容,如果未能解决你的问题,请参考以下文章

permission 文档 翻译 运行时权限

Android 6.0 运行时权限处理

如何在运行时请求位置权限

如何在运行时请求位置权限

可以在 Android Marshmallow (API 23) 的运行时权限模型中同步请求权限吗?

位置更新不适用于允许运行时权限