如何使用融合位置API优化电池-Android
您好,我在android中面临以下位置API问题如何使用融合位置API优化电池-Android,android,android-intent,gps,android-location,android-fusedlocation,Android,Android Intent,Gps,Android Location,Android Fusedlocation,您好,我在android中面临以下位置API问题 电池消耗高达30%-40%,导致大量电池耗电。 状态栏中的位置图标始终处于打开状态,即使在应用程序关闭且卸载应用程序时,它也会自动关闭。 要求: 应用程序打开时需要用户位置 我需要有用户的位置,即使在应用程序未打开或未使用的基础上距离-需要在后台的用户位置 方法: 使用全球定位系统 API使用了具有待定意图的融合位置API LocationManager-检查GPS开/关状态 代码演练: 在OnCreate中,我正在获取location
- 电池消耗高达30%-40%,导致大量电池耗电。
- 状态栏中的位置图标始终处于打开状态,即使在应用程序关闭且卸载应用程序时,它也会自动关闭。
- 应用程序打开时需要用户位置
- 我需要有用户的位置,即使在应用程序未打开或未使用的基础上距离-需要在后台的用户位置李>
// get GPS state.
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
if (isGPSLocationEnabled(locationManager)) {
buildGooleLocationApiClient();
} else if (isNetworkLocationEnabled(locationManager)) {
buildGooleLocationApiClient();
} else {
showAlert();
}
private void buildGooleLocationApiClient() {
if (Build.VERSION.SDK_INT >= 23) {
int isFineLocationPermission = ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION);
int isCoarseLocationPermission = ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION);
if (isFineLocationPermission == PackageManager.PERMISSION_DENIED || isCoarseLocationPermission == PackageManager.PERMISSION_DENIED) {
requestPermission();
} else {
checkGoogleLocationApiClient();
}
} else {
checkGoogleLocationApiClient();
}
}
构建GoogleAPI客户端:
private void checkGoogleLocationApiClient() {
try {
if (mGoogleApiClient != null) {
if (mGoogleApiClient.isConnected()) {
getMyLocationCampaigns();
} else {
mGoogleApiClient.connect();
}
} else {
buildGoogleApiClient();
}
} catch (Exception e) {
e.printStackTrace();
}
}
private void getMyLocationCampaigns() {
if (mCurrentLocation != null) {
getData(mCurrentLocation.getLatitude()+"",mCurrentLocation.getLongitude()+"");
} else {
try {
mCurrentLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
getData(mCurrentLocation.getLatitude()+"",mCurrentLocation.getLongitude()+"");
} catch (SecurityException ex) {
ex.printStackTrace();
getData("","");
}
}
}
private synchronized void buildGoogleApiClient() {
try {
Log.i(TAG, "activity Building GoogleApiClient===");
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
createLocationRequest();
} catch (Exception e) {
e.printStackTrace();
getData("","");
}
}
private void createLocationRequest() {
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(60 * 60 * 1000);
mLocationRequest.setFastestInterval(60 * 1000);
mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
mLocationRequest.setSmallestDisplacement(100);
connectGoogleApiClient();
}
private void connectGoogleApiClient() {
if (mGoogleApiClient != null) {
if (!mGoogleApiClient.isConnected())
mGoogleApiClient.connect();
}
}
@Override
public void onLocationChanged(Location location) {
mCurrentLocation = location;
}
@Override
public void onConnected(@Nullable Bundle bundle) {
if (mCurrentLocation == null) {
try {
mCurrentLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
if (mCurrentLocation != null) {
// MyAPICALL getData(mCurrentLocation.getLatitude()+"",mCurrentLocation.getLongitude()+"");
} else {
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient,mLocationRequest, this);
mCurrentLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
if (mCurrentLocation == null) {
if (locationManager != null) {
String provider = Utils.getUserLastLocation(locationManager);
if (provider != null) {
try {
Location location = locationManager.getLastKnownLocation(provider);
if (location != null) {
getData(location.getLatitude() + "", location.getLongitude() + "");
} else {
getData("", "");
}
} catch (SecurityException e) {
e.printStackTrace();
}
}
}
} else {
getData(mCurrentLocation.getLatitude()+"",mCurrentLocation.getLongitude()+"");
}
}
} catch (SecurityException ex) {
ex.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
getData("","");
}
}
}
方法在后台获取具有挂起意图的位置
private void startLocationUpdates() {
try {
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);
}
}
} catch (SecurityException se) {
se.printStackTrace();
}
}
广播接收器:如果设备重新启动:
public class LocationBroadcastReceiver extends BroadcastReceiver implements
GoogleApiClient.ConnectionCallbacks,GoogleApiClient.OnConnectionFailedListener, LocationListener {
Context context;
protected GoogleApiClient mGoogleApiClient;
protected LocationRequest mLocationRequest;
protected Location mCurrentLocation;
public static Boolean mRequestingLocationUpdates = false;
SharedPreferences checkUserStatus;
public LocationBroadcastReceiver() {
}
@Override
public void onReceive(Context context, Intent intent) {
// TODO: This method is called when the BroadcastReceiver is receiving
// an Intent broadcast.
try {
this.context = context;
checkUserStatus = context.getSharedPreferences(Params.LOGIN_DETAILS_PREFERENCE, 0);
String isUserLogedIn = checkUserStatus.getString(Params.TOKEN,"");
// if user is still logged in then only trigger background service
if (!isUserLogedIn.equals("")) {
buildGoogleApiClient();
if (mGoogleApiClient != null) {
if (mGoogleApiClient.isConnected() && mRequestingLocationUpdates) {
startLocationUpdates();
} else {
buildGoogleApiClient();
}
} else {
buildGoogleApiClient();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void onConnected(Bundle bundle) {
startLocationUpdates();
}
@Override
public void onConnectionSuspended(int i) {
mGoogleApiClient.connect();
}
@Override
public void onConnectionFailed(ConnectionResult connectionResult) {
Log.i("Broadcast receiver", "Connection failed: ConnectionResult.getErrorCode() = " + connectionResult.getErrorCode());
}
@Override
public void onLocationChanged(Location location) {
mCurrentLocation = location;
}
protected synchronized void buildGoogleApiClient() {
mGoogleApiClient = new GoogleApiClient.Builder(context)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
createLocationRequest();
}
protected void createLocationRequest() {
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(60 * 60 * 1000);
mLocationRequest.setFastestInterval(60 * 1000);
mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
mLocationRequest.setSmallestDisplacement(100);
}
protected void startLocationUpdates() {
try {
Intent receiverIntentService = new Intent(context,LocationIntentService.class);
PendingIntent pendingIntent = PendingIntent.getService(context,1,receiverIntentService,0);
LocationServices.FusedLocationApi.requestLocationUpdates(
mGoogleApiClient, mLocationRequest, pendingIntent);
}catch (SecurityException se) {
se.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
}
My intent服务类:获取用户更新的位置并进行API调用
public class LocationIntentService extends IntentService {
Context context;
Bitmap myBitmap;
URL url;
SharedPreferences.Editor mMyLastLocationHolder;
SharedPreferences mMyLastLocation;
SharedPreferences checkUserStatus;
public LocationIntentService() {
super("LocationIntentService");
}
@Override
protected void onHandleIntent(Intent intent) {
if (intent != null) {
Bundle bundle = intent.getExtras();
if (bundle != null) {
Location location = bundle.getParcelable("com.google.android.location.LOCATION");
if (location != null) {
context = getApplicationContext();
// API call to server
updateAPI(location.getLatitude()+"",location.getLongitude()+"");
Log.v("TAG LOCATION ", " ==== " + location.getLatitude() + " - " + location.getLongitude() + " ==== ");
Log.v("TAG LOCATION ", " ==== calling my-campaigns near me ========");
}
}
}
}
/**
* Handle action Foo in the provided background thread with the provided
* parameters.
*/
private void handleActionFoo(String param1, String param2) {
// TODO: Handle action Foo
throw new UnsupportedOperationException("Not yet implemented");
}
/**
* Handle action Baz in the provided background thread with the provided
* parameters.
*/
private void handleActionBaz(String param1, String param2) {
// TODO: Handle action Baz
throw new UnsupportedOperationException("Not yet implemented");
}
}
我希望这能帮助您找到最佳解决方案/方法 个人更喜欢使用具有一定优先级和间隔的GoogleAppClient和LocationRequest。 编写一个实现以下接口的服务:
public class PositionService extends服务实现GoogleAppClient.ConnectionCallbacks、GoogleAppClient.OnConnectionFailedListener、LocationListener{}
public void onCreate() {
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
mLocationRequest = LocationRequest.create()
.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY)
.setInterval(mInterval).setFastestInterval(mFastInterval);
mGoogleApiClient.connect();
}
进入onDestroy()方法,使MGoogleAppClient断开连接
@Override
public void onDestroy() {
mGoogleApiClient.disconnect();
}
现在实现接口
@Override
public void onLocationChanged(Location location) {
Log.d("NewLocation", location.toString());
}
@Override
public void onConnected(@Nullable Bundle bundle) throws SecurityException {
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
}
@Override
public void onConnectionSuspended(int i) {
}
@Override
public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
}
现在,基于LocationRequest的设置,GoogleAppClient将通知您调用onLocationChanged()回调的位置
您的业务逻辑应该放在onLocationChanged()方法中。只需为LocationRequest选择一个好的间隔时间和优先级。(见附件)
请参阅有关的官方文档,我的解决方案就是基于此
我习惯于在前台启动服务,以防止操作系统出现意外行为(例如服务被终止)这只会解释更好的逻辑 不要使用长时间运行的服务或IntentService,只需使用Firebase JobDispatcher或任何第三方lib Jobscheduler API,以便将所有位置更新代码移动到Jobscheduler() 根据您的位置更新间隔启动作业,根据您的要求配置或更改作业!!与长期运行的服务相比,它确实是一个更好的解决方案!!!(您可以使用eventBus或RxBus在活动或片段中更新位置!!) 提示:每次作业在作业关闭前启动位置更新时,安装程序都会出现3秒或更长的系统延迟,因为有时GoogleapClient会在延迟后花费更多时间更新新更新的GPS时间。您可以关闭GoogleapClient,在运行JobService的情况下进行所有不需要的回拨。通过检测用户活动,使用Google Aware Api或Google Fit Api智能控制作业配置 一体式作业调度程序库: 注意:代码将很快更新文档
活动应强烈考虑何时删除所有位置请求 输入背景(例如onPause()),或至少交换 请求的间隔较大,质量较低
因此,当我面临类似问题时,我所做的是:这些步骤帮助我使用FusedLocationApi将我的应用程序的电池使用率从>30%降低到我正在做类似的事情(我使用的是长时间运行的服务,而不是IntentService)&我的电池使用率最低(每3分钟更新一次位置)。我怀疑你的问题更可能来自LocationManager。你能在没有看到这些的情况下尝试一下吗?马特-谢谢你的回答,但是当你可以使用fusedlocationAPI和PendingEvent来达到这个目的时,为什么你需要创建一个单独的服务呢。后台服务耗电更多,必须在fusedlocation自行管理的位置显式处理。我想知道您对给定解决方案的建议的思考过程和原因。我参考了官方文档,它建议使用LocationListener(或实现相应的接口)。我创建一个单独的服务没有具体的原因。