本文主要讲解如何使用ArcGIS Runtime SDK for Android 在地图中显示移动设备的当前位置。
1.创建Android项目
2.添加Runtime SDK依赖
前两步本文省略,初学者可参照ArcGIS Runtime SDK for Android 入门(1):第一个地图应用程序(二维)
3.添加权限及OpenGL ES支持
在AndroidManifest.xml中添加:
注1:若移动设备Android版本为6.0及以上,不仅要在manifest中添加权限,还需要在Activity中代码动态获取权限。
注2:若使用Android模拟器AVD进行调试,需要设置模拟定位,步骤:
点击模拟器右侧工具栏的按钮,在出现的界面的Location选项卡中设置Longtitude及Latitude数值,之后点击“send”即可,注意经纬度为WGS84坐标系,若要进行坐标拾取,推荐使用谷歌地球获取。
4.设置界面布局
在layout中的布局XML中添加:
由于本例使用的Spinner下拉框比较特殊,列表项是由文字和图片组成,因此需要设置下拉框的布局,在layout中的布局XML中添加spinner_layout.xml:
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 {
private final int groupid;
private final ArrayList list;
private final LayoutInflater inflater;
public SpinnerAdapter(Activity context, int groupid, int id, ArrayList
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 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可以进行简单的定位的相关操作: