com.google.samples.apps.iosched.map.MapActivity.java Source code

Java tutorial

Introduction

Here is the source code for com.google.samples.apps.iosched.map.MapActivity.java

Source

/*
 * Copyright 2014 Google Inc. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.google.samples.apps.iosched.map;

import android.Manifest;
import android.app.FragmentManager;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.design.widget.Snackbar;
import android.support.v4.app.ActivityCompat;
import android.support.v7.widget.Toolbar;
import android.view.MenuItem;
import android.view.View;

import com.google.samples.apps.iosched.R;
import com.google.samples.apps.iosched.navigation.NavigationModel;
import com.google.samples.apps.iosched.provider.ScheduleContract;
import com.google.samples.apps.iosched.ui.BaseActivity;
import com.google.samples.apps.iosched.util.AnalyticsHelper;
import com.google.samples.apps.iosched.util.PermissionsUtils;

import static com.google.samples.apps.iosched.util.LogUtils.makeLogTag;

/**
 * Activity that displays a {@link com.google.samples.apps.iosched.map.MapFragment} and a {@link
 * com.google.samples.apps.iosched.map.MapInfoFragment}. Supports 'detached' mode, where the toolbar
 * contains an up navigation option that finishes this Activity. (see {@link #EXTRA_DETACHED_MODE}
 * Optionally a room can be specified via {@link #EXTRA_ROOM} that pans the map to its indicated
 * marker.
 *
 * @see com.google.samples.apps.iosched.map.MapInfoFragment#newInstace(android.content.Context)
 */
public class MapActivity extends BaseActivity implements SlideableInfoFragment.Callback, MapFragment.Callbacks,
        ActivityCompat.OnRequestPermissionsResultCallback {

    private static final String TAG = makeLogTag(MapActivity.class);

    private static final int REQUEST_LOCATION_PERMISSION = 1;

    public static final String[] PERMISSIONS = new String[] { Manifest.permission.ACCESS_FINE_LOCATION };

    private static final String SCREEN_LABEL = "Map";

    /**
     * When specified, will automatically point the map to the requested room.
     */
    public static final String EXTRA_ROOM = "com.google.android.iosched.extra.ROOM";

    public static final String EXTRA_DETACHED_MODE = "com.google.samples.apps.iosched.EXTRA_DETACHED_MODE";

    public static final String BUNDLE_STATE_MAPVIEW = "mapview";

    private boolean mDetachedMode;

    protected MapFragment mMapFragment;

    private MapInfoFragment mInfoFragment;

    private View mInfoContainer;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        FragmentManager fm = getFragmentManager();
        mMapFragment = (MapFragment) fm.findFragmentByTag("map");

        mDetachedMode = getIntent().getBooleanExtra(EXTRA_DETACHED_MODE, false);

        if (isFinishing()) {
            return;
        }

        setContentView(R.layout.map_act);
        mInfoContainer = findViewById(R.id.map_detail_popup);

        // ANALYTICS SCREEN: View the Map screen on a phone
        // Contains: Nothing (Page name is a constant)
        AnalyticsHelper.sendScreenView(SCREEN_LABEL);

        overridePendingTransition(0, 0);
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        // Save the mapview state in a separate bundle parameter
        final Bundle mapviewState = new Bundle();
        mMapFragment.onSaveInstanceState(mapviewState);
        outState.putBundle(BUNDLE_STATE_MAPVIEW, mapviewState);
    }

    @Override
    protected void onPostCreate(Bundle savedInstanceState) {
        super.onPostCreate(savedInstanceState);
        if (mDetachedMode) {
            final Toolbar toolbar = getToolbar();
            toolbar.setNavigationIcon(R.drawable.ic_up);
            toolbar.setNavigationOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    finish();
                }
            });
        }

        if (mMapFragment == null) {
            // Either restore the state of the map or read it from the Intent extras.
            if (savedInstanceState != null) {
                // Restore state from existing bundle
                Bundle previousState = savedInstanceState.getBundle(BUNDLE_STATE_MAPVIEW);
                mMapFragment = MapFragment.newInstance(previousState);
            } else {
                // Get highlight room id (if specified in intent extras)
                final String highlightRoomId = getIntent().hasExtra(EXTRA_ROOM)
                        ? getIntent().getExtras().getString(EXTRA_ROOM)
                        : null;
                mMapFragment = MapFragment.newInstance(highlightRoomId);
            }
            getFragmentManager().beginTransaction().add(R.id.fragment_container_map, mMapFragment, "map").commit();
        }

        if (mInfoFragment == null) {
            mInfoFragment = MapInfoFragment.newInstace(this);
            getFragmentManager().beginTransaction().add(R.id.fragment_container_map_info, mInfoFragment, "mapsheet")
                    .commit();
        }

        mDetachedMode = getIntent().getBooleanExtra(EXTRA_DETACHED_MODE, false);

        attemptEnableMyLocation();
    }

    @Override
    public void onBackPressed() {
        if (mInfoFragment != null && mInfoFragment.isExpanded()) {
            mInfoFragment.minimize();
        } else {
            super.onBackPressed();
        }
    }

    @Override
    protected NavigationModel.NavigationItemEnum getSelfNavDrawerItem() {
        return mDetachedMode ? NavigationModel.NavigationItemEnum.INVALID : NavigationModel.NavigationItemEnum.MAP;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        if (getIntent().getBooleanExtra(EXTRA_DETACHED_MODE, false) && item.getItemId() == android.R.id.home) {
            finish();
        }
        return super.onOptionsItemSelected(item);
    }

    /**
     * Adjust the padding in the map fragment when the info fragment has been resized. The size is
     * self reported from the fragment and has to be adjusted before it can be applied to the map.
     * <p/>
     * For {@link com.google.samples.apps.iosched.map.InlineInfoFragment} (that is only displayed on
     * the left of the screen), the full extend of its container layout (including padding) is
     * passed to the map fragment. For {@link com.google.samples.apps.iosched.map
     * .SlideableInfoFragment} (that is only displayed at the bottom of the screen), its actual
     * height is passed through to the map.
     */
    @Override
    public void onInfoSizeChanged(int left, int top, int right, int bottom) {
        if (mMapFragment != null) {
            if (mInfoFragment instanceof InlineInfoFragment) {
                // InlineInfoFragment is shown on the left on tablet layouts.
                // Use the right edge of its containers for padding of the map.
                //TODO: RTL support - compare left and right positioning
                if (right > 0) {
                    mMapFragment.setMapInsets(mInfoContainer.getRight(), 0, 0, 0);
                } else {
                    mMapFragment.setMapInsets(0, 0, 0, 0);
                }
            } else if (mInfoFragment instanceof SlideableInfoFragment) {
                // SlideableInfoFragment is only shown on phone layouts at the bottom of the screen,
                // but only up to 50% of the total height of the screen
                if ((float) top / (float) bottom > SlideableInfoFragment.MAX_PANEL_PADDING_FACTOR) {

                    mMapFragment.setMapInsets(0, 0, 0, bottom - top);
                }
                final int bottomPadding = Math.min(bottom - top,
                        Math.round(bottom * SlideableInfoFragment.MAX_PANEL_PADDING_FACTOR));
                mMapFragment.setMapInsets(0, 0, 0, bottomPadding);
            }
            // F
        }
    }

    @Override
    public void onSessionClicked(String sessionId) {
        // ANALYTICS EVENT: Click on a session in the Maps screen.
        // Contains: The session ID.
        AnalyticsHelper.sendEvent(SCREEN_LABEL, "selectsession", sessionId);
        startActivity(new Intent(Intent.ACTION_VIEW, ScheduleContract.Sessions.buildSessionUri(sessionId)));
    }

    @Override
    public void onInfoShowVenue() {
        if (mInfoFragment != null) {
            mInfoFragment.showVenue();
        }
        setTabletInfoVisibility(View.VISIBLE);

    }

    @Override
    public void onInfoShowTitle(String label, int icon) {
        if (mInfoFragment != null) {
            mInfoFragment.showTitleOnly(icon, label);
        }
        setTabletInfoVisibility(View.VISIBLE);

    }

    @Override
    public void onInfoShowSessionlist(String roomId, String roomTitle, int roomType) {
        if (mInfoFragment != null) {
            mInfoFragment.showSessionList(roomId, roomTitle, roomType);
        }
        setTabletInfoVisibility(View.VISIBLE);

    }

    @Override
    public void onInfoShowFirstSessionTitle(String roomId, String roomTitle, int roomType) {
        if (mInfoFragment != null) {
            mInfoFragment.showFirstSessionTitle(roomId, roomTitle, roomType);
        }
        setTabletInfoVisibility(View.VISIBLE);
    }

    @Override
    public void onInfoHide() {
        if (mInfoFragment != null) {
            mInfoFragment.hide();
        }
        setTabletInfoVisibility(View.GONE);
    }

    private void setTabletInfoVisibility(int visibility) {
        final View view = findViewById(R.id.map_detail_popup);
        if (view != null) {
            view.setVisibility(visibility);

        }
    }

    /**
     * Enables the 'My Location' feature on the map fragment if the location permission has been
     * granted. If the permission is not available yet, it is requested.
     */
    public void attemptEnableMyLocation() {
        // Check if the permission has already been granted.
        if (PermissionsUtils.permissionsAlreadyGranted(this, PERMISSIONS)) {
            // Permission has been granted.
            if (mMapFragment != null) {
                mMapFragment.setMyLocationEnabled(true);
                return;
            }
        }

        // The permissions have not been granted yet. Request them.
        ActivityCompat.requestPermissions(this, PERMISSIONS, REQUEST_LOCATION_PERMISSION);
    }

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

        if (requestCode != REQUEST_LOCATION_PERMISSION) {
            return;
        }

        if (permissions.length == PERMISSIONS.length && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            // Permission has been granted.
            if (mMapFragment != null) {
                mMapFragment.setMyLocationEnabled(true);
            }
        } else {
            // Permission was denied. Display error message that disappears after a short while.
            PermissionsUtils.displayConditionalPermissionDenialSnackbar(this, R.string.map_permission_denied,
                    PERMISSIONS, REQUEST_LOCATION_PERMISSION, false);

        }
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }
}