住所・地名・施設名などで検索を行い、画面の地図を移動させられるようにしました #260

Merged w-katsumasa merged 1 commit into nitta-lab-2023:master from nitta-lab-2023:search_location on 5 Oct 2023
Showing 3 changed files
View
1
■■■■
app/src/main/AndroidManifest.xml
package="com.example.nemophila">
 
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.INTERNET"/>
<application
android:name=".Nemophila"
android:allowBackup="true"
View
65
app/src/main/java/com/example/nemophila/MapsActivity.java
import com.example.nemophila.entities.AccountNameJson;
import com.example.nemophila.entities.Shop;
import com.example.nemophila.viewmodels.FriendViewModel;
import com.example.nemophila.viewmodels.ShopsViewModel;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;
import com.google.android.material.navigation.NavigationView;
 
import java.util.ArrayList;
import java.util.Collection;
 
// geocode Test
handler = new Handler();
 
// // 検索バーの処理
// SearchView searchView = findViewById(R.id.tool_search);
// searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
// @Override
// public boolean onQueryTextSubmit(String query) {
// new Thread(() -> {
// geoCode(query);
// }).start();
// return false;
// }
//
// @Override
// public boolean onQueryTextChange(String newText) {
// return false;
// }
// });
// 検索バーの処理
SearchView searchView = findViewById(R.id.tool_search);
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
 
//文字列を入力後にEnterなど、検索確定したとき
@Override
public boolean onQueryTextSubmit(String query) {
if(query == null) {
Toast.makeText(MapsActivity.this,
String.format("住所や施設名を入力してください"),
Toast.LENGTH_SHORT)
.show();
} else {
System.out.println("------検索内容---------");
System.out.println(query);
System.out.println("----------------------");
//mapsFragment側で地名検索,見つかった場合はその地点に画面移動
mapsFragment.SeachLocation(query);
}
return false;
}
 
//検索文字に変化があったとき
@Override
public boolean onQueryTextChange(String newText) {
System.out.println("------文字列変化検出------");
System.out.println(newText);
System.out.println("----------------------");
return false;
}
});
 
//filterDialog = new FilterDialog();
 
// サイドメニューのボタン
View
278
app/src/main/java/com/example/nemophila/MapsFragment.java
import android.graphics.drawable.Drawable;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.AsyncTask;
import android.os.Bundle;
import android.provider.Settings;
import android.util.Log;
import android.view.LayoutInflater;
import android.widget.ImageButton;
import android.widget.TextView;
import android.widget.Toast;
 
import android.content.Context;
import android.location.Address;
import android.location.Geocoder;
import android.text.TextUtils;
import java.io.IOException;
import java.util.List;
import java.util.Locale;
 
import com.example.nemophila.databinding.ActivityMainBinding;
import com.example.nemophila.entities.AccountNameJson;
import com.example.nemophila.entities.Post;
import com.example.nemophila.entities.Shop;
import com.example.nemophila.viewmodels.PostsViewModel;
import com.example.nemophila.viewmodels.ShopsViewModel;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.maps.*;
import com.google.maps.model.GeocodingResult;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.BitmapDescriptor;
import com.google.android.gms.maps.model.BitmapDescriptorFactory;
PostsViewModel postsViewModel;
 
Nemophila nemophila;
private GoogleMap mMap;
private GeoApiContext geoApiContext;
private ActivityMainBinding binding;
private LatLng currentLatlng = null;
private LatLng initialLatlng;
private LatLng shopLatlng;
}
});
 
 
 
// 店情報の更新が入った時の処理(LiveDataへの購読)
shopsViewModel.getShopsLiveData().observe(getActivity(), shops -> {
Toast.makeText(getActivity(),
String.format("表示していない店を確認しました。ピンを立てます"),
Toast.LENGTH_SHORT)
.show();
for (Shop shop : shops) {
if ( shopsViewModel.getMarker(shop) == null) { //フレンド以外の投稿のピンも立てたい場合
//各shopに対応するMarkerがなければMarkerを立てる
shopLatlng = new LatLng(shop.getLatitude(), shop.getLongitude());
System.out.println(shopLatlng);
Marker createMarker = mMap.addMarker(new MarkerOptions().position(shopLatlng).title(""));
//マーカーに店情報を持たせる
createMarker.setTag(shop);
 
//ShopToMarkerに紐づけ
shopsViewModel.setShopAndMarker(shop, createMarker);
System.out.println(friendsData);
 
ArrayList<String> userIdSet = (ArrayList<String>)shop.getUserIdSet().clone();
friendsData.add(nemophila.getUid());
userIdSet.retainAll(friendsData);
 
//自分とそのフレンド以外の投稿は確認しない
if( userIdSet.size() > 0) {
//場合分け
//フィルターを一切かけていないとき
if(nemophila.getSelectGenres().isEmpty() && nemophila.getSelectFriends().isEmpty()){
createMarker.setVisible(true);
for (Shop shop : shops) {
if (shopsViewModel.getMarker(shop) == null) { //フレンド以外の投稿のピンも立てたい場合
//各shopに対応するMarkerがなければMarkerを立てる
shopLatlng = new LatLng(shop.getLatitude(), shop.getLongitude());
System.out.println(shopLatlng);
Marker createMarker = mMap.addMarker(new MarkerOptions().position(shopLatlng).title(""));
//マーカーに店情報を持たせる
createMarker.setTag(shop);
 
//ShopToMarkerに紐づけ
shopsViewModel.setShopAndMarker(shop, createMarker);
System.out.println(friendsData);
 
ArrayList<String> userIdSet = (ArrayList<String>) shop.getUserIdSet().clone();
friendsData.add(nemophila.getUid());
userIdSet.retainAll(friendsData);
 
//自分とそのフレンド以外の投稿は確認しない
if (userIdSet.size() > 0) {
//場合分け
//フィルターを一切かけていないとき
if (nemophila.getSelectGenres().isEmpty() && nemophila.getSelectFriends().isEmpty()) {
createMarker.setVisible(true);
}
//ジャンルのみフィルターをかけているとき
else if (nemophila.getSelectFriends().isEmpty()) {
for (String genre : nemophila.getSelectGenres()) {
if (shop.getGenreSet().contains(genre)) {
createMarker.setVisible(true);
break;
} else {
createMarker.setVisible(false);
}
}
//ジャンルのみフィルターをかけているとき
else if(nemophila.getSelectFriends().isEmpty()) {
for(String genre : nemophila.getSelectGenres()) {
if(shop.getGenreSet().contains(genre)) {
}
//フレンドのみフィルターをかけているとき
else if (nemophila.getSelectGenres().isEmpty()) {
for (String friendId : nemophila.getSelectFriends()) {
if (shop.getUserIdSet().contains(friendId)) {
createMarker.setVisible(true);
break;
} else {
createMarker.setVisible(false);
}
}
}
//どちらもフィルターをかけているとき
else {
for (String genre : nemophila.getSelectGenres()) {
for (String friendId : nemophila.getSelectFriends()) {
if (shop.getGenreSet().contains(genre) && shop.getUserIdSet().contains(friendId)) {
createMarker.setVisible(true);
break;
} else {
createMarker.setVisible(false);
}
}
}
//フレンドのみフィルターをかけているとき
else if(nemophila.getSelectGenres().isEmpty()) {
for(String friendId : nemophila.getSelectFriends()) {
if(shop.getUserIdSet().contains(friendId)) {
createMarker.setVisible(true);
break;
} else {
createMarker.setVisible(false);
}
}
}
//どちらもフィルターをかけているとき
else {
for(String genre : nemophila.getSelectGenres()) {
for(String friendId : nemophila.getSelectFriends()) {
if (shop.getGenreSet().contains(genre) && shop.getUserIdSet().contains(friendId)) {
createMarker.setVisible(true);
break;
} else {
createMarker.setVisible(false);
}
}
}
}
} else {
createMarker.setVisible(false);
}
} else {
createMarker.setVisible(false);
}
}
}
});
 
// 長押しを認識した後の処理(LiveDataへの購読)
shopsViewModel.getNearShopsLiveData().observe(getActivity(), shops -> {
String.format("近辺の店を確認しました。ダイアログを表示します"),
Toast.LENGTH_SHORT)
.show();
 
//長押し時は周辺のピンを全て取得し、ダイアログに表示する
DialogFragment dialogFragment = new MapsDialogFragment(shops);
dialogFragment.show(getActivity().getSupportFragmentManager(),"mapsdialog");
//長押し時は周辺のピンを全て取得し、ダイアログに表示する
DialogFragment dialogFragment = new MapsDialogFragment(shops);
dialogFragment.show(getActivity().getSupportFragmentManager(), "mapsdialog");
});
 
//初期画面の座標(現在地をロードするまで表示)
//initialLatlng = new LatLng(39,138);
shopsViewModel.setViewArea(nemophila.getCameraLongitude() + 1, nemophila.getCameraLatitude() + 1, nemophila.getCameraLongitude() - 1, nemophila.getCameraLatitude() - 1);
});
 
 
// test用 座標を確認するため
// タップした時のリスナーをセット
mMap.setOnMapClickListener(tapLocation -> {
// map(ピン以外)をtapされた位置の緯度経度
tapLatlng = new LatLng(tapLocation.latitude, tapLocation.longitude);
Toast.makeText(getActivity(),
String.format("%s", tapLatlng),
Toast.LENGTH_SHORT)
.show();
});
// test用 座標を確認するため
// タップした時のリスナーをセット
mMap.setOnMapClickListener(tapLocation -> {
// map(ピン以外)をtapされた位置の緯度経度
tapLatlng = new LatLng(tapLocation.latitude, tapLocation.longitude);
Toast.makeText(getActivity(),
String.format("%s", tapLatlng),
Toast.LENGTH_SHORT)
.show();
});
 
 
//長押し時に店を作成し、その座標にピンを立てる
//長押し時にその座標を保存し、投稿画面に移り、Shop作成完了時にはピンを立て、Shop画面に移行
//長押しでダイアログを表示
//テスト用
//shopsViewModel.longClickViewArea(longpushLocation.longitude+1, longpushLocation.latitude+1, longpushLocation.longitude-1, longpushLocation.latitude-1);
//本番環境は↓の範囲で
shopsViewModel.longClickViewArea(longpushLocation.longitude+0.001, longpushLocation.latitude+0.001, longpushLocation.longitude-0.001, longpushLocation.latitude-0.001);
shopsViewModel.longClickViewArea(longpushLocation.longitude + 0.001, longpushLocation.latitude + 0.001, longpushLocation.longitude - 0.001, longpushLocation.latitude - 0.001);
});
 
// ピンをクリックした場合
mMap.setOnMarkerClickListener(new GoogleMap.OnMarkerClickListener() {
@Override
public boolean onMarkerClick(Marker marker) {
//現在地マーカーをクリックしたときのみ例外
if(marker.getTag() == null) {
if (marker.getTag() == null) {
//以下の処理をストップ
return false;
}
 
!= PackageManager.PERMISSION_GRANTED) {
 
requestPermissionLauncher.launch(
Manifest.permission.ACCESS_FINE_LOCATION);
}
else{
} else {
locationStart();
}
 
((MapsActivity) getContext()).setMapsFragment(this);
bd = BitmapDescriptorFactory.fromBitmap(afterBitmap);
}
 
 
private void zoomMap(double latitude, double longitude) {
public void zoomMap(double latitude, double longitude) {
// 表示する東西南北の緯度経度を設定
double south = latitude * (1 - 0.00005);
double west = longitude * (1 - 0.00005);
double north = latitude * (1 + 0.00005);
LatLng current_location = new LatLng(latitude, longitude);
 
//初回現在地取得時
if (currentMarker == null) {
currentMarker=mMap.addMarker(new MarkerOptions().position(current_location).title("現在地").icon(bd));
currentMarker = mMap.addMarker(new MarkerOptions().position(current_location).title("現在地").icon(bd));
} else {
//2回目移行
currentMarker.setPosition(current_location);
}
new ActivityResultContracts.RequestPermission(),
isGranted -> {
if (isGranted) {
locationStart();
}
else {
} else {
Toast toast = Toast.makeText(getActivity(),
"これ以上なにもできません", Toast.LENGTH_SHORT);
toast.show();
}
});
 
//現在地の取得
@SuppressLint("MissingPermission")
private void locationStart(){
Log.d("debug","locationStart()");
private void locationStart() {
Log.d("debug", "locationStart()");
 
// LocationManager インスタンス生成
locationManager =
(LocationManager) getContext().getSystemService(getContext().LOCATION_SERVICE);
 
@Override
public void onLocationChanged(Location location) {
//初期画面は現在地を中心にするため...
if (currentLatlng == null){
if (currentLatlng == null) {
//↓現在地ロード後画面中心を現在地にする場合
//zoomMap(location.getLatitude(), location.getLongitude());
//ロード画面の終了
//getView().findViewById(R.id.LL_Load).setVisibility(View.GONE);
//現在地ボタンを表示
getView().findViewById(R.id.currentButton).setVisibility(View.VISIBLE);
ImageButton button1 = getView().findViewById(R.id.currentButton);
 
button1.setOnClickListener( v -> {
button1.setOnClickListener(v -> {
Log.d("debug", "currentbutton, 現在地にカメラを移動");
System.out.println(shopsViewModel.getShopsLiveData().getValue());
//現在地にカメラを移動
zoomMap(currentLatlng.latitude, currentLatlng.longitude);
//LatLng型で受け取っておく
currentLatlng = new LatLng(location.getLatitude(), location.getLongitude());
 
//現在地アイコンを表示.このsetIcon内にzoomMap処理もあるので注意
setIcon(location.getLatitude(),location.getLongitude());
setIcon(location.getLatitude(), location.getLongitude());
}
 
//住所・施設名などから緯度経度を検索するメソッド
public void SeachLocation(String seachText) {
// Geocoderを使用して緯度経度を取得し移動
LatLng latLng = getLatLngFromAddress(seachText);
if (latLng != null) {
System.out.println("-------検索地点の座標取得完了!--------");
System.out.println("緯度: " + latLng.latitude + "\n経度: " + latLng.longitude);
System.out.println("-----------------------------------");
 
Toast.makeText(getActivity(),
String.format("該当の地点に移動します"),
Toast.LENGTH_SHORT)
.show();
nemophila.setZoom(18f);
zoomMap(latLng.latitude, latLng.longitude);
} else {
//緯度経度取得ミス
System.out.println("-------検索地点の座標取得失敗--------");
Toast.makeText(getActivity(),
String.format("該当の地点が見つかりませんでした"),
Toast.LENGTH_SHORT)
.show();
}
}
 
// 住所から緯度経度を取得するメソッド
private LatLng getLatLngFromAddress(String address) {
Geocoder geocoder = new Geocoder(requireContext(), Locale.getDefault());
try {
List<Address> addresses = geocoder.getFromLocationName(address, 1);
if (addresses != null && !addresses.isEmpty()) {
Address firstAddress = addresses.get(0);
double latitude = firstAddress.getLatitude();
double longitude = firstAddress.getLongitude();
return new LatLng(latitude, longitude);
}
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
 
@Override
public void onProviderEnabled(String provider) {