【问题标题】:android check if user turned off locationandroid检查用户是否关闭了位置
【发布时间】:2017-11-10 05:55:06
【问题描述】:

我正在构建一个应用程序,我必须在其中不断保存用户的位置,然后将其发送到服务器。为此,我在服务中使用 FusedLocationApis。我第一次要求用户打开位置。 它运行良好。

现在,如果用户无意中关闭了该位置,该怎么办。我该怎么通知他?开发人员是否必须处理这个问题,或者他们只是把它留给用户?

我想为此给他一个 android 通知。为此,我需要不断检查我们在服务中启用的位置。我有一个工作代码(函数 checkHighAccuracyLocationMode)。但是我应该在哪里做这个检查(checkHighAccuracyLocationMode)? 每次在此服务中启动哪个功能?或者,如果我能获得一个在用户关闭其位置时启动的功能?

这是我的服务:

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

private Location mLastLocation;
private Location mCurrentLocation;
private String mLastUpdateTime;
private dataBaseHandler db_helper;

@Override
public int onStartCommand(Intent intent, int flags, int startId){
    initialise();
    return super.onStartCommand(intent, flags, startId);
}

@Override
public void onCreate() {
    super.onCreate();
    db_helper = new dataBaseHandler(getApplicationContext(),dataBaseHandler.DATABASE_NAME,null,1);
}

@Override
public void onDestroy() {
    stopLocationUpdates();
    singletGoogleClientApi.setinstancenull();
    singletLocationRequest.setinstancenull();
    super.onDestroy();
}

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

private void initialise(){
    Log.e("ghgdhu","qaws");
    if (singletGoogleClientApi.getinstance().getGoogleApiCLient() == null) {
        singletGoogleClientApi.getinstance().setmSingletGoogleApiClient(new GoogleApiClient.Builder(this)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .addApi(LocationServices.API)
                .build());
        singletGoogleClientApi.getinstance().getGoogleApiCLient().connect();
        createLocationRequest();
    }

    if(!singletGoogleClientApi.getinstance().getGoogleApiCLient().isConnected()){
        singletGoogleClientApi.getinstance().getGoogleApiCLient().connect();
        createLocationRequest();
    }
}

protected void createLocationRequest() {
    if(singletLocationRequest.getinstance().getLocationRequest() == null) {
        singletLocationRequest.getinstance().setSingletLocationRequest(new LocationRequest()
        .setInterval(10000)
        .setFastestInterval(5000).setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY));
    }
}

public static boolean checkHighAccuracyLocationMode(Context context) {
    int locationMode = 0;
    String locationProviders;

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT){
        //Equal or higher than API 19/KitKat
        try {
            locationMode = Settings.Secure.getInt(context.getContentResolver(), Settings.Secure.LOCATION_MODE);
            if (locationMode == Settings.Secure.LOCATION_MODE_HIGH_ACCURACY){
                return true;
            }
        } catch (Settings.SettingNotFoundException e) {
            e.printStackTrace();
        }
    }else{
        //Lower than API 19
        locationProviders = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.LOCATION_PROVIDERS_ALLOWED);

        if (locationProviders.contains(LocationManager.GPS_PROVIDER) && locationProviders.contains(LocationManager.NETWORK_PROVIDER)){
            return true;
        }
    }
    return false;
}


@Override
public void onLocationChanged(Location location) {
    Log.e("qazxsw","inONLocationCHanged");
    mCurrentLocation = location;
    Log.e("loc : ",Double.toString(mCurrentLocation.getLatitude()));
    Toast.makeText(this, "My Location: "+Double.toString(mCurrentLocation.getLatitude())+ " , " + Double.toString(mCurrentLocation.getLongitude()),
            Toast.LENGTH_SHORT).show();
    mLastUpdateTime = DateFormat.getTimeInstance().format(new Date());
    if(!checkHighAccuracyLocationMode(getBaseContext())){
        Log.e("turned OFF","LOCATION");
    }
    else {
        Log.e("ONNNNN","LOCATION");
    }
    db_helper.Insert(mLastUpdateTime,mCurrentLocation.getLatitude(),mCurrentLocation.getLongitude());
}

protected void stopLocationUpdates() {
    LocationServices.FusedLocationApi.removeLocationUpdates(singletGoogleClientApi.
            getinstance().getGoogleApiCLient(), this);
}

@Override
public void onConnected(@Nullable Bundle bundle) {
    startLocationUpdates();
}

protected void startLocationUpdates() {
    try {
        if(singletLocationRequest.getinstance().getLocationRequest()!=null &&
                singletGoogleClientApi.getinstance().getGoogleApiCLient()!=null){
            Log.e("requesting","yES BRO");
            LocationServices.FusedLocationApi.requestLocationUpdates(
                    singletGoogleClientApi.getinstance().getGoogleApiCLient(), singletLocationRequest.getinstance().getLocationRequest(), this);
            mLastLocation = LocationServices.FusedLocationApi.getLastLocation(
                    singletGoogleClientApi.getinstance().getGoogleApiCLient());
        }
        else {
            initialise();
        }
    }
    catch (SecurityException e) {
        e.getStackTrace();
    }
}

@Override
public void onConnectionSuspended(int i) {
    Log.e("ON CONNECTION SUSPENDED","PETROL");

}

@Override
public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
    Log.e("COnnection ","DIESEL");

}

}

【问题讨论】:

  • 覆盖方法 onProviderDisabled 。这是您为场景编写逻辑的地方。详情请参考developer.android.com/reference/android/location/…
  • @Jimmy 我之前尝试过覆盖 onProviderEnabled/Disabled 方法。但我认为以我目前的实施方式,我将无法这样做。
  • @Jimmy 我想如果我通过 LocationManager 而不是通过 goooglefusedAPI 去实现所有方法。你怎么看?
  • 如果您能够覆盖 onLocationChanged ,那么您也可以为 onProviderDisabled 提供实现。无需更改任何内容,您已经在实现 LocationListener,只需覆盖该方法即可。

标签: android location fusedlocationproviderapi


【解决方案1】:

您可以使用位置状态更改receiver 来了解用户何时手动切换位置 GpsReceiver.java

public class GpsReceiver extends BroadcastReceiver {
    private final LocationCallBack locationCallBack;

    /**
     * initializes receiver with callback
     * @param iLocationCallBack Location callback
     */
    public GpsReceiver(LocationCallBack iLocationCallBack){
            this.locationCallBack = iLocationCallBack;
    }

    /**
     * triggers on receiving external broadcast
     * @param context Context
     * @param intent Intent
     */
    @Override
    public void onReceive(Context context, Intent intent) {
        if (intent.getAction().matches("android.location.PROVIDERS_CHANGED")) {
            locationCallBack.onLocationTriggered();
        }
    }
}

创建一个interface 以将 GPS 更改传达给Activity

public interface LocationCallBack {
    /**
     * on Location switch triggered
     */
    void onLocationTriggered();
}

ActivityonCreate() 中注册receiver 以开始收听GPS 状态变化

public void onCreate(Bundle savedInstance){
//---
registerReceiver(new GpsReceiver(new LocationCallBack() {
            @Override
            public void onLocationTriggered() {
                //Location state changed
            }
        }), new IntentFilter(LocationManager.PROVIDERS_CHANGED_ACTION));
//---
}

【讨论】:

  • 这对我很有效。但请确保在 Activity 被终止时调用 unregisterReceiver() 以防止泄漏
  • 在前台服务中,我想检查位置是否“开启”并在位置关闭时通知用户。我怎样才能做到这一点?即使应用关闭,该前台服务也会运行。
【解决方案2】:

此代码在 Android 9 (Pie) 版本上完美运行

主要活动

public class MainActivity extends AppCompatActivity {

    private MyLocationReceiver mLocationReceiver;

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

        mLocationReceiver = new MyLocationReceiver(this, Snackbar.make(findViewById(android.R.id.content), "Location service is not enabled", Snackbar.LENGTH_INDEFINITE));

    }

    @Override
    protected void onResume() {
        super.onResume();
        registerReceiver(mLocationReceiver, new IntentFilter(LocationManager.PROVIDERS_CHANGED_ACTION));
    }

    @Override
    protected void onPause() {
        super.onPause();
        try {
            unregisterReceiver(mLocationReceiver);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

我的位置接收器

public class MyLocationReceiver extends BroadcastReceiver {

    private static final String TAG = "MyLocationReceiver";
    private Context context;
    private Snackbar snackbar;

    public MyLocationReceiver(Context context, Snackbar snackbar){
        this.context = context;
        this.snackbar = snackbar;
    }

    @Override
    public void onReceive(Context context, Intent intent) {

        LocationManager locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);

        if (intent.getAction().matches("android.location.PROVIDERS_CHANGED")) {
            boolean gpsEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
            boolean networkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
            if(gpsEnabled && networkEnabled) {
                if (snackbar != null) {
                    snackbar.dismiss();
                }
                Log.d(TAG, "GPS is enabled");
            } else {
                snackbar.show();
                Log.d(TAG, "GPS is disabled");
            }
        }

    }

}

【讨论】:

    【解决方案3】:

    您可以使用以下来检查位置可用性:

    LocationManager lm = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
        try {
            gps_enabled = lm.isProviderEnabled(LocationManager.GPS_PROVIDER);
        }catch (Exception ex){}
        try{
            network_enabled = lm.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
        }catch (Exception ex){}
        if(!gps_enabled && !network_enabled){
            AlertDialog.Builder dialog = new AlertDialog.Builder(this);
            dialog.setMessage(getResources().getString(R.string.gps_network_not_enabled));
            dialog.setPositiveButton(getResources().getString(R.string.open_location_settings), new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface paramDialogInterface, int paramInt) {                 
                    Intent myIntent = new Intent( Settings.ACTION_LOCATION_SOURCE_SETTINGS);
                    Startup.this.startActivity(myIntent);                    
                }
            });
            dialog.setNegativeButton(getString(R.string.Cancel), new DialogInterface.OnClickListener() {
    
                @Override
                public void onClick(DialogInterface paramDialogInterface, int paramInt) {
                    // TODO Auto-generated method stub
    
                }
            });
            dialog.show();
        }
    

    【讨论】:

    • (顺便说一句:我们希望答案写得尽可能清楚,尽可能遵守英语规则,并且没有任何“txtspk”。谢谢!)
    猜你喜欢
    • 2019-12-09
    • 2011-10-24
    • 2014-07-26
    • 2013-01-29
    • 1970-01-01
    • 2013-08-11
    • 1970-01-01
    • 1970-01-01
    • 2021-06-11
    相关资源
    最近更新 更多