简体   繁体   English

GoogleApiClient:当服务在后台时,隐藏状态栏上的GPS图标

[英]GoogleApiClient: hide GPS icon on status bar when a service is in the background

I'm using GoogleApiClient to implement a location listener service, but the GPS icon is always being displayed, even with the service in background. 我正在使用GoogleApiClient来实现位置监听器服务,但即使服务在后台,也始终显示GPS图标。 How to disable the GPS icon when the service is in the background? 服务在后台时如何禁用GPS图标?

在此输入图像描述

Follow the sources below: 请遵循以下来源:

Activity 活动

public class ShowDistanceActivity extends AppCompatActivity implements ILocationConstants {

protected static final String TAG = ShowDistanceActivity.class.getSimpleName();


@Bind(R.id.tvLocationData)
TextView tvLocationData;

@Bind(R.id.toolbar)
Toolbar toolbar;


/**
 * Receiver listening to Location updates and updating UI in activity
 */
private LocationReceiver locationReceiver;

/**
 * Permission util with callback mechanism to avoid boilerplate code
 * <p/>
 * https://github.com/kayvannj/PermissionUtil
 */
private PermissionUtil.PermissionRequestObject mBothPermissionRequest;


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

    ButterKnife.bind(this);

    setSupportActionBar(toolbar);

    locationReceiver = new LocationReceiver();


}


private void startLocationService() {

    Intent serviceIntent = new Intent(this, LocationService.class);
    startService(serviceIntent);

}

@Override
protected void onStart() {
    super.onStart();

    LocalBroadcastManager.getInstance(this).registerReceiver(locationReceiver, new IntentFilter(LOACTION_ACTION));


    /**
     * Runtime permissions are required on Android M and above to access User's location
     */
    if (AppUtils.hasM() && !(ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED
            && ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED)) {

        askPermissions();

    } else {

        startLocationService();

    }

}

/**
 * Ask user for permissions to access GPS location on Android M
 */
public void askPermissions() {

    mBothPermissionRequest =
            PermissionUtil.with(this).request(Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION).onResult(
                    new Func2() {
                        @Override
                        protected void call(int requestCode, String[] permissions, int[] grantResults) {

                            if (grantResults[0] == PackageManager.PERMISSION_GRANTED && grantResults[1] == PackageManager.PERMISSION_GRANTED) {

                                startLocationService();

                            } else {

                                Toast.makeText(ShowDistanceActivity.this, R.string.permission_denied, Toast.LENGTH_LONG).show();
                            }
                        }

                    }).ask(PERMISSION_ACCESS_LOCATION_CODE);

}


@Override
protected void onStop() {
    super.onStop();

    LocalBroadcastManager.getInstance(this).unregisterReceiver(locationReceiver);
}

private class LocationReceiver extends BroadcastReceiver {


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


        if (null != intent && intent.getAction().equals(LOACTION_ACTION)) {

            String locationData = intent.getStringExtra(LOCATION_MESSAGE);

            tvLocationData.setText(locationData);
        }

    }
}


@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {

    if (null != mBothPermissionRequest) {
        mBothPermissionRequest.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}

} }

Service 服务

public class LocationService extends Service implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener, ILocationConstants, IPreferenceConstants {


private static final String TAG = LocationService.class.getSimpleName();

/**
 * Provides the entry point to Google Play services.
 */
protected GoogleApiClient mGoogleApiClient;

/**
 * Stores parameters for requests to the FusedLocationProviderApi.
 */
protected LocationRequest mLocationRequest;

/**
 * Represents a geographical location.
 */
protected Location mCurrentLocation;


private String mLatitudeLabel;
private String mLongitudeLabel;
private String mLastUpdateTimeLabel;
private String mDistance;


/**
 * Time when the location was updated represented as a String.
 */
protected String mLastUpdateTime;

private Location oldLocation;

private Location newLocation;


private AppPreferences appPreferences;

/**
 * Total distance covered
 */
private float distance;


@Override
public void onCreate() {
    super.onCreate();

    Log.d(TAG, "onCreate() called");

    appPreferences = new AppPreferences(this);

    oldLocation = new Location("Point A");
    newLocation = new Location("Point B");

    mLatitudeLabel = getString(R.string.latitude_label);
    mLongitudeLabel = getString(R.string.longitude_label);
    mLastUpdateTimeLabel = getString(R.string.last_update_time_label);
    mDistance = getString(R.string.distance);

    mLastUpdateTime = "";

    distance = appPreferences.getFloat(PREF_DISTANCE, 0);

    Log.d(TAG, "onCreate Distance: " + distance);


}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {

    Log.d(TAG, "onStartCommand called");

    buildGoogleApiClient();

    mGoogleApiClient.connect();

    if (mGoogleApiClient.isConnected()) {
        startLocationUpdates();
    }

    return Service.START_STICKY;

}


/**
 * Builds a GoogleApiClient. Uses the {@code #addApi} method to request the
 * LocationServices API.
 */
protected synchronized void buildGoogleApiClient() {

    Log.d(TAG, "buildGoogleApiClient() called");

    mGoogleApiClient = new GoogleApiClient.Builder(this)
            .addConnectionCallbacks(this)
            .addOnConnectionFailedListener(this)
            .addApi(LocationServices.API)
            .build();
    createLocationRequest();
}


protected void createLocationRequest() {

    Log.d(TAG, "createLocationRequest() called");

    mLocationRequest = new LocationRequest();

    mLocationRequest.setInterval(UPDATE_INTERVAL_IN_MILLISECONDS);

    mLocationRequest.setFastestInterval(FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS);

    mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);

    mLocationRequest.setSmallestDisplacement(DISPLACEMENT);
}

/**
 * Requests location updates from the FusedLocationApi.
 */
protected void startLocationUpdates() {

    try {

        Log.d(TAG, "startLocationUpdates called");

        LocationServices.FusedLocationApi.requestLocationUpdates(
                mGoogleApiClient, mLocationRequest, this);

    } catch (SecurityException ex) {

        ex.printStackTrace();
    }
}


/**
 * Updates the latitude, the longitude, and the last location time in the UI.
 */
private void updateUI() {

    if (null != mCurrentLocation) {

        StringBuilder sbLocationData = new StringBuilder();
        sbLocationData.append(mLatitudeLabel)
                .append(" ")
                .append(mCurrentLocation.getLatitude())
                .append("\n")
                .append(mLongitudeLabel)
                .append(" ")
                .append(mCurrentLocation.getLongitude())
                .append("\n")
                .append(mLastUpdateTimeLabel)
                .append(" ")
                .append(mLastUpdateTime)
                .append("\n")
                .append(mDistance)
                .append(" ")
                .append(getUpdatedDistance())
                .append(" meters");


        /*
         * update preference with latest value of distance
         */
        appPreferences.putFloat(PREF_DISTANCE, distance);

        Log.d(TAG, "Location Data:\n" + sbLocationData.toString());

        sendLocationBroadcast(sbLocationData.toString());
    } else {

        Toast.makeText(this, R.string.unable_to_find_location, Toast.LENGTH_SHORT).show();
    }
}


/**
 * Send broadcast using LocalBroadcastManager to update UI in activity
 *
 * @param sbLocationData
 */
private void sendLocationBroadcast(String sbLocationData) {

    Log.d(TAG, "sendLocationBroadcast() called");

    Intent locationIntent = new Intent();
    locationIntent.setAction(LOACTION_ACTION);
    locationIntent.putExtra(LOCATION_MESSAGE, sbLocationData);

    LocalBroadcastManager.getInstance(this).sendBroadcast(locationIntent);

}

/**
 * Removes location updates from the FusedLocationApi.
 */
protected void stopLocationUpdates() {

    Log.d(TAG, "stopLocationUpdates() called");

    LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
}


@Override
public void onDestroy() {

    Log.d(TAG, "onDestroy() called");

    appPreferences.putFloat(PREF_DISTANCE, distance);

    stopLocationUpdates();

    mGoogleApiClient.disconnect();

    Log.d(TAG, "onDestroy Distance " + distance);

    super.onDestroy();
}


/**
 * Runs when a GoogleApiClient object successfully connects.
 */
@Override
public void onConnected(Bundle connectionHint) throws SecurityException {
    Log.i(TAG, "Connected to GoogleApiClient");


    if (mCurrentLocation == null) {
        mCurrentLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
        mLastUpdateTime = DateFormat.getTimeInstance().format(new Date());
        updateUI();
    }

    startLocationUpdates();

}

/**
 * Callback that fires when the location changes.
 */
@Override
public void onLocationChanged(Location location) {

    Log.d(TAG, "onLocationChanged() called");

    mCurrentLocation = location;
    mLastUpdateTime = DateFormat.getTimeInstance().format(new Date());
    updateUI();
}

@Override
public void onConnectionSuspended(int cause) {

    Log.d(TAG, "onConnectionSuspended() called");

    mGoogleApiClient.connect();
}

@Override
public void onConnectionFailed(ConnectionResult result) {

    Log.i(TAG, "Connection failed: ConnectionResult.getErrorCode() = " + result.getErrorCode());
}


private float getUpdatedDistance() {

    /**
     * There is 68% chance that user is with in 100m from this location.
     * So neglect location updates with poor accuracy
     */


    if (mCurrentLocation.getAccuracy() > ACCURACY_THRESHOLD) {

        Log.d(TAG, "getUpdatedDistance() called");

        return distance;
    }


    if (oldLocation.getLatitude() == 0 && oldLocation.getLongitude() == 0) {

        oldLocation.setLatitude(mCurrentLocation.getLatitude());
        oldLocation.setLongitude(mCurrentLocation.getLongitude());

        newLocation.setLatitude(mCurrentLocation.getLatitude());
        newLocation.setLongitude(mCurrentLocation.getLongitude());

        return distance;
    } else {

        oldLocation.setLatitude(newLocation.getLatitude());
        oldLocation.setLongitude(newLocation.getLongitude());

        newLocation.setLatitude(mCurrentLocation.getLatitude());
        newLocation.setLongitude(mCurrentLocation.getLongitude());

    }


    /**
     * Calculate distance between last two geo locations
     */
    distance += newLocation.distanceTo(oldLocation);

    return distance;
}


@Override
public IBinder onBind(Intent intent) {

    throw new UnsupportedOperationException("Not yet implemented");
}

} }

Manifest 表现

Android Manifest declaration Android Manifest声明

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.technosavy.showmedistance">
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity
            android:name=".ShowDistanceActivity"
            android:label="@string/app_name"
            android:theme="@style/AppTheme.NoActionBar">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>


        <service
            android:name=".service.LocationService"
            android:enabled="true"
            android:exported="true"></service>

    </application>

</manifest>

Please, any help is welcome. 拜托,欢迎任何帮助。

To remove the GPS icon you need to use cached and wi-fi location settings (from memory). 要删除GPS图标,您需要使用缓存和Wi-Fi位置设置(从内存中)。 In your code make the following changes. 在您的代码中进行以下更改。

In Manifest, remove : 在Manifest中, 删除

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

In Service, change the following: 在服务中,更改以下内容:

mLocationRequest.setInterval(10000L);
mLocationRequest.setFastestInterval(5000L);
// Do NOT use LocationRequest.PRIORITY_HIGH_ACCURACY here
// Instead use one of the other option.
mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
//mLocationRequest.setPriority(LocationRequest.PRIORITY_LOW_POWER);
//mLocationRequest.setPriority(LocationRequest.PRIORITY_NO_POWER);
// Remove setSmallestDisplacement() as it should not be used
// unless you are using a GPS / PRIORITY_HIGH_ACCURACY
//mLocationRequest.setSmallestDisplacement(DISPLACEMENT);

Pretty sure this is will remove the GPS icon but you will also only get the FusedLocationApi.getLastLocation() values when the onConnected() method is called (very possible this will be low accuracy). 很确定这将删除GPS图标,但是当调用onConnected()方法时,您也只能获得FusedLocationApi.getLastLocation()值(这很可能是低精度)。

The onLocationChanged() method may never trigger until another application makes a location request at a higher priority or with more accuracy. onLocationChanged()方法可能永远不会触发,直到另一个应用程序以更高的优先级或更准确的方式发出位置请求。

The new fused location providers take a slightly different approach compared to previous methods. 与以前的方法相比,新的融合位置提供商采用了略微不同的方法。 Developers now choose how much battery power is used to calculate a location instead of which device components are used to calculate it. 开发人员现在选择使用多少电池电量来计算位置,而不是使用哪些设备组件来计算它。 It uses any available combination of GPS, Wi-Fi, mobile networks, and onboard sensors to calculate the location. 它使用GPS,Wi-Fi,移动网络和板载传感器的任何可用组合来计算位置。

The LocationRequest priority settings are now: LocationRequest优先级设置现在是:

PRIORITY_NO_POWER (passively listens for location updates from other clients) PRIORITY_LOW_POWER (~10km "city" accuracy) PRIORITY_BALANCED_POWER_ACCURACY (~100m "block" accuracy) PRIORITY_HIGH_ACCURACY (accurate as possible at the expense of battery life) Google describes the LocationRequest class here: http://developer.android.com/reference/com/google/android/gms/location/LocationRequest.html PRIORITY_NO_POWER(被动地侦听来自其他客户端的位置更新)PRIORITY_LOW_POWER(~10km“city”准确度)PRIORITY_BALANCED_POWER_ACCURACY(~100m“块”准确度)PRIORITY_HIGH_ACCURACY(尽可能准确以电池寿命为代价)Google在此描述了LocationRequest类: http: //developer.android.com/reference/com/google/android/gms/location/LocationRequest.html

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM