【问题标题】:SyncAdapter onPerformSync get current locationSyncAdapter onPerformSync 获取当前位置
【发布时间】:2015-09-11 17:18:31
【问题描述】:

onPerformSync 发生时,我需要当前位置,但我不想设置一个单独的服务,该服务始终处于活动状态,请求位置,因为我的SyncAdapter 周期呈指数级后退,因此同步之间的周期可能相隔数小时.在每次同步之间运行位置请求会很浪费。

我计划使用GoogleApiClientLocationServices.FusedLocationApi.requestLocationUpdates 然后Thread.sleep(###) onPerformSync 线程,直到找到位置。

但是我读到需要在 main looper and that it makes callbacks on that thread 上调用 requestLocationUpdates,在这种情况下,我预计它会无法返回位置结果,因为我正在调用它的线程上睡觉。

我需要开始自己的弯针线吗?

还有其他/更好的方法可以从 onPerformSync 获取当前位置吗?

【问题讨论】:

    标签: android-syncadapter location-services


    【解决方案1】:

    事实证明我的担心是没有道理的,我的方法确实有效,没有错误。我在下面整理了一个方便的示例类,以防其他人想要这样做:

    public class cSyncLocation  implements ConnectionCallbacks, OnConnectionFailedListener, LocationListener
    {   
    
        // =======================================================
        // private vars
        // =======================================================
        private GoogleApiClient moGoogleApiClient;
        private LocationRequest moLocationRequest;
        private Location moCurrentLocation; 
        private static final int kTIMEOUT_MILLISECONDS = 2500;
    
        // =======================================================
        // public static vars
        // =======================================================
    
        // =======================================================
        // public methods
        // =======================================================
    
        public void Start(Context oContext)
        {
            if (moGoogleApiClient == null)
            {
                moGoogleApiClient = new GoogleApiClient.Builder(oContext)
                                    .addApi(LocationServices.API)
                                    .addConnectionCallbacks(this)
                                    .addOnConnectionFailedListener(this)
                                    .build();
            }
            if (moLocationRequest == null)
            {
                moLocationRequest = new LocationRequest();
    
                moLocationRequest.setInterval(1);
                moLocationRequest.setFastestInterval(1);
                moLocationRequest.setInterval(1);
                moLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
            }
            // Start the connection
            if (moGoogleApiClient != null) 
            {
                if (!moGoogleApiClient.isConnecting() && !moGoogleApiClient.isConnected())
                    moGoogleApiClient.connect();
                else if (moCurrentLocation == null)
                    LocationServices.FusedLocationApi.requestLocationUpdates(moGoogleApiClient, moLocationRequest, this);
    
            }
        }
    
        public void Stop()
        {
            if (moGoogleApiClient != null && moGoogleApiClient.isConnected())
                LocationServices.FusedLocationApi.removeLocationUpdates(moGoogleApiClient, this);
            if (moGoogleApiClient != null)
                moGoogleApiClient.disconnect();     
        }
    
        public Location GetLocationBlocking(Context oContext)
        {
            if (moCurrentLocation == null)
            {
                intTimeout = kTIMEOUT_MILLISECONDS;
                Start(oContext);
                while(intTimeout > 0 && aFrmLocationActivity.IsLastLocationExpired(oContext))
                {
                    Thread.sleep(100);
                    intTimeout -= 100;
                }
                Stop();
            }
            return moCurrentLocation;
        }
    
        // =======================================================
        // Location API Events
        // =======================================================
    
        @Override
        public void onLocationChanged(Location oLocation) 
        {
            if (oLocation != null)
            {
                moCurrentLocation = oLocation;
            }
        }
    
        // =======================================================
        // Google API Connection Events
        // =======================================================
    
    
        @Override
        public void onConnected(Bundle connectionHint) 
        {
            // Connected to Google Play services! The good stuff goes here.
            if (moGoogleApiClient != null)
            {
                Location oLocation = LocationServices.FusedLocationApi.getLastLocation(moGoogleApiClient);
                if (oLocation != null)
                    moCurrentLocation = oLocation;
                else
                    LocationServices.FusedLocationApi.requestLocationUpdates(moGoogleApiClient, moLocationRequest, this);
            }
        }
    
        @Override
        public void onConnectionSuspended(int cause) 
        {
            //...
        }
    
        @Override
        public void onConnectionFailed(ConnectionResult result) 
        {
            //...
        }       
    
    
    }
    

    如何使用它,在你的onPerformSync方法中这样调用它

    cSyncLocation oSyncLocation = new cSyncLocation();
    Location oLocation = oSyncLocation.GetLocationBlocking(getContext());
    

    显然你会想要添加一些异常处理并处理空位置结果。

    【讨论】:

    • 这对我不起作用,onLocationChanged 从未被调用过。
    • 检查您在 Manifest 中有使用权限 ACCESS_FINE_LOCATION。如果您的目标是并在 Android 6.0(API 级别 23)或更高版本上运行,那么您需要在应用程序的 UI 部分向用户请求访问位置的权限,一旦获得许可,它也应该在同步适配器上工作。但也许它只是在找到位置之前超时。
    • 我尝试使用 ACCESS_COARSE_LOCATION 权限接收位置信息。当我将其更改为 ACCESS_FINE_LOCATION 时,问题已得到解决。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-15
    • 1970-01-01
    • 2014-05-20
    • 1970-01-01
    相关资源
    最近更新 更多