Computer >> 컴퓨터 >  >> 프로그래밍 >> Android

안드로이드에서 주소로 위도·경도 좌표 구하는 방법 (Geocoder 예제)

이 튜토리얼에서는 안드로이드에서 사용자가 입력한 주소 문자열을 Geocoder API로 변환하여 위도(latitude)와 경도(longitude)를 화면에 표시하는 방법을 단계별로 알아봅니다.

1단계: 새 프로젝트 만들기

Android Studio에서 File → New Project를 선택하고, 필요한 정보를 모두 입력하여 새 프로젝트를 생성합니다.

2단계: 레이아웃 작성 (activity_main.xml)

res/layout/activity_main.xml 파일에 아래 코드를 추가합니다. 주소 입력란(EditText), 검색 버튼(Button), 결과를 표시할 TextView로 구성된 간단한 화면입니다.

<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:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:text="Enter Address"
      android:id="@+id/textViewAddress"
      android:textAppearance="?android:attr/textAppearanceMedium"
      android:layout_alignParentStart="true" />
   <EditText
      android:layout_width="fill_parent"
      android:layout_height="wrap_content"
      android:id="@+id/editTextAddress"
      android:layout_alignParentTop="true"
      android:layout_toEndOf="@+id/textViewAddress"
      android:singleLine="true"
      android:text="" />
   <Button
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:text="Show Lat/Long"
      android:id="@+id/addressButton"
      android:layout_below="@+id/textViewAddress"
      android:layout_toEndOf="@+id/textViewAddress"
      android:layout_marginTop="50dp" />
   <TextView
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:textAppearance="?android:attr/textAppearanceLarge"
      android:text=""
      android:id="@+id/latLongTV"
      android:layout_centerVertical="true"
      android:layout_toEndOf="@+id/textViewAddress" />
</RelativeLayout>

3단계: 메인 액티비티 작성 (MainActivity.java)

src/MainActivity.java에 아래 코드를 추가합니다. 버튼을 클릭하면 입력된 주소를 읽어 GeoCodingLocation 클래스에 전달하고, Handler를 통해 비동기로 전달받은 결과를 TextView에 출력합니다.

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
   Button addressButton;
   TextView textViewAddress;
   TextView textViewLatLong;
   @Override
   protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);
      textViewAddress = findViewById(R.id.textViewAddress);
      textViewLatLong = findViewById(R.id.latLongTV);
      addressButton = findViewById(R.id.addressButton);
      addressButton.setOnClickListener(new View.OnClickListener() {
         @Override
         public void onClick(View arg0) {
            EditText editText = findViewById(R.id.editTextAddress);
            String address = editText.getText().toString();
            GeoCodingLocation locationAddress = new GeoCodingLocation();
            locationAddress.getAddressFromLocation(address, getApplicationContext(), new
               GeoCoderHandler());
         }
      });
   }
   private class GeoCoderHandler 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;
         }
         textViewLatLong.setText(locationAddress);
      }
   }
}

4단계: 지오코딩 클래스 작성 (GeoCodeLocation.java)

새 자바 클래스를 만들고 다음 코드를 추가합니다. 이 클래스는 백그라운드 스레드에서 Geocoder의 getFromLocationName() 메서드를 호출해 주소를 좌표로 변환합니다. 네트워크 작업이므로 UI 스레드를 차단하지 않도록 별도의 스레드에서 실행되며, 결과는 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 GeoCodeLocation {
   private static final String TAG = "GeoCodeLocation";
   public static void getAddressFromLocation(final String
   locationAddress,
   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 addressList = geocoder.getFromLocationName(locationAddress, 1);
               if (addressList != null && addressList.size() > 0) {
                  Address address = (Address)
                     addressList.get(0);
                  StringBuilder sb = new StringBuilder();
                  sb.append(address.getLatitude()).append("\n");
                  sb.append(address.getLongitude()).append("\n");
                  result = sb.toString();
               }
            } catch (IOException e) {
               Log.e(TAG, "Unable to connect to Geocoder", e);
            } finally {
               Message message = Message.obtain();
               message.setTarget(handler);
               if (result != null) {
                  message.what = 1;
                  Bundle bundle = new Bundle();
                  result = "Address: " + locationAddress +
                     "\n\nLatitude and Longitude
                     :\n" + result;
                  bundle.putString("address", result);
                  message.setData(bundle);
               } else {
                  message.what = 1;
                  Bundle bundle = new Bundle();
                  result = "Address: " + locationAddress +
                     "\n Unable to get Latitude and
                     Longitude for this address location.";
                  bundle.putString("address", result);
                  message.setData(bundle);
               }
               message.sendToTarget();
            }
         }
      };
      thread.start();
   }
}

5단계: 권한 설정 (AndroidManifest.xml)

androidManifest.xml에 위치 권한과 인터넷 권한을 추가합니다. Geocoder는 내부적으로 Google의 위치 서비스에 접근하므로 두 권한이 반드시 필요합니다.

<?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_FINE_LOCATION" />
   <uses-permission
      android:name="android.permission.INTERNET" />
   <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 버튼을 클릭하세요. 실행할 기기를 선택하면 앱이 설치되고 기본 화면이 표시됩니다. 주소를 입력한 뒤 Show Lat/Long 버튼을 누르면 해당 위치의 위도와 경도가 화면에 나타납니다.

안드로이드에서 주소로 위도·경도 좌표 구하는 방법 (Geocoder 예제)

안드로이드에서 주소로 위도·경도 좌표 구하는 방법 (Geocoder 예제)

참고 사항

Geocoder는 기기에 백엔드 위치 서비스가 있는 경우에만 정상 동작하므로, 에뮬레이터에서 테스트할 때는 Google Play 서비스가 포함된 시스템 이미지를 사용하는 것이 좋습니다. 또한 getFromLocationName()은 네트워크 호출이기 때문에 IOException 예외 처리가 필수이며, 최신 프로젝트에서는 android.support.v7.app.AppCompatActivity 대신 androidx.appcompat.app.AppCompatActivity를 사용하는 것을 권장합니다.