MapBox定位与离线地图下载Android
生活随笔
收集整理的這篇文章主要介紹了
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中自定义模板代码,快速输
- 下一篇: 【numpy】20道numpy题目