이 글에서는 안드로이드(Android)에서 위도(latitude)와 경도(longitude) 좌표를 이용해 실제 주소를 조회하는 방법을 단계별로 살펴봅니다.
주소 변환에는 안드로이드에서 기본 제공하는 Geocoder 클래스를 사용합니다. Geocoder는 좌표를 지정하면 해당 위치의 주소 목록을 반환하는 역지오코딩(Reverse Geocoding) 기능을 담당하며, 네트워크 작업이 필요하므로 반드시 백그라운드 스레드에서 호출해야 한다는 점을 기억하세요.
전체 구현 순서
1단계 — 새 프로젝트 생성
Android Studio에서 File ⇒ New Project 메뉴로 이동한 후, 새 프로젝트 생성에 필요한 정보를 모두 입력하여 프로젝트를 만듭니다.
2단계 — 레이아웃 파일 작성
res/layout/activity_main.xml에 아래 코드를 추가합니다. 주소를 표시할 TextView와 주소 조회를 시작하는 Button으로 화면을 구성합니다.
<RelativeLayout xmlns:android="https://schemas.android.com/apk/res/android" xmlns:tools="https://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:padding="16sp" tools:context=".MainActivity"> <TextView android:text="" android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/textView" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="40dp" android:text="Show Address" android:id="@+id/btnShowAddress" android:layout_centerHorizontal="true" /> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:id="@+id/tvAddress" android:layout_alignParentBottom="true" android:layout_marginBottom="134dp" android:layout_alignParentEnd="true" /> </RelativeLayout>
3단계 — MainActivity 작성
src/MainActivity.java에 다음 코드를 추가합니다. 버튼 클릭 시 위치 서비스에서 좌표를 가져오고, Geocoder를 통해 주소를 조회한 뒤 Handler로 결과를 UI에 반영합니다. 위치 제공자가 꺼져 있을 경우 설정 화면으로 이동하도록 안내하는 알림 대화상자도 함께 구현했습니다.
import android.support.v7.app.AppCompatActivity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.location.Location;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.provider.Settings;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
Button btnShowAddress;
TextView tvAddress;
Location location;
AppLocationService appLocationService;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tvAddress = findViewById(R.id.tvAddress);
appLocationService = new
AppLocationService(MainActivity.this);
btnShowAddress = findViewById(R.id.btnShowAddress);
btnShowAddress.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View arg0) {
location = appLocationService.getLocation(LocationManager.GPS_PROVIDER);
double latitude = 13.1000727;
double longitude = 80.2126274;
LocationAddress locationAddress = new LocationAddress();
locationAddress.getAddressFromLocation(latitude, longitude,
getApplicationContext(), new GeoCodeHandler());
showSettingsAlert();
}
public void showSettingsAlert() {
AlertDialog.Builder alertDialog = new AlertDialog.Builder(MainActivity.this);
alertDialog.setTitle("SETTINGS");
alertDialog.setMessage("Enable Location
Provider! Go to settings menu?");
alertDialog.setPositiveButton("Settings", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
MainActivity.this.startActivity(intent);
}
});
alertDialog.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});
alertDialog.show();
}
class GeoCodeHandler extends Handler {
@Override
public void handleMessage(Message message) {
String locationAddress;
switch (message.what) {
case 1:
Bundle bundle = message.getData();
locationAddress = bundle.getString("address");
break;
default:
locationAddress = null;
}
tvAddress.setText(locationAddress);
}
}
});
}
}4단계 — 위치 서비스 클래스 생성
새 자바 클래스 ApplicationService.java를 만들고 아래 코드를 추가합니다. 이 클래스는 GPS 제공자를 통해 최신 위치 정보를 요청하고 마지막으로 알려진 위치를 반환하는 역할을 합니다.
import android.annotation.SuppressLint;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.IBinder;
@SuppressLint("Registered")
public class AppLocationService extends Service implements LocationListener {
protected LocationManager locationManager;
Location location;
private static final long MIN_DISTANCE_FOR_UPDATE = 10;
private static final long MIN_TIME_FOR_UPDATE = 1000 * 60 * 2;
public AppLocationService(Context context) {
locationManager = (LocationManager) context.getSystemService(LOCATION_SERVICE);
}
@SuppressLint("MissingPermission")
public Location getLocation(String provider) {
if (locationManager.isProviderEnabled(provider)) {
locationManager.requestLocationUpdates(provider,
MIN_TIME_FOR_UPDATE,
MIN_DISTANCE_FOR_UPDATE, this);
if (locationManager != null) {
location = locationManager.getLastKnownLocation(provider);
return location;
}
}
return null;
}
@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;
}
}5단계 — 주소 변환 클래스 생성
새 자바 클래스 LocationAddress.java를 만들고 아래 코드를 추가합니다. 이 클래스는 백그라운드 스레드에서 Geocoder를 호출해 좌표를 주소로 변환하고, 그 결과를 Handler를 통해 메인 스레드로 전달합니다.
import android.content.Context;
import android.location.Address;
import android.location.Geocoder;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import java.io.IOException;
import java.util.List;
import java.util.Locale;
class LocationAddress {
private static final String TAG = "LocationAddress";
static void getAddressFromLocation(final double latitude,
final double longitude, final Context context, final Handler
handler) {
Thread thread = new Thread() {
@Override
public void run() {
Geocoder geocoder = new Geocoder(context,
Locale.getDefault());
String result = null;
try {
List<Address> addressList =
geocoder.getFromLocation(
latitude, longitude, 1);
if (addressList != null &&
addressList.size() > 0) {
Address address = addressList.get(0);
StringBuilder sb = new
StringBuilder();
for (int i = 0; i < address.getMaxAddressLineIndex(); i++) {
sb.append(address.getAddressLine(i)).append("
");
}
sb.append(address.getLocality()).append("
");
sb.append(address.getPostalCode()).append("
");
sb.append(address.getCountryName());
result = sb.toString();
}
} catch (IOException e) {
Log.e(TAG, "Unable connect to Geocoder", e);
} finally {
Message message = Message.obtain();
message.setTarget(handler);
if (result != null) {
message.what = 1;
Bundle bundle = new Bundle();
result = "Latitude: " + latitude + " Longitude: " + longitude +
"
Address:
" + result;
bundle.putString("address", result);
message.setData(bundle);
} else {
message.what = 1;
Bundle bundle = new Bundle();
result = "Latitude: " + latitude + " Longitude: " + longitude +
"
Unable to get address for
this lat-long.";
bundle.putString("address" , result);
message.setData(bundle);
}
message.sendToTarget();
}
}
};
thread.start();
}
}6단계 — 매니페스트 권한 설정
androidManifest.xml에 아래 코드를 추가합니다. 위치 정보 접근을 위해 ACCESS_COARSE_LOCATION과 ACCESS_FINE_LOCATION 권한 선언이 반드시 필요합니다.
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="https://schemas.android.com/apk/res/android" package="app.com.sample"> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
앱 실행 및 결과 확인
이제 애플리케이션을 실행해 보겠습니다. 실제 안드로이드 기기가 컴퓨터에 연결되어 있다고 가정합니다. Android Studio에서 프로젝트의 액티비티 파일 중 하나를 연 뒤 툴바의 실행(Run) 아이콘을 클릭하세요. 옵션 목록에서 본인의 모바일 기기를 선택하면, 기기 화면에 앱의 기본 화면이 표시됩니다.
버튼을 누르면 지정된 위도·경도 좌표가 Geocoder로 전달되고, 잠시 후 해당 위치의 도시명, 우편번호, 국가명이 포함된 전체 주소가 화면 하단 TextView에 나타납니다. 네트워크 상태가 좋지 않거나 좌표에 대응하는 주소가 없는 경우에는 주소를 가져올 수 없다는 안내 문구가 대신 표시됩니다.