首页 > 解决方案 > 尽管华为 P10 Lite Android 8 上没有电池耗尽,但电池耗尽通知开启

问题描述

我的一位同事收到通知,说我帮助开发的一个应用程序在后台运行时会很快耗尽她的电池电量。到目前为止,她是我认识的第一个通过我们的应用程序收到此通知的人。

让我描述一下应用程序的功能/需要:当用户启动应用程序时,设备会本地化一次。之后,用户必须按下按钮来更新他们的位置。每当用户切换到特定活动时,都会对服务器进行 ping 操作以更新应用程序中的数据。使用该应用程序不需要除 GPS 以外的其他权限。仅在主动使用应用程序时才对服务器进行 ping 操作,并且仅更新位置。

这是服务器通信的代码。

/**
 * Queries for Stores in the BoundingBox defined by the given GeoCoordinates.
 * After the Async- Query was successful the Stores which are in the Resultset but currently not
 * loaded are queryed for and added to the global Adapter and an
 * ID-Filter is put in place limiting the List to the retrieved ones.
 *
 * @param topLeft     TopLeft- Coordinates for the Query
 * @param bottomRight BottomRight- Coordinates for the Query
 */
private void queryForStoresInBoundingBox(lokalfuchs.de.lokalfuchs.api.model.Location topLeft, lokalfuchs.de.lokalfuchs.api.model.Location bottomRight) {

    //query elasticsearch for all stores in the given region
    StoreService.getInstance().queryForStoresInGeoPointBoundingBox(
            topLeft, bottomRight, new ElasticsearchQueryCallback() {
                @Override
                public void querySuccesful(final List<Integer> ids) {
                    //from the list of ids which lie in the currently visible region: determine which are not currently loaded
                    final List<Integer> missingStores = StoreService.getInstance().getStoreAdapter().findMissingItemIds(ids);
                    final List<Integer> missingOffers = OfferService.getInstance().findMissingStoreIds(ids);
                    if (!missingStores.isEmpty()) {
                        //request these missing items and add them in the adapter
                        StoreService.getInstance().requestStores(null, null, missingStores.toArray(new Integer[missingStores.size()]), new StoreRequestCallback() {
                            @Override
                            public void requestSuccesful(final List<Store> stores) {
                                // !! TODO dont ask for offers without out valid offer ids you will get from elastic search!
                                OfferService.getInstance().requestOffers(null, missingOffers.toArray(new Integer[missingOffers.size()]), null, null, new OfferRequestCallback() {
                                    @Override
                                    public void requestSuccesful(final List<Offer> offers) {

                                        // TODO replace quick fix, just fetching valid offers with elastic offerIds
                                        // only continue with valid offers
                                        final List<Offer> validOffers = new ArrayList<>();

                                        SimpleDateFormat parserEndDate = new SimpleDateFormat(getResources().getString(R.string.date_pattern));
                                        Date currentDate = new Date();
                                        for (Offer offer : offers) {
                                            try {
                                                Date endDate = parserEndDate.parse(offer.getEndDate());

                                                if (endDate != null && currentDate.compareTo(endDate) < 0) {
                                                    validOffers.add(offer);
                                                    continue;
                                                }
                                            } catch (ParseException e) {
                                                e.printStackTrace();
                                            }
                                        }

                                        //add to adapter on ui-thread
                                        MapActivity.this.runOnUiThread(new Runnable() {
                                            @Override
                                            public void run() {
                                                Map<Integer, List<Integer>> allStoreOffers = OfferService.getInstance().getOffers();
                                                ItemAdapter adapter = OfferService.getInstance().getOfferAdapter();

                                                final List<Offer> handledOffers = (LocationService.getInstance().getLastLocation() != null) ? OfferService.getInstance().calculateDistancesAndRemoveExpiredOffers(
                                                        validOffers, new com.google.maps.model.LatLng(LocationService.getInstance().getLastLocation().getLatitude(), LocationService.getInstance().getLastLocation().getLongitude())) : validOffers;

                                                for (Offer o : handledOffers) {
                                                    OfferService.getInstance().getOfferAdapter().getItems().put(o.getId(), o);
                                                    List<Integer> storeOffers = allStoreOffers.get(o.getStoreId());
                                                    if (storeOffers == null) {
                                                        storeOffers = new ArrayList<>();
                                                        allStoreOffers.put(o.getStoreId(), storeOffers);
                                                    }
                                                    if (!storeOffers.contains(o.getId())) {
                                                        storeOffers.add(o.getId());
                                                        adapter.getItems().put(o.getId(), o);
                                                    }
                                                }
                                                Map<Integer, MappableItem> list = StoreService.getInstance().getStoreAdapter().getItems();

                                                for (Store store : stores)
                                                    list.put(store.getId(), store);
                                                StoreService.getInstance().getStoreAdapter().setIdFilter(new ItemIdFilter(ids));
                                            }
                                        });
                                    }

                                    @Override
                                    public void requestFailed(int errorCode) {
                                    }
                                });
                            }

                            @Override
                            public void requestFailed(int errorCode) {

                            }
                        });
                    } else {
                        //there are no missing items - add the filter immediately instead of after the query
                        StoreService.getInstance().getStoreAdapter().setIdFilter(new ItemIdFilter(ids));
                    }

                }

                @Override
                public void queryFailed() {

                }
            });
}

public void queryForStoresInGeoPointBoundingBox(@NonNull Location top_left, @NonNull Location bottom_right, final @NonNull ElasticsearchQueryCallback callback) {

    //if the coordinates are not correctly ordered reoder them
    if (top_left.getLat() < bottom_right.getLat()) {
        Double temp = top_left.getLat();
        top_left.setLat(bottom_right.getLat());
        bottom_right.setLat(temp);
    }
    if (top_left.getLon() > bottom_right.getLon()) {
        Double temp = top_left.getLon();
        top_left.setLon(bottom_right.getLon());
        bottom_right.setLon(temp);
    }

    this.elasticSearchInterface.elasticSearchStoreIdsGeopointRequest(new ElasticSearchInterface.SearchQuery(top_left, bottom_right, false), LokalFuchs.DEFAULT_SIZE).enqueue(new Callback<ElasticSearchInterface.SearchResult>() {
        @Override
        public void onResponse(Call<ElasticSearchInterface.SearchResult> call, Response<ElasticSearchInterface.SearchResult> response) {
            //check for response-code 200
            if (response.code() == 200) {
                //prepare resultlist
                List<Integer> storeIds = new ArrayList<>();

                //and iterate over all hits extracting the ids
                for (ElasticSearchInterface.SearchResult.Hits hit : response.body().hits.hits) {
                    if (hit.fields.id.length > 0)
                        storeIds.add(hit.fields.id[0]);
                }
                callback.querySuccesful(storeIds);
            } else {
                callback.queryFailed();
            }
        }

        @Override
        public void onFailure(Call<ElasticSearchInterface.SearchResult> call, Throwable t) {
            callback.queryFailed();
        }
    });

}

我忘了提到数据加载需要很长时间,可能超过 4 秒。

这是本地化的代码。

/**
 * asking for localisation permission
 * <p>
 * if ok:
 * start location updates 
 * if not set isRequesting to false
 *
 * @param activity Activity
 */
public boolean requestLocation(Activity activity) {

    if (AppService.getInstance().checkPermission(Manifest.permission.ACCESS_FINE_LOCATION, activity, R.string.missing_gps_permission, null)) {
        this.isRequesting = true;
             this.locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this);
        return true;
    } else {
        return false;
    }
}

 /**
 * register Callback for change of position
 *
 * @param locationChangedCallback Callback für for position change
 */
public void registerCallback(LocationChangedCallback locationChangedCallback) {
    if (!this.locationChangedCallbacks.contains(locationChangedCallback)) {
        this.locationChangedCallbacks.add(locationChangedCallback);
    }
}

@Override
public void onMapReady(GoogleMap googleMap) {
[...]
    //register for location-changes and request the location once
    Location location = LocationService.getInstance().getLastLocation();

    //if we have a location use it
    if (location == null) {
        this.googleMap.moveCamera(CameraUpdateFactory.zoomTo(15));
        this.googleMap.moveCamera(CameraUpdateFactory.newLatLng(new LatLng(52.520008, 13.404954)));
        LocationService.getInstance().registerCallback(this);
        LocationService.getInstance().requestLocation(this);
    } else {
        LatLng position = new LatLng(location.getLatitude(), location.getLongitude());
        this.markMyPosition(position);
        this.googleMap.moveCamera(CameraUpdateFactory.zoomTo(15));
        this.googleMap.moveCamera(CameraUpdateFactory.newLatLng(position));
    }
[...]
}

我检查了她手机上的电池消耗详细信息,即使应用程序处于活动状态并且 GPS 仅使用不到 10 秒,CPU 也没有太多工作要做。该应用程序在过去 30 天内下载了 20 mb。她仍然在大约 15 分钟后收到通知,她必须关闭它才能消除通知。到目前为止,她在使用任何其他应用程序时都没有遇到这个问题,也没有其他人报告过这个问题。

有谁知道问题可能是什么,或者我可以做些什么来找出导致这个问题的原因?

标签: android

解决方案


推荐阅读