Android 定位服务耗尽电池 - 融合定位 API
Posted
技术标签:
【中文标题】Android 定位服务耗尽电池 - 融合定位 API【英文标题】:Android Location Services draining the Battery - Fused Location API 【发布时间】:2017-05-04 04:23:27 【问题描述】:我们有一个基于位置的应用程序,我们正在尝试根据用户位置推送一些活动通知。但这似乎会耗尽手机的电池电量,有时会消耗高达 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();
【问题讨论】:
1.你的BaseActivity
中有什么 2. 我在 Google 示例中没有看到 LocationManager
- github.com/googlesamples/android-play-location/blob/master/… 我想知道它是否调用设备 LocationManager 而不是 Google 的 Fused Location API 3. 你在哪里停止位置更新?
@MorrisonChang BaseActivity -> 是父活动,它与应用程序的其他活动保持公共参数。我不需要编写多个时间相同的代码,我可以从活动中调用它们。当 GPS 不可用时使用 LocationManager。
【参考方案1】:
代替
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米左右的精度。使用这样的粗略精度通常会消耗更少的功率。
【讨论】:
以上是关于Android 定位服务耗尽电池 - 融合定位 API的主要内容,如果未能解决你的问题,请参考以下文章