在我的應用程序中,我有一個經典的「MyLocationButton」的MapFragment。 在較舊的API上我沒有任何問題,但是因爲Google要求開發者使用運行時權限,所以我遇到了這個問題:當用戶點擊ALLOW時,已經說過的按鈕沒有出現,至少沒有直到用戶刷新這個片段。有沒有辦法讓用戶的媒體在獲得權限後立即刷新片段?Android運行時Permissions:捕捉用戶的新聞「允許」
編輯: 我使用嵌套的片段,我發現我的問題是,你可以在的AOSP Issue Tracker此頁面看到的一樣。我已經使用最新版本的Android API(v24)解決了這個問題。
我會後我的MapFragment:
public class MapFragment extends Fragment implements OnMapReadyCallback, GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener, PetrolStationsArray.PetrolStationsListener {
private GoogleMap mGoogleMap;
private int mMapType;
private static LatLng mPosition;
private static float mZoom;
private CoordinatorLayout mCoordinatorLayout;
private View mLocationButton;
private AppCompatImageButton mTurnGPSOn;
private FragmentManager mFragmentManager;
private FragmentTransaction mFragmentTransaction;
private SupportMapFragment mSupportMapFragment;
private SupportPlaceAutocompleteFragment mSupportPlaceAutocompleteFragment;
private LocalBroadcastManager mLocalBroadcastManager;
private PetrolStationsArray mPetrolStationsArray;
protected LocationRequest mLocationRequest;
protected GoogleApiClient mGoogleApiClient;
Marker mCurrLocationMarker;
private CountDownTimer mDragTimer;
private boolean mTimerIsRunning = false;
// Design pattern to instantiate a new fragment.
public static MapFragment newInstance() {
MapFragment fragment = new MapFragment();
return fragment;
}
/********************************************************/
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Since API 23, Android requests you check for Location Permissions.
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
checkLocationPermission();
}
mMapType = Integer.parseInt(loadPreferences(SETTINGS_PREFERENCES, MAP_KEY));
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_map, container, false);
mLocalBroadcastManager = LocalBroadcastManager.getInstance(getContext());
mPetrolStationsArray = PetrolStationsArray.get();
mDragTimer = new CountDownTimer(DRAG_TIMER_INTERVAL, DRAG_TIMER_INTERVAL + 1) {
@Override
public void onTick(long l) {
}
@Override
public void onFinish() {
mTimerIsRunning = false;
mPetrolStationsArray.setPosition(mPosition);
}
};
return view;
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
// Initialise a new fragment inside of this one.
mFragmentManager = getChildFragmentManager();
mSupportMapFragment = (SupportMapFragment) mFragmentManager.findFragmentByTag(MAP_FRAGMENT_TAG);
mSupportPlaceAutocompleteFragment = (SupportPlaceAutocompleteFragment) mFragmentManager.findFragmentByTag(AUTOCOMPLETE_FRAGMENT_TAG);
mCoordinatorLayout = (CoordinatorLayout) view.findViewById(R.id.coordinator_layout);
/*
** Never inflate fragments inside other fragments in a layout.xml!
** Do it programmatically.
** See here for reference: http://stackoverflow.com/a/19815266/4938112.
*/
if (mSupportMapFragment == null) {
mSupportMapFragment = new SupportMapFragment();
fragmentTransaction(mFragmentManager, mSupportMapFragment, R.id.map_fragment_container, MAP_FRAGMENT_TAG);
}
// Asynchronous thread to load map.
mSupportMapFragment.getMapAsync(this);
if (mSupportPlaceAutocompleteFragment == null) {
mSupportPlaceAutocompleteFragment = new SupportPlaceAutocompleteFragment();
fragmentTransaction(mFragmentManager, mSupportPlaceAutocompleteFragment, R.id.card_view, AUTOCOMPLETE_FRAGMENT_TAG);
}
// Filter for a specific place type.
AutocompleteFilter typeFilter = new AutocompleteFilter.Builder()
.setTypeFilter(AutocompleteFilter.TYPE_FILTER_CITIES | AutocompleteFilter.TYPE_FILTER_ADDRESS)
.build();
mSupportPlaceAutocompleteFragment.setFilter(typeFilter);
mSupportPlaceAutocompleteFragment.setOnPlaceSelectedListener(new PlaceSelectionListener() {
@Override
public void onPlaceSelected(Place place) {
LatLng position = place.getLatLng();
CameraUpdate centre = CameraUpdateFactory.newLatLng(position);
CameraUpdate zoom = CameraUpdateFactory.zoomTo(ZOOM_LEVEL);
mGoogleMap.moveCamera(centre);
mGoogleMap.animateCamera(zoom);
}
@Override
public void onError(Status status) {
Log.d("PLACE_ERROR", "An error occurred: " + status);
}
});
mTurnGPSOn = ((AppCompatImageButton) view.findViewById(R.id.turn_gps_on));
mTurnGPSOn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
// Ask if the user wants to open the GPS - settings.
displayPromptToEnableGPS(getActivity());
}
});
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
}
@Override
public void onMapReady(GoogleMap googleMap) {
this.mGoogleMap = googleMap;
mGoogleMap.setMapType(mMapType);
if (mPosition != null) {
CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLngZoom(mPosition, mZoom);
mGoogleMap.moveCamera(cameraUpdate);
}
mGoogleMap.setTrafficEnabled(true);
mGoogleMap.getUiSettings().setMapToolbarEnabled(false);
mGoogleMap.setOnCameraChangeListener(new GoogleMap.OnCameraChangeListener() {
@Override
public void onCameraChange(CameraPosition cameraPosition) {
mPosition = cameraPosition.target;
mZoom = cameraPosition.zoom;
if (mTimerIsRunning) {
mDragTimer.cancel();
}
mDragTimer.start();
mTimerIsRunning = true;
}
});
// Get the "My Position" button.
mLocationButton = ((View) mSupportMapFragment.getView().findViewById(Integer.parseInt("1")).getParent()).findViewById(Integer.parseInt("2"));
RelativeLayout.LayoutParams rlp = (RelativeLayout.LayoutParams) mLocationButton.getLayoutParams();
Resources r = getActivity().getResources();
int px = (int) TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP,
10,
r.getDisplayMetrics()
);
// Position on right bottom.
rlp.addRule(RelativeLayout.ALIGN_PARENT_TOP, 0);
rlp.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM, RelativeLayout.TRUE);
rlp.setMargins(0, 0, px, px);
turnOnMyLocation();
}
@Override
public void onPause() {
super.onPause();
// Stop location updates when Activity is no longer active.
if (mGoogleApiClient != null && mGoogleApiClient.isConnected()) {
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
}
mPetrolStationsArray.removePetrolStationListener(this);
}
@Override
public void onResume() {
super.onResume();
mPetrolStationsArray.setPetrolStationsListener(this);
}
@Override
public void onListUpdated() {
// Cleaning all the markers.
if (mGoogleMap != null) {
mGoogleMap.clear();
}
List<PetrolStation> petrolStationList = mPetrolStationsArray.getList();
for (PetrolStation petrolStation : petrolStationList) {
double lat = petrolStation.getLat();
double lon = petrolStation.getLon();
String name = petrolStation.getName();
if (mGoogleMap != null) {
mGoogleMap.addMarker(new MarkerOptions()
.position(new LatLng(lat, lon))
.title(name));
}
}
}
@Override
public void onServerRequest() {
}
@Override
public void onConnected(Bundle bundle) {
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(1000);
mLocationRequest.setFastestInterval(1000);
mLocationRequest.setPriority(LocationRequest.PRIORITY_LOW_POWER);
if (ContextCompat.checkSelfPermission(getContext(), Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
}
}
@Override
public void onConnectionSuspended(int i) {
// TODO
}
@Override
public void onConnectionFailed(ConnectionResult connectionResult) {
// TODO
}
@Override
public void onLocationChanged(Location location) {
if (mCurrLocationMarker != null) {
mCurrLocationMarker.remove();
}
// Just a check to overtake the
// 'java.lang.IllegalStateException: Fragment MapFragment{42f519d0} not attached to Activity'
// exception I've encountered.
if (!isAdded()) {
return;
}
// Stop location updates.
if (mGoogleApiClient != null) {
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
}
}
// Start the transaction between different fragments.
private void fragmentTransaction(FragmentManager mFragmentManager, Fragment fragment, int id, String tag) {
mFragmentTransaction = mFragmentManager.beginTransaction();
mFragmentTransaction.add(id, fragment, tag);
mFragmentTransaction.commit();
mFragmentManager.executePendingTransactions();
}
/*********************************************
************ LOCATION PERMISSIONS ************
*********************************************/
@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode) {
case MY_PERMISSIONS_REQUEST_LOCATION: {
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
turnOnMyLocation();
} else {
// Permission denied, boo! Disable the functionality that depends on this permission.
String message = getResources().getString(R.string.permission_denied);
Snackbar snackbar = Snackbar
.make(mCoordinatorLayout, message, Snackbar.LENGTH_LONG)
.setAction(R.string.close_snack_bar, new View.OnClickListener() {
@Override
public void onClick(View view) {
}
});
snackbar.show();
}
}
}
}
// Ask for permission (START DIALOG) in Android APIs >= 23.
public boolean checkLocationPermission() {
if (ContextCompat.checkSelfPermission(getContext(), Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// Should we show an explanation?
if (shouldShowRequestPermissionRationale(Manifest.permission.ACCESS_FINE_LOCATION)) {
// Prompt the user once explanation has been shown.
requestPermissions(new String[] {
Manifest.permission.ACCESS_FINE_LOCATION
}, MY_PERMISSIONS_REQUEST_LOCATION);
} else {
// No explanation needed, we can request the permission.
requestPermissions(new String[] {
Manifest.permission.ACCESS_FINE_LOCATION
}, MY_PERMISSIONS_REQUEST_LOCATION);
}
return false;
} else {
return true;
}
}
public void turnOnMyLocation() {
// Initialise Google Play Services.
if (mGoogleApiClient == null) {
buildGoogleApiClient();
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (ContextCompat.checkSelfPermission(getContext(), Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
mGoogleMap.setMyLocationEnabled(true);
}
} else {
mGoogleMap.setMyLocationEnabled(true);
}
}
// Let's build our Location Services API Client.
protected synchronized void buildGoogleApiClient() {
mGoogleApiClient = new GoogleApiClient
.Builder(getContext())
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
mGoogleApiClient.connect();
}
public static void displayPromptToEnableGPS(final Activity activity) {
final AlertDialog.Builder builder = new AlertDialog.Builder(activity);
final String action = Settings.ACTION_LOCATION_SOURCE_SETTINGS;
final String message = MyFuelApp.getAppContext().getResources().getString(R.string.open_gps_settings);
builder.setMessage(message)
.setPositiveButton(MyFuelApp.getAppContext().getResources().getString(R.string.confirm_ok),
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface d, int id) {
activity.startActivity(new Intent(action));
d.dismiss();
}
})
.setNegativeButton(MyFuelApp.getAppContext().getResources().getString(R.string.deny_no),
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface d, int id) {
d.cancel();
}
});
builder.create().show();
}
}
通常這是通過使用onRequestPermissionsResult函數完成的。 –
我已經嘗試刷新我的_onRequestPermissionsResult_函數中的片段,但我無法真正瞭解如何進行片段刷新。任何提示? 謝謝你的回覆。 – Davide3i
http://stackoverflow.com/questions/20702333/refresh-fragment-at-reload這可能有幫助 – Eenvincible