210202
GPS로 현재위치(위도, 경도)가져오기 설명 본문
아래 사이트를 참고해서 현재 위치를 가져오는 기능을 구현했는데 참고 사이트에서는 위도 경도를 가져와서 주소까지 표시했다. 내가 하려는 프로젝트는 위도 경도만 가져오면 되기 때문에 코드를 조금 수정했다.
https://webnautes.tistory.com/1315
먼저 GpsTracker.java 파일이다.
public class GpsTracker extends Service implements LocationListener {
private final Context mContext;
Location location;
double latitude;
double longitude;
private static final long MIN_DISTANCE_CHANGE_FOR_UPDATES = 10;
private static final long MIN_TIME_BW_UPDATES = 1000 * 60 * 1;
protected LocationManager locationManager;
public GpsTracker(Context context) {
this.mContext = context;
getLocation();
}
public Location getLocation() {
try {
locationManager = (LocationManager) mContext.getSystemService(LOCATION_SERVICE);
boolean isGPSEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
boolean isNetworkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
if (!isGPSEnabled && !isNetworkEnabled) {
} else {
int hasFineLocationPermission = ContextCompat.checkSelfPermission(mContext,
Manifest.permission.ACCESS_FINE_LOCATION);
int hasCoarseLocationPermission = ContextCompat.checkSelfPermission(mContext,
Manifest.permission.ACCESS_COARSE_LOCATION);
if (hasFineLocationPermission == PackageManager.PERMISSION_GRANTED &&
hasCoarseLocationPermission == PackageManager.PERMISSION_GRANTED) {
;
} else
return null;
if (isNetworkEnabled) {
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, MIN_TIME_BW_UPDATES, MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
if (locationManager != null)
{
location = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
if (location != null)
{
latitude = location.getLatitude();
longitude = location.getLongitude();
}
}
}
if (isGPSEnabled)
{
if (location == null)
{
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, MIN_TIME_BW_UPDATES, MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
if (locationManager != null)
{
location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if (location != null)
{
latitude = location.getLatitude();
longitude = location.getLongitude();
}
}
}
}
}
}
catch (Exception e)
{
Log.d("@@@", ""+e.toString());
}
return location;
}
public double getLatitude()
{
if(location != null)
{
latitude = location.getLatitude();
}
return latitude;
}
public double getLongitude()
{
if(location != null)
{
longitude = location.getLongitude();
}
return longitude;
}
@Override
public void onLocationChanged(Location location)
{
}
@Override
public void onProviderDisabled(String provider)
{
}
@Override
public void onProviderEnabled(String provider)
{
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras)
{
}
@Override
public IBinder onBind(Intent arg0)
{
return null;
}
public void stopUsingGPS()
{
if(locationManager != null)
{
locationManager.removeUpdates(GpsTracker.this);
}
}
}
전체적으로 수행하는 순서는 다음과 같다.
1. GpsTracker 객체가 생성되면 getLocation 메소드를 실행한다.
2. getLocation 메소드는 locationManger를 통해서 GPS와 네트워크가 사용가능한지 체크한다.(isGPSEnabled, isNetworkEnabled)
3. 만약 GPS와 네트워크가 사용가능하다면(else 부분) 위치에 접근할 수 있는 권한(hasFineLocationPermission, hasCoarseLocationPermission)을 획득한다.
4. 그 후 GPS와 네트워크중 무엇이 사용가능한지 체크하고 권한에 맞게 locationManger를 사용하여 위치를 가져온다.
getLatitude와 getLongitude 메소드를 통해 위도와 경도를 얻을 수 있다.
다음은 GPSActivty.java 파일이다.
public class GPSActivity extends AppCompatActivity {
private GpsTracker gpsTracker;
private static final int GPS_ENABLE_REQUEST_CODE = 2001;
private static final int PERMISSIONS_REQUEST_CODE = 100;
String[] REQUIRED_PERMISSIONS = {Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_gps);
if (checkLocationServicesStatus()) {
checkRunTimePermission();
} else {
showDialogForLocationServiceSetting();
}
Button ShowLocationButton = (Button) findViewById(R.id.button);
ShowLocationButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View arg0) {
gpsTracker = new GpsTracker(GPSActivity.this);
double latitude = gpsTracker.getLatitude();
double longitude = gpsTracker.getLongitude();
Toast.makeText(GPSActivity.this, "현재위치 \n위도 " + latitude + "\n경도 " + longitude, Toast.LENGTH_LONG).show();
}
});
}
/*
* ActivityCompat.requestPermissions를 사용한 퍼미션 요청의 결과를 리턴받는 메소드입니다.
*/
@Override
public void onRequestPermissionsResult(int permsRequestCode,
@NonNull String[] permissions,
@NonNull int[] grandResults) {
if (permsRequestCode == PERMISSIONS_REQUEST_CODE && grandResults.length == REQUIRED_PERMISSIONS.length) {
// 요청 코드가 PERMISSIONS_REQUEST_CODE 이고, 요청한 퍼미션 개수만큼 수신되었다면
boolean check_result = true;
// 모든 퍼미션을 허용했는지 체크합니다.
for (int result : grandResults) {
if (result != PackageManager.PERMISSION_GRANTED) {
check_result = false;
break;
}
}
if (check_result) {
//위치 값을 가져올 수 있음
;
} else {
// 거부한 퍼미션이 있다면 앱을 사용할 수 없는 이유를 설명해주고 앱을 종료합니다.2 가지 경우가 있습니다.
if (ActivityCompat.shouldShowRequestPermissionRationale(this, REQUIRED_PERMISSIONS[0])
|| ActivityCompat.shouldShowRequestPermissionRationale(this, REQUIRED_PERMISSIONS[1])) {
Toast.makeText(GPSActivity.this, "퍼미션이 거부되었습니다. 앱을 다시 실행하여 퍼미션을 허용해주세요.", Toast.LENGTH_LONG).show();
finish();
} else {
Toast.makeText(GPSActivity.this, "퍼미션이 거부되었습니다. 설정(앱 정보)에서 퍼미션을 허용해야 합니다. ", Toast.LENGTH_LONG).show();
}
}
}
}
void checkRunTimePermission() {
//런타임 퍼미션 처리
// 1. 위치 퍼미션을 가지고 있는지 체크합니다.
int hasFineLocationPermission = ContextCompat.checkSelfPermission(GPSActivity.this,
Manifest.permission.ACCESS_FINE_LOCATION);
int hasCoarseLocationPermission = ContextCompat.checkSelfPermission(GPSActivity.this,
Manifest.permission.ACCESS_COARSE_LOCATION);
if (hasFineLocationPermission == PackageManager.PERMISSION_GRANTED &&
hasCoarseLocationPermission == PackageManager.PERMISSION_GRANTED) {
// 2. 이미 퍼미션을 가지고 있다면
// ( 안드로이드 6.0 이하 버전은 런타임 퍼미션이 필요없기 때문에 이미 허용된 걸로 인식합니다.)
// 3. 위치 값을 가져올 수 있음
} else { //2. 퍼미션 요청을 허용한 적이 없다면 퍼미션 요청이 필요합니다. 2가지 경우(3-1, 4-1)가 있습니다.
// 3-1. 사용자가 퍼미션 거부를 한 적이 있는 경우에는
if (ActivityCompat.shouldShowRequestPermissionRationale(GPSActivity.this, REQUIRED_PERMISSIONS[0])) {
// 3-2. 요청을 진행하기 전에 사용자가에게 퍼미션이 필요한 이유를 설명해줄 필요가 있습니다.
Toast.makeText(GPSActivity.this, "이 앱을 실행하려면 위치 접근 권한이 필요합니다.", Toast.LENGTH_LONG).show();
// 3-3. 사용자게에 퍼미션 요청을 합니다. 요청 결과는 onRequestPermissionResult에서 수신됩니다.
ActivityCompat.requestPermissions(GPSActivity.this, REQUIRED_PERMISSIONS,
PERMISSIONS_REQUEST_CODE);
} else {
// 4-1. 사용자가 퍼미션 거부를 한 적이 없는 경우에는 퍼미션 요청을 바로 합니다.
// 요청 결과는 onRequestPermissionResult에서 수신됩니다.
ActivityCompat.requestPermissions(GPSActivity.this, REQUIRED_PERMISSIONS,
PERMISSIONS_REQUEST_CODE);
}
}
}
//여기부터는 GPS 활성화를 위한 메소드들
private void showDialogForLocationServiceSetting() {
AlertDialog.Builder builder = new AlertDialog.Builder(GPSActivity.this);
builder.setTitle("위치 서비스 비활성화");
builder.setMessage("앱을 사용하기 위해서는 위치 서비스가 필요합니다.\n"
+ "위치 설정을 수정하실래요?");
builder.setCancelable(true);
builder.setPositiveButton("설정", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int id) {
Intent callGPSSettingIntent
= new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS);
startActivityForResult(callGPSSettingIntent, GPS_ENABLE_REQUEST_CODE);
}
});
builder.setNegativeButton("취소", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
}
});
builder.create().show();
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case GPS_ENABLE_REQUEST_CODE:
//사용자가 GPS 활성 시켰는지 검사
if (checkLocationServicesStatus()) {
if (checkLocationServicesStatus()) {
Log.d("@@@", "onActivityResult : GPS 활성화 되있음");
checkRunTimePermission();
return;
}
}
break;
}
}
public boolean checkLocationServicesStatus() {
LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
return locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)
|| locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
}
}
전체적으로 수행하는 순서는 다음과 같다.
1. 액티비티가 실행되면 checkLocationServicesStatus 메소드를 실행한다.
2. locationManager 객체를 사용하여 권한에 접근할 수 있는지 여부를 확인한다.
3. 만약 권한에 접근할 수 있다면 checkRunTimePermission 메소드를 실행하고 접근할 수 없다면 showDialogForLocationServiceSetting를 수행한다.
4. 버튼을 누르면 gpsTracker 객체를 생성하고 getLatitude와 getLongitude 메소드를 사용하여 latitude와 longitude에 위도와 경도를 설정해준다.
5. 설정된 위도와 경도는 Toast로 표시된다.(이 부분은 테스트용이고 실제로는 사용하지 않음)
checkRunTimePermission 메소드는 위치 퍼미션을 가지고 있지 않으면 퍼미션 요청을 하는 메소드이고
showDialogForLocationServiceSetting 메소드는 권한을 설정해주기 위한 다이얼로그창을 띄워주는 메소드이다.
예제와 달라진점은 위치를 표시해주는 TextView와 getCurrentAddress 메소드의 삭제부분이다.
예제는 버튼을 누를때마다 갱신되게 하는데 주기적으로 갱신시키려면 어떻게 해야할지 고민해봐야겠다.
'Android' 카테고리의 다른 글
몇초마다 자동으로 텍스트뷰 변하게하기(Github 오픈소스) (2) | 2020.02.20 |
---|---|
페이지 슬라이딩 애니메이션 아래에서 위로 구현하기 (0) | 2020.02.18 |
커스텀 리스트뷰 구현 + AsyncTask 사용 시 View에 반영 안되는 경우 (0) | 2020.02.18 |
네이버 API로 검색시 정보 불러오기 설명 + Json형식으로 활용 (0) | 2020.02.17 |
TMap API를 사용하여 현재 위치에 마커 구현하기 (0) | 2020.02.16 |