지오코딩 GeoCoding (주소,지명 ↔ 위도,경도 변환) 예제
안드로이드: 지오코딩 GeoCoding (주소,지명 ↔ 위도,경도 변환)
지오코딩(GeoCoding) 이란 '주소나 지명' 을 '좌표 (위도, 경도)' 로 변환시키는 작업이다. 혹은 반대로 '좌표(위도, 경도)' 를 '주소나 지명' 으로 변환하는 작업 (역 지오코딩: Reverse GeoCoding) 이라 한다.
예를 들면 '서울 시청' 을 지오코딩 하면 좌표가 ( 37.56647, 126.977963 ) 이 튀어 나오는 겁니다.
사실 이런 서비스는 이미 구글맵 등에서도 제공되었죠. 구글맵에서 특정 지점 위에서 마우스우클릭 - '이곳이 궁금한가요?' 실행하면 위도, 경도 가 나왔죠.
지오코딩 서비스는 역시 안드로이드 플랫폼을 만든 구글 답게 구글에서 제공해주는 거고, 안드로이드 API 에 Geocoder 객체 + Address 객체 를 통해 서비스 사용이 가능합니다.
안드로이드에서 지오코딩을 구현하는 주요 Step 은 다음과 같습니다.
Step1 : 메니페스트 파일에 인터넷(INTERNET) 과 위치정보 서비스(ACCESS_FINE_LOCATION) 권한을 받아옵니다
Step2 : Geocoder 객체 생성
Step3 : '좌표(위도, 경도)' 를 '주소나 지명' 으로 변환하는 경우
getFromLocation() 메소드 사용. 결과는 List<Address> 형태
: '주소나 지명' 을 '좌표(위도, 경도)' 으로 변환하는 경우
getFromLocationName() 메소드 사용. 결과는 List<Address> 형태
Step4 : Address 객체의 toString(), getCountryName(), getLatitude(), getLongitude(), getPostalCode(), getPhone() 메소드 등을 통해 세부정보 추출 가능
아래 에제에서는
1) '좌표(위도, 경도)' 를 '주소나 지명' 변환
2) '주소나 지명' 을 '좌표(위도, 경도)' 으로 변환
두가지를 해볼거고, 각각에 대해 변환된 문자열 출력과, 변환된 위도,경도 좌표를 통해 지도를 보여주는 것을 구현해봅니다. 이때 지도는 묵시적 인텐트 (implicit intent) 로 호출합니다. (묵시적 인텐트 에 대해서는 지난 포스팅 참조 → 클릭)
[AndroidManifest.xml]
인터넷(INTERNET) 과 위치정보 서비스(ACCESS_FINE_LOCATION) 권한을 받아옵니다
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.INTERNET"/>
[activity_main.xml]
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:text="위도"
android:textAppearance="?android:attr/textAppearanceLarge" />
<EditText
android:id="@+id/editText1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:ems="10"
android:inputType="numberDecimal" />
<EditText
android:id="@+id/editText2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/editText1"
android:layout_alignTop="@+id/textView2"
android:ems="10"
android:inputType="numberDecimal" />
<TextView
android:id="@+id/textView3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_below="@+id/editText2"
android:layout_marginTop="26dp"
android:text="주소"
android:textAppearance="?android:attr/textAppearanceLarge" />
<EditText
android:id="@+id/editText3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/editText2"
android:layout_alignTop="@+id/textView3"
android:ems="10" >
<requestFocus />
</EditText>
<TextView
android:id="@+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_below="@+id/editText1"
android:layout_marginTop="22dp"
android:text="경도"
android:textAppearance="?android:attr/textAppearanceLarge" />
<Button
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBaseline="@+id/editText2"
android:layout_alignBottom="@+id/editText2"
android:layout_alignParentRight="true"
android:text="변환1" />
<Button
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBaseline="@+id/textView3"
android:layout_alignBottom="@+id/textView3"
android:layout_alignParentRight="true"
android:text="변환2" />
<TextView
android:id="@+id/textView4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:layout_below="@+id/button2"
android:layout_marginTop="28dp"
android:text="조회한 주소정보 출력"
android:textAppearance="?android:attr/textAppearanceMedium" />
<Button
android:id="@+id/button3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="@+id/editText2"
android:layout_alignRight="@+id/editText2"
android:text="지도1" />
<Button
android:id="@+id/button4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBaseline="@+id/editText3"
android:layout_alignBottom="@+id/editText3"
android:layout_alignRight="@+id/editText3"
android:text="지도2" />
</RelativeLayout>
[MainActiviy.java]
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 지오코딩(GeoCoding) : 주소,지명 => 위도,경도 좌표로 변환
// 위치정보를 얻기위한 권한을 획득, AndroidManifest.xml
// ACCESS_FINE_LOCATION : 현재 나의 위치를 얻기 위해서 필요함
// INTERNET : 구글서버에 접근하기위해서 필요함
final TextView tv = (TextView) findViewById(R.id.textView4); // 결과창
Button b1 = (Button)findViewById(R.id.button1);
Button b2 = (Button)findViewById(R.id.button2);
Button b3 = (Button)findViewById(R.id.button3);
Button b4 = (Button)findViewById(R.id.button4);
final EditText et1 = (EditText)findViewById(R.id.editText1);
final EditText et2 = (EditText)findViewById(R.id.editText2);
final EditText et3 = (EditText)findViewById(R.id.editText3);
final Geocoder geocoder = new Geocoder(this);
b1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 위도,경도 입력 후 변환 버튼 클릭
List<Address> list = null;
try {
double d1 = Double.parseDouble(et1.getText().toString());
double d2 = Double.parseDouble(et2.getText().toString());
list = geocoder.getFromLocation(
d1, // 위도
d2, // 경도
10); // 얻어올 값의 개수
} catch (IOException e) {
e.printStackTrace();
Log.e("test", "입출력 오류 - 서버에서 주소변환시 에러발생");
}
if (list != null) {
if (list.size()==0) {
tv.setText("해당되는 주소 정보는 없습니다");
} else {
tv.setText(list.get(0).toString());
}
}
}
});
b2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
List<Address> list = null;
String str = et3.getText().toString();
try {
list = geocoder.getFromLocationName(
str, // 지역 이름
10); // 읽을 개수
} catch (IOException e) {
e.printStackTrace();
Log.e("test","입출력 오류 - 서버에서 주소변환시 에러발생");
}
if (list != null) {
if (list.size() == 0) {
tv.setText("해당되는 주소 정보는 없습니다");
} else {
tv.setText(list.get(0).toString());
// list.get(0).getCountryName(); // 국가명
// list.get(0).getLatitude(); // 위도
// list.get(0).getLongitude(); // 경도
}
}
}
});
b3.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 위도,경도 입력 후 지도 버튼 클릭 => 지도화면으로 인텐트 날리기
double d1 = Double.parseDouble(et1.getText().toString());
double d2 = Double.parseDouble(et2.getText().toString());
Intent intent = new Intent(
Intent.ACTION_VIEW,
Uri.parse("geo:" + d1 + "," + d2));
startActivity(intent);
}
});
b4.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 주소입력후 지도2버튼 클릭시 해당 위도경도값의 지도화면으로 이동
List<Address> list = null;
String str = et3.getText().toString();
try {
list = geocoder.getFromLocationName
(str, // 지역 이름
10); // 읽을 개수
} catch (IOException e) {
e.printStackTrace();
Log.e("test","입출력 오류 - 서버에서 주소변환시 에러발생");
}
if (list != null) {
if (list.size() == 0) {
tv.setText("해당되는 주소 정보는 없습니다");
} else {
// 해당되는 주소로 인텐트 날리기
Address addr = list.get(0);
double lat = addr.getLatitude();
double lon = addr.getLongitude();
String sss = String.format("geo:%f,%f", lat, lon);
Intent intent = new Intent(
Intent.ACTION_VIEW,
Uri.parse(sss));
startActivity(intent);
}
}
}
});
} // end of onCreate
} // end of class
[실행화면]
위 시작화면에서 적절한 주소, 혹은 지명 등을 입력하고 [변환2] 버튼을 누르면
아래와 같이 지오코딩 된 전체정보를 볼수 있습니다. toString() 결과값
한변 [지도2] 버튼을 누르면, 아래와 같이 지도 앱으로 묵시적인텐트를 날려서
해당 지도앱이 넘겨받은 위도,경도 값으로 지도 표시를 합니다.
반면 상단의 위도, 경도 값을 직접 입력하고 [변환1] 을 누르면 이또한 지오코딩이 된 결과값이 나옵니다.
출처: https://bitsoul.tistory.com/135 [Happy Programmer~]
'프로그래밍 > Android (Java)' 카테고리의 다른 글
android 에서 기기에 저장된 파일 이름 변경하기 (0) | 2019.09.20 |
---|---|
안드로이드 파일공유 PROVIDER (0) | 2019.09.16 |
폴리라인 (polyline) 그리기 (0) | 2019.09.05 |
권한 여부 체크하기 (0) | 2019.09.04 |
저장소 파일 불러올 때 읽기 권한 요청 설정 (0) | 2019.09.04 |