taomenggo init
This commit is contained in:
15
locationkit/src/main/AndroidManifest.xml
Normal file
15
locationkit/src/main/AndroidManifest.xml
Normal file
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (c) 2022 NetEase, Inc. All rights reserved. -->
|
||||
<!-- Use of this source code is governed by a MIT license that can be -->
|
||||
<!-- found in the LICENSE file. -->
|
||||
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.netease.yunxin.kit.locationkit"
|
||||
|
||||
>
|
||||
|
||||
<queries>
|
||||
<package android:name="com.autonavi.minimap"/>
|
||||
</queries>
|
||||
<application android:allowNativeHeapPointerTagging="false"/>
|
||||
</manifest>
|
||||
@@ -0,0 +1,133 @@
|
||||
// Copyright (c) 2022 NetEase, Inc. All rights reserved.
|
||||
// Use of this source code is governed by a MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
package com.netease.yunxin.kit.locationkit;
|
||||
|
||||
import static com.netease.yunxin.kit.locationkit.LocationConstant.LIB_TAG;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Point;
|
||||
import android.os.Bundle;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.widget.FrameLayout;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import com.amap.api.maps.AMap;
|
||||
import com.amap.api.maps.AMapOptions;
|
||||
import com.amap.api.maps.CameraUpdateFactory;
|
||||
import com.amap.api.maps.MapView;
|
||||
import com.amap.api.maps.UiSettings;
|
||||
import com.amap.api.maps.model.LatLng;
|
||||
import com.netease.yunxin.kit.alog.ALog;
|
||||
import com.netease.yunxin.kit.chatkit.map.IChatMap;
|
||||
import com.netease.yunxin.kit.chatkit.map.ILocationListener;
|
||||
import com.netease.yunxin.kit.chatkit.map.MapMode;
|
||||
|
||||
public class ChatMapWrapper implements IChatMap {
|
||||
public FrameLayout interceptView;
|
||||
public MapMode mode;
|
||||
public MapView mapView;
|
||||
public AMap aMap;
|
||||
public ILocationListener locationListener;
|
||||
public final String TAG = "ChatMapWrapper";
|
||||
|
||||
public ChatMapWrapper(
|
||||
@NonNull Context context, @Nullable Bundle savedInstanceState, @NonNull MapMode mapMode) {
|
||||
ALog.d(LIB_TAG, TAG, "construction, mapMode:" + mapMode);
|
||||
mode = mapMode;
|
||||
interceptView =
|
||||
new FrameLayout(context) {
|
||||
@Override
|
||||
public boolean onInterceptTouchEvent(MotionEvent ev) {
|
||||
// 消息中的地图不可点击
|
||||
if (mapMode == MapMode.LOCATION) {
|
||||
ALog.d(
|
||||
LIB_TAG,
|
||||
TAG,
|
||||
"onInterceptTouchEvent, locationListener:" + (locationListener == null));
|
||||
if (locationListener != null) {
|
||||
if (ev.getAction() == MotionEvent.ACTION_UP) {
|
||||
int[] screenLocation = new int[2];
|
||||
mapView.getLocationOnScreen(screenLocation);
|
||||
int height = mapView.getHeight();
|
||||
|
||||
int width = mapView.getWidth();
|
||||
int screenX = screenLocation[0] + width / 2;
|
||||
int screenY = screenLocation[1] + height / 2;
|
||||
Point point = new Point(screenX, screenY);
|
||||
LatLng latLng = mapView.getMap().getProjection().fromScreenLocation(point);
|
||||
ALog.d(
|
||||
LIB_TAG,
|
||||
TAG,
|
||||
"latitude="
|
||||
+ latLng.latitude
|
||||
+ ",longitude = "
|
||||
+ latLng.longitude
|
||||
+ ",screenX="
|
||||
+ screenX
|
||||
+ ","
|
||||
+ screenY);
|
||||
locationListener.onScreenLocationChange(latLng.latitude, latLng.longitude);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
mapView = new MapView(context);
|
||||
mapView.onCreate(savedInstanceState);
|
||||
interceptView.addView(mapView);
|
||||
aMap = mapView.getMap();
|
||||
aMap.setOnMapLoadedListener(
|
||||
() -> {
|
||||
UiSettings uiSettings = aMap.getUiSettings();
|
||||
if (mode == MapMode.MESSAGE) {
|
||||
uiSettings.setLogoPosition(AMapOptions.LOGO_MARGIN_LEFT);
|
||||
uiSettings.setAllGesturesEnabled(false);
|
||||
uiSettings.setCompassEnabled(false);
|
||||
uiSettings.setMyLocationButtonEnabled(false);
|
||||
} else {
|
||||
uiSettings.setZoomGesturesEnabled(true);
|
||||
uiSettings.setScrollGesturesEnabled(true);
|
||||
}
|
||||
aMap.moveCamera(CameraUpdateFactory.zoomTo(17));
|
||||
// location, detail
|
||||
uiSettings.setZoomControlsEnabled(false);
|
||||
uiSettings.setLogoBottomMargin(-150);
|
||||
});
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public View getMapView() {
|
||||
return interceptView;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
mapView.onResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
mapView.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(@NonNull Bundle outState) {
|
||||
mapView.onSaveInstanceState(outState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLocationListener(@NonNull ILocationListener listener) {
|
||||
locationListener = listener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
mapView.onDestroy();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
// Copyright (c) 2022 NetEase, Inc. All rights reserved.
|
||||
// Use of this source code is governed by a MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
package com.netease.yunxin.kit.locationkit;
|
||||
|
||||
public class LocationConstant {
|
||||
public static final String LIB_TAG = "ChatKit-UI";
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
// Copyright (c) 2022 NetEase, Inc. All rights reserved.
|
||||
// Use of this source code is governed by a MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
package com.netease.yunxin.kit.locationkit;
|
||||
|
||||
import android.content.Context;
|
||||
import com.amap.api.location.AMapLocationClient;
|
||||
import com.amap.apis.utils.core.api.AMapUtilCoreApi;
|
||||
import com.netease.yunxin.kit.chatkit.ui.ChatKitClient;
|
||||
|
||||
public class LocationKitClient {
|
||||
public static void init(Context context) {
|
||||
//地图隐私合规
|
||||
AMapLocationClient.updatePrivacyShow(context, true, true);
|
||||
AMapLocationClient.updatePrivacyAgree(context, true);
|
||||
AMapUtilCoreApi.setCollectInfoEnable(false);//不允许采集个人及设备信息
|
||||
ChatKitClient.setPageMapProvider(new PageMapImpl());
|
||||
ChatKitClient.setMessageMapProvider(new MessageMapImpl());
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
// Copyright (c) 2022 NetEase, Inc. All rights reserved.
|
||||
// Use of this source code is governed by a MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
package com.netease.yunxin.kit.locationkit;
|
||||
|
||||
import com.amap.api.services.poisearch.PoiSearch;
|
||||
import com.netease.yunxin.kit.chatkit.map.ChatLocationBean;
|
||||
|
||||
public class LocationUtils {
|
||||
|
||||
public static boolean isSameLatLng(ChatLocationBean bean, PoiSearch.SearchBound searchBound) {
|
||||
|
||||
if (bean == null && (searchBound == null || searchBound.getCenter() == null)) {
|
||||
return true;
|
||||
} else if (bean != null && searchBound != null && searchBound.getCenter() != null) {
|
||||
return bean.isSameLatLng(
|
||||
searchBound.getCenter().getLatitude(), searchBound.getCenter().getLongitude());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
// Copyright (c) 2022 NetEase, Inc. All rights reserved.
|
||||
// Use of this source code is governed by a MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
package com.netease.yunxin.kit.locationkit;
|
||||
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import com.netease.yunxin.kit.common.ui.action.ActionItem;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class MapNavigator {
|
||||
public static final String PACKAGE_NAME_GAODE = "com.autonavi.minimap";
|
||||
public static final String PACKAGE_NAME_TENCENT = "com.google.android.apps.maps";
|
||||
|
||||
public static void mapNavigation(
|
||||
Context context, String action, String address, double lat, double lng) {
|
||||
|
||||
if (PACKAGE_NAME_TENCENT.equals(action)) {
|
||||
tencentGuide(context, address, new double[] {lat, lng});
|
||||
} else {
|
||||
aMapNavigation(context, address, lat, lng);
|
||||
}
|
||||
}
|
||||
|
||||
public static void aMapNavigation(Context context, String address, double lat, double lng) {
|
||||
try {
|
||||
Intent intent =
|
||||
Intent.parseUri(
|
||||
"androidamap://viewMap?sourceApplication=NIMUIKit"
|
||||
+ "&poiname="
|
||||
+ address
|
||||
+ "&lat="
|
||||
+ lat
|
||||
+ "&lon="
|
||||
+ lng
|
||||
+ "&dev=0",
|
||||
0);
|
||||
context.startActivity(intent);
|
||||
} catch (URISyntaxException e) {
|
||||
e.printStackTrace();
|
||||
} catch (ActivityNotFoundException activityNotFoundException) {
|
||||
Uri uri = Uri.parse("market://details?id=" + PACKAGE_NAME_GAODE);
|
||||
Intent marketIntent = new Intent(Intent.ACTION_VIEW, uri);
|
||||
context.startActivity(marketIntent);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* google导航
|
||||
*
|
||||
* @param context
|
||||
* @param location
|
||||
*/
|
||||
public static void tencentGuide(Context context, String address, double[] location) {
|
||||
try {
|
||||
Uri gmmIntentUri =
|
||||
Uri.parse("google.navigation:q="+ location[0]+","+ location[1]+"");
|
||||
Intent mapIntent =new Intent(Intent.ACTION_VIEW, gmmIntentUri);
|
||||
mapIntent.setPackage("com.google.android.apps.maps");
|
||||
context.startActivity(mapIntent);
|
||||
} catch (ActivityNotFoundException activityNotFoundException) {
|
||||
Uri uri = Uri.parse("market://details?id=" + PACKAGE_NAME_TENCENT);
|
||||
Intent marketIntent = new Intent(Intent.ACTION_VIEW, uri);
|
||||
context.startActivity(marketIntent);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* google导航
|
||||
*
|
||||
* @param context
|
||||
* @param location
|
||||
*/
|
||||
public static void googleGuide(Context context, String location) {
|
||||
try {
|
||||
Uri gmmIntentUri =
|
||||
Uri.parse("google.navigation:q="+ location);
|
||||
Intent mapIntent =new Intent(Intent.ACTION_VIEW, gmmIntentUri);
|
||||
mapIntent.setPackage("com.google.android.apps.maps");
|
||||
context.startActivity(mapIntent);
|
||||
} catch (ActivityNotFoundException activityNotFoundException) {
|
||||
Uri uri = Uri.parse("market://details?id=" + PACKAGE_NAME_TENCENT);
|
||||
Intent marketIntent = new Intent(Intent.ACTION_VIEW, uri);
|
||||
context.startActivity(marketIntent);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static ArrayList<ActionItem> getMapChoice() {
|
||||
ArrayList<ActionItem> mapList = new ArrayList<>();
|
||||
|
||||
ActionItem aMapItem =
|
||||
new ActionItem(PACKAGE_NAME_GAODE, -1, R.string.location_amap_nav_title)
|
||||
.setTitleColorResId(R.color.choice_dialog_title);
|
||||
mapList.add(aMapItem);
|
||||
ActionItem tMapItem =
|
||||
new ActionItem(PACKAGE_NAME_TENCENT, -1, R.string.location_tencent_nav_title)
|
||||
.setTitleColorResId(R.color.choice_dialog_title);
|
||||
mapList.add(tMapItem);
|
||||
return mapList;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
// Copyright (c) 2022 NetEase, Inc. All rights reserved.
|
||||
// Use of this source code is governed by a MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
package com.netease.yunxin.kit.locationkit;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import com.amap.api.maps.AMap;
|
||||
import com.amap.api.maps.CameraUpdateFactory;
|
||||
import com.amap.api.maps.model.BitmapDescriptorFactory;
|
||||
import com.amap.api.maps.model.CameraPosition;
|
||||
import com.amap.api.maps.model.LatLng;
|
||||
import com.amap.api.maps.model.MarkerOptions;
|
||||
import com.netease.yunxin.kit.chatkit.map.IChatMap;
|
||||
import com.netease.yunxin.kit.chatkit.map.IMessageMapProvider;
|
||||
import com.netease.yunxin.kit.chatkit.map.MapMode;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class MessageMapImpl implements IMessageMapProvider {
|
||||
private static final String TAG = "MessageMapImpl";
|
||||
private final Map<String, List<IChatMap>> chatMapInterfaceMap = new HashMap<>();
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public IChatMap createChatMap(
|
||||
@NonNull String key, @NonNull Context context, @Nullable Bundle savedInstanceState) {
|
||||
IChatMap chatMap = new ChatMapWrapper(context, savedInstanceState, MapMode.MESSAGE);
|
||||
putValueToMap(key, chatMap);
|
||||
return chatMap;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public View setLocation(@NonNull IChatMap chatMap, double lat, double lng) {
|
||||
if (chatMap instanceof ChatMapWrapper) {
|
||||
AMap aMap = ((ChatMapWrapper) chatMap).aMap;
|
||||
LatLng latLng = new LatLng(lat, lng);
|
||||
aMap.moveCamera(
|
||||
CameraUpdateFactory.newCameraPosition(
|
||||
CameraPosition.builder().target(latLng).zoom(17).build()));
|
||||
aMap.clear();
|
||||
MarkerOptions options =
|
||||
new MarkerOptions()
|
||||
.icon(BitmapDescriptorFactory.fromResource(R.drawable.ic_location_marker))
|
||||
.position(latLng)
|
||||
.draggable(false);
|
||||
aMap.addMarker(options);
|
||||
}
|
||||
return chatMap.getMapView();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroyChatMap(@NonNull String key, @Nullable IChatMap chatMap) {
|
||||
if (chatMap == null) {
|
||||
return;
|
||||
}
|
||||
chatMap.onDestroy();
|
||||
removeValueFromMap(key, chatMap);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void releaseAllChatMap(@NonNull String key) {
|
||||
List<IChatMap> tempChatMapList = new ArrayList<>(getKeyFromMap(key));
|
||||
clearValueFromMap(key);
|
||||
for (IChatMap chatMap : tempChatMapList) {
|
||||
chatMap.onDestroy();
|
||||
}
|
||||
}
|
||||
|
||||
private void putValueToMap(String key, IChatMap chatMap) {
|
||||
getKeyFromMap(key).add(chatMap);
|
||||
}
|
||||
|
||||
private void removeValueFromMap(String key, IChatMap chatMap) {
|
||||
getKeyFromMap(key).remove(chatMap);
|
||||
}
|
||||
|
||||
private void clearValueFromMap(String key) {
|
||||
getKeyFromMap(key).clear();
|
||||
}
|
||||
|
||||
private List<IChatMap> getKeyFromMap(String key) {
|
||||
List<IChatMap> chatMapList = chatMapInterfaceMap.get(key);
|
||||
if (chatMapList == null) {
|
||||
chatMapList = new ArrayList<>();
|
||||
chatMapInterfaceMap.put(key, chatMapList);
|
||||
}
|
||||
return chatMapList;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,445 @@
|
||||
// Copyright (c) 2022 NetEase, Inc. All rights reserved.
|
||||
// Use of this source code is governed by a MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
package com.netease.yunxin.kit.locationkit;
|
||||
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.SystemClock;
|
||||
import android.text.TextUtils;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import com.amap.api.location.AMapLocation;
|
||||
import com.amap.api.location.AMapLocationClient;
|
||||
import com.amap.api.location.AMapLocationClientOption;
|
||||
import com.amap.api.location.AMapLocationListener;
|
||||
import com.amap.api.maps.AMap;
|
||||
import com.amap.api.maps.CameraUpdateFactory;
|
||||
import com.amap.api.maps.LocationSource;
|
||||
import com.amap.api.maps.model.BitmapDescriptorFactory;
|
||||
import com.amap.api.maps.model.LatLng;
|
||||
import com.amap.api.maps.model.Marker;
|
||||
import com.amap.api.maps.model.MarkerOptions;
|
||||
import com.amap.api.maps.model.MyLocationStyle;
|
||||
import com.amap.api.services.core.AMapException;
|
||||
import com.amap.api.services.core.LatLonPoint;
|
||||
import com.amap.api.services.core.PoiItem;
|
||||
import com.amap.api.services.poisearch.PoiResult;
|
||||
import com.amap.api.services.poisearch.PoiSearch;
|
||||
import com.netease.yunxin.kit.alog.ALog;
|
||||
import com.netease.yunxin.kit.chatkit.map.ChatLocationBean;
|
||||
import com.netease.yunxin.kit.chatkit.map.IChatMap;
|
||||
import com.netease.yunxin.kit.chatkit.map.ILocationSearchCallback;
|
||||
import com.netease.yunxin.kit.chatkit.map.IPageMapProvider;
|
||||
import com.netease.yunxin.kit.chatkit.map.MapMode;
|
||||
import com.netease.yunxin.kit.common.ui.dialog.BottomChoiceDialog;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class PageMapImpl
|
||||
implements IPageMapProvider,
|
||||
LocationSource,
|
||||
AMapLocationListener,
|
||||
PoiSearch.OnPoiSearchListener {
|
||||
private static final String TAG = "AMapWrapper";
|
||||
|
||||
private WeakReference<Context> wkContext;
|
||||
private ChatMapWrapper chatMapWrapper;
|
||||
|
||||
// location
|
||||
private LocationSource.OnLocationChangedListener mListener;
|
||||
private AMapLocationClient mLocationClient;
|
||||
private ChatLocationBean currentLocation;
|
||||
private String searchText = "searchText";
|
||||
private String searchTag = "";
|
||||
private PoiSearch.SearchBound doSearchBound;
|
||||
private LatLng markLatLng;
|
||||
private List<Marker> addMarkerList = new ArrayList<>();
|
||||
private List<ChatLocationBean> locationPoiCache;
|
||||
private ILocationSearchCallback searchCallback;
|
||||
private final int SEARCH_BOUND = 5000;
|
||||
|
||||
@Override
|
||||
public void createChatMap(
|
||||
@NonNull Context context,
|
||||
@Nullable Bundle savedInstanceState,
|
||||
@NonNull MapMode mapMode,
|
||||
@Nullable ILocationSearchCallback searchCallback) {
|
||||
ALog.i(TAG, "createChatMap, mapMode:" + mapMode);
|
||||
wkContext = new WeakReference<>(context);
|
||||
chatMapWrapper = new ChatMapWrapper(wkContext.get(), savedInstanceState, mapMode);
|
||||
this.searchCallback = searchCallback;
|
||||
|
||||
AMap aMap = chatMapWrapper.aMap;
|
||||
aMap.moveCamera(CameraUpdateFactory.zoomTo(17));
|
||||
if (chatMapWrapper.mode == MapMode.LOCATION) {
|
||||
MyLocationStyle myLocationStyle = new MyLocationStyle();
|
||||
// 定位一次,且将视角移动到地图中心点。
|
||||
myLocationStyle.myLocationType(MyLocationStyle.LOCATION_TYPE_LOCATE);
|
||||
myLocationStyle.myLocationIcon(
|
||||
BitmapDescriptorFactory.fromResource(R.drawable.ic_my_location_in));
|
||||
myLocationStyle.anchor(0.5f, 0.5f);
|
||||
myLocationStyle.showMyLocation(true);
|
||||
aMap.setMyLocationStyle(myLocationStyle);
|
||||
|
||||
// 通过aMap对象设置定位数据源的监听
|
||||
aMap.setLocationSource(PageMapImpl.this);
|
||||
// 设置为true表示显示定位层并可触发定位,false表示隐藏定位层并不可触发定位,默认是false
|
||||
aMap.setMyLocationEnabled(true);
|
||||
} else {
|
||||
aMap.setLocationSource(null);
|
||||
aMap.setMyLocationEnabled(false);
|
||||
}
|
||||
|
||||
chatMapWrapper.setLocationListener(
|
||||
(latitude, longitude) -> {
|
||||
// changeLocation(latitude, longitude, true);
|
||||
LatLng latLng = new LatLng(latitude, longitude);
|
||||
onMakerChange(latLng);
|
||||
// 搜索定位周边
|
||||
doSearch(
|
||||
"", new PoiSearch.SearchBound(new LatLonPoint(latitude, longitude), SEARCH_BOUND));
|
||||
});
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public IChatMap getChatMap() {
|
||||
return chatMapWrapper;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public ChatLocationBean getCurrentLocation() {
|
||||
ALog.i(TAG, "map getCurrentLocation");
|
||||
return currentLocation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void searchPoi(String keyWord) {
|
||||
ALog.i(TAG, "map searchPoi:" + keyWord);
|
||||
LatLonPoint bound = null;
|
||||
if (currentLocation != null) {
|
||||
bound = new LatLonPoint(currentLocation.getLat(), currentLocation.getLng());
|
||||
}
|
||||
doSearch(keyWord, new PoiSearch.SearchBound(bound, SEARCH_BOUND));
|
||||
}
|
||||
|
||||
private void doSearch(String keyWord, PoiSearch.SearchBound searchBound) {
|
||||
if (TextUtils.equals(searchText, keyWord) && isSameBound(searchBound, doSearchBound)) {
|
||||
ALog.i(TAG, "doSearch key:" + keyWord + "is same");
|
||||
return;
|
||||
}
|
||||
String city = "";
|
||||
if (currentLocation != null) {
|
||||
city = currentLocation.getCity();
|
||||
}
|
||||
searchText = keyWord;
|
||||
doSearchBound = searchBound;
|
||||
ALog.i(
|
||||
TAG, "doSearch key:" + keyWord + ", city:" + city + ", is bound:" + (searchBound != null));
|
||||
// 第一个参数表示搜索字符串,第二个参数表示poi搜索类型,第三个参数表示poi搜索区域(空字符串代表全国)
|
||||
PoiSearch.Query mPoiSearchQuery = new PoiSearch.Query(keyWord, "", city);
|
||||
mPoiSearchQuery.requireSubPois(true); //true 搜索结果包含POI父子关系; false
|
||||
mPoiSearchQuery.setCityLimit(false);
|
||||
mPoiSearchQuery.setPageSize(10);
|
||||
mPoiSearchQuery.setPageNum(0);
|
||||
searchTag = String.valueOf(SystemClock.elapsedRealtime());
|
||||
ALog.i(TAG, "doSearch tag:" + searchTag);
|
||||
mPoiSearchQuery.setExtensions(searchTag);
|
||||
try {
|
||||
// POI搜索
|
||||
PoiSearch poiSearch = new PoiSearch(wkContext.get(), mPoiSearchQuery);
|
||||
poiSearch.setOnPoiSearchListener(this);
|
||||
if (searchBound != null && TextUtils.isEmpty(keyWord)) {
|
||||
poiSearch.setBound(searchBound);
|
||||
}
|
||||
poiSearch.searchPOIAsyn();
|
||||
} catch (AMapException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doLocation() {
|
||||
ALog.i(TAG, "doLocation");
|
||||
if (mLocationClient != null) {
|
||||
locationPoiCache = null;
|
||||
// 此方法为每隔固定时间会发起一次定位请求,为了减少电量消耗或网络流量消耗,
|
||||
// 注意设置合适的定位时间的间隔(最小间隔支持为2000ms),并且在合适时间调用stopLocation()方法来取消定位请求
|
||||
// 在定位结束后,在合适的生命周期调用onDestroy()方法
|
||||
// 在单次定位情况下,定位无论成功与否,都无需调用stopLocation()方法移除请求,定位sdk内部会移除
|
||||
mLocationClient.startLocation();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLocationChanged(AMapLocation aMapLocation) {
|
||||
if (mListener != null && aMapLocation != null) {
|
||||
if (aMapLocation.getErrorCode() == 0) {
|
||||
ALog.i(TAG, "onLocationChanged -->> " + aMapLocation.toStr());
|
||||
currentLocation =
|
||||
new ChatLocationBean(
|
||||
aMapLocation.getPoiName(),
|
||||
aMapLocation.getAddress(),
|
||||
aMapLocation.getCity(),
|
||||
aMapLocation.getLatitude(),
|
||||
aMapLocation.getLongitude(),
|
||||
0,
|
||||
true);
|
||||
mListener.onLocationChanged(aMapLocation); // 显示系统小蓝点
|
||||
// 搜索定位周边
|
||||
doSearch(
|
||||
"",
|
||||
new PoiSearch.SearchBound(
|
||||
new LatLonPoint(aMapLocation.getLatitude(), aMapLocation.getLongitude()),
|
||||
SEARCH_BOUND));
|
||||
} else {
|
||||
ALog.e(
|
||||
TAG,
|
||||
"定位失败, code:" + aMapLocation.getErrorCode() + " -->> " + aMapLocation.getErrorInfo());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void activate(OnLocationChangedListener onLocationChangedListener) {
|
||||
ALog.i(TAG, "LocationSource activate -->> ");
|
||||
mListener = onLocationChangedListener;
|
||||
if (mLocationClient == null) {
|
||||
try {
|
||||
mLocationClient = new AMapLocationClient(wkContext.get());
|
||||
AMapLocationClientOption mLocationOption = new AMapLocationClientOption();
|
||||
// 设置定位监听
|
||||
mLocationClient.setLocationListener(this);
|
||||
// 设置为高精度定位模式
|
||||
mLocationOption.setLocationMode(AMapLocationClientOption.AMapLocationMode.Hight_Accuracy);
|
||||
// 获取一次定位结果:
|
||||
mLocationOption.setOnceLocation(true);
|
||||
// 设置定位参数
|
||||
mLocationClient.setLocationOption(mLocationOption);
|
||||
doLocation();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ALog.e(TAG, "location active error: " + e.getMessage());
|
||||
}
|
||||
} else {
|
||||
doLocation();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deactivate() {
|
||||
ALog.i(TAG, "LocationSource deactivate.");
|
||||
mListener = null;
|
||||
if (mLocationClient != null) {
|
||||
mLocationClient.stopLocation();
|
||||
mLocationClient.onDestroy();
|
||||
}
|
||||
mLocationClient = null;
|
||||
searchCallback = null;
|
||||
locationPoiCache = null;
|
||||
currentLocation = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void changeLocation(double lat, double lng, boolean withAnim) {
|
||||
ALog.i(TAG, "changeLocation to lat:" + lat + " lng:" + lng + "location");
|
||||
chatMapWrapper.aMap.clear();
|
||||
// 添加自己的位置
|
||||
if (currentLocation != null) {
|
||||
onMakerChange(
|
||||
new LatLng(currentLocation.getLat(), currentLocation.getLng()),
|
||||
currentLocation.isSameLatLng(lat, lng)
|
||||
? R.drawable.ic_my_location_in
|
||||
: R.drawable.ic_my_location_to,
|
||||
true);
|
||||
}
|
||||
LatLng latLng = new LatLng(lat, lng);
|
||||
onMakerChange(latLng);
|
||||
float zoom = chatMapWrapper.aMap.getCameraPosition().zoom;
|
||||
if (withAnim) {
|
||||
chatMapWrapper.aMap.animateCamera(CameraUpdateFactory.newLatLngZoom(latLng, zoom));
|
||||
} else {
|
||||
chatMapWrapper.aMap.moveCamera(CameraUpdateFactory.newLatLngZoom(latLng, zoom));
|
||||
}
|
||||
}
|
||||
|
||||
private void onMakerChange(LatLng latLng) {
|
||||
onMakerChange(latLng, R.drawable.ic_location_marker, false);
|
||||
}
|
||||
|
||||
private void onMakerChange(LatLng latLng, int markerId, boolean center) {
|
||||
MarkerOptions options =
|
||||
new MarkerOptions()
|
||||
.icon(BitmapDescriptorFactory.fromResource(markerId))
|
||||
.position(latLng)
|
||||
.draggable(false);
|
||||
if (center) {
|
||||
options.anchor(0.5f, 0.5f);
|
||||
}
|
||||
clearMarker();
|
||||
markLatLng = latLng;
|
||||
Marker marker = chatMapWrapper.aMap.addMarker(options);
|
||||
if (!center) {
|
||||
addMarkerList.add(marker);
|
||||
}
|
||||
}
|
||||
|
||||
private void clearMarker() {
|
||||
for (Marker marker : addMarkerList) {
|
||||
marker.remove();
|
||||
}
|
||||
}
|
||||
|
||||
/** POI信息查询回调方法 */
|
||||
@Override
|
||||
public void onPoiSearched(PoiResult poiResult, int code) {
|
||||
if (code == AMapException.CODE_AMAP_SUCCESS) {
|
||||
if (poiResult != null && poiResult.getQuery() != null) {
|
||||
ALog.i(TAG, "onPoiSearched extension:" + poiResult.getQuery().getExtensions());
|
||||
if (!TextUtils.equals(searchTag, poiResult.getQuery().getExtensions())) {
|
||||
return;
|
||||
}
|
||||
if (locationPoiCache == null && searchCallback != null && poiResult.getPois() != null) {
|
||||
// 缓存定位地址列表
|
||||
locationPoiCache = convert(poiResult.getPois(), false);
|
||||
// 添加定位地址
|
||||
if (currentLocation != null) {
|
||||
currentLocation.setSelected(true);
|
||||
locationPoiCache.add(0, currentLocation);
|
||||
} else {
|
||||
if (locationPoiCache.size() > 0) {
|
||||
locationPoiCache.get(0).setSelected(true);
|
||||
}
|
||||
}
|
||||
|
||||
ALog.i(TAG, "onPoiSearched locationPoiResult:" + locationPoiCache);
|
||||
searchCallback.onSuccess(locationPoiCache);
|
||||
return;
|
||||
}
|
||||
List<PoiItem> poiItems = poiResult.getPois();
|
||||
if (searchCallback != null && poiItems != null) {
|
||||
ALog.i(TAG, "onPoiSearched result:" + poiItems);
|
||||
List<ChatLocationBean> searchResult = convert(poiItems, false);
|
||||
//在定位位置搜索,需要把当前位置放在搜索结果第一个
|
||||
if (currentLocation != null
|
||||
&& poiResult.getQuery() != null
|
||||
&& TextUtils.isEmpty(poiResult.getQuery().getQueryString())
|
||||
&& LocationUtils.isSameLatLng(currentLocation, poiResult.getBound())) {
|
||||
searchResult.add(0, currentLocation);
|
||||
currentLocation.setSelected(true);
|
||||
} else {
|
||||
if (searchResult.size() > 0) {
|
||||
searchResult.get(0).setSelected(true);
|
||||
}
|
||||
}
|
||||
searchCallback.onSuccess(searchResult);
|
||||
}
|
||||
} else {
|
||||
ALog.e(TAG, "onPoiSearched no result:" + code);
|
||||
// 没有搜索到相关数据。
|
||||
if (searchCallback != null) {
|
||||
searchCallback.onFailed();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ALog.e(TAG, "onPoiSearched error:" + code);
|
||||
if (searchCallback != null) {
|
||||
searchCallback.onError(code);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resumeLocationResult() {
|
||||
if (searchCallback != null) {
|
||||
ALog.i(TAG, "resumeLocationResult locationPoiResult:" + locationPoiCache);
|
||||
searchCallback.onSuccess(locationPoiCache);
|
||||
}
|
||||
}
|
||||
|
||||
private List<ChatLocationBean> convert(List<PoiItem> poiItems, boolean firstSelect) {
|
||||
ArrayList<ChatLocationBean> chatLocationBeans = new ArrayList<>();
|
||||
boolean first = firstSelect;
|
||||
for (PoiItem item : poiItems) {
|
||||
LatLonPoint point = item.getLatLonPoint();
|
||||
ChatLocationBean bean =
|
||||
new ChatLocationBean(
|
||||
item.getTitle(),
|
||||
item.getSnippet(),
|
||||
item.getCityName(),
|
||||
point.getLatitude(),
|
||||
point.getLongitude(),
|
||||
item.getDistance() > 0 ? item.getDistance() : null,
|
||||
first);
|
||||
first = false;
|
||||
chatLocationBeans.add(bean);
|
||||
}
|
||||
return chatLocationBeans;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPoiItemSearched(PoiItem poiItem, int code) {}
|
||||
|
||||
@Override
|
||||
public void jumpOutMap(
|
||||
@NonNull Context context, @NonNull String address, double lat, double lng) {
|
||||
// BottomChoiceDialog choiceDialog = new BottomChoiceDialog(context, MapNavigator.getMapChoice());
|
||||
// choiceDialog.setOnChoiceListener(
|
||||
// new BottomChoiceDialog.OnChoiceListener() {
|
||||
// @Override
|
||||
// public void onChoice(@NonNull String type) {
|
||||
// MapNavigator.mapNavigation(context, type, address, lat, lng);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void onCancel() {}
|
||||
// });
|
||||
// choiceDialog.show();
|
||||
|
||||
MapNavigator.tencentGuide(context,address,new double[] {lat, lng});
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
private boolean isSameBound(PoiSearch.SearchBound search, PoiSearch.SearchBound target) {
|
||||
if (search == null && target == null) {
|
||||
return true;
|
||||
} else if (search != null
|
||||
&& target != null
|
||||
&& search.getCenter() != null
|
||||
&& target.getCenter() != null) {
|
||||
ALog.i(
|
||||
TAG,
|
||||
"isSameBound"
|
||||
+ search.getCenter().getLatitude()
|
||||
+ "="
|
||||
+ target.getCenter().getLatitude()
|
||||
+ ","
|
||||
+ search.getCenter().getLongitude()
|
||||
+ "="
|
||||
+ search.getCenter().getLongitude());
|
||||
return TextUtils.equals(
|
||||
String.valueOf(search.getCenter().getLatitude()),
|
||||
String.valueOf(target.getCenter().getLatitude()))
|
||||
&& TextUtils.equals(
|
||||
String.valueOf(search.getCenter().getLongitude()),
|
||||
String.valueOf(search.getCenter().getLongitude()));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
wkContext.clear();
|
||||
searchText = "searchText";
|
||||
doSearchBound = null;
|
||||
}
|
||||
}
|
||||
BIN
locationkit/src/main/res/drawable-xxxhdpi/ic_location_marker.png
Normal file
BIN
locationkit/src/main/res/drawable-xxxhdpi/ic_location_marker.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.8 KiB |
BIN
locationkit/src/main/res/drawable-xxxhdpi/ic_my_location_in.png
Normal file
BIN
locationkit/src/main/res/drawable-xxxhdpi/ic_my_location_in.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 7.4 KiB |
BIN
locationkit/src/main/res/drawable-xxxhdpi/ic_my_location_to.png
Normal file
BIN
locationkit/src/main/res/drawable-xxxhdpi/ic_my_location_to.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 9.8 KiB |
10
locationkit/src/main/res/values-en/string.xml
Normal file
10
locationkit/src/main/res/values-en/string.xml
Normal file
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ Copyright (c) 2022 NetEase, Inc. All rights reserved.
|
||||
~ Use of this source code is governed by a MIT license that can be found in the LICENSE file.
|
||||
-->
|
||||
|
||||
<resources>
|
||||
<string name="location_amap_nav_title">AutoNavi Maps</string>
|
||||
<string name="location_tencent_nav_title">Google Maps</string>
|
||||
</resources>
|
||||
12
locationkit/src/main/res/values-ja/string.xml
Normal file
12
locationkit/src/main/res/values-ja/string.xml
Normal file
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ Copyright (c) 2022 NetEase, Inc. All rights reserved.
|
||||
~ Use of this source code is governed by a MIT license that can be
|
||||
~ found in the LICENSE file.
|
||||
-->
|
||||
|
||||
<resources>
|
||||
|
||||
<string name="location_amap_nav_title">高德地圖</string>
|
||||
<string name="location_tencent_nav_title">Google Maps</string>
|
||||
</resources>
|
||||
12
locationkit/src/main/res/values-zh/string.xml
Normal file
12
locationkit/src/main/res/values-zh/string.xml
Normal file
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ Copyright (c) 2022 NetEase, Inc. All rights reserved.
|
||||
~ Use of this source code is governed by a MIT license that can be
|
||||
~ found in the LICENSE file.
|
||||
-->
|
||||
|
||||
<resources>
|
||||
|
||||
<string name="location_amap_nav_title">高德地图</string>
|
||||
<string name="location_tencent_nav_title">Google地图</string>
|
||||
</resources>
|
||||
4
locationkit/src/main/res/values/colors.xml
Normal file
4
locationkit/src/main/res/values/colors.xml
Normal file
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="choice_dialog_title">#333333</color>
|
||||
</resources>
|
||||
12
locationkit/src/main/res/values/string.xml
Normal file
12
locationkit/src/main/res/values/string.xml
Normal file
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ Copyright (c) 2022 NetEase, Inc. All rights reserved.
|
||||
~ Use of this source code is governed by a MIT license that can be
|
||||
~ found in the LICENSE file.
|
||||
-->
|
||||
|
||||
<resources>
|
||||
|
||||
<string name="location_amap_nav_title">高德地圖</string>
|
||||
<string name="location_tencent_nav_title">Google地圖</string>
|
||||
</resources>
|
||||
Reference in New Issue
Block a user