在 TabLayout 中请求权限后,TabLayout 不更新用户位置

TabLayout not updating user location after asking for permissions within TabLayout

我设法将 Google 地图 API 合并到 TabLayout 中,但它有 2 个问题。一种是该应用程序立即询问用户位置,一种是授予权限但不显示新的更新位置。 谁能帮帮我?

主要活动

public class MainActivity extends AppCompatActivity
        implements NavigationView.OnNavigationItemSelectedListener{

    private Toolbar toolbar;
    private TabLayout tabLayout;
    private ViewPager viewPager;
    private PagerAdapter pagerAdapter;
    private DrawerLayout drawerLayout;
    //private ViewPagerAdapter viewPagerAdapter;
    private String[] pageTitle = {"myPlanner", "News", "Parking"};
    private String studyRooms = "http://library2.csumb.edu/mrbs/mobilenow.php";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);


        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        drawerLayout = (DrawerLayout) findViewById(R.id.drawerLayout);
        setSupportActionBar(toolbar);

        //create default navigation drawer toggle
        ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(this, drawerLayout, toolbar,
                R.string.navigation_drawer_open, R.string.navigation_drawer_close);
        drawerLayout.addDrawerListener(toggle);
        toggle.syncState();


        tabLayout = (TabLayout) findViewById(R.id.tab_layout);
        tabLayout.setupWithViewPager(viewPager);
        for (int i = 0; i < 3; i++) {
            //TabLayout.Tab tab = tabLayout.getTabAt(i);
            //tab.setCustomView(pagerAdapter.getTabView(i));
            tabLayout.addTab(tabLayout.newTab().setText(pageTitle[i]));
        }

        //set gravity for tab bar
        tabLayout.setTabGravity(TabLayout.GRAVITY_FILL);
        //handling navigation view item event
        NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
        assert navigationView != null;
        navigationView.setNavigationItemSelectedListener(this);

        viewPager = (ViewPager)findViewById(R.id.view_pager);
        pagerAdapter = new PagerAdapter(getSupportFragmentManager(), MainActivity.this);
        viewPager.setAdapter(pagerAdapter);


        //setting Tab layout (number of Tabs = number of ViewPager pages)
        viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
        viewPager.setOffscreenPageLimit(3);
        tabLayout.addOnTabSelectedListener(new TabLayout.ViewPagerOnTabSelectedListener(viewPager));

    }

    class PagerAdapter extends FragmentPagerAdapter{

        String tabTitles[] = new String[]{"myPlanner", "News", "Parking"};
        public Fragment[] fragments = new Fragment[tabTitles.length];
        Context context;

        public PagerAdapter(FragmentManager fm, Context context){
            super(fm);
            this.context = context;
        }

        @Override
        public int getCount(){
            return tabTitles.length;
        }

        @Override
        public Fragment getItem(int position){
            switch (position){
                case 0:
                    return new myPlanner();
                case 1:
                    return new News();
                case 2:
                    return new MapsFragment();
            }
            return null;
        }

        public View getTabView(int position) {
            View tab = LayoutInflater.from(MainActivity.this).inflate(R.layout.custom_tab, null);
            TextView tv = (TextView) tab.findViewById(R.id.custom_text);
            tv.setText(tabTitles[position]);
            return tab;
        }


        @Override
        public CharSequence getPageTitle(int position){
            //Generate title based on item position
            return tabTitles[position];
        }

        @Override
        public Object instantiateItem(ViewGroup container, int position){
            Fragment createdFragment = (Fragment)super.instantiateItem(container,position);
            fragments[position] = createdFragment;
            return createdFragment;
        }

    }

    @Override
    public void onRequestPermissionsResult(int requestCode, String permissions[],int[] grantResults){

        if(requestCode == MapsFragment.MY_PERMISSIONS_REQUEST_LOCATION){
            MapsFragment mapFragment = (MapsFragment) pagerAdapter.fragments[2];
            if(mapFragment != null){
                mapFragment.onRequestPermissionsResult(requestCode,permissions,grantResults);
            }
        }
        else{
            super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        }
    }



    /*
    Method for the navigation Drawer that takes in the id from the navigation drawer
    and based on the view, an action will be performed.
     */
    @Override
    public boolean onNavigationItemSelected(MenuItem item) {
        int id = item.getItemId();

        if (id == R.id.DinningCommonsItem) {
            viewPager.setCurrentItem(0);
        } else if (id == R.id.LibraryStudyRooms) {
            Uri uri = Uri.parse(studyRooms);
            Intent intent = new Intent(Intent.ACTION_VIEW, uri);
            startActivity(intent);
           // viewPager.setCurrentItem(1);
        } else if (id == R.id.MapYourRoute) {
            viewPager.setCurrentItem(2);
        } else if (id == R.id.CampusPD) {
            Intent i = new Intent(Intent.ACTION_DIAL, Uri.parse("tel:" + "18316550268"));
            i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            startActivity(i);

        } else if (id == R.id.close) {
            finish();
        }
        drawerLayout.closeDrawer(GravityCompat.START);
        return true;
    }

    @Override
    public void onBackPressed() {
        assert drawerLayout != null;
        if (drawerLayout.isDrawerOpen(GravityCompat.START)) {
            drawerLayout.closeDrawer(GravityCompat.START);
        } else {
            super.onBackPressed();
        }
    }

}

MapsFragment

public class MapsFragment extends SupportMapFragment implements OnMapReadyCallback,GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener, LocationListener{

    GoogleMap mGoogleMap;
    LocationRequest mLocationRequest;
    GoogleApiClient mGoogleApiClient;
    Location mLastLocation;
    Marker mCurrLocationMarker;

    MapView mMapView;
    View mView;
    LocationManager locationManager;
    static final int REQUEST_LOCATION = 1;

    @Override
    public void onResume() {
        super.onResume();
        Log.d("MapsFragment", "Inside onResume");
        setUpMapIfNeeded();
    }

    private void setUpMapIfNeeded() {
        Log.d("MapsFragment", "Inside setUpMapIfNeeded");

        if (mGoogleMap == null) {
            getMapAsync(this);
        }
    }

    //This method gets called when the activity's view is obstructed.
    @Override
    public void onPause() {
        super.onPause();
        Log.d("MapsFragment", "Inside onPause");

        //mMapView.onPause();
        //Stop location updates when Activity is no longer active
        if(mGoogleApiClient != null){
            LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient,this);
        }
    }

    //Call back method for when map is ready to be used.
    @Override
    public void onMapReady(GoogleMap googleMap){
        Log.d("MapsFragment", "Inside onMapReady");

        mGoogleMap =  googleMap;
        mGoogleMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);

        //Initialize Google Play Services
        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M){
            if(ContextCompat.checkSelfPermission(getActivity(),
                    Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED){
                //Location Permission already granted
                buildGoogleApiClient();
                mGoogleMap.setMyLocationEnabled(true);
            }else{
                //Request location permission
                checkLocationPermission();
            }
        }
        else{
            buildGoogleApiClient();
            mGoogleMap.setMyLocationEnabled(true);
        }
    }


    private void buildGoogleApiClient() {
        Log.d("MapsFragment", "Inside buildGoogleApiClient");

        mGoogleApiClient = new GoogleApiClient.Builder(getActivity())
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .addApi(LocationServices.API)
                .build();
        mGoogleApiClient.connect();
    }

    //After calling connect(), this method will be invoked asynch when the
    //connect request has successfully completed.
    @Override
    public void onConnected(@Nullable Bundle bundle) {
        Log.d("MapsFragment", "Inside onConnected");

        mLocationRequest =  new LocationRequest();
        mLocationRequest.setInterval(1000);
        mLocationRequest.setFastestInterval(1000);
        mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);

        if(ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.ACCESS_FINE_LOCATION)
                == PackageManager.PERMISSION_GRANTED){
            LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient,
                    mLocationRequest, this);
        }
    }

    @Override
    public void onConnectionSuspended(int i) {

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

    }

    @Override
    public void onLocationChanged(Location location) {
        Log.d("MapsFragment", "Inside onLocationChanged");

        mLastLocation = location;
        if(mCurrLocationMarker != null){
            mCurrLocationMarker.remove();
        }

        //Place current location marker
        LatLng latLng = new LatLng(location.getLatitude(),location.getLongitude());
        MarkerOptions markerOptions = new MarkerOptions();
        markerOptions.position(latLng);
        markerOptions.title("Current Position");
        markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_MAGENTA));
        mCurrLocationMarker = mGoogleMap.addMarker(markerOptions);

        //Move map Camera
        mGoogleMap.moveCamera(CameraUpdateFactory.newLatLng(latLng));
        mGoogleMap.animateCamera(CameraUpdateFactory.zoomBy(11));

        //Optionally, stop location updates if only current location is needed
        if(mGoogleApiClient != null){
            LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient,this);
        }
    }

    public static final int MY_PERMISSIONS_REQUEST_LOCATION = 99;

    private void checkLocationPermission() {
        Log.d("MapsFragment", "Inside checkLocationPermission");

        if(ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.ACCESS_FINE_LOCATION)
                != PackageManager.PERMISSION_GRANTED){
            //Should we show an explanation?
            if(ActivityCompat.shouldShowRequestPermissionRationale(getActivity(),
                    Manifest.permission.ACCESS_FINE_LOCATION)){

                //Show an explanation to the user *asyncly* -- dont block
                //this thread waiting for the user's response! After the user
                //sees the explanation try again to request the permission
                new AlertDialog.Builder(getActivity())
                        .setTitle("Location permission needed")
                        .setMessage("This app needs the Location permission, please accept to use location functionality")
                        .setPositiveButton("OK", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int i) {
                                //prompt the user once the explanation has been shown
                                ActivityCompat.requestPermissions(getActivity(),
                                        new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
                                        MY_PERMISSIONS_REQUEST_LOCATION);
                            }
                        })
                        .create()
                        .show();
            }
            else{
                //NO explanation needed, we can request the permission.
                ActivityCompat.requestPermissions(getActivity(),
                        new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
                        MY_PERMISSIONS_REQUEST_LOCATION);
            }
        }
    }


    @Override
    public void onRequestPermissionsResult(int requestCode, String permissions[]
            , int[] grantResults){
        Log.d("MapsFragment", "Inside onRequestPermissionsResult");

        switch (requestCode){
            case MY_PERMISSIONS_REQUEST_LOCATION:{
                //If request is cancelled, the results arrays are empty
                if(grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED){
                    //Permission was granted do the location-related task you need to do.
                    if(ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.ACCESS_FINE_LOCATION)
                            == PackageManager.PERMISSION_GRANTED){

                        if(mGoogleApiClient == null){
                            buildGoogleApiClient();
                        }
                        mGoogleMap.setMyLocationEnabled(true);
                    }
                }
                else{
                    //permissions were denied. Disable the functionality that depends onthis permission
                    Toast.makeText(getActivity(), "Permission denied",Toast.LENGTH_LONG).show();
                }
                return;
            }//Other case lines to check for other permissions this app might request
        }

    }

请试试这个 class,它工作正常。

public class MapsFragmentDemo extends com.google.android.gms.maps.MapFragment implements OnMapReadyCallback, GoogleApiClient.ConnectionCallbacks,
    GoogleApiClient.OnConnectionFailedListener, LocationListener {


private static final int REQUEST_LOCATION = 1;
private final int REQUEST_CHECK_SETTINGS = 300;
GoogleMap mGoogleMap;
LocationRequest mLocationRequest;
GoogleApiClient mGoogleApiClient;
Location mLastLocation;
Marker mCurrLocationMarker;
boolean isFragmentVisible = false;
private LocationSettingsRequest.Builder builder;
private PendingResult<LocationSettingsResult> result;

@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
    super.setUserVisibleHint(isVisibleToUser);
    if (isVisibleToUser) {
        isFragmentVisible = true;
        Log.d("MapsFragment", "Inside Visible");
        getMapAsync(this);
        createLocationRequest();
        buildGoogleApiClient();

    }
}


protected void createLocationRequest() {
    mLocationRequest = new LocationRequest();
    mLocationRequest.setInterval(1000);
    mLocationRequest.setFastestInterval(1000);
    mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
    mLocationRequest.setSmallestDisplacement(.5f);

}


@Override
public void onResume() {
    super.onResume();
    Log.d("MapsFragment", "Inside onResume");
    if (isFragmentVisible) {
        Log.d("MapsFragment", "Inside onResume true");
        if (mGoogleApiClient != null && mGoogleApiClient.isConnected()) {
            if (checkAccessPermission())
                startLocationUpdates();

            else
                askForPermission();
        }
    }
}

@Override
public void onPause() {
    super.onPause();
    Log.d("MapsFragment", "Inside onPause");
    stopLocationUpdates();
}

@Override
public void onStop() {
    super.onStop();
    Log.d("MapsFragment", "onStop fired ..............");
    if (mGoogleApiClient != null && !mGoogleApiClient.isConnected())
        mGoogleApiClient.disconnect();

}

protected void stopLocationUpdates() {
    if (mGoogleApiClient != null)
        LocationServices.FusedLocationApi.removeLocationUpdates(
                mGoogleApiClient, this);
}

protected void startLocationUpdates() {
    if (mGoogleApiClient != null) {

        accessLocation();
    }
}

private boolean checkAccessPermission() {
    return (ContextCompat.checkSelfPermission(getActivity(), android.Manifest.permission.ACCESS_FINE_LOCATION)
            == PackageManager.PERMISSION_GRANTED);
}

@SuppressWarnings("MissingPermission")
private void accessLocation() {
    LocationServices.FusedLocationApi.requestLocationUpdates(
            mGoogleApiClient, mLocationRequest, this);
    if (mGoogleMap != null)
        mGoogleMap.setMyLocationEnabled(true);
}

private void askForPermission() {
    // Should we show an explanation?
    if (android.support.v4.app.ActivityCompat.shouldShowRequestPermissionRationale(getActivity(),
            android.Manifest.permission.ACCESS_FINE_LOCATION)) {
        new AlertDialog.Builder(getActivity())
                .setTitle("Location permission needed")
                .setMessage("This app needs the Location permission, please accept to use location functionality")
                .setPositiveButton("OK", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int i) {
                        //prompt the user once the explanation has been shown
                        FragmentCompat.requestPermissions(MapsFragmentDemo.this,
                                new String[]{android.Manifest.permission.ACCESS_FINE_LOCATION},
                                REQUEST_LOCATION);
                    }
                })
                .create()
                .show();
    } else
        FragmentCompat.requestPermissions(MapsFragmentDemo.this,
                new String[]{android.Manifest.permission.ACCESS_FINE_LOCATION},
                REQUEST_LOCATION);
}


//Call back method for when map is ready to be used.
@Override
public void onMapReady(GoogleMap googleMap) {
    Log.d("MapsFragment", "Inside onMapReady");

    mGoogleMap = googleMap;
    mGoogleMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);


}

private void buildGoogleApiClient() {
    Log.d("MapsFragment", "Inside buildGoogleApiClient");

    mGoogleApiClient = new GoogleApiClient.Builder(getActivity())
            .addConnectionCallbacks(this)
            .addOnConnectionFailedListener(this)
            .addApi(LocationServices.API)
            .build();
    mGoogleApiClient.connect();
}


@Override
public void onConnected(@Nullable Bundle bundle) {
    Log.d("MapsFragment", "Inside onConnected");

    builder = new LocationSettingsRequest.Builder().addLocationRequest(mLocationRequest);
    result = LocationServices.SettingsApi.checkLocationSettings(mGoogleApiClient, builder.build());
    result.setResultCallback(new ResultCallback<LocationSettingsResult>() {
        @Override
        public void onResult(LocationSettingsResult result) {
            final Status status = result.getStatus();
            final LocationSettingsStates mState = result.getLocationSettingsStates();
            switch (status.getStatusCode()) {
                case LocationSettingsStatusCodes.SUCCESS:
                    if (!checkAccessPermission()) {

                        askForPermission();

                    } else
                        startLocationUpdates();
                    break;
                case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
                    try {
                        status.startResolutionForResult(getActivity(), REQUEST_CHECK_SETTINGS);
                    } catch (IntentSender.SendIntentException e) {
                    }
                    break;
                case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
                    break;
            }
        }
    });


}

public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    switch (requestCode) {
        case REQUEST_CHECK_SETTINGS:
            switch (resultCode) {
                case Activity.RESULT_OK:
                    if (!checkAccessPermission()) {

                        askForPermission();

                    } else
                        startLocationUpdates();
                    break;
                case Activity.RESULT_CANCELED:

                    break;
            }
            break;
    }
}

@Override
public void onConnectionSuspended(int i) {

}

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

}

@Override
public void onLocationChanged(Location location) {
    mGoogleMap.clear();
    Log.d("MapsFragment", "Inside onLocationChanged");
    LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude());

    MarkerOptions markerOptions = new MarkerOptions();
    markerOptions.position(latLng);
    markerOptions.title("Current Position");
    markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_MAGENTA));
    Marker currLocationMarker = mGoogleMap.addMarker(markerOptions);


    CameraPosition cameraPosition = new CameraPosition.Builder()
            .target(latLng).zoom(14).build();


    mGoogleMap.animateCamera(CameraUpdateFactory
            .newCameraPosition(cameraPosition));

    //Optionally, stop location updates if only current location is needed
    if (mGoogleApiClient != null) {
        stopLocationUpdates();
    }

}

@Override
public void onRequestPermissionsResult(int requestCode, String permissions[]
        , int[] grantResults) {
    Log.d("MapsFragment", "Inside onRequestPermissionsResult");

    switch (requestCode) {
        case REQUEST_LOCATION: {
            //If request is cancelled, the results arrays are empty
            if (grantResults.length > 0
                    && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                // permission was granted
                accessLocation();
            } else {
                // permission was denied
                Toast.makeText(getActivity(), "Permission denied", Toast.LENGTH_LONG).show();
            }
            return;
        }//Other case lines to check for other permissions this app might request
    }

}

}