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

Android에서 네트워크 프로바이더(NETWORK_PROVIDER)로 현재 주소 가져오는 방법

개요

이 튜토리얼에서는 Android에서 LocationManager의 네트워크 프로바이더(NETWORK_PROVIDER)를 사용해 기기의 마지막으로 알려진 위치를 확인하고, Geocoder를 통해 해당 위도·경도 좌표를 실제 주소 문자열로 변환하는 방법을 단계별로 알아봅니다.

1단계: 새 프로젝트 생성

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

2단계: 레이아웃 파일 작성

res/layout/activity_main.xml에 아래 코드를 추가합니다.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="https://schemas.android.com/apk/res/android"
   xmlns:app="https://schemas.android.com/apk/res-auto"
   xmlns:tools="https://schemas.android.com/tools"
   android:layout_width="match_parent"
   android:gravity="center"
   android:layout_height="match_parent"
   tools:context=".MainActivity">
   <TextView
      android:id="@+id/text"
      android:textSize="30sp"
      android:layout_width="match_parent"
      android:layout_height="match_parent" />
</LinearLayout>

위 코드에서는 현재 주소를 화면에 표시하기 위해 TextView 하나를 배치했습니다.

3단계: MainActivity 작성

src/MainActivity.java에 아래 코드를 추가합니다.

package com.example.myapplication;

import android.Manifest;
import android.content.pm.PackageManager;
import android.location.Address;
import android.location.Geocoder;
import android.location.Location;
import android.location.LocationManager;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.RequiresApi;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AppCompatActivity;
import android.widget.TextView;

import java.io.IOException;
import java.util.List;

public class MainActivity extends AppCompatActivity {
   TextView textView;
   Location location;
   double describeContents;
   List<Address> addresses;
   Geocoder geocoder;

   @RequiresApi(api = Build.VERSION_CODES.P)
   @Override
   protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);
      textView = findViewById(R.id.text);
      LocationManager locationManager = (LocationManager) this.getSystemService(LOCATION_SERVICE);
      if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
         ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION}, 101);
      }
      location = locationManager
      .getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
      geocoder = new Geocoder(this);
   }

   @RequiresApi(api = Build.VERSION_CODES.O)
   @Override
   public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
      switch (requestCode) {
         case 101:
            if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
               if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
                  return;
               }
               try {
                  addresses = geocoder.getFromLocation(location.getLatitude(), location.getLongitude(), 10);
                  Address address = addresses.get(0);
                  textView.setText("" + address.getAddressLine(0));
               } catch (IOException e) {
                  e.printStackTrace();
               }
            } else {
               //not granted
            }
            break;
            default:
               super.onRequestPermissionsResult(requestCode, permissions, grantResults);
      }
   }

   @RequiresApi(api = Build.VERSION_CODES.O)
   @Override
   protected void onResume() {
      super.onResume();
      if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
         return;
      }
      try {
         addresses = geocoder.getFromLocation(location.getLatitude(), location.getLongitude(), 10);
         Address address = addresses.get(0);
         textView.setText("" + address.getAddressLine(0));
      } catch (IOException e) {
         e.printStackTrace();
      }
   }
}

위 코드의 핵심 동작 흐름은 다음과 같습니다.

  • 권한 확인 및 요청: ACCESS_FINE_LOCATIONACCESS_COARSE_LOCATION 권한이 부여되었는지 검사하고, 승인되지 않았다면 시스템 권한 다이얼로그를 띄운 뒤 결과를 onRequestPermissionsResult() 콜백에서 처리합니다.
  • 위치 조회: getLastKnownLocation(LocationManager.NETWORK_PROVIDER)를 호출하여 Wi-Fi 및 이동통신 기지국 정보를 기반으로 계산된 마지막 위치를 가져옵니다. GPS보다 빠르고 배터리 소모가 적다는 장점이 있습니다.
  • 주소 변환(역지오코딩): Geocoder.getFromLocation()에 위도와 경도를 전달하면 최대 10개의 주소 후보가 리스트로 반환되며, 그중 첫 번째 항목의 상세 주소(getAddressLine(0))를 TextView에 출력합니다.

4단계: 매니페스트 설정

AndroidManifest.xml에 아래 코드를 추가합니다.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="https://schemas.android.com/apk/res/android"
package="com.example.myapplication">

   <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
   <uses-permission android:name="android.permission.INTERNET"/>
   <uses-permission android:name="android.permission.READ_PHONE_STATE" />
   <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>

매니페스트에는 위치 권한 외에도, Geocoder가 내부적으로 온라인 지오코딩 서비스를 호출할 수 있도록 INTERNET 권한이 반드시 선언되어야 합니다. 런타임에서 ACCESS_FINE_LOCATION까지 요청하고 있으므로, 매니페스트에 해당 권한을 함께 추가해 두는 것이 안전합니다.

앱 실행 및 결과 확인

이제 앱을 실행해 보겠습니다. 실제 Android 기기를 컴퓨터에 연결한 상태에서 Android Studio 툴바의 Run 아이콘을 클릭하세요. 기기 목록에서 본인의 모바일 기기를 선택하면 앱이 설치·실행되고, 화면에 다음과 같이 현재 위치의 주소가 표시됩니다.

Android에서 네트워크 프로바이더(NETWORK_PROVIDER)로 현재 주소 가져오는 방법

추가 팁

  • getLastKnownLocation()은 캐시된 위치가 없을 경우 null을 반환할 수 있으므로, 실제 앱에서는 반드시 null 여부를 확인한 뒤 사용하는 것이 좋습니다.
  • Google Play Services를 사용할 수 있는 환경이라면, 더 정확하고 배터리 효율이 좋은 FusedLocationProviderClient API 사용을 권장합니다.