Android 定位服务耗尽电池 - 融合定位 API
Android Location Services draining the Battery - Fused Location API
我们有一个基于位置的应用程序,我们试图根据用户的位置推送一些活动通知。但这似乎正在耗尽 phone 的电池,有时会消耗高达 30-35% 的电量。
下面是 Location 在我们应用中的实现。
public class DashboardActivity extends BaseActivity implements GoogleApiClient.OnConnectionFailedListener, GoogleApiClient.ConnectionCallbacks,
LocationListener, ExitConfirmationDialog.OnExitResponseListner {
private final int HAS_PERMISSION_COARSE_LOCATION = 1;
private final int HAS_PERMISSION_FINE_LOCATION = 2;
LocationManager locationManager;
CustomTextViewDemi mNotificationCount;
String count = "";
Menu menu;
List<CreateFragmentsPojo> fragments;
boolean isSettingsScreenOpen = false;
int backPresedCount = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_dashboard);
setTitle("Dashboard");
setupNavigationView(0);
fragments = new ArrayList<>();
Utils.HandleViews(mLayout, false);
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
if (isGPSLocationEnabled(locationManager)) {
buildGooleApiClient();
} else if (isNetworkLocationEnabled(locationManager)) {
buildGooleApiClient();
} else {
showAlert();
}
}
private void buildGooleApiClient() {
buildGoogleApiClient();
if (Build.VERSION.SDK_INT >= 23) {
requestPermission();
} else {
if (mGoogleApiClient != null) {
if (mGoogleApiClient.isConnected()) {
getUserCurrentLocation();
} else {
mGoogleApiClient.connect();
}
} else {
getDashBoard("", "");
}
}
}
public void getData(String lat, String lng) {
if (Utils.isInternetConnection(this)) {
getCampaignDetails(lat, lng);
} else {
Utils.HandleViews(progressBar, false);
Utils.showMessages(this, Params.CHECK_INTERNET_MESSAGE, true);
}
}
private void getUserCurrentLocation() {
try {
Utils.HandleViews(progressBar, true);
if (mGoogleApiClientAwareness == null) {
buildGoogleApiAwarenessClient();
}
Awareness.SnapshotApi.getLocation(mGoogleApiClientAwareness)
.setResultCallback(new ResultCallback<LocationResult>() {
@Override
public void onResult(@NonNull LocationResult locationResult) {
if (!locationResult.getStatus().isSuccess()) {
Log.e("awareness demo api ", "Could not get location.");
if (mGoogleApiClient != null) {
try {
Location mLastLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
if (mLastLocation != null) {
getDashBoard(mLastLocation.getLatitude() + "", mLastLocation.getLongitude() + "");
} else {
getDashBoard("", "");
}
} catch (SecurityException e) {
e.printStackTrace();
}
} else {
if (locationManager != null) {
String provider = Utils.getUserLastLocation(locationManager);
if (provider != null) {
try {
Location location = locationManager.getLastKnownLocation(provider);
if (location != null) {
getDashBoard(location.getLatitude() + "", location.getLongitude() + "");
} else {
getDashBoard("", "");
}
} catch (SecurityException e) {
e.printStackTrace();
}
}
}
}
}
try {
Location location = locationResult.getLocation();
if (location != null) {
getDashBoard(location.getLatitude() + "", location.getLongitude() + "");
} else {
getDashBoard("", "");
}
} catch (Exception e) {
e.printStackTrace();
}
}
});
} catch (SecurityException se) {
se.printStackTrace();
}
}
private void showAlert() {
final AlertDialog.Builder dialog = new AlertDialog.Builder(this);
dialog.setTitle("Enable Location")
.setMessage("Your Locations Settings is set to 'Off'.\nPlease Enable Location to " +
"get campaigns at your location.")
.setPositiveButton("Location Settings", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface paramDialogInterface, int paramInt) {
isSettingsScreenOpen = true;
Intent myIntent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
startActivityForResult(myIntent, 201);
}
})
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface paramDialogInterface, int paramInt) {
getUserCurrentLocation();
}
});
dialog.show();
}
/**
* Get user permissions for location based updates
*/
@TargetApi(23)
private void requestPermission() {
int HAS_REQUEST_PERMISSION_COARSE_LOCATION = ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION);
if (HAS_REQUEST_PERMISSION_COARSE_LOCATION
!= PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.shouldShowRequestPermissionRationale(this, android.Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
new AlertDialog.Builder(this)
.setTitle("Request Permission")
.setMessage("Provide permission to access your location")
.setNegativeButton(android.R.string.cancel, null)
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION},
HAS_PERMISSION_COARSE_LOCATION);
}
}).create().show();
} else {
requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION},
HAS_PERMISSION_COARSE_LOCATION);
}
} else {
requestFineLocationPermission();
}
}
@TargetApi(23)
private void requestFineLocationPermission() {
int HAS_REQUEST_PERMISSION_FINE_LOCATION = ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION);
if (HAS_REQUEST_PERMISSION_FINE_LOCATION
!= PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.shouldShowRequestPermissionRationale(this, android.Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
new AlertDialog.Builder(this)
.setTitle("Request Permission")
.setMessage("Provide permission to access your location")
.setNegativeButton(android.R.string.cancel, null)
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
HAS_PERMISSION_FINE_LOCATION);
}
}).create().show();
} else {
requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
HAS_PERMISSION_FINE_LOCATION);
}
} else {
getUserCurrentLocation();
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == HAS_PERMISSION_COARSE_LOCATION) {
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
requestFineLocationPermission();
}
} else if (requestCode == HAS_PERMISSION_FINE_LOCATION) {
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
getUserCurrentLocation();
}
}
}
/**
* Call to detect new campaigns near by
*/
private void getUserLocationBackgroundProcess() {
try {
//Utils.getCurrentLocation(this);
startLocationUpdates();
} catch (Exception e) {
e.printStackTrace();
}
}
private boolean isGPSLocationEnabled(LocationManager locationManager) {
return locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
}
private boolean isNetworkLocationEnabled(LocationManager locationManager) {
return locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
}
protected synchronized void buildGoogleApiAwarenessClient() {
try {
Log.i(TAG, "activity Building GoogleApiClient===");
mGoogleApiClientAwareness = new GoogleApiClient.Builder(this)
.addApi(Awareness.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
mGoogleApiClientAwareness.connect();
//createLocationRequest();
} catch (Exception e) {
e.printStackTrace();
}
}
protected synchronized void buildGoogleApiClient() {
try {
Log.i(TAG, "activity Building GoogleApiClient===");
buildGoogleApiAwarenessClient();
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
createLocationRequest();
} catch (Exception e) {
e.printStackTrace();
getUserCurrentLocation();
}
}
protected void createLocationRequest() {
mGoogleApiClient.connect();
mLocationRequest = new LocationRequest();
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
mLocationRequest.setSmallestDisplacement(30);
}
@Override
public void onLocationChanged(Location location) {
mCurrentLocation = location;
}
@Override
public void onConnected(@Nullable Bundle bundle) {
getUserCurrentLocation();
// startLocationUpdates();
}
protected void startLocationUpdates() {
try {
mRequestingLocationUpdates = true;
Intent receiverIntentService = new Intent(this, LocationIntentService.class);
PendingIntent pendingIntent = PendingIntent.getService(this, 1, receiverIntentService, 0);
if (mGoogleApiClient != null) {
if (mGoogleApiClient.isConnected()) {
LocationServices.FusedLocationApi.requestLocationUpdates(
mGoogleApiClient, mLocationRequest, pendingIntent);
}
/*else {
mGoogleApiClient.connect();
LocationServices.FusedLocationApi.requestLocationUpdates(
mGoogleApiClient, mLocationRequest, pendingIntent);
}*/
} else {
buildGoogleApiClient();
}
} catch (SecurityException se) {
se.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
protected void onResume() {
super.onResume();
try {
if (isSettingsScreenOpen) {
isSettingsScreenOpen = false;
getUserCurrentLocation();
}
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void onConnectionSuspended(int i) {
}
@Override
public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
}
@Override
protected void onStop() {
super.onStop();
if (mGoogleApiClient != null) {
if (mGoogleApiClient.isConnected())
mGoogleApiClient.disconnect();
}
}
}
而不是
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
试试这个
mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
mlocationrequest.setSmallestDisplacement(30); //higher priority
位移参数设置为30米
//如果设备不移动或越过该距离,则不会收到位置更新。
//setInterval as above 1 mins.
mlocationrequest.setInterval(60000); // Update location every 1 minute
mlocationrequest.setFastestInterval(10000);
LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY级精度被认为是100米左右的精度。使用像这样的粗精度通常会消耗更少的功率。
我们有一个基于位置的应用程序,我们试图根据用户的位置推送一些活动通知。但这似乎正在耗尽 phone 的电池,有时会消耗高达 30-35% 的电量。
下面是 Location 在我们应用中的实现。
public class DashboardActivity extends BaseActivity implements GoogleApiClient.OnConnectionFailedListener, GoogleApiClient.ConnectionCallbacks,
LocationListener, ExitConfirmationDialog.OnExitResponseListner {
private final int HAS_PERMISSION_COARSE_LOCATION = 1;
private final int HAS_PERMISSION_FINE_LOCATION = 2;
LocationManager locationManager;
CustomTextViewDemi mNotificationCount;
String count = "";
Menu menu;
List<CreateFragmentsPojo> fragments;
boolean isSettingsScreenOpen = false;
int backPresedCount = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_dashboard);
setTitle("Dashboard");
setupNavigationView(0);
fragments = new ArrayList<>();
Utils.HandleViews(mLayout, false);
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
if (isGPSLocationEnabled(locationManager)) {
buildGooleApiClient();
} else if (isNetworkLocationEnabled(locationManager)) {
buildGooleApiClient();
} else {
showAlert();
}
}
private void buildGooleApiClient() {
buildGoogleApiClient();
if (Build.VERSION.SDK_INT >= 23) {
requestPermission();
} else {
if (mGoogleApiClient != null) {
if (mGoogleApiClient.isConnected()) {
getUserCurrentLocation();
} else {
mGoogleApiClient.connect();
}
} else {
getDashBoard("", "");
}
}
}
public void getData(String lat, String lng) {
if (Utils.isInternetConnection(this)) {
getCampaignDetails(lat, lng);
} else {
Utils.HandleViews(progressBar, false);
Utils.showMessages(this, Params.CHECK_INTERNET_MESSAGE, true);
}
}
private void getUserCurrentLocation() {
try {
Utils.HandleViews(progressBar, true);
if (mGoogleApiClientAwareness == null) {
buildGoogleApiAwarenessClient();
}
Awareness.SnapshotApi.getLocation(mGoogleApiClientAwareness)
.setResultCallback(new ResultCallback<LocationResult>() {
@Override
public void onResult(@NonNull LocationResult locationResult) {
if (!locationResult.getStatus().isSuccess()) {
Log.e("awareness demo api ", "Could not get location.");
if (mGoogleApiClient != null) {
try {
Location mLastLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
if (mLastLocation != null) {
getDashBoard(mLastLocation.getLatitude() + "", mLastLocation.getLongitude() + "");
} else {
getDashBoard("", "");
}
} catch (SecurityException e) {
e.printStackTrace();
}
} else {
if (locationManager != null) {
String provider = Utils.getUserLastLocation(locationManager);
if (provider != null) {
try {
Location location = locationManager.getLastKnownLocation(provider);
if (location != null) {
getDashBoard(location.getLatitude() + "", location.getLongitude() + "");
} else {
getDashBoard("", "");
}
} catch (SecurityException e) {
e.printStackTrace();
}
}
}
}
}
try {
Location location = locationResult.getLocation();
if (location != null) {
getDashBoard(location.getLatitude() + "", location.getLongitude() + "");
} else {
getDashBoard("", "");
}
} catch (Exception e) {
e.printStackTrace();
}
}
});
} catch (SecurityException se) {
se.printStackTrace();
}
}
private void showAlert() {
final AlertDialog.Builder dialog = new AlertDialog.Builder(this);
dialog.setTitle("Enable Location")
.setMessage("Your Locations Settings is set to 'Off'.\nPlease Enable Location to " +
"get campaigns at your location.")
.setPositiveButton("Location Settings", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface paramDialogInterface, int paramInt) {
isSettingsScreenOpen = true;
Intent myIntent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
startActivityForResult(myIntent, 201);
}
})
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface paramDialogInterface, int paramInt) {
getUserCurrentLocation();
}
});
dialog.show();
}
/**
* Get user permissions for location based updates
*/
@TargetApi(23)
private void requestPermission() {
int HAS_REQUEST_PERMISSION_COARSE_LOCATION = ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION);
if (HAS_REQUEST_PERMISSION_COARSE_LOCATION
!= PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.shouldShowRequestPermissionRationale(this, android.Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
new AlertDialog.Builder(this)
.setTitle("Request Permission")
.setMessage("Provide permission to access your location")
.setNegativeButton(android.R.string.cancel, null)
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION},
HAS_PERMISSION_COARSE_LOCATION);
}
}).create().show();
} else {
requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION},
HAS_PERMISSION_COARSE_LOCATION);
}
} else {
requestFineLocationPermission();
}
}
@TargetApi(23)
private void requestFineLocationPermission() {
int HAS_REQUEST_PERMISSION_FINE_LOCATION = ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION);
if (HAS_REQUEST_PERMISSION_FINE_LOCATION
!= PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.shouldShowRequestPermissionRationale(this, android.Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
new AlertDialog.Builder(this)
.setTitle("Request Permission")
.setMessage("Provide permission to access your location")
.setNegativeButton(android.R.string.cancel, null)
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
HAS_PERMISSION_FINE_LOCATION);
}
}).create().show();
} else {
requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
HAS_PERMISSION_FINE_LOCATION);
}
} else {
getUserCurrentLocation();
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == HAS_PERMISSION_COARSE_LOCATION) {
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
requestFineLocationPermission();
}
} else if (requestCode == HAS_PERMISSION_FINE_LOCATION) {
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
getUserCurrentLocation();
}
}
}
/**
* Call to detect new campaigns near by
*/
private void getUserLocationBackgroundProcess() {
try {
//Utils.getCurrentLocation(this);
startLocationUpdates();
} catch (Exception e) {
e.printStackTrace();
}
}
private boolean isGPSLocationEnabled(LocationManager locationManager) {
return locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
}
private boolean isNetworkLocationEnabled(LocationManager locationManager) {
return locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
}
protected synchronized void buildGoogleApiAwarenessClient() {
try {
Log.i(TAG, "activity Building GoogleApiClient===");
mGoogleApiClientAwareness = new GoogleApiClient.Builder(this)
.addApi(Awareness.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
mGoogleApiClientAwareness.connect();
//createLocationRequest();
} catch (Exception e) {
e.printStackTrace();
}
}
protected synchronized void buildGoogleApiClient() {
try {
Log.i(TAG, "activity Building GoogleApiClient===");
buildGoogleApiAwarenessClient();
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
createLocationRequest();
} catch (Exception e) {
e.printStackTrace();
getUserCurrentLocation();
}
}
protected void createLocationRequest() {
mGoogleApiClient.connect();
mLocationRequest = new LocationRequest();
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
mLocationRequest.setSmallestDisplacement(30);
}
@Override
public void onLocationChanged(Location location) {
mCurrentLocation = location;
}
@Override
public void onConnected(@Nullable Bundle bundle) {
getUserCurrentLocation();
// startLocationUpdates();
}
protected void startLocationUpdates() {
try {
mRequestingLocationUpdates = true;
Intent receiverIntentService = new Intent(this, LocationIntentService.class);
PendingIntent pendingIntent = PendingIntent.getService(this, 1, receiverIntentService, 0);
if (mGoogleApiClient != null) {
if (mGoogleApiClient.isConnected()) {
LocationServices.FusedLocationApi.requestLocationUpdates(
mGoogleApiClient, mLocationRequest, pendingIntent);
}
/*else {
mGoogleApiClient.connect();
LocationServices.FusedLocationApi.requestLocationUpdates(
mGoogleApiClient, mLocationRequest, pendingIntent);
}*/
} else {
buildGoogleApiClient();
}
} catch (SecurityException se) {
se.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
protected void onResume() {
super.onResume();
try {
if (isSettingsScreenOpen) {
isSettingsScreenOpen = false;
getUserCurrentLocation();
}
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void onConnectionSuspended(int i) {
}
@Override
public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
}
@Override
protected void onStop() {
super.onStop();
if (mGoogleApiClient != null) {
if (mGoogleApiClient.isConnected())
mGoogleApiClient.disconnect();
}
}
}
而不是
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
试试这个
mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
mlocationrequest.setSmallestDisplacement(30); //higher priority
位移参数设置为30米 //如果设备不移动或越过该距离,则不会收到位置更新。
//setInterval as above 1 mins.
mlocationrequest.setInterval(60000); // Update location every 1 minute
mlocationrequest.setFastestInterval(10000);
LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY级精度被认为是100米左右的精度。使用像这样的粗精度通常会消耗更少的功率。