2017-09-29 137 views
26

我無法弄清楚,爲什麼LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient,mLocationRequest, this);「FusedLocationApi」是劃掉,並在其說法已經過時點。 Click here to view Image的Android LocationServices.FusedLocationApi棄用

import android.location.Location; 
import android.location.LocationListener; 
import android.support.annotation.NonNull; 
import android.support.annotation.Nullable; 
import android.support.v4.app.FragmentActivity; 
import android.os.Bundle; 

import com.google.android.gms.common.ConnectionResult; 
import com.google.android.gms.common.api.GoogleApiClient; 
import com.google.android.gms.location.LocationRequest; 
import com.google.android.gms.location.LocationServices; 
import com.google.android.gms.maps.CameraUpdateFactory; 
import com.google.android.gms.maps.GoogleMap; 
import com.google.android.gms.maps.OnMapReadyCallback; 
import com.google.android.gms.maps.SupportMapFragment; 
import com.google.android.gms.maps.model.LatLng; 
import com.google.android.gms.maps.model.MarkerOptions; 

public class MaintainerMapActivity extends FragmentActivity implements OnMapReadyCallback, GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener{ 

private GoogleMap mMap; 
GoogleApiClient mGoogleApiClient; 
Location mLastLocaton; 
LocationRequest mLocationRequest; 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_maintainer_map2); 
    // Obtain the SupportMapFragment and get notified when the map is ready to be used. 
    SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager() 
      .findFragmentById(R.id.map); 
    mapFragment.getMapAsync(this); 
} 


@Override 
public void onMapReady(GoogleMap googleMap) { 
    mMap = googleMap; 

    // Add a marker in Sydney and move the camera 
    LatLng sydney = new LatLng(-34, 151); 
    mMap.addMarker(new MarkerOptions().position(sydney).title("Marker in Sydney")); 
    mMap.moveCamera(CameraUpdateFactory.newLatLng(sydney)); 
} 

@Override 
public void onLocationChanged(Location location) { 

} 

@Override 
public void onStatusChanged(String provider, int status, Bundle extras) { 

} 

@Override 
public void onProviderEnabled(String provider) { 

} 

@Override 
public void onProviderDisabled(String provider) { 

} 

@Override 
public void onConnected(@Nullable Bundle bundle) { 
    mLocationRequest = new LocationRequest(); 
    mLocationRequest.setInterval(1000); 
    mLocationRequest.setFastestInterval(1000); 
    mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY); 

    LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient,mLocationRequest, this); 
} 

@Override 
public void onConnectionSuspended(int i) { 

} 

@Override 
public void onConnectionFailed(@NonNull ConnectionResult connectionResult) { 

} 

}

+0

如果是不推薦使用,請檢查我使用的是LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient,mLocationRequest,this); –

+0

你能解釋一下你的問題 –

+0

@OmarHayat FusedLocationApi被交叉出 – vvvv

回答

61

最新的更新(11月21日):警告已經不復存在了。Google Play services 11.6 November 6, 2017, release note說:Fixed FusedLocationProviderClient issue that occasionally caused crashes when Google Play services updated.我認爲,當它在後臺自行更新播放服務不會崩潰。所以我們現在可以使用新的FusedLocationProviderClient

重要更新(10月24日):**昨天谷歌更新了其官方的開發頁面a warning,說

請繼續使用FusedLocationProviderApi上課不遷移到FusedLocationProviderClient直到類谷歌Play服務版本12.0.0是可用的,預計2018年年初面市。使用FusedLocationProviderClient版本12.0.0導致客戶端應用程序崩潰時,谷歌Play服務更新的設備上了。對此造成的任何不便,我們深表歉意。

enter image description here 所以我認爲我們應該繼續使用過時的LocationServices.FusedLocationApi直到谷歌解決這個問題。

原來的答案

這是發生,因爲棄用最近版本的谷歌播放服務FusedLocationProviderApi。你可以檢查它here。官方指南現建議使用FusedLocationProviderClient。你可以找到詳細的指南here

爲e.g內onCreate()創建FusedLocationProviderClient實例

mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this); 

,並請求最後已知位置的所有你所要做的就是調用

mFusedLocationClient.getLastLocation() 
    .addOnSuccessListener(this, new OnSuccessListener<Location>() { 
     @Override 
     public void onSuccess(Location location) { 
      // Got last known location. In some rare situations, this can be null. 
      if (location != null) { 
       // Logic to handle location object 
      } 
     } 
    }); 

簡單,不是嗎?

+0

謝謝你現在的作品:) – vvvv

+0

哈哈一直在找四周不知道如何標記爲答案XD – vvvv

+0

@vvvv你不應該把這個標記爲答案嗎?因爲我很確定很多人會在不久的將來面對這個問題,你的問題和這個答案可以幫助他們找到正確的解決方案。 –

0

是的,它是過時!
下面是在使用新FusedLocationProviderClient你需要一些點。

  1. 導入爲進口com.google.android.gms.location.FusedLocationProviderClient;
  2. 我注意到你正在實施LocationListener接口。在mFusedLocationClient.requestLocationUpdates()方法中,現在它不會將LocationListener作爲參數。您可以提供LocationCallback。因爲這是一個抽象類,所以你不能像LocationListener那樣實現它。如Google的guide中提到的那樣,製作回撥方法並將其傳遞給Google,而不是「this」。導入爲import com.google.android.gms.location.LocationCallback;
  3. 隨着LocationCallback,你就會有onLocationResult(),而不是onLocationChanged()。它將返回LocationResult對象而不是位置對象。使用LocationResult.getLastLocation()獲取此結果對象中可用的最近位置。將它導入爲import com.google.android.gms.location.LocationResult;
0

爲了理智,我堅持11.2.0。我不明白這個棄用。由於十一月/ 03/2017年,谷歌文檔,至今仍使參考:LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, mListener);

3
// Better to use GoogleApiClient to show device location. I am using this way in my aap. 

    public class SuccessFragment extends Fragment{ 
     private TextView txtLatitude, txtLongitude, txtAddress; 
     private AddressResultReceiver mResultReceiver; 

     //Define fields for Google API Client 
     private FusedLocationProviderClient mFusedLocationClient; 
     private Location lastLocation; 
     private LocationRequest locationRequest; 
     private LocationCallback mLocationCallback; 

     private static final int REQUEST_PERMISSIONS_REQUEST_CODE = 14; 

     @Nullable 
     @Override 
     public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { 
      View view = inflater.inflate(R.layout.fragment_location, container, false); 

      txtLatitude = (TextView) view.findViewById(R.id.txtLatitude); 
      txtLongitude = (TextView) view.findViewById(R.id.txtLongitude); 
      txtAddress = (TextView) view.findViewById(R.id.txtAddress); 

      mResultReceiver = new AddressResultReceiver(null); 
      try { 
       mFusedLocationClient = LocationServices.getFusedLocationProviderClient(getActivity()); 
       mFusedLocationClient.getLastLocation() 
         .addOnSuccessListener(getActivity(), new OnSuccessListener<Location>() { 
          @Override 
          public void onSuccess(Location location) { 
           // Got last known location. In some rare situations this can be null. 
           if (location != null) { 
            // Logic to handle location object 
            txtLatitude.setText(String.valueOf(location.getLatitude())); 
            txtLongitude.setText(String.valueOf(location.getLongitude())); 
            if (mResultReceiver != null) 
             txtAddress.setText(mResultReceiver.getAddress()); 
           } 
          } 
         }); 
       locationRequest = LocationRequest.create(); 
       locationRequest.setInterval(5000); 
       locationRequest.setFastestInterval(1000); 
       if (txtAddress.getText().toString().equals("")) 
        locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY); 
       else 
        locationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY); 

       mLocationCallback = new LocationCallback() { 
        @Override 
        public void onLocationResult(LocationResult locationResult) { 
         for (Location location : locationResult.getLocations()) { 
          // Update UI with location data 
          txtLatitude.setText(String.valueOf(location.getLatitude())); 
          txtLongitude.setText(String.valueOf(location.getLongitude())); 
         } 
        } 

        ; 
       }; 
      } catch (SecurityException ex) { 
       ex.printStackTrace(); 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } 
      return view; 
     } 

     @Override 
     public void onStart() { 
      super.onStart(); 

      if (!checkPermissions()) { 
       startLocationUpdates(); 
       requestPermissions(); 
      } else { 
       getLastLocation(); 
       startLocationUpdates(); 
      } 
     } 

     @Override 
     public void onPause() { 
      stopLocationUpdates(); 
      super.onPause(); 
     } 

     /** 
     * Return the current state of the permissions needed. 
     */ 
     private boolean checkPermissions() { 
      int permissionState = ActivityCompat.checkSelfPermission(getActivity(), 
        Manifest.permission.ACCESS_COARSE_LOCATION); 
      return permissionState == PackageManager.PERMISSION_GRANTED; 
     } 

     private void startLocationPermissionRequest() { 
      ActivityCompat.requestPermissions(getActivity(), 
        new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, 
        REQUEST_PERMISSIONS_REQUEST_CODE); 
     } 


     private void requestPermissions() { 
      boolean shouldProvideRationale = 
        ActivityCompat.shouldShowRequestPermissionRationale(getActivity(), 
          Manifest.permission.ACCESS_COARSE_LOCATION); 

      // Provide an additional rationale to the user. This would happen if the user denied the 
      // request previously, but didn't check the "Don't ask again" checkbox. 
      if (shouldProvideRationale) { 
       Log.i(TAG, "Displaying permission rationale to provide additional context."); 

       showSnackbar(R.string.permission_rationale, android.R.string.ok, 
         new View.OnClickListener() { 
          @Override 
          public void onClick(View view) { 
           // Request permission 
           startLocationPermissionRequest(); 
          } 
         }); 

      } else { 
       Log.i(TAG, "Requesting permission"); 
       // Request permission. It's possible this can be auto answered if device policy 
       // sets the permission in a given state or the user denied the permission 
       // previously and checked "Never ask again". 
       startLocationPermissionRequest(); 
      } 
     } 

     /** 
     * Callback received when a permissions request has been completed. 
     */ 
     @Override 
     public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, 
               @NonNull int[] grantResults) { 
      Log.i(TAG, "onRequestPermissionResult"); 
      if (requestCode == REQUEST_PERMISSIONS_REQUEST_CODE) { 
       if (grantResults.length <= 0) { 
        // If user interaction was interrupted, the permission request is cancelled and you 
        // receive empty arrays. 
        Log.i(TAG, "User interaction was cancelled."); 
       } else if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { 
        // Permission granted. 
        getLastLocation(); 
       } else { 
        // Permission denied. 

        // Notify the user via a SnackBar that they have rejected a core permission for the 
        // app, which makes the Activity useless. In a real app, core permissions would 
        // typically be best requested during a welcome-screen flow. 

        // Additionally, it is important to remember that a permission might have been 
        // rejected without asking the user for permission (device policy or "Never ask 
        // again" prompts). Therefore, a user interface affordance is typically implemented 
        // when permissions are denied. Otherwise, your app could appear unresponsive to 
        // touches or interactions which have required permissions. 
        showSnackbar(R.string.permission_denied_explanation, R.string.settings, 
          new View.OnClickListener() { 
           @Override 
           public void onClick(View view) { 
            // Build intent that displays the App settings screen. 
            Intent intent = new Intent(); 
            intent.setAction(
              Settings.ACTION_APPLICATION_DETAILS_SETTINGS); 
            Uri uri = Uri.fromParts("package", 
              BuildConfig.APPLICATION_ID, null); 
            intent.setData(uri); 
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 
            startActivity(intent); 
           } 
          }); 
       } 
      } 
     } 


     /** 
     * Provides a simple way of getting a device's location and is well suited for 
     * applications that do not require a fine-grained location and that do not need location 
     * updates. Gets the best and most recent location currently available, which may be null 
     * in rare cases when a location is not available. 
     * <p> 
     * Note: this method should be called after location permission has been granted. 
     */ 
     @SuppressWarnings("MissingPermission") 
     private void getLastLocation() { 
      mFusedLocationClient.getLastLocation() 
        .addOnCompleteListener(getActivity(), new OnCompleteListener<Location>() { 
         @Override 
         public void onComplete(@NonNull Task<Location> task) { 
          if (task.isSuccessful() && task.getResult() != null) { 
           lastLocation = task.getResult(); 

           txtLatitude.setText(String.valueOf(lastLocation.getLatitude())); 
           txtLongitude.setText(String.valueOf(lastLocation.getLongitude())); 

          } else { 
           Log.w(TAG, "getLastLocation:exception", task.getException()); 
           showSnackbar(getString(R.string.no_location_detected)); 
          } 
         } 
        }); 
     } 

     private void stopLocationUpdates() { 
      mFusedLocationClient.removeLocationUpdates(mLocationCallback); 
     } 

     private void startLocationUpdates() { 
      if (ActivityCompat.checkSelfPermission(getActivity(), Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(getActivity(), Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { 
       // TODO: Consider calling 
       // ActivityCompat#requestPermissions 
       // here to request the missing permissions, and then overriding 
       // public void onRequestPermissionsResult(int requestCode, String[] permissions, 
       //           int[] grantResults) 
       // to handle the case where the user grants the permission. See the documentation 
       // for ActivityCompat#requestPermissions for more details. 
       return; 
      } 
      mFusedLocationClient.requestLocationUpdates(locationRequest, mLocationCallback, null); 
     } 

     private void showSnackbar(final String text) { 
      if (canvasLayout != null) { 
       Snackbar.make(canvasLayout, text, Snackbar.LENGTH_LONG).show(); 
      } 
     } 


     private void showSnackbar(final int mainTextStringId, final int actionStringId, 
            View.OnClickListener listener) { 
      Snackbar.make(getActivity().findViewById(android.R.id.content), 
        getString(mainTextStringId), 
        Snackbar.LENGTH_INDEFINITE) 
        .setAction(getString(actionStringId), listener).show(); 
     } 
    } 


    // And our fragment_location.xml 

    <?xml version="1.0" encoding="utf-8"?> 
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
      android:id="@+id/locationLayout" 
      android:layout_below="@+id/txtAddress" 
      android:layout_width="match_parent" 
      android:layout_height="@dimen/activity_margin_30dp" 
      android:orientation="horizontal"> 

      <TextView 
       android:id="@+id/txtLatitude" 
       android:layout_width="@dimen/activity_margin_0dp" 
       android:layout_height="@dimen/activity_margin_30dp" 
       android:layout_weight="0.5" 
       android:gravity="center" 
       android:hint="@string/latitude" 
       android:textAllCaps="false" 
       android:textColorHint="@color/colorPrimaryDark" 
       android:textColor="@color/colorPrimaryDark" /> 

      <TextView 
       android:id="@+id/txtLongitude" 
       android:layout_width="@dimen/activity_margin_0dp" 
       android:layout_height="@dimen/activity_margin_30dp" 
       android:layout_weight="0.5" 
       android:gravity="center" 
       android:hint="@string/longitude" 
       android:textAllCaps="false" 
       android:textColorHint="@color/colorPrimary" 
       android:textColor="@color/colorPrimary" /> 
     </LinearLayout> 
0

問題是你的import語句

刪除此>>進口android.location.LocationListener;

add >> import com.google.android.gms.location.LocationListener;