[출처: https://developer.android.com/training/location/index.html]
Google Play Services SDK 다운로드 및 설치
프로젝트에 Google Play Services 라이브러리 추가
새로운 빌드 규칙 추가
dependencies {
...
implementation 'com.google.android.gms:play-services-location:18.0.0'
}
툴바에서 Sync Project with Graddle File
또는 Sync Now
클릭
[출처: https://developers.google.com/android/guides/setup]
Android Manifest 파일에서 권한 설정
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.kwanwoo.android.locationservice" >
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
</manifest>
Android 6.0 (API level 23) 이상부터는 앱 실행 중에 사용하려는 권한(permission)을 반드시 요청
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(
MainActivity.this, // MainActivity 액티비티의 객체 인스턴스를 나타냄
new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, // 요청할 권한 목록을 설정한 String 배열
REQUEST_PERMISSIONS_FOR_LOCATION_UPDATES // 사용자 정의 int 상수. 권한 요청 결과를 받을 때
);
return;
}
액티비티 onCreate()메소드에서 다음 코드를 통해 통합 위치 정보 제공자 (Fused Location Provider) 클라이언트 객체를 얻어온다.
private FusedLocationProviderClient mFusedLocationClient;
@Override
protected void onCreate(Bundle savedInstanceState) {
//...
mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
//...
}
public class MainActivity extends AppCompatActivity {
private FusedLocationProviderClient mFusedLocationClient;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
Button get_last_location_button = (Button) findViewById(R.id.get_last_location_button);
get_last_location_button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
getLastLocation();
}
});
}
private void getLastLocation() {
// to be defined
}
}
FusedLocationProvider의 getLastLocation() 메소드 이용
위치 접근에 필요한 권한 설정
getLastLocation() 메소드를 호출하면 Task 객체를 반환
Task가 성공적으로 완료 후 호출되는 OnSuccessListener 등록
onSuccess() 메소드를 통해 디바이스에 마지막으로 알려진 위치를 Location 객체 (위도, 경도, 정확도, 고도 값 등을 얻을 수 있음)로 받음
private void getLastLocation() {
// 1. 위치 접근에 필요한 권한 검사 및 요청
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(
MainActivity.this, // MainActivity 액티비티의 객체 인스턴스를 나타냄
new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, // 요청할 권한 목록을 설정한 String 배열
REQUEST_PERMISSIONS_FOR_LAST_KNOWN_LOCATION // 사용자 정의 int 상수. 권한 요청 결과를 받을 때
);
return;
}
// 2. Task<Location> 객체 반환
Task task = mFusedLocationClient.getLastLocation();
// 3. Task가 성공적으로 완료 후 호출되는 OnSuccessListener 등록
task.addOnSuccessListener(this, new OnSuccessListener<Location>() {
@Override
public void onSuccess(Location location) {
// 4. 마지막으로 알려진 위치(location 객체)를 얻음.
if (location != null) {
mLastLocation = location;
updateUI();
} else
Toast.makeText(getApplicationContext(),
"No location detected",
Toast.LENGTH_SHORT)
.show();
}
});
}
private void updateUI() {
double latitude = 0.0;
double longitude = 0.0;
float precision = 0.0f;
TextView latitudeTextView = (TextView) findViewById(R.id.latitude_text);
TextView longitudeTextView = (TextView) findViewById(R.id.longitude_text);
TextView precisionTextView = (TextView) findViewById(R.id.precision_text);
if (mLastLocation != null) {
latitude = mLastLocation.getLatitude();
longitude = mLastLocation.getLongitude();
precision = mLastLocation.getAccuracy();
}
latitudeTextView.setText("Latitude: " + latitude);
longitudeTextView.setText("Longitude: " + longitude);
precisionTextView.setText("Precision: " + precision);
}
업데이트 중지 버튼 클릭시,
private Button mStartUpdatesButton;
private Button mStopUpdatesButton;
private boolean mRequestingLocationUpdates;
@Override
protected void onCreate(Bundle savedInstanceState) {
// ...
mStartUpdatesButton = findViewById(R.id.start_updates_button);
mStartUpdatesButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (!mRequestingLocationUpdates) {
startLocationUpdates();
mRequestingLocationUpdates = true;
mStartUpdatesButton.setEnabled(false);
mStopUpdatesButton.setEnabled(true);
}
}
});
mStopUpdatesButton = findViewById(R.id.stop_updates_button);
mStopUpdatesButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (mRequestingLocationUpdates) {
stopLocationUpdates();
mRequestingLocationUpdates = false;
mStartUpdatesButton.setEnabled(true);
mStopUpdatesButton.setEnabled(false);
}
}
});
}
private LocationCallback mLocationCallback;
final private int REQUEST_PERMISSIONS_FOR_LOCATION_UPDATES = 101;
private void startLocationUpdates() {
// 1. 위치 요청 (Location Request) 설정
LocationRequest locRequest = LocationRequest.create();
locRequest.setInterval(10000);
locRequest.setFastestInterval(5000);
locRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
// 2. 위치 업데이트 콜백 정의
mLocationCallback = new LocationCallback() {
@Override
public void onLocationResult(LocationResult locationResult) {
super.onLocationResult(locationResult);
mLastLocation = locationResult.getLastLocation();
updateUI();
}
};
// 3. 위치 접근에 필요한 권한 검사
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(
MainActivity.this, // MainActivity 액티비티의 객체 인스턴스를 나타냄
new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, // 요청할 권한 목록을 설정한 String 배열
REQUEST_PERMISSIONS_FOR_LOCATION_UPDATES // 사용자 정의 int 상수. 권한 요청 결과를 받을 때
);
return;
}
// 4. 위치 업데이트 요청
mFusedLocationClient.requestLocationUpdates(locRequest,
mLocationCallback,
null /* Looper */);
}
통합 위치 정보 제공자에 위치 요청에 대한 설정을 지정하려면, LocationRequest 객체를 생성하고, 다음 메소드를 통해서 파라미터를 설정
LocationRequest locRequest = LocationRequest.create();
locRequest.setInterval(10000); // 10초 보다 빠를 수도 느릴 수도 있음
locRequest.setFastestInterval(5000); // 5초 보다 더 빠를 순 없음
locRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
통합 위치 정보 제공자 (Fused Location Provider)는 위치 정보가 가용할 때, 설정된 LocationCallback 객체의 onLocationResult(LocationResult result) 콜백 메소드를 호출
mLocationCallback = new LocationCallback() {
@Override
public void onLocationResult(LocationResult locationResult) {
for (Location location : locationResult.getLocations()) {
// Update UI with location data
// ...
}
};
};
[사전 조건]
mFusedLocationClient.requestLocationUpdates(
mLocationRequest, // LocationRequest 객체
mLocationCallback, // LocationCallback 객체
null // looper
);
위치 업데이트 중단
public void stopLocationUpdates() {
mFusedLocationClient.removeLocationUpdates(mLocationCallback);
}
Geocoding 방법
Address class:
protected void onCreate(Bundle savedInstanceState) {
// ...
Button getAddressButton = (Button) findViewById(R.id.address_button);
getAddressButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
getAddress();
}
});
}
private void getAddress() {
TextView addressTextView = (TextView) findViewById(R.id.address_text);
try {
Geocoder geocoder = new Geocoder(this, Locale.KOREA);
List<Address> addresses = geocoder.getFromLocation(mLastLocation.getLatitude(),mLastLocation.getLongitude(),1);
if (addresses.size() >0) {
Address address = addresses.get(0);
addressTextView.setText(String.format("\n[%s]\n[%s]\n[%s]\n[%s]",
address.getFeatureName(),
address.getThoroughfare(),
address.getLocality(),
address.getCountryName()
));
}
} catch (IOException e) {
Log.e(TAG, "Failed in using Geocoder",e);
}
}
https://github.com/kwanulee/AndroidProgramming/blob/master/examples/LocationService/app/src/main/java/com/kwanwoo/android/locationservice/MainActivity.java#L89-L95 https://github.com/kwanulee/AndroidProgramming/blob/master/examples/LocationService/app/src/main/java/com/kwanwoo/android/locationservice/MainActivity.java#L211-L229
try {
Geocoder geocoder = new Geocoder(this, Locale.KOREA);
* List<Address> addresses = geocoder.getFromLocationName(input,1);
if (addresses.size() >0) {
Address bestResult = (Address) addresses.get(0);
mResultText.setText(String.format("[ %s , %s ]",
bestResult.getLatitude(),
bestResult.getLongitude()));
}
} catch (IOException e) {
Log.e(getClass().toString(),"Failed in using Geocoder.", e);
return;
}