在某些设备上单击按钮获取应用程序中的位置时 Android 没有响应

Getting Android not responding while getting location in application on the button click for some devices

在 GPS 跟踪器服务中获取位置的代码

import android.Manifest;
import android.app.Activity;
import android.app.Service;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentSender;
import android.content.pm.PackageManager;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.IBinder;
import android.provider.Settings;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AlertDialog;
import android.util.Log;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.PendingResult;
import com.google.android.gms.common.api.Result;
import com.google.android.gms.common.api.ResultCallback;
import com.google.android.gms.common.api.Status;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationServices;
import com.google.android.gms.location.LocationSettingsRequest;
import com.google.android.gms.location.LocationSettingsStatusCodes;

import java.security.Provider;


public class GPSTracker extends Service
        implements LocationListener, GoogleApiClient.OnConnectionFailedListener, GoogleApiClient.ConnectionCallbacks {

    private final Context mContext;

    // Flag for GPS status
    boolean isGPSEnabled = false;

    // Flag for network status
    boolean isNetworkEnabled = false;

    // Flag for GPS status
    boolean canGetLocation = false;

    Location location; // Location
    double latitude; // Latitude
    double longitude; // Longitude

    // The minimum distance to change Updates in meters
    private static final long MIN_DISTANCE_CHANGE_FOR_UPDATES = 10; // 10 meters

    // The minimum time between updates in milliseconds
    private static final long MIN_TIME_BW_UPDATES = 1000 * 60 * 1; // 1 minute

    // Declaring a Location Manager
    protected LocationManager locationManager;
    GoogleApiClient googleApiClient;
    private Location mylocation;
    private final static int REQUEST_CHECK_SETTINGS_GPS = 0x1;



    public GPSTracker(Context context) {
        this.mContext = context;
        setUpGClient();
        getLocation();

    }
/*Function for setting up Googleapiclient*/
    private void setUpGClient() {

        googleApiClient = new GoogleApiClient.Builder(mContext)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .addApi(LocationServices.API)
                .build();
        googleApiClient.connect();
    }
/*Function use to gett location*/
    public Location getLocation() {
        try {
            locationManager = (LocationManager) mContext
                    .getSystemService(LOCATION_SERVICE);

            // Getting GPS status
            isGPSEnabled = locationManager
                    .isProviderEnabled(LocationManager.GPS_PROVIDER);

            // Getting network status
            isNetworkEnabled = locationManager
                    .isProviderEnabled(LocationManager.NETWORK_PROVIDER);

            if (!isGPSEnabled && !isNetworkEnabled) {
                // No network provider is enabled
            } else {
                this.canGetLocation = true;
                if (isNetworkEnabled) {
                    locationManager.requestLocationUpdates(
                            LocationManager.NETWORK_PROVIDER,
                            MIN_TIME_BW_UPDATES,
                            MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
                    Log.d("Network", "Network");
                    if (locationManager != null) {

                        location = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);

                        if (location != null) {
                            latitude = location.getLatitude();
                            longitude = location.getLongitude();
                        }
                    }
                }
                // If GPS enabled, get latitude/longitude using GPS Services
                if (isGPSEnabled) {
                    if (location == null) {
                        locationManager.requestLocationUpdates(
                                LocationManager.GPS_PROVIDER,
                                MIN_TIME_BW_UPDATES,
                                MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
                        Log.d("GPS Enabled", "GPS Enabled");
                        if (locationManager != null) {
                            location = locationManager
                                    .getLastKnownLocation(LocationManager.GPS_PROVIDER);
                            if (location != null) {
                                latitude = location.getLatitude();
                                longitude = location.getLongitude();
                            }
                        }
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return location;
    }

    /**
     * Stop using GPS listener
     * Calling this function will stop using GPS in your app.
     */
    public void stopUsingGPS() {
        if (locationManager != null) {
            locationManager.removeUpdates(GPSTracker.this);
        }
    }

    /* Function to get latitude*/
    public double getLatitude() {
        if (location != null) {
            latitude = location.getLatitude();
        }

        // return latitude
        return latitude;
    }


    /*Function to get longitude */
    public double getLongitude() {
        if (location != null) {
            longitude = location.getLongitude();
        }

        // return longitude
        return longitude;
    }

    /* Function to check GPS/Wi-Fi enabled @return boolean */
    public boolean canGetLocation() {
        return this.canGetLocation;
    }


    /**
     * Function to show settings alert dialog.
     * On pressing the Settings button it will launch Settings Options.
     */
    public void showSettingsAlert() {
        AlertDialog.Builder alertDialog = new AlertDialog.Builder(mContext);

        // Setting Dialog Title
        alertDialog.setTitle("GPS settings");

        // Setting Dialog Message
        alertDialog.setMessage("GPS is not enabled. Do you want to go to settings menu?");

        // On pressing the Settings button.
        alertDialog.setPositiveButton("Settings", new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int which) {
                Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
                mContext.startActivity(intent);
            }
        });

        // On pressing the cancel button
        alertDialog.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int which) {
                dialog.cancel();
            }
        });

        // Showing Alert Message
        alertDialog.show();
    }


    /*Function shows the dialogue to Automatic turn on the location */

    public void autoTurnOnGPS() {
        mylocation = LocationServices.FusedLocationApi.getLastLocation(googleApiClient);
        LocationRequest locationRequest = new LocationRequest();
        locationRequest.setInterval(3000);
        locationRequest.setFastestInterval(3000);
        locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);

        LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder()
                .addLocationRequest(locationRequest);
        builder.setAlwaysShow(true);
/*
                        LocationServices.FusedLocationApi
                                .requestLocationUpdates(googleApiClient, locationRequest, (LocationListener) this);
*/
        PendingResult result =
                LocationServices.SettingsApi
                        .checkLocationSettings(googleApiClient, builder.build());
        result.setResultCallback(new ResultCallback() {
            @Override
            public void onResult(@NonNull Result result) {

                final Status status = result.getStatus();
                switch (status.getStatusCode()) {
                    case LocationSettingsStatusCodes.SUCCESS:
                        // All location settings are satisfied.
                        // You can initialize location requests here.
                        int permissionLocation = ContextCompat
                                .checkSelfPermission(mContext,
                                        Manifest.permission.ACCESS_FINE_LOCATION);
                        if (permissionLocation == PackageManager.PERMISSION_GRANTED) {
                            mylocation = LocationServices.FusedLocationApi
                                    .getLastLocation(googleApiClient);
                        }
                        break;
                    case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
                        // Location settings are not satisfied.
                        // But could be fixed by showing the user a dialog.
                        try {
                            // Show the dialog by calling startResolutionForResult(),
                            // and check the result in onActivityResult().
                            // Ask to turn on GPS automatically
                            status.startResolutionForResult((Activity) mContext,
                                    REQUEST_CHECK_SETTINGS_GPS);

                        } catch (IntentSender.SendIntentException e) {
                            // Ignore the error.
                        }
                        break;
                    case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
                        // Location settings are not satisfied. However, we have no way to fix the
                        // settings so we won't show the dialog.
                        //finish();
                        break;
                }

            }


        });


    }

    @Override
    public void onLocationChanged(Location location) {

    }


    @Override
    public void onProviderDisabled(String provider) {
    }


    @Override
    public void onProviderEnabled(String provider) {
    }


    @Override
    public void onStatusChanged(String provider, int status, Bundle extras) {
    }


    @Override
    public IBinder onBind(Intent arg0) {
        return null;
    }

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

    }

    @Override
    public void onConnectionSuspended(int i) {

    }

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

    }



}

调用GPS Tracker服务的方法代码

 public static String googleLiveLocation(Context context) {
    gps = new GPSTracker(context);
    // Check if GPS enabled
    String LatLon_current = null;
    if (gps.canGetLocation()) {
        Location location = gps.getLocation();
        while (location == null) {
            location = gps.getLocation();
            if (location != null)
                break;
        }
        if (location != null) {
            double latitude = gps.getLatitude();
            double longitude = gps.getLongitude();
            String latitude_s = Double.toString(latitude);
            String lon = Double.toString(longitude);
            LatLon_current = latitude_s + ":" + lon;
        }



    } else {

        gps.autoTurnOnGPS();
    }
    return LatLon_current;
}

点击按钮的代码

if (ContextCompat.checkSelfPermission
                        (context, android.Manifest.permission.ACCESS_FINE_LOCATION)
                        == PackageManager.PERMISSION_GRANTED &&
                        ContextCompat.checkSelfPermission(context, android.Manifest.permission.ACCESS_COARSE_LOCATION)
                                == PackageManager.PERMISSION_GRANTED) {

                    final String LatLon_current = CommonMethods.googleLiveLocation(context);

                    if (LatLon_current != null) {
                        builder = new AlertDialog.Builder(this, AlertDialog.THEME_HOLO_LIGHT);
                        builder.setMessage(getResources().getString(R.string.start_attendance))
                                .setTitle("Confirm!")
                                .setIcon(R.drawable.nabu)
                                .setCancelable(true)
                                .setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
                                    public void onClick(DialogInterface dialog, int which) {
                                        dialog.dismiss();
                                    }
                                })
                                .setNeutralButton(android.R.string.ok,
                                        new DialogInterface.OnClickListener() {
                                            @Override
                                            public void onClick(DialogInterface dialog,
                                                                int whichButton) {
                                                callStartTimer(LatLon_current);
                                                dialog.dismiss();


                                            }
                                        }).show();
                    }
                } else {
                    ActivityCompat.requestPermissions(AttendanceMarkActivity.this,
                            new String[]{android.Manifest.permission.ACCESS_FINE_LOCATION,
                                    android.Manifest.permission.ACCESS_COARSE_LOCATION},
                            TAG_CODE_PERMISSION_LOCATION);

                }

Android 没有响应错误

    "main" prio=5 tid=1 Native
  | group="main" sCount=1 dsCount=0 obj=0x7556e000 self=0xaad95f18
  | sysTid=4764 nice=0 cgrp=default sched=0/0 handle=0x4000fbec
  | state=S schedstat=( 6512778158 5383102303 26014 ) utm=517 stm=134 core=2 HZ=100
  | stack=0xff000000-0xff002000 stackSize=8MB
  | held mutexes=
  #00  pc 0000000000012974  /system/lib/libc.so (syscall+28)
  #01  pc 00000000000aecf7  /system/lib/libart.so (_ZN3art17ConditionVariable4WaitEPNS_6ThreadE+82)
  #02  pc 0000000000291e41  /system/lib/libart.so (_ZN3artL12GoToRunnableEPNS_6ThreadE+772)
  #03  pc 000000000008c8c1  /system/lib/libart.so (_ZN3art12JniMethodEndEjPNS_6ThreadE+8)
  #04  pc 0000000000c66011  /system/framework/arm/boot.oat (Java_android_os_BinderProxy_transactNative__ILandroid_os_Parcel_2Landroid_os_Parcel_2I+156)
  at android.os.BinderProxy.transactNative (Native method)
  at android.os.BinderProxy.transact (Binder.java:496)
  at android.location.ILocationManager$Stub$Proxy.requestLocationUpdates (ILocationManager.java:581)
  at android.location.LocationManager.requestLocationUpdates (LocationManager.java:867)
  at android.location.LocationManager.requestLocationUpdates (LocationManager.java:459)
  at com.genexttutors.utils.GPSTracker.getLocation (GPSTracker.java:124)
  at com.genexttutors.utils.CommonMethods.googleLiveLocation (CommonMethods.java:169)
  at com.genexttutors.activities.AttendanceMarkActivity.onClick (AttendanceMarkActivity.java:183)
  at android.view.View.performClick (View.java:5076)
  at android.view.View$PerformClick.run (View.java:20279)
  at android.os.Handler.handleCallback (Handler.java:739)
  at android.os.Handler.dispatchMessage (Handler.java:95)
  at android.os.Looper.loop (Looper.java:135)
  at android.app.ActivityThread.main (ActivityThread.java:5910)
  at java.lang.reflect.Method.invoke! (Native method)
  at java.lang.reflect.Method.invoke (Method.java:372)
  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run (ZygoteInit.java:1405)
  at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:1200)

以下是此代码发出 ANR

的设备

首先 - 不要使用 GPSTracker。密码坏了。它大部分时间都不起作用。有关完整说明,请参阅 http://gabesechansoftware.com/location-tracking/

其次 - 您的 googleLiveLocation 已完全损坏。它有一个等待非空位置的无限循环。这不仅(永远)不起作用,而且在主线程上调用时会确保出现 ANR。

摆脱所有这些代码。使用一个可以正常工作的位置库(那里有一个 link,尽管您必须向它添加运行时权限)。并使用回调——你永远不能在主线程上等待某事发生。