IT 이모저모

Google Map Fragment 만들기

exien 2018. 5. 9. 16:48

이번에는 Google Map API를 Fragment에서 생성해보겠습니다.

기존의 Activity에서 Google Map 사용하는 법과 다릅니다.

우선 NullPointerException과 함께 오류가 발생할텐데요.


Fragment로 구현하기 위해 MapView를 사용합니다.


Activity와 Fragment XML에서 Map 호출하는 컴포넌트부터 다릅니다.

Activity에서는 com.google.android.gms.maps.SupportMapFragment를 사용합니다.

<fragment

  android:id="@+id/map"

  android:name="com.google.android.gms.maps.SupportMapFragment"

  class="com.google.android.gms.maps.SupportMapFragment"

  android:layout_width="match_parent"

  android:layout_height="match_parent">


Fragment에서는 com.google.android.gms.maps.MapView 를 호출합니다.

<com.google.android.gms.maps.MapView

  android:id="@+id/map"

  android:name="com.google.android.gms.maps.MapFragment"

  android:layout_width="match_parent"

  android:layout_height="match_parent"

  />


첫 기본 Fragment를 생성을 합니다.


public class MapFragment extends Fragment {

  @Override

  public View onCreateView(LayoutInflater inflater, ViewGroup container,

                           Bundle savedInstanceState) {


      View rootView = inflater.inflate(R.layout.fragment_map, container, false);

      return rootView;

  }

}


Google Map을 사용하려면 GoogleMap과 MapView 변수가 필요합니다.

private GoogleMap googleMap;

private MapView mapView;


소스 코드를 추가합니다.

** Create와 Resume을 해줘야합니다. 안하면 아무것도 나타지 않습니다.

Create를 하기 위해서는 Bundle를 받아야 합니다.


** 전체 소스코드는 포스트 하단 부에 있습니다.


@Override

public View onCreateView(LayoutInflater inflater, ViewGroup container,

                       Bundle savedInstanceState) {

  View rootView = inflater.inflate(R.layout.fragment_map2, container, false);

  mapView = (MapView) rootView.findViewById(R.id.map);

  mapView.onCreate(savedInstanceState);

  mapView.onResume();

  mapView.getMapAsync(this);

  return rootView;

  }

}


이어서 추가해야할 소스들입니다.

@Override

public void onSaveInstanceState(Bundle outState) {

  super.onSaveInstanceState(outState);

  mapView.onSaveInstanceState(outState);

}


@Override

public void onResume() {

  super.onResume();

  mapView.onResume();

  initializeMap();

}

@Override

public void onPause() {

  super.onPause();

  mapView.onPause();

}

@Override

public void onDestroy() {

  super.onDestroy();

  mapView.onDestroy();

}

@Override

public void onLowMemory() {

  super.onLowMemory();

  mapView.onLowMemory();

}


액티비티가 처음 생성될 때 실행되는 함수

/** http://joekarl.github.io/2013/11/01/android-map-view-inside-fragment/ */

@Override

public void onActivityCreated(Bundle savedInstanceState) {

  super.onCreate(savedInstanceState);

MapsInitializer.initialize(getActivity().getApplicationContext());


  if (mapView != null) {

      mapView.onCreate(savedInstanceState);

  }

  initializeMap();

}


private void initializeMap() {

  if (googleMap == null && mapsSupported) {

      mapView = (MapView) getActivity().findViewById(R.id.map);

      googleMap = mapView.getMap();

      GpsInfo gps = new GpsInfo(getActivity().getApplicationContext());

      //gps.getLocation();

      // GPS 사용유무 가져오기

      if (gps.isGetLocation()) {

          double latitude = gps.getLatitude();

          double longitude = gps.getLongitude();

          // Creating a LatLng object for the current location

          //LatLng latLng = new LatLng(37.28,126.97243608534338);

          LatLng latLng = new LatLng(latitude, longitude);

          ex_point = latLng;

          // Showing the current location in Google Map                              googleMap.moveCamera(CameraUpdateFactory.newLatLng(latLng));

          // Map 을 zoom 합니다.

          googleMap.animateCamera(CameraUpdateFactory.zoomTo(13));

          // 마커 설정.

          MarkerOptions optFirst = new MarkerOptions();

          optFirst.alpha(0.5f);

          optFirst.anchor(0.5f, 0.5f);

          optFirst.position(latLng);// 위도 • 경도

          optFirst.title("현재 지점");// 제목 미리보기           optFirst.icon(BitmapDescriptorFactory.fromResource(R.drawable.marker));

          googleMap.addMarker(optFirst).showInfoWindow();

          isInit = true;

      }

  }

}




전체 코드입니다.

Map2Fragment.java 소스 코드입니다.

package sincere.kimjungchul.smartwheel;


import android.graphics.Point;

import android.os.Bundle;

import android.os.Handler;

import android.os.Message;

import android.util.Log;

import android.view.LayoutInflater;

import android.view.View;

import android.view.ViewGroup;

import android.widget.Button;

import android.widget.TextView;

import android.widget.Toast;

import com.actionbarsherlock.app.SherlockFragment;

import com.google.android.gms.auth.GooglePlayServicesAvailabilityException;

import com.google.android.gms.common.ConnectionResult;

import com.google.android.gms.common.GooglePlayServicesNotAvailableException;

import com.google.android.gms.common.GooglePlayServicesUtil;

import com.google.android.gms.maps.CameraUpdateFactory;

import com.google.android.gms.maps.GoogleMap;

import com.google.android.gms.maps.MapView;

import com.google.android.gms.maps.MapsInitializer;

import com.google.android.gms.maps.OnMapReadyCallback;

import com.google.android.gms.maps.SupportMapFragment;

import com.google.android.gms.maps.model.BitmapDescriptorFactory;

import com.google.android.gms.maps.model.LatLng;

import com.google.android.gms.maps.model.MarkerOptions;

import com.google.android.gms.maps.model.PolylineOptions;


import sincere.kimjungchul.smartwheel.GPS.GpsInfo;


/**

* Created by user on 2015-07-18.

*/

public class map2Fragment extends SherlockFragment implements OnMapReadyCallback {


  private int timer = 0;

  private GoogleMap googleMap;

  private MapView mapView;

  private LatLng ex_point;

  private LatLng current_point;

  private boolean isInit = false;

  private boolean mapsSupported = true;


  private boolean isBtnClickStart = false; // Start클릭이먼저 클릭되었는가? 안그러면 hanlder 오류

  Handler handler;

  Handler time_handler;


  private TextView tv_timer;


  @Override

  public void onMapReady(GoogleMap googleMap) {

      initializeMap();

  }


  @Override

  public void onSaveInstanceState(Bundle outState) {

      super.onSaveInstanceState(outState);

      mapView.onSaveInstanceState(outState);

  }


  @Override

  public void onResume() {

      super.onResume();

      mapView.onResume();

      initializeMap();

  }


  @Override

  public void onPause() {

      super.onPause();

      mapView.onPause();

  }


  @Override

  public void onDestroy() {

      super.onDestroy();

      mapView.onDestroy();

  }


  @Override

  public void onLowMemory() {

      super.onLowMemory();

      mapView.onLowMemory();

  }


  /** http://joekarl.github.io/2013/11/01/android-map-view-inside-fragment/ */

  @Override

  public void onActivityCreated(Bundle savedInstanceState) {

      super.onCreate(savedInstanceState);


      MapsInitializer.initialize(getActivity().getApplicationContext());


      if (mapView != null) {

          mapView.onCreate(savedInstanceState);

      }

      initializeMap();

  }


  private void initializeMap() {

      if (googleMap == null && mapsSupported) {

          mapView = (MapView) getActivity().findViewById(R.id.map);

          googleMap = mapView.getMap();


          GpsInfo gps = new GpsInfo(getActivity().getApplicationContext());

          //gps.getLocation();

          // GPS 사용유무 가져오기

          if (gps.isGetLocation()) {

              double latitude = gps.getLatitude();

              double longitude = gps.getLongitude();


              // Creating a LatLng object for the current location


              //LatLng latLng = new LatLng(37.28,126.97243608534338);

              LatLng latLng = new LatLng(latitude, longitude);

              ex_point = latLng;


              // Showing the current location in Google Map

              googleMap.moveCamera(CameraUpdateFactory.newLatLng(latLng));


              // Map 을 zoom 합니다.

              googleMap.animateCamera(CameraUpdateFactory.zoomTo(13));


              // 마커 설정.

              MarkerOptions optFirst = new MarkerOptions();

              optFirst.alpha(0.5f);

              optFirst.anchor(0.5f, 0.5f);

              optFirst.position(latLng);// 위도 • 경도

              optFirst.title("현재 지점");// 제목 미리보기

              optFirst.icon(BitmapDescriptorFactory.fromResource(R.drawable.marker));

              googleMap.addMarker(optFirst).showInfoWindow();


              isInit = true;

          }

      }

  }


  @Override

  public View onCreateView(LayoutInflater inflater, ViewGroup container,

                           Bundle savedInstanceState) {


      View rootView = inflater.inflate(R.layout.fragment_map2, container, false);

      mapView = (MapView) rootView.findViewById(R.id.map);


      mapView.onCreate(savedInstanceState);


      mapView.onResume();

      mapView.getMapAsync(this);


      ex_point = new LatLng(0, 0);

      current_point = new LatLng(0, 0);

      final Button btn_timer_start = (Button) rootView.findViewById(R.id.btn_timer_start);

      final Button btn_timer_finish = (Button) rootView.findViewById(R.id.btn_timer_finish);

      final Button btn_timer_reset = (Button) rootView.findViewById(R.id.btn_timer_reset);

      tv_timer = (TextView) rootView.findViewById(R.id.tv_timer);



      btn_timer_start.setOnClickListener(new View.OnClickListener() {

          @Override

          public void onClick(View view) {

              if (view.getId() == R.id.btn_timer_start) {

                  if (isBtnClickStart == true) {

                      Toast.makeText(getActivity(), "이미 시작되었습니다.", Toast.LENGTH_SHORT).show();

                      return;

                  }

                  Toast.makeText(getActivity(), "타이머를 시작합니다.", Toast.LENGTH_SHORT).show();

                  isBtnClickStart = true;

                  GpsInfo gps = new GpsInfo(getActivity().getApplicationContext());

                  // GPS 사용유무 가져오기

                  if (gps.isGetLocation()) {

                      Log.d("GPS사용", "찍힘" + timer);

                      double latitude = gps.getLatitude();

                      double longitude = gps.getLongitude();

                      LatLng latLng = new LatLng(latitude, longitude);

                      // 마커 설정.

                      MarkerOptions optFirst = new MarkerOptions();

                      optFirst.alpha(0.5f);

                      optFirst.anchor(0.5f, 0.5f);

                      optFirst.position(latLng);// 위도 • 경도

                      optFirst.title("라이딩 시작지점");

                      optFirst.icon(BitmapDescriptorFactory.fromResource(R.drawable.marker));

                      googleMap.addMarker(optFirst).showInfoWindow();

                  }

                  time_handler = new Handler() {

                      @Override

                      public void handleMessage(Message msg) {

                          time_handler.sendEmptyMessageDelayed(0, 1000); // 1초 간격으로

                          timer++;

                          tv_timer.setText("주행시간 : " + timer + " 초");

                          if (timer % 5 == 0) {

                              GpsInfo gps = new GpsInfo(getActivity().getApplicationContext());

                              // GPS 사용유무 가져오기

                              if (gps.isGetLocation()) {

                                  Log.d("GPS사용", "찍힘 : " + timer);

                                  double latitude = gps.getLatitude();

                                  double longitude = gps.getLongitude();

                                  // 현재 화면에 찍힌 포인트로 부터 위도와 경도를 알려준다.

                                  LatLng latLng = new LatLng(latitude, longitude);

                                  // Showing the current location in Google Map

                                  googleMap.moveCamera(CameraUpdateFactory.newLatLng(latLng));


                                  // Map 을 zoom 합니다.

                                  googleMap.animateCamera(CameraUpdateFactory.zoomTo(15));


                                  current_point = latLng;

                                  googleMap.addPolyline(new PolylineOptions().color(0xFFFF0000).width(30.0f).geodesic(true).add(latLng).add(ex_point));

                                  ex_point = latLng;


                                  // 마커 설정.

                                  MarkerOptions optFirst = new MarkerOptions();

                                  optFirst.alpha(0.5f);

                                  optFirst.anchor(0.5f, 0.5f);

                                  optFirst.position(latLng);// 위도 • 경도

                                  optFirst.icon(BitmapDescriptorFactory.fromResource(R.drawable.marker));

                                  googleMap.addMarker(optFirst).showInfoWindow();

                              }

                          }

                      }

                  };

                  time_handler.sendEmptyMessage(0);


                  /*

                  handler = new Handler() {

                      @Override

                      public void handleMessage(Message msg) {

                          handler.sendEmptyMessageDelayed(0, 5000); // 5초 간격으로






                      }

                  };

                  handler.sendEmptyMessage(0);

                  */

              }


          }

      });



      btn_timer_finish.setOnClickListener(new View.OnClickListener() {

          @Override

          public void onClick(View view) {

              if (view.getId() == R.id.btn_timer_finish) {

                  if (isBtnClickStart == true) {

                      Toast.makeText(getActivity(), "타이머를 멈춥니다.", Toast.LENGTH_SHORT).show();

                      time_handler.removeMessages(0);

                      isBtnClickStart = false;

                  } else {

                      Toast.makeText(getActivity(), "타이머가 시작되지 않았습니다.", Toast.LENGTH_SHORT).show();

                  }

              }

          }

      });


      btn_timer_reset.setOnClickListener(new View.OnClickListener() {

          @Override

          public void onClick(View view) {

              if (view.getId() == R.id.btn_timer_reset) {

                  if (isBtnClickStart != true) {

                      ;

                  } else {

                      time_handler.removeMessages(0);

                  }

                  Toast.makeText(getActivity(), "타이머를 리셋합니다.", Toast.LENGTH_SHORT).show();

                  timer = 0;

                  tv_timer.setText("주행시간 : " + timer + " 초");

                  isBtnClickStart = false;


              }

          }

      });

      return rootView;

  }

}



fragment_map2.xml 코드입니다.

<?xml version="1.0" encoding="utf-8"?>

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"

  android:layout_width="match_parent"

  android:layout_height="match_parent"

  android:background="#fff"

  android:orientation="vertical" >


  <com.google.android.gms.maps.MapView

      android:id="@+id/map"

      android:name="com.google.android.gms.maps.MapFragment"

      android:layout_width="match_parent"

      android:layout_height="match_parent"

      />

  <LinearLayout

      android:layout_marginBottom="5dp"

      android:id="@+id/fragment_map2_LL_1"

      android:layout_width="match_parent"

      android:layout_height="wrap_content"

      android:gravity="center"

      android:orientation="horizontal"

      android:layout_alignParentBottom="true"

      android:layout_centerHorizontal="true"

      >


      <Button

          android:id="@+id/btn_timer_start"

          android:layout_width="80dp"

          android:layout_height="40dp"

          android:layout_marginRight="10dp"

          android:text="Start"

          android:background="@color/color_button"

          android:textColor="@color/color_WHITE"/>


      <Button

          android:id="@+id/btn_timer_finish"

          android:layout_width="80dp"

          android:layout_height="40dp"

          android:layout_marginRight="10dp"

          android:text="Stop"

          android:background="@color/color_button"

          android:textColor="@color/color_WHITE"/>


      <Button

          android:id="@+id/btn_timer_reset"

          android:layout_width="80dp"

          android:layout_height="40dp"

          android:layout_marginRight="10dp"

          android:text="Reset"

          android:background="@color/color_button"

          android:textColor="@color/color_WHITE"

          />


      <Button

          android:id="@+id/btn_ridingfor_analysis"

          android:layout_width="100dp"

          android:layout_height="40dp"

          android:text="통계"

          android:background="@color/color_button"

          android:textColor="@color/color_WHITE"

          />

  </LinearLayout>

  <TextView

      android:id="@+id/tv_timer_introduce"

      android:layout_gravity="center"

      android:gravity="center"

      android:layout_width="match_parent"

      android:layout_height="wrap_content"

      android:text="라이딩 기록"

      android:textSize="30sp"

      android:textColor="@color/color_MAIN"/>

  <TextView

      android:layout_gravity="center"

      android:gravity="center"

      android:layout_width="match_parent"

      android:layout_height="wrap_content"

      android:id="@+id/tv_timer"

      android:textSize="20sp"

      android:layout_below="@id/tv_timer_introduce"

      android:layout_alignParentStart="true"

      android:text="주행시간 : 0 초" />


</RelativeLayout>