Firestore: 현재 위치와 시각 구해서 DB에 저장하기
</br>
이제 DB를 읽는 건 했으니 쓰는 작업을 해 보자~~
프로젝트에서, 사용자가 고양이를 목격해 버튼을 누르면 작은 마커를 생성하고 DB에 현재 위치와 시각으로 목격 정보를 저장하는 함수를 만들었다.
FusedLocationProviderClient fusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED){
permissionCheck();
return;
}
fusedLocationClient.getLastLocation()
.addOnSuccessListener(this, new OnSuccessListener<Location>() {
@Override
public void onSuccess(Location location) {
if( location != null ){
double latitude = location.getLatitude();
double longitude = location.getLongitude();
Log.d("LOCATIONTEST", "위도: " + String.valueOf(latitude) + ", 경도: " + String.valueOf(longitude));
Map<String, Object> data = new HashMap<>();
data.put("name", selected);
if( selected.equals("??") ){
data.put("type", "white");
}
else{
data.put("type", namesAndTypes.get(selected));
}
data.put("latitude", latitude);
data.put("longitude", longitude);
Date currentTime = Calendar.getInstance().getTime();
String yyyyMM = new SimpleDateFormat("yyyyMM", Locale.getDefault()).format(currentTime);
String dd = new SimpleDateFormat("dd", Locale.getDefault()).format(currentTime);
String detectedTime = new SimpleDateFormat("HH:mm", Locale.getDefault()).format(currentTime);
data.put("detectedTime", detectedTime);
Map<String, Object> newDoc = new HashMap<>();
newDoc.put("date", yyyyMM);
mDatabase.document("catSmallMarkers/" + yyyyMM)
.get()
.addOnCompleteListener(task -> {
if( task.isSuccessful() ){
Map<String, Object>
getDB = task.getResult().getData();
if( getDB == null ){
Log.d("DB Error", "Error get DB no data", task.getException());
mDatabase.document("catSmallMarkers/" + yyyyMM)
.set(newDoc)
.addOnSuccessListener(documentReference -> Log.d("ADD","new Doc"))
.addOnFailureListener(e -> Log.d("ADD","Error adding: ",e));
}
}
else{
Log.d("SHOW", "Error show DB", task.getException());
}
});
mDatabase.collection("catSmallMarkers/" + yyyyMM + "/" + dd)
.add(data)
.addOnSuccessListener(documentReference -> Log.d("ADD","Document added"))
.addOnFailureListener(e -> Log.d("ADD","Error adding: ",e));
}
}
});
DB에 고양이 이름, 타입과 현재 사용자의 위치와 시각으로 목격 정보를 저장하는 부분이다.
</br>
현재 위치 구하기
현재 위도와 경도를 구하기~~
처음에 구글맵 현재 위치, android GoogleMap current location 등 별의 별 검색어로 다 검색했지만 다 deprecated 함수라느니, 나오지 않았다…
https://developers.google.com/maps/documentation/android-sdk/location
자꾸 저 내 위치 레이어 추가해서 파란색으로 보여주는 거만 나옴…
알고 보니까 구글맵 기능을 안 쓰고 그냥 얻을 수 있었다! ㅋㅋ뻘짓함
FusedLocationProviderClient fusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED){
permissionCheck();
return;
}
fusedLocationClient.getLastLocation()
.addOnSuccessListener(this, new OnSuccessListener<Location>() {
@Override
public void onSuccess(Location location) {
if( location != null ){
double latitude = location.getLatitude();
double longitude = location.getLongitude();
Log.d("LOCATIONTEST", "위도: " + String.valueOf(latitude) + ", 경도: " + String.valueOf(longitude));
}
}
});
물론 위치 정보를 얻어야 하니 퍼미션 체크는 반드시 해야 한다.
.getLastLocation()
으로 마지막에 알려진 위치를 얻어 온다. gps를 켜고 있고 문제가 없다면 이게 현재 위치나 다름 없다.
</br>
현재 시각 구하기
Date currentTime = Calendar.getInstance().getTime();
String yyyyMM = new SimpleDateFormat("yyyyMM", Locale.getDefault()).format(currentTime);
String dd = new SimpleDateFormat("dd", Locale.getDefault()).format(currentTime);
String detectedTime = new SimpleDateFormat("HH:mm", Locale.getDefault()).format(currentTime);
자바의 SimpleDateFormat
을 사용한다. 포맷에 맞게 입력만 해 주면 잘 나온다.
문자 | 뜻 |
---|---|
y | 연도 |
M | 월(1~12) |
d | 일(1~31) |
H | 시(0~23) |
h | 시(1~12) |
m | 분(0~59) |
s | 초(0~59) |
대충 잘 쓰이는 것들~~ 더 보려면 구글에 SimpleDateFormat 검색
</br>
DB에 쓰기
Map<String, Object> data = new HashMap<>();
// ***********
put some data
// ***********
mDatabase.collection(collectionPath)
.add(data)
.addOnSuccessListener(documentReference -> Log.d("ADD","Document added"))
.addOnFailureListener(e -> Log.d("ADD","Error adding: ",e));
Map<String, Object>
에 데이터들을 넣고, 컬렉션 또는 문서를 그냥 추가해 주면 됨~~
문서를 추가하는 함수는 .add()
와 .set()
두 가지가 있다.
add()와 set()의 차이
간단함!! .set()
은 문서의 ID를 사용자가 지정해서 문서를 추가할 때이고, .add()
는 ID를 자동 생성해서 문서를 추가한다.
즉 .add()
는 문서의 ID를 별도로 지정할 필요가 없을 때 사용함.
// *********** 1
mDatabase.collection(collectionPath)
.document(documentName)
.set(data);
// *********** 2
mDatabase.document(collectionPath/documentName)
.set(data);
// *********** 3
mDatabase.collection(collectionPath)
.document()
.set(data);
// *********** 4
mDatabase.collection(collectionPath)
.add(data);
위 코드에서 1과 2가 같고, 3과 4가 같다.
1, 2는 collectionPath에 documentName이라는 ID의 문서를 추가한다.
3, 4는 collectionPath에 임의의 자동 생성된 ID의 문서를 추가한다.
</br>
주의할 점
예를 들어 내 프로젝트의 경우 작은 마커 정보들을 위와 같이 [ 연월 - 일 - 각 데이터가 담긴 문서들 ]로 구분할 필요가 있었다.
즉 [ 컬렉션 - 문서(연월) - 컬렉션(일) - 문서(데이터) ]의 중첩된 구조.
그렇다면
mDatabase.collection("catSmallMarkers/" + yyyyMM + "/" + dd)
.add(data);
이렇게 패스를 중첩해서 대충 새로 만들어 주면 잘 돌아갈까? 가 문제인데… 그냥 이러면 안 된다!!
이미 문서가 만들어진 상태에서 추가하는 건 상관없다. 그러나 예를 들어 7월의 1일, 컬렉션에 새로 ( 컬렉션/202107/01/정보 )를 넣는다면, 문서(연월, 202107)이 비어 있는 문서가 될 수 있기 때문…
위 사진은 ( temp/empty?/isEmpty?/a )로 컬렉션 temp에 바로 패스를 통해 a를 추가한 모습이다.
즉 컬렉션 temp에 empty?라는 문서는 없는데 바로 mDatabase.collection("temp/empty?/isEmpty?/a").set(data)
로 a를 추가함.
이 문서에 데이터가 없다고 적혀 있는데, 실제로 돌려 보면 잘 안 돌아간다. 문서를 설명하는 데이터는 꼭 있어야 해서 그렇다는 것 같다.
Map<String, Object> newDoc = new HashMap<>();
newDoc.put("date", yyyyMM);
mDatabase.document("catSmallMarkers/" + yyyyMM)
.get()
.addOnCompleteListener(task -> {
if( task.isSuccessful() ){
Map<String, Object>
getDB = task.getResult().getData();
// catSmallMarkers 컬렉션에 yyyyMM라는 문서가 있는 지 확인한다.
if( getDB == null ){ // 없으면 set으로 문서를 만든다.
Log.d("DB Error", "Error get DB no data", task.getException());
mDatabase.document("catSmallMarkers/" + yyyyMM)
.set(newDoc)
.addOnSuccessListener(documentReference -> Log.d("ADD","new Doc"))
.addOnFailureListener(e -> Log.d("ADD","Error adding: ",e));
}
}
else{
Log.d("SHOW", "Error show DB", task.getException());
}
});
// 이후 정상적으로 dd(날짜) 컬렉션에 data를 담은 문서 추가.
Map<String, Object> data = new HashMap<>();
// ***********
put some data
// ***********
mDatabase.collection("catSmallMarkers/" + yyyyMM + "/" + dd)
.add(data)
.addOnSuccessListener(documentReference -> Log.d("ADD","Document added"))
.addOnFailureListener(e -> Log.d("ADD","Error adding: ",e));
null 체크 한 번 해주는 거랑 비슷하다고 보면 될 듯~~
댓글남기기