안녕하세요! @gbgg입니다.
이번 포스팅에서는 가장 가까운 위치에 있는 유저를 찾기위한 사전작업을 진행해볼까 합니다.
GPS, WiFI를 통해 현재 위치의 경도, 위도를 알아낸 뒤 이 값으로 현재 위치 값을 표시해 보겠습니다.
다음 포스팅에서는 경도, 위도, 주소값을 파이어베이스 데이터베이스에 저장하고 가장 가까운 거리에 있는 유저를 찾아보겠습니다.
제가 전문가가 아니다보니 부족한 점이나 잘못된 부분이 있을 수 있습니다. 피드백 주시면 즉시 반영하겠습니다.
실시간 데이터베이스
개발할 앱/웹 등이 정보를 제공하거나 받아와야 할 경우, 또는 데이터를 주고 받아야 할 경우 등등 데이터베이스 기능은 개발에 있어 필수라고 생각합니다. 파이어베이스에서는 다양한 백엔드 서비스를 제공하고 있는데 그 중 가장 대표적인 기능이 '실시간 데이터베이스' 입니다.
이번 포스팅에서는 GPS, WIFI를 통해 현재 위치의 위도와 경도를 알아낸 뒤 이 데이터들도 주소값까지 추출해보겠습니다.
이번 포스팅은 다음 포스팅에서의 거리 측정 작업을 위한 안드로이드 앱 개발 포스팅입니다. 파이어베이스에 관한 내용은 없습니다.
준비물
1. Google 계정
2. Android Studio 1.5 이상
앱 개발을 위해 안드로이드 스튜디오를 설치하였습니다.
위 링크로 들어가셔서 다운받으시면 됩니다.
먼저 어떤식으로 가까운 유저를 찾아낼 지 간략하게 구성도로 표시해보겠습니다.
파이어베이스에서 데이터를 전송한다기보다는 앱에서 호출한다고 볼 수 있습니다. 다만 이해를 위해 위와 같이 표시해 보았습니다.
앱에서 현재 유저의 위도, 경도, 주소 값을 업데이트하여 특정 child에 전송합니다.
이 값들은 파이어베이스의 한 child에 쌓여있고 앱에서 자신의 토큰값을 가진 child의 위도 경도 값과 다른 모든 유저들의 위도 경도 값을 대조하여 가장 가까운 유저를 찾아냅니다.
찾아낸 유저의 토큰값으로 해당 유저정보를 가져오고 거리를 표시합니다.
유저와의 거리 측정은 생각보다 많은 어플리케이션에서 사용됩니다.
근처 맛집을 찾아주는 앱, 주변 사용자를 찾아주는 채팅 앱 등등 많은 앱에서 상호간의 거리를 측정하여 위치와 정보를 표시하는 등 다양하게 사용되고 있습니다.
이러한 기능들을 파이어베이스를 통해 아주아주 간단하게 구현해 보겠습니다.
구현에 앞서 앱에서 위도와 경도, 주소값을 알아내야합니다. 그 부분부터 진행해보겠습니다.
가장 먼저 위도와 경도를 표시할 EditText 2개와 버튼 두개를 생성해보겠습니다.
지난 포스팅에서 진행했던 부분 아래에 추가하였습니다. 파란색으로 드래그해둔 부분만 생성하시면 됩니다.
위도와 경도를 찾기 위해서는 인터넷과 위치정보서비스 두 가지 권한이 필요합니다.
좌측에 있는 메뉴에서 [AndroidManifest.xml] 을 클릭합니다.
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
위 두가지 퍼미션을 추가합니다.
API 23: Android 6.0 (Marshmallow)버젼 이상에서 작업 시 'Call requires permission which may be rejected by user' 에러가 발생할 수 있습니다.
이럴 땐 위 사진 처럼 아래 퍼미션도 추가해주면 됩니다.
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
좌측에 있는 메뉴에서 [MainActivity.java] 를 클릭합니다.
위 앱디자인에서 생성한 버튼 view들을 연결하기 위해 Button 2개와 EditText 2개, 위도 경도값 저장을 위한 Double형 변수 2개를 선언합니다.
private Button sendbt_location;
private Button sendbt_location2;
private EditText editdt_latitude;
private EditText editdt_longitude;
private Double longitude = null;
private Double latitude = null;
onCreate 아래에 View 4개를 연결하겠습니다.
뷰 이름은 각각 editdt_latitude, editdt_longitude, sendbt_location, sendbt_location2로 설정하였습니다.
editdt_latitude = (EditText) findViewById(R.id.editText3);
editdt_longitude = (EditText) findViewById(R.id.editText4);
sendbt_location = (Button) findViewById(R.id.button4);
sendbt_location2 = (Button) findViewById(R.id.button5);
sendbt_location 에 대한 클릭 리스너를 생성한 뒤 위치 갱신을 위한 메소드를 입력합니다.
위치 공급자는 네트워크로, 메소드명은 'locationListener'로 설정하겠습니다.
sendbt_location.setOnClickListener(new Button.OnClickListener() {
public void onClick(View v) {
LocationManager lm = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
lm.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,100,1, locationListener);
}
});
locationListener에 대한 클래스를 생성하였습니다.
location에 관한 이벤트는 위와 같이 여러가지가 있습니다. 이 중 위도와 경도만 사용하였습니다.
처음에 생성한 Double형 변수에 longitude = location.getLongitude(); 값을 저장합니다.
editdt_latitude.setText("" + longitude); EditText에는 setText를 사용하여 값을 넣어보겠습니다.
private LocationListener locationListener = new LocationListener() {
@Override
public void onLocationChanged(Location location) {
longitude = location.getLongitude();
latitude = location.getLatitude();
editdt_latitude.setText("" + longitude);
editdt_longitude.setText("" + latitude);
}
@Override
public void onProviderDisabled(String provider) {}
@Override
public void onProviderEnabled(String provider) {}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {}
};
이제 위도와 경도 값은 EditText에 표시됩니다. 이 값을 사용하여 주소 값을 가져오려면 우선 갱신을 멈춰야합니다.
lm.removeUpdates(locationListener); 이 명령어를 넣으면 위치갱신이 중단됩니다.
위치 갱신을 중단한 후 getLocation 메소드를 호출하여 주소값을 가져와보겠습니다.
버튼2에 대한 리스너를 생성하고 다음과 같이 입력합니다.
sendbt_location2.setOnClickListener(new Button.OnClickListener() {
public void onClick(View v) {
LocationManager lm = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
lm.removeUpdates(locationListener);
getLocation(latitude,longitude);
}
});
lat, lng 인자값을 갖는 getLocation 를 생성합니다.
Geocoder geocoder = new Geocoder(this, Locale.KOREAN);
구글에서 제공하는 GeoCoding 서비스는 좌표(위도, 경도)를 주소로 변환하거나 반대로 주소를 좌표(위도,경도)로 변환시켜주는 서비스입니다.
이 서비스를 사용하기 위해 Geocoder 객체를 생성합니다.
List<Address> addresses = geocoder.getFromLocation(lat, lng, 1);
getFromLocation(위도, 경도, 얻을 값의 개수)
다음과 같이 입력합니다.
public void getLocation(double lat, double lng){
String addressString = null;
Geocoder geocoder = new Geocoder(this, Locale.KOREAN);
try {
List<Address> addresses = geocoder.getFromLocation(lat, lng, 1);
if (addresses.size() > 0) {
addressString = addresses.get(0).toString();
}
} catch (IOException e) {
e.printStackTrace();
}
System.out.println(addressString);
}
자! 완료되었습니다.
위,경도받기 버튼을 누르면 EditText에 위도와 경도 값이 표시되고
주소 받기 버튼을 누르면 addressString 변수에 주소값이 전달됩니다.
위도와 경도 값을 받은 결과입니다.
주소받기 버튼을 클릭하면 갱신이 중단됩니다.
addressString 값을 표기한 결과입니다.
아파트 동호수까지 상세하게 나오길래 어쩔수 없이 모자이크처리 했습니다;;
Firebase 실시간 데이터베이스
이번 포스팅에서 얻은 데이터들을 이제 파이어베이스와 연동하여 가장 가까운 유저를 찾아보겠습니다.
다음 포스팅에서 찾아뵙겠습니다! @gbgg
지난 포스팅
[Firebase] 1. 혁신적인 백엔드플랫폼 파이어베이스(Firebase)
[Firebase] 2. 파이어베이스(Firebase) 실시간 데이터베이스에 데이터 쓰기 (app)
[Firebase] 3. 파이어베이스(Firebase) 실시간 데이터베이스 불러오기, 리스트에 내용 표시하기
[Firebase] 4. 파이어베이스(Firebase) 실시간 데이터베이스. Token값으로 UserProfile 관리하기