ArcGIS Runtime SDK for Android 学习(5):显示移动设备当前位置

    本文主要讲解如何使用ArcGIS Runtime SDK for Android 在地图中显示移动设备的当前位置。

1.创建Android项目   

2.添加Runtime SDK依赖   前两步本文省略,初学者可参照ArcGIS Runtime SDK for Android 学习笔记(1):第一个地图应用程序(二维)

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)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老师的指导

猜你喜欢

转载自blog.csdn.net/smart3s/article/details/81044134