0

我需要应用启动时的位置。我跟随这个tut withlocallocationapi得到LastLocation:https://developer.android.com/training/location/retrieve-current.html在应用启动时获取位置地址

当查询地址的AsyncTask通过一个按钮执行,但当我把相同的片段放在oncreate或onstart,然后获得NPE,它可能是完美的定位修复需要很长时间。

我想要加载活动,显示ProgressBar &然后显示位置,而不必点击按钮。

解决方法是在onstart短暂延迟后执行AsyncTask,但我猜测应该有更高效的东西。

public class MainActivity extends ActionBarActivity implements 
    ConnectionCallbacks, OnConnectionFailedListener{ 


protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 
    mAddress = (TextView) findViewById(R.id.address); 
    mActivityIndicator = 
      (ProgressBar) findViewById(R.id.address_progress); 

    buildGoogleApiClient(); 
} 

protected synchronized void buildGoogleApiClient() { 
    mGoogleApiClient = new GoogleApiClient.Builder(this) 
      .addConnectionCallbacks(this) 
      .addOnConnectionFailedListener(this) 
      .addApi(LocationServices.API) 
      .build(); 
} 


@Override 
protected void onStart() { 
    super.onStart(); 
    mGoogleApiClient.connect(); 
} 

@Override 
protected void onStop() { 
    super.onStop(); 
    if (mGoogleApiClient.isConnected()) { 
     mGoogleApiClient.disconnect(); 
    } 
} 

public void onConnected(Bundle connectionHint) { 
    mLastLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient); 
} 

private class GetAddressTask extends AsyncTask<Location, Void, String> 
{ 
    Context mContext; 
    public GetAddressTask(Context context) { 
     super(); 
     mContext = context; 
    } 
    @Override 
    protected String doInBackground(Location... params) { 
     Geocoder geocoder = 
       new Geocoder(mContext, Locale.getDefault()); 
     // Get the current location from the input parameter list 
     Location loc = params[0]; 
     // Create a list to contain the result address 
     List<Address> addresses = null; 
     try { 
      addresses = geocoder.getFromLocation(loc.getLatitude(), 
        loc.getLongitude(), 1); 
     } catch (IOException e1) { 
      Log.e("LocationSampleActivity", 
        "IO Exception in getFromLocation()"); 
      e1.printStackTrace(); 
      return ("IO Exception trying to get address"); 
     } catch (IllegalArgumentException e2) { 
      // Error message to post in the log 
      String errorString = "Illegal arguments " + 
        Double.toString(loc.getLatitude()) + 
        " , " + 
        Double.toString(loc.getLongitude()) + 
        " passed to address service"; 
      Log.e("LocationSampleActivity", errorString); 
      e2.printStackTrace(); 
      return errorString; 
     } 
     // If the reverse geocode returned an address 
     if (addresses != null && addresses.size() > 0) { 
      // Get the first address 
      Address address = addresses.get(0); 
      /* 
      * Format the first line of address (if available), 
      * city, and country name. 
      */ 
      String addressText = String.format(
        "%s, %s, %s", 
        // If there's a street address, add it 
        address.getMaxAddressLineIndex() > 0 ? 
          address.getAddressLine(0) : "", 
        // Locality is usually a city 
        address.getLocality(), 
        // The country of the address 
        address.getCountryName()); 
      // Return the text 
      return addressText; 
     } else { 
      return "No address found"; 
     } 
    } 

    @Override 
    protected void onPostExecute(String address) { 
     // Set activity indicator visibility to "gone" 
     mActivityIndicator.setVisibility(View.GONE); 
     // Display the results of the lookup. 
     mAddress.setText(address); 
    } 
} 

public void getAddress(View v) { 
    // Ensure that a Geocoder services is available 
    if (Build.VERSION.SDK_INT >= 
      Build.VERSION_CODES.GINGERBREAD 
      && 
      Geocoder.isPresent()) { 
     // Show the activity indicator 
     mActivityIndicator.setVisibility(View.VISIBLE); 
     /* 
     * Reverse geocoding is long-running and synchronous. 
     * Run it on a background thread. 
     * Pass the current location to the background task. 
     * When the task finishes, 
     * onPostExecute() displays the address. 
     */ 
     (new GetAddressTask(this)).execute(mLastLocation); 
    } 
} 
+0

第一:请检查空在doInBackground。您获得最后位置的电话并不能保证它始终返回值。尽管如此,这不是一个好的做法。考虑在onConmected()中创建LocationRequest,并请求位置回调/侦听器,并在onLocationChanged(Location loc)中获取您的位置/运行getAddress方法。关于实施情况,请立即通知Google –

回答

1

除非GoogleApiClient处于连接状态,否则API调用将失败。您请求它在onStart中连接并且它是异步连接的。你显然不应该在onStart中放置一个随机延迟,而且你不应该在AsyncTask中这样做,因为这将是片状的。

在发生onConnected回调时(或之后)发起您的API调用。也许使用条件逻辑,这样如果您的应用程序恢复,则不会再次进行呼叫。

0

既然这是一个直接的答案,我会在这里发表。

简而言之:请看看我的要点

https://gist.github.com/2022a4d2c21d73f042eb

释:

GoogleApiClient成功连接到谷歌的服务后,它不能获得一眨不眨的完整信息,您应该意识到这一点。所以基本上,您会希望向您要使用的API(FuseLocation API,Google Fit API ...)发出请求。而onConnected()方法是您开始请求的地方。 GoogleAPIClient为您提供的每个API都将以自己的方式实现回调,您也应该查看文档。所以请考虑看看我的要点,并提供反馈,如果它的工作。

0

执行下列操作(顺便说一句,我试图以正确的格式输入代码,但它不会采取很抱歉,如果下面看起来邋遢):

  1. 在的onCreate,请设置您GoogleApiClient :

    mGoogleApiClient = new GoogleApiClient.Builder(this) 
         .addConnectionCallbacks(this) 
         .addOnConnectionFailedListener(this) 
         .addApi(LocationServices.API) 
         .build(); 
    
    mLocationRequest = LocationRequest.create() 
         .setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY) 
         .setInterval(10000).setFastestInterval(5000); 
    
  2. 处理通信/的onResume,连接到您的GoogleApiClient:

    mGoogleApiClient.connect();

  3. 在的onPause,从GoogleApiClient断开:

    if (mGoogleApiClient.isConnected()) { 
        LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this); 
        mGoogleApiClient.disconnect(); 
    } 
    
  4. 在的onConnect回调方法,执行以下操作:

    LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient,mLocationRequest,FragmentPostActivity。这个);

  5. 在onLocationChanged,让你的位置,然后断开:

    公共无效onLocationChanged(位置定位){

    mLastLocation = location; 
    if (mGoogleApiClient.isConnected() && mLastLocation != null) { 
        Log.e("LocationChanged", String.valueOf(location.getLatitude()) + " Longitude: " + String.valueOf(location.getLongitude())); 
        LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this); 
        mGoogleApiClient.disconnect(); 
    } 
    

    }