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. 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 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)
requestPermissions()
is asynchronous . 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
This sample app and this sample app illustrate how to request runtime permissions and use them with 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.
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. But they don't.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.