728x90
FusedLocationProviderClient를 사용해 구글 맵에 현재 위치를 표시하는 예제입니다.
우선 Google Maps Android Api를 사용하는 방법은 아래 게시글에 나와있으니 참고하시길 바랍니다.
https://stickode.tistory.com/152
1. AndroidManifest.xml 에서 위치정보 접근을 위한 퍼미션을 추가해줍니다.
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
2. Layout
-> snackbar 추가를 위해 layout id를 추가해줍니다.
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/layout_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MapActivity">
<fragment
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/map"
android:name="com.google.android.gms.maps.SupportMapFragment"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
3. java
package com.example.everyrunrenew;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import android.Manifest;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.location.Address;
import android.location.Geocoder;
import android.location.Location;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.Looper;
import android.provider.Settings;
import android.util.Log;
import android.view.View;
import android.widget.Toast;
import android.widget.ToggleButton;
import com.google.android.gms.location.FusedLocationProviderClient;
import com.google.android.gms.location.LocationCallback;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationResult;
import com.google.android.gms.location.LocationServices;
import com.google.android.gms.location.LocationSettingsRequest;
import com.google.android.gms.maps.CameraUpdate;
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.Marker;
import com.google.android.gms.maps.model.MarkerOptions;
import com.google.android.material.snackbar.Snackbar;
import java.io.IOException;
import java.util.List;
import java.util.Locale;
public class MapActivity extends AppCompatActivity implements OnMapReadyCallback, ActivityCompat.OnRequestPermissionsResultCallback {
private GoogleMap mMap;
private Marker currentMarker = null;
private static final String TAG = "googlemap";
private static final int GPS_ENABLE_REQUEST_CODE = 2001;
private static final int UPDATE_INTERVAL_MS = 1000; // 1초
private static final int FASTEST_UPDATE_INTERVAL_MS = 500; // 0.5초
// OnRequestPermissionsResultCallback에서 수신된 결과에서 ActivityCompat.OnRequestPermissionsResultCallback를 사용한 퍼미션 요청을 구별하기 위함
private static final int PERMISSION_REQUEST_CODE = 100;
boolean needRequest = false;
// 앱을 실행하기 위해 필요한 퍼미션 정의
String[] REQUIRED_PERMISSION = {Manifest.permission.ACCESS_FINE_LOCATION,Manifest.permission.ACCESS_COARSE_LOCATION };
Location mCurrentLocation;
LatLng currentPosition;
private FusedLocationProviderClient mFusedLocationClient;
private LocationRequest locationRequest; // 주의
private Location location;
private View mLayout; // snackbar 사용하기 위함.
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_map);
locationRequest = new LocationRequest()
.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
.setInterval(UPDATE_INTERVAL_MS)
.setFastestInterval(FASTEST_UPDATE_INTERVAL_MS);
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder();
builder.addLocationRequest(locationRequest);
mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
}
@Override
public void onMapReady(@NonNull GoogleMap googleMap) {
Log.d(TAG, "onMapReady: 들어옴 ");
mMap = googleMap;
// 지도의 초기위치 이동
setDefaultLocation();
// 런타임 퍼미션 처리
// 1. 위치 퍼미션을 가지고 있는지 확인합니다.
int hasFineLocationPermission = ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION);
int hasCoarseLocationPermission = ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION);
if(hasFineLocationPermission == PackageManager.PERMISSION_GRANTED && hasCoarseLocationPermission == PackageManager.PERMISSION_GRANTED){
// 2. 이미 퍼미션을 가지고 있다면
startLocationUpdates(); // 3. 위치 업데이트 실행
}else{
// 2. 퍼미션 요청을 허용한 적 없다면 퍼미션 요청하기
if(ActivityCompat.shouldShowRequestPermissionRationale(this, REQUIRED_PERMISSION[0])){
// 요청 진행하기 전에 퍼미션이 왜필요한지 설명
Snackbar.make(mLayout, "이 앱을 실행하려면 위치 접근 권한이 필요합니다.", Snackbar.LENGTH_INDEFINITE).setAction("확인", new View.OnClickListener() {
@Override
public void onClick(View view) {
// 사용자에게 퍼미션 요청, 요청 결과는 onRequestPermisionResult에서 수신
ActivityCompat.requestPermissions(MapActivity.this, REQUIRED_PERMISSION, PERMISSION_REQUEST_CODE);
}
}).show();
}else{
// 사용자가 퍼미션 거부를 한적이 없는 경우 퍼미션 요청을 바로 함.
// 요청 결과는 onRequestPermissionResult에서 수신된다.
ActivityCompat.requestPermissions(this, REQUIRED_PERMISSION, PERMISSION_REQUEST_CODE);
}
}
mMap.getUiSettings().setMyLocationButtonEnabled(true);
mMap.setOnMapClickListener(new GoogleMap.OnMapClickListener() {
@Override
public void onMapClick(@NonNull LatLng latLng) {
Log.d(TAG, "onMapClick: ");
}
});
}
LocationCallback locationCallback = new LocationCallback() {
@Override
public void onLocationResult(@NonNull LocationResult locationResult) {
super.onLocationResult(locationResult);
List<Location> locationList = locationResult.getLocations();
if(locationList.size() > 0){
location = locationList.get(locationList.size() -1);
currentPosition = new LatLng(location.getLatitude(), location.getLongitude());
String markerTitle = getCurrentAddress(currentPosition);
String markerSnippet = "위도 :" + String.valueOf(location.getLatitude()) + "경도 :" +
String.valueOf(location.getLongitude());
// 현재 위치에 마커 생성하고 이동
setCurrentLocation(location, markerTitle, markerSnippet);
mCurrentLocation = location;
}
}
};
private String getCurrentAddress(LatLng currentPosition) {
// 지오코더 gps를 주소로 변환
Geocoder geocoder = new Geocoder(this, Locale.getDefault());
List<Address> addresses;
try{
addresses = geocoder.getFromLocation(
currentPosition.latitude,
currentPosition.longitude,
1
);
}catch (IOException ioException){
// 네트워크 문제
Toast.makeText(this, "지오코더 서비스 사용불가", Toast.LENGTH_LONG).show();
return "지오코더 서비스 사용 불가";
}catch (IllegalArgumentException illegalArgumentException){
Toast.makeText(this,"잘못된 GPS 좌표", Toast.LENGTH_LONG).show();
return "잘못된 GPS 좌표";
}
if(addresses == null || addresses.size() == 0){
Toast.makeText(this,"주소 미발견", Toast.LENGTH_LONG).show();
return "주소 미발견";
}else{
Address address = addresses.get(0);
return address.getAddressLine(0).toString();
}
}
private void setCurrentLocation(Location location, String markerTitle, String markerSnippet) {
if(currentMarker != null)
{
currentMarker.remove();
}
LatLng currentLatLng = new LatLng(location.getLatitude(), location.getLongitude());
MarkerOptions markerOptions = new MarkerOptions();
markerOptions.position(currentLatLng);
markerOptions.title(markerTitle);
markerOptions.snippet(markerSnippet);
markerOptions.draggable(true);
currentMarker = mMap.addMarker(markerOptions);
CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLng(currentLatLng);
mMap.moveCamera(cameraUpdate);
}
private void startLocationUpdates() {
if(!checkLocationServicesStatus()){
showDiologForLocationServiceSetting();
}else{
int hasFineLocationPermission = ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION);
int hasCoarseLocationPermission = ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION);
if(hasFineLocationPermission != PackageManager.PERMISSION_GRANTED|| hasCoarseLocationPermission != PackageManager.PERMISSION_GRANTED ){
Log.d(TAG, "startLocationUpdates: 퍼미션 없음");
return;
}
mFusedLocationClient.requestLocationUpdates(locationRequest, locationCallback, Looper.myLooper());
if(checkPermission()){
mMap.setMyLocationEnabled(true);
}
}
}
@Override
protected void onStart() {
super.onStart();
Log.d(TAG, "onStart: ");
if(checkPermission()){
mFusedLocationClient.requestLocationUpdates(locationRequest, locationCallback, null);
if(mMap!=null){
mMap.setMyLocationEnabled(true);
}
}
}
@Override
protected void onStop() {
super.onStop();
if(mFusedLocationClient != null){
mFusedLocationClient.removeLocationUpdates(locationCallback);
}
}
private boolean checkPermission(){
int hasFineLocationPermission = ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION);
int hasCoarseLocationPermission = ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION);
if(hasFineLocationPermission != PackageManager.PERMISSION_GRANTED|| hasCoarseLocationPermission != PackageManager.PERMISSION_GRANTED ){
Log.d(TAG, "startLocationUpdates: 퍼미션 없음");
return false;
}else{
return true;
}
}
private void showDiologForLocationServiceSetting() {
AlertDialog.Builder builder = new AlertDialog.Builder(MapActivity.this);
builder.setTitle("위치 서비스 비활성화");
builder.setMessage("앱을 사용하기 위해서는 위치 서비스가 필요합니다. 위치설정을 수정하시겠습니까?");
builder.setCancelable(true);
builder.setPositiveButton("설정", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
Intent callGPSSettingIntent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
startActivityForResult(callGPSSettingIntent, GPS_ENABLE_REQUEST_CODE);
}
});
builder.setNegativeButton("취소", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
dialogInterface.cancel();
}
});
builder.create().show();
}
private boolean checkLocationServicesStatus() {
LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
return locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER) || locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
}
private void setDefaultLocation() {
// 기본 위치
LatLng DEFAULT_LOCATION = new LatLng(37.56, 126.97);
String markerTitle = "위치 정보 가져올 수 없음";
String markerSnippet = "위치 퍼미션과 GPS 활성 여부를 확인하세요";
if(currentMarker != null){
currentMarker.remove();
}
MarkerOptions markerOptions = new MarkerOptions();
markerOptions.position(DEFAULT_LOCATION);
markerOptions.title(markerTitle);
markerOptions.snippet(markerSnippet);
markerOptions.draggable(true);
currentMarker = mMap.addMarker(markerOptions);
CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLngZoom(DEFAULT_LOCATION, 15);
mMap.moveCamera(cameraUpdate);
}
}
'안드로이드 자바' 카테고리의 다른 글
[Java][Android] 내 음성을 raw pcm data format 음원에 저장하기. (2) | 2023.05.12 |
---|---|
[Android][Java] ConnectivityManager 네트워크 상태 모니터링 (0) | 2023.05.11 |
[Android][JAVA] WorkerManager 사용해서 백그라운드 작업하기 (2) | 2023.05.06 |
[Android][Java] 앱이 요청한 권한(permission)의 이름을 화면에 출력해보기 (0) | 2023.05.05 |
[Android][JAVA] MPAndroidChart 라이브러리에서 xAxis 에 String 값 넣기 (0) | 2023.05.03 |