[英]Client must have ACCESS_FINE_LOCATION permission to request PRIORITY_HIGH_ACCURACY locations runtime error
There are plenty of similar questions asked but none seem to solve my problem. 有很多类似的问题,但似乎没有解决我的问题。
I have applied run time permissions as mentioned on the documentation, still I am getting a run time error on the line 我已经应用了文档中提到的运行时权限,但我仍然遇到运行时错误
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
Here is my complete code. 这是我的完整代码。
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());
}
} }
Also I have given permission in the manifest file. 我也在清单文件中给予了许可。
So, this is the error stack trace on run time 因此,这是运行时的错误堆栈跟踪
10-24 17:13:02.857 2224-2379/com.example.ashutosh.location E/AbstractTracker: Can't create handler inside thread that has not called Looper.prepare() 0-24 17:13:03.184 2224-2224/com.example.ashutosh.location E/AndroidRuntime: FATAL EXCEPTION: main Process: com.example.ashutosh.location, PID: 2224 java.lang.SecurityException: Client must have ACCESS_FINE_LOCATION permission to request PRIORITY_HIGH_ACCURACY locations. 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位置。 at android.os.Parcel.readException(Parcel.java:1620) at android.os.Parcel.readException(Parcel.java:1573) at com.google.android.gms.internal.zzed.zzb(Unknown Source) at com.google.android.gms.internal.zzcda.zza(Unknown Source) at com.google.android.gms.internal.zzcdd.zza(Unknown Source) at com.google.android.gms.internal.zzcdj.zza(Unknown Source) at com.google.android.gms.internal.zzccc.zza(Unknown Source) at com.google.android.gms.internal.zzbay.zzb(Unknown Source) at com.google.android.gms.internal.zzbca.zze(Unknown Source) at com.google.android.gms.internal.zzbcx.zze(Unknown Source) at com.google.android.gms.internal.zzbcp.zze(Unknown Source) at com.google.android.gms.internal.zzccb.requestLocationUpdates(Unknown Source) at com.example.ashutosh.location.MainActivity.onConnected(MainActivity.java:122) at com.google.android.gms.common.internal.zzac.zzn(Unknown Source) at com.google.android.gms.internal.zzbcp.zzm(Unknown Source) at com.google.android.gms.internal.zzbcd.zzpY(Unknown Sou 在android.os.Parcel.readException(Parcel.java:1620)的android.os.Parcel.readException(Parcel.java:1573)at com.google.android.gms.internal.zzed.zzb(Unknown Source)at 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.zz上的com.google.android.gms.internal.zzccc.zza(未知来源)com.google.android.gms.internal.zz .zze(未知来源)com.google.android.gms.internal.zzbcx.zze(未知来源)com.google.android.gms.internal.zzbcp.zze(未知来源)com.google.android.gms .internal.zzccb.requestLocationUpdates(未知来源)位于com.google.ashutosh.location.MainActivity.onConnected(MainActivity.java:122)com.google.android.gms.common.internal.zzac.zzn(未知来源)at at com.google.android.gms.internal.zzbcp.zzm(未知来源)com.google.android.gms.internal.zzbcd.zzpY(Unknown Sou) rce) at com.google.android.gms.internal.zzbcd.onConnected(Unknown Source) at com.google.android.gms.internal.zzbcx.onConnected(Unknown Source) at com.google.android.gms.internal.zzbbi.onConnected(Unknown Source) at com.google.android.gms.common.internal.zzaa.onConnected(Unknown Source) at com.google.android.gms.common.internal.zzn.zzrj(Unknown Source) at com.google.android.gms.common.internal.zze.zzs(Unknown Source) at com.google.android.gms.common.internal.zzi.zzrk(Unknown Source) at com.google.android.gms.common.internal.zzh.handleMessage(Unknown Source) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:152) at android.app.ActivityThread.main(ActivityThread.java:5497) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) rce)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.app.AooT.Thread.main上的android.os.Handler.dispatchMessage(Handler.java:102)android.os.Looper.loop(Looper.java:152)(ActivityThread.java:5497 )com.android.internal.os.ZygoteInit.main中的com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run(ZygoteInit.java:726)中的java.lang.reflect.Method.invoke(Native Method)(ZygoteInit)的.java:616)
requestPermissions()
is asynchronous . requestPermissions()
是异步的 。 When it returns, you do not yet have permission. 返回时,您还没有权限。 The user has not even been asked about the permission. 用户甚至没有被问及许可。
You need to do your location logic in two places: 您需要在两个地方执行您的位置逻辑:
Up front, if you have permission already 如果您已经获得许可,请提前预定
In onRequestPermissionResult()
, if you requested permissions and the user granted them 在onRequestPermissionResult()
,如果您请求了权限并且用户授予了权限
This sample app and this sample app illustrate how to request runtime permissions and use them with LocationClient
. 此示例应用程序和此示例应用程序说明了如何请求运行时权限并将其与LocationClient
一起使用。
Try this sequence, 试试这个顺序,
@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
}
} }
I hate the following solution but I did not find any better. 我讨厌以下解决方案,但我没有找到更好的解决方案。 If you request location API from Google API's and you do: .addApi(LocationServices.API)
, you need to have location permitted before connecting GoogleAPI's. 如果您从Google API请求位置API并执行: .addApi(LocationServices.API)
,则需要在连接GoogleAPI之前允许位置。
Thus, 从而,
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()
}
}
}
When the Permission registrar is a class that calls a callback when a permission changed 当权限注册商是一个在权限更改时调用回调的类
class SomeActivity: Activity() {
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) {
MyPermissionChangeRegistrar.callCallbacks()
}
}
IMMHO, Google ought to protect against such cases internally. IMMHO,Google应该在内部防范此类案件。 But they don't. 但他们没有。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.