如何使用融合位置API优化电池-Android

如何使用融合位置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

您好,我在android中面临以下位置API问题

  • 电池消耗高达30%-40%,导致大量电池耗电。

  • 状态栏中的位置图标始终处于打开状态,即使在应用程序关闭且卸载应用程序时,它也会自动关闭。

要求:

  • 应用程序打开时需要用户位置
  • 我需要有用户的位置,即使在应用程序未打开或未使用的基础上距离-需要在后台的用户位置
方法:

  • 使用全球定位系统

  • API使用了具有待定意图的融合位置API

  • LocationManager-检查GPS开/关状态

  • 代码演练:

  • 在OnCreate中,我正在获取location manager实例—获取location manager实例

  • 检查GPS是否启用或网络状态是否可用,否则显示对话框以启用位置:代码:-

    // get GPS state.
        locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
    
    
        if (isGPSLocationEnabled(locationManager)) {
            buildGooleLocationApiClient();
        } else if (isNetworkLocationEnabled(locationManager)) {
            buildGooleLocationApiClient();
        } else {
            showAlert();
        }
    
  • GoolgelocationAppClient代码:在这个方法中,我检查android版本,请求权限并启用服务

    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。 编写一个实现以下接口的服务:

  • GoogleAppClient.ConnectionCallbacks
  • GoogleAppClient.OnConnectionFailedListener
  • 位置侦听器

    public class PositionService extends服务实现GoogleAppClient.ConnectionCallbacks、GoogleAppClient.OnConnectionFailedListener、LocationListener{}

  • 使用GoogleAppClient和LocationRequest类

    进入onCreate()实例化GoogleAppClient对象、LocationRequest对象并使MgoogleAppClient连接

    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()),或至少交换 请求的间隔较大,质量较低

    因此,当我面临类似问题时,我所做的是:

  • 我创建了两个定位请求,第一个优先级为priority\u HIGH\u precision,间隔为1分钟,而第二个优先级为priority\u LOW\u POWER,内部位移为1小时,最小位移为1公里
  • 当应用程序启动时,我使用第一个位置请求(高优先级)来获得更频繁和准确的位置更新
  • 当应用程序进入后台时,我会切换到第二个位置请求(低优先级),以消除电池使用,同时减少位置更新的频率
  • (可选)您还可以在应用程序启动时获取电池百分比,并根据限制(例如15%)选择在应用程序位于前台时您可能希望使用的位置请求

  • 这些步骤帮助我使用FusedLocationApi将我的应用程序的电池使用率从>30%降低到我正在做类似的事情(我使用的是长时间运行的服务,而不是IntentService)&我的电池使用率最低(每3分钟更新一次位置)。我怀疑你的问题更可能来自LocationManager。你能在没有看到这些的情况下尝试一下吗?马特-谢谢你的回答,但是当你可以使用fusedlocationAPI和PendingEvent来达到这个目的时,为什么你需要创建一个单独的服务呢。后台服务耗电更多,必须在fusedlocation自行管理的位置显式处理。我想知道您对给定解决方案的建议的思考过程和原因。我参考了官方文档,它建议使用LocationListener(或实现相应的接口)。我创建一个单独的服务没有具体的原因。