当前位置:
首页 >
MapBox定位与离线地图下载Android
发布时间:2023/12/20
45
豆豆
生活随笔
收集整理的这篇文章主要介绍了
MapBox定位与离线地图下载Android
小编觉得挺不错的,现在分享给大家,帮大家做个参考.
因为业务需要,在Android实现Mapbox离线地图下载和实时定位,仿照着官方的例子实现,网上的demo也比较少,
主要代码
如下所示:
public class MainActivity extends MapActicity implements OnLocationClickListener, PermissionsListener, OnCameraTrackingChangedListener {private static final String TAG = "地图下载";public static final String JSON_CHARSET = "UTF-8";public static final String JSON_FIELD_REGION_NAME = "FIELD_REGION_NAME";private NumberProgressBar progressBar;private MapboxMap map;private boolean isEndNotified;private int regionSelected;private int count_complete_err=0;// Offline objectsprivate OfflineManager offlineManager;private OfflineRegion offlineRegion;private Button downloadButton;private Button listButton;private LocationComponent locationComponent;private PermissionsManager permissionsManager;private boolean isLocating = false;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);mapView = findViewById(R.id.mapView);mapView.onCreate(savedInstanceState);mapView.getMapAsync(new OnMapReadyCallback() {@Overridepublic void onMapReady(@NonNull MapboxMap mapboxMap) {map = mapboxMap;progressBar = findViewById(R.id.progress_bar);offlineManager = OfflineManager.getInstance(MainActivity.this);downloadButton = findViewById(R.id.down);listButton = findViewById(R.id.list);downloadButton.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {downloadRegionDialog();}});listButton.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {downLoadMap();}});map.setStyle(new Style.Builder().fromUrl(getString(R.string.style_hubei)), new Style.OnStyleLoaded() {@Overridepublic void onStyleLoaded(@NonNull Style style) { // map.getStyle().getLayer("ss").setProperties(PropertyFactory.);}});}});}/*** 输入离线地图区域名称*/private void downloadRegionDialog() {AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);final EditText regionNameEdit = new EditText(MainActivity.this);regionNameEdit.setHint(getString(R.string.set_region_name_hint));builder.setTitle(getString(R.string.dialog_title)).setView(regionNameEdit).setMessage(getString(R.string.dialog_message)).setPositiveButton(getString(R.string.dialog_positive_button), new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {String regionName = regionNameEdit.getText().toString();if (regionName.length() == 0) {Toast.makeText(MainActivity.this, getString(R.string.dialog_toast), Toast.LENGTH_SHORT).show();} else {downloadRegion(regionName);}}}).setNegativeButton(getString(R.string.dialog_negative_button), new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {dialog.cancel();}});builder.show();}/*** 下载当前视图范围内地图的离线地图** @param regionName*/private void downloadRegion(final String regionName) {startProgress();String styleUrl = map.getStyle().getUrl();//获取当前视图范围,地图下载范围LatLngBounds bounds = map.getProjection().getVisibleRegion().latLngBounds;//下载多少级之间的瓦片double minZoom = map.getCameraPosition().zoom; // double maxZoom = map.getMaxZoomLevel();double maxZoom = minZoom + 3;float pixelRatio = this.getResources().getDisplayMetrics().density;OfflineTilePyramidRegionDefinition definition = new OfflineTilePyramidRegionDefinition(styleUrl, bounds, minZoom, maxZoom, pixelRatio);byte[] metadata;try {JSONObject jsonObject = new JSONObject();jsonObject.put(JSON_FIELD_REGION_NAME, regionName);String json = jsonObject.toString();metadata = json.getBytes(JSON_CHARSET);} catch (Exception exception) {Timber.e("Failed to encode metadata: %s", exception.getMessage());metadata = null;}offlineManager.createOfflineRegion(definition, metadata, new OfflineManager.CreateOfflineRegionCallback() {@Overridepublic void onCreate(OfflineRegion offlineRegion) {Timber.d("Offline region created: %s", regionName);MainActivity.this.offlineRegion = offlineRegion;launchDownload();}@Overridepublic void onError(String error) {Timber.e("Error: %s", error);}});}/*** 监听下载进度*/private void launchDownload() {offlineRegion.setObserver(new OfflineRegion.OfflineRegionObserver() {@Overridepublic void onStatusChanged(OfflineRegionStatus status) { // 计算百分比double percentage = status.getRequiredResourceCount() >= 0? (100.0 * (status.getCompletedResourceCount()+count_complete_err )/ status.getRequiredResourceCount()) :0.0;if (status.isComplete()||percentage>=100) { // 下载完endProgress(getString(R.string.end_progress_success));return;} else {setPercentage((int) Math.round(percentage));Log.e(TAG, String.valueOf(percentage));}}@Overridepublic void onError(OfflineRegionError error) {Log.e(TAG,"下载错误");Log.e(TAG,error.getMessage());count_complete_err++;}@Overridepublic void mapboxTileCountLimitExceeded(long limit) {Timber.e("Mapbox tile count limit exceeded: %s", limit);}});// Change the region stateofflineRegion.setDownloadState(OfflineRegion.STATE_ACTIVE);}public void downLoadMap() {regionSelected = 0;// 查询离线列表offlineManager.listOfflineRegions(new OfflineManager.ListOfflineRegionsCallback() {@Overridepublic void onList(final OfflineRegion[] offlineRegions) {if (offlineRegions == null || offlineRegions.length == 0) {Toast.makeText(getApplicationContext(), getString(R.string.toast_no_regions_yet), Toast.LENGTH_SHORT).show();return;}// 将结果添加到列表ArrayList<String> offlineRegionsNames = new ArrayList<>();for (OfflineRegion offlineRegion : offlineRegions) {offlineRegionsNames.add(getRegionName(offlineRegion));}final CharSequence[] items = offlineRegionsNames.toArray(new CharSequence[offlineRegionsNames.size()]);//弹框AlertDialog dialog = new AlertDialog.Builder(MainActivity.this).setTitle(getString(R.string.navigate_title)).setSingleChoiceItems(items, 0, new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {regionSelected = which;}}).setPositiveButton(getString(R.string.navigate_positive_button), new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int id) {Toast.makeText(MainActivity.this, items[regionSelected], Toast.LENGTH_LONG).show();//跳转到选中区域LatLngBounds bounds = ((OfflineTilePyramidRegionDefinition)offlineRegions[regionSelected].getDefinition()).getBounds();double regionZoom = ((OfflineTilePyramidRegionDefinition)offlineRegions[regionSelected].getDefinition()).getMinZoom();CameraPosition cameraPosition = new CameraPosition.Builder().target(bounds.getCenter()).zoom(regionZoom).build();map.moveCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));}}).setNeutralButton(getString(R.string.navigate_neutral_button_title), new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int id) { //删除progressBar.setProgress(0);progressBar.setVisibility(View.VISIBLE);offlineRegions[regionSelected].delete(new OfflineRegion.OfflineRegionDeleteCallback() {@Overridepublic void onDelete() {progressBar.setVisibility(View.INVISIBLE);progressBar.setProgress(0);Toast.makeText(getApplicationContext(), getString(R.string.toast_region_deleted),Toast.LENGTH_LONG).show();}@Overridepublic void onError(String error) {progressBar.setVisibility(View.INVISIBLE);progressBar.setProgress(0);Timber.e("Error: %s", error);}});}}).setNegativeButton(getString(R.string.navigate_negative_button_title), null).create();dialog.show();}@Overridepublic void onError(String error) {Timber.e("Error: %s", error);}});}private String getRegionName(OfflineRegion offlineRegion) {String regionName;try {byte[] metadata = offlineRegion.getMetadata();String json = new String(metadata, JSON_CHARSET);JSONObject jsonObject = new JSONObject(json);regionName = jsonObject.getString(JSON_FIELD_REGION_NAME);} catch (Exception exception) {Timber.e("Failed to decode metadata: %s", exception.getMessage());regionName = "未命名";}return regionName;}// Progress bar methodsprivate void startProgress() {count_complete_err=0;// Disable buttonsdownloadButton.setEnabled(false);listButton.setEnabled(false);// Start and show the progress barisEndNotified = false;progressBar.setProgress(0);progressBar.setVisibility(View.VISIBLE);}private void setPercentage(final int percentage) {progressBar.setProgress(0);progressBar.setProgress(percentage);}private void endProgress(final String message) { // Don't notify more than onceif (isEndNotified) {return;}// Enable buttonsdownloadButton.setEnabled(true);listButton.setEnabled(true);// Stop and hide the progress barisEndNotified = true;progressBar.setProgress(0);progressBar.setVisibility(View.GONE);// Show a toastToast.makeText(MainActivity.this, message, Toast.LENGTH_LONG).show();}@Overridepublic void onExplanationNeeded(List<String> permissionsToExplain) {Toast.makeText(this, "需要定位权限", Toast.LENGTH_LONG).show();}@Overridepublic void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {permissionsManager.onRequestPermissionsResult(requestCode, permissions, grantResults);}@Overridepublic void onPermissionResult(boolean granted) {if (granted) {map.getStyle(new Style.OnStyleLoaded() {@Overridepublic void onStyleLoaded(@NonNull Style style) {enableLocationComponent(style);}});} else {Toast.makeText(this, "获取定位权限失败", Toast.LENGTH_LONG).show();finish();}}@SuppressWarnings({"MissingPermission"})@Overridepublic void onLocationComponentClick() {if (locationComponent.getLastKnownLocation() != null) {Toast.makeText(this,"纬度" + locationComponent.getLastKnownLocation().getLatitude() + "经度" +locationComponent.getLastKnownLocation().getLongitude(), Toast.LENGTH_LONG).show();}}@SuppressWarnings({"MissingPermission"})private void enableLocationComponent(@NonNull Style loadedMapStyle) { // Check if permissions are enabled and if not requestif (PermissionsManager.areLocationPermissionsGranted(this)) {// Create and customize the LocationComponent's optionsLocationComponentOptions customLocationComponentOptions = LocationComponentOptions.builder(this).elevation(5).accuracyAlpha(.6f).accuracyColor(Color.RED).foregroundDrawable(android.R.drawable.ic_menu_mylocation).build();// Get an instance of the componentlocationComponent = map.getLocationComponent();LocationComponentActivationOptions locationComponentActivationOptions =LocationComponentActivationOptions.builder(this, loadedMapStyle).locationComponentOptions(customLocationComponentOptions).build();locationComponent.activateLocationComponent(locationComponentActivationOptions);locationComponent.setLocationComponentEnabled(true);locationComponent.setCameraMode(CameraMode.TRACKING);locationComponent.setRenderMode(RenderMode.COMPASS);locationComponent.addOnLocationClickListener(this);// Add the camera tracking listener. Fires if the map camera is manually moved.locationComponent.addOnCameraTrackingChangedListener(this);} else {permissionsManager = new PermissionsManager(this);permissionsManager.requestLocationPermissions(this);}}@Overridepublic void onCameraTrackingDismissed() {}@Overridepublic void onCameraTrackingChanged(int currentMode) {}public void locate(View view) {Button button = (Button) view;if (isLocating) {isLocating = false;button.setText("定位");locationComponent.setLocationComponentEnabled(false);locationComponent.removeOnCameraTrackingChangedListener(this);locationComponent.removeOnLocationClickListener(this);} else {if (map.getStyle() != null) {button.setText("关闭定位");enableLocationComponent(map.getStyle());isLocating = true;}}}}效果图
效果如下图所示:
简要说明一下操作,点击开始下载,自动下载当前屏幕区域内的离线地图,根据下载进度,进度条自动计算,下载完成后,点击下载列表,打开离线列表,点击其中的选项,点击确定,会自动跳转到对应的离线地图区域,这时候断开网络连接,也还是继续显示的。点击定位按钮,自动跳转到当前位置。
说明
总结
以上是生活随笔为你收集整理的MapBox定位与离线地图下载Android的全部内容,希望文章能够帮你解决所遇到的问题。
- 上一篇: 在pycharm中自定义模板代码,快速输
- 下一篇: android实现应用商店开发,基于An