ArcGIS Runtime SDK for Android 入門(5):顯示移動裝置當前位置
本文主要講解如何使用ArcGIS Runtime SDK for Android 在地圖中顯示移動裝置的當前位置。
1.建立Android專案
2.新增Runtime SDK依賴
3.新增許可權及OpenGL ES支援
在AndroidManifest.xml中新增:
<uses-permission android:name="android.permission.INTERNET" /><!--聯網許可權--> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /><!--粗略定位許可權--> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /><!--精確定位許可權--> <uses-feature android:glEsVersion="0x00020000" android:required="true" /><!--OpenGL ES支援-->
注1:若移動裝置Android版本為6.0及以上,不僅要在manifest中新增許可權,還需要在Activity中程式碼動態獲取許可權。
注2:若使用Android模擬器AVD進行除錯,需要設定模擬定位,步驟:
點選模擬器右側工具欄的按鈕,在出現的介面的Location選項卡中設定Longtitude及Latitude數值,之後點選“send”即可,注意經緯度為WGS84座標系,若要進行座標拾取,推薦使用谷歌地球獲取。
4.設定介面佈局
在layout中的佈局XML中新增:
<!-- MapView控制元件 --> <com.esri.arcgisruntime.mapping.view.MapView android:id="@+id/mapView" android:layout_width="match_parent" android:layout_height="match_parent"> </com.esri.arcgisruntime.mapping.view.MapView> <!-- 下拉框控制元件 --> <Spinner android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/spinner" android:layout_alignParentBottom="true" android:layout_alignParentRight="true" android:layout_marginBottom="22dp" android:background="#00000000" android:popupBackground="#00000000" android:overlapAnchor="false"/>
由於本例使用的Spinner下拉框比較特殊,列表項是由文字和圖片組成,因此需要設定下拉框的佈局,在layout中的佈局XML中新增spinner_layout.xml:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android= "http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <TextView android:id="@+id/txt" android:layout_width="wrap_content" android:layout_height="wrap_content" android:paddingTop="5dp" android:textColor="#FFF" android:textSize="20sp" android:gravity="end" android:textStyle="bold|normal" android:layout_weight="0.9"/> <ImageView android:id="@+id/img" android:layout_width="wrap_content" android:layout_height="wrap_content" android:padding="10dp" android:layout_weight="0.1" android:contentDescription="@null"/> </LinearLayout>
5.Spinner圖片素材準備,準備了各個按鈕的適用不同解析度的影象:
下載地址:https://download.csdn.net/download/smart3s/10541268
6.編寫程式碼:
程式碼實現基本流程:
(1)從MapView中獲取LocationDisplay
(2)對LocationDisplay設定定位模式
Re-Center – 中心點顯示定位
Navigation Mode – 導航模式
Compass Mode – 羅盤模式
(3)開啟或結束定位
開始定位:mLocationDisplay.startAsync();
結束定位:mLocationDisplay.stop();
定位是否開啟:mLocationDisplay.isStarted();
詳細步驟:
(1)Spinner擴充套件:
ItemData.java:Spinner下拉框項變數,儲存操作名稱和圖片ID
public class ItemData {
private final String text;
private final Integer imageId;
public ItemData(String text, Integer imageId) {
this.text = text;
this.imageId = imageId;
}
public String getText() {
return text;
}
public Integer getImageId() {
return imageId;
}
}
SpinnerAdapter.java:下拉框介面卡變數,用來控制Spinner的顯示
public class SpinnerAdapter extends ArrayAdapter<ItemData> {
private final int groupid;
private final ArrayList<ItemData> list;
private final LayoutInflater inflater;
public SpinnerAdapter(Activity context, int groupid, int id, ArrayList<ItemData>
list) {
super(context, id, list);
this.list = list;
inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
this.groupid = groupid;
}
public View getView(int position, View convertView, ViewGroup parent) {
View itemView = inflater.inflate(groupid, parent, false);
ImageView imageView = (ImageView) itemView.findViewById(R.id.img);
imageView.setImageResource(list.get(position).getImageId());
TextView textView = (TextView) itemView.findViewById(R.id.txt);
textView.setText(list.get(position).getText());
return itemView;
}
public View getDropDownView(int position, View convertView, ViewGroup
parent) {
return getView(position, convertView, parent);
}
}
(2)MainActivity.java:
變數準備:
//MapView控制元件變數
private MapView mMapView;
//位置顯示變數
private LocationDisplay mLocationDisplay;
//下拉框變數
private Spinner mSpinner;
//若系統環境為Android6.0及以上版本,僅在manifest中新增許可權是不夠的,需要程式碼動態獲取許可權
//許可權請求碼
private int requestCode = 2;
//許可權名稱
String[] reqPermissions = new String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission
.ACCESS_COARSE_LOCATION};
onCreate方法:
// 定位按鈕列表
mSpinner = (Spinner) findViewById(R.id.spinner);
// 從佈局中獲取MapView,並使用影像作為底圖
mMapView = (MapView) findViewById(R.id.mapView);
ArcGISMap mMap = new ArcGISMap(Basemap.createImagery());
mMapView.setMap(mMap);
//獲取定位元件類
mLocationDisplay = mMapView.getLocationDisplay();
// 設定位置改變監聽
mLocationDisplay.addDataSourceStatusChangedListener(new LocationDisplay.DataSourceStatusChangedListener() {
@Override
public void onStatusChanged(LocationDisplay.DataSourceStatusChangedEvent dataSourceStatusChangedEvent) {
// 如果LocationDisplay啟動OK,則繼續。
if (dataSourceStatusChangedEvent.isStarted()){
return;
}
// 沒有錯誤報告,然後繼續。
if (dataSourceStatusChangedEvent.getError() == null){
return;
}
// 如果發現錯誤,處理啟動失敗。
// 檢查許可權,看看是否失敗可能是由於缺乏許可權。
boolean permissionCheck1 = ContextCompat.checkSelfPermission(MainActivity.this, reqPermissions[0]) ==
PackageManager.PERMISSION_GRANTED;
boolean permissionCheck2 = ContextCompat.checkSelfPermission(MainActivity.this, reqPermissions[1]) ==
PackageManager.PERMISSION_GRANTED;
if (!(permissionCheck1 && permissionCheck2)) {
// 如果許可權尚未授予,請向使用者請求許可權。
ActivityCompat.requestPermissions(MainActivity.this, reqPermissions, requestCode);
} else {
// 向用戶報告其他未知的故障型別—例如,在裝置上可能無法啟用位置服務。
String message = String.format("Error in DataSourceStatusChangedListener: %s", dataSourceStatusChangedEvent
.getSource().getLocationDataSource().getError().getMessage());
Toast.makeText(MainActivity.this, message, Toast.LENGTH_LONG).show();
// 更新UI以反映位置顯示,實際上沒有啟動
mSpinner.setSelection(0, true);
}
}
});
// 設定位置按鈕列表
ArrayList<ItemData> list = new ArrayList<>();
list.add(new ItemData("Stop", R.drawable.locationdisplaydisabled));
list.add(new ItemData("On", R.drawable.locationdisplayon));
list.add(new ItemData("Re-Center", R.drawable.locationdisplayrecenter));
list.add(new ItemData("Navigation", R.drawable.locationdisplaynavigation));
list.add(new ItemData("Compass", R.drawable.locationdisplayheading));
//建立並繫結Spinner介面卡
SpinnerAdapter adapter = new SpinnerAdapter(this, R.layout.spinner_layout, R.id.txt, list);
mSpinner.setAdapter(adapter);
//Spinner點選事件
mSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
switch (position) {
case 0:
// 停止顯示位置
if (mLocationDisplay.isStarted())
mLocationDisplay.stop();
break;
case 1:
// 開始顯示位置
if (!mLocationDisplay.isStarted())
mLocationDisplay.startAsync();
break;
case 2:
// 底圖地圖顯示到中心
mLocationDisplay.setAutoPanMode(LocationDisplay.AutoPanMode.RECENTER);
if (!mLocationDisplay.isStarted())
mLocationDisplay.startAsync();
break;
case 3:
// 開始導航模式(此模式,最佳適用於駕車導航)
mLocationDisplay.setAutoPanMode(LocationDisplay.AutoPanMode.NAVIGATION);
if (!mLocationDisplay.isStarted())
mLocationDisplay.startAsync();
break;
case 4:
// 開始羅盤模式(此模式最佳適用於使用者步行時的路徑導航)
mLocationDisplay.setAutoPanMode(LocationDisplay.AutoPanMode.COMPASS_NAVIGATION);
if (!mLocationDisplay.isStarted())
mLocationDisplay.startAsync();
break;
}
}
@Override
public void onNothingSelected(AdapterView<?> parent) { }
});
其他:
//當接收到許可權請求回撥時呼叫
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
// 如果請求被拒絕,結果陣列是空值
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// 位置被授予許可。這可能是由於未能啟動該系統而引發的。
// LocationDisplay,再次定位
mLocationDisplay.startAsync();
} else {
// 如果被拒絕,顯示toast以告知使用者所選擇的內容。如果LocationDisplay再次啟動,請求許可權UX將被再次顯示,選項應該被顯示以允許不再顯示UX。
// 另一種方法是禁用功能,因此請求不再顯示
Toast.makeText(MainActivity.this, getResources().getString(R.string.location_permission_denied), Toast
.LENGTH_SHORT).show();
// 更新UI以反映位置顯示,實際上沒有啟動
mSpinner.setSelection(0, true);
}
}
7.執行App可以進行簡單的定位的相關操作:
感謝luq老師的指導