ArcGIS for Android 100.3.0(9):GPS定位

ArcGIS Runtime 100定位类——LocationDisplay

其官方解释为:管理当前位置在显示地图里的展示,包括当前位置的信息,符号,以及随地图的平移、旋转、缩放等进行自动变化。

也就是有了这个类,不仅可以获取当前位置信息进行定位,也可以将位置信息展示出来。

api:

https://developers.arcgis.com/android/latest/apireference/reference/com/esri/arcgisruntime/mapping/view/LocationDisplay.html

定位权限

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

直接上代码:

public class LocationActivity extends AppCompatActivity implements PermissionUtils.PermissionCallbacks {

    private static final int REQUEST_PERMISSION_CODE = 0;

    private MapView mMapView;

    private LocationDisplay mLocationDisplay;

    private String[] permissions = {
            Manifest.permission.ACCESS_FINE_LOCATION,
            Manifest.permission.ACCESS_COARSE_LOCATION
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_location);

        mMapView = (MapView) findViewById(R.id.mapview);

        String theURLString = "http://map.geoq.cn/arcgis/rest/services/ChinaOnlineCommunity/MapServer";
        ArcGISTiledLayer mainArcGISTiledLayer = new ArcGISTiledLayer(theURLString);
        Basemap mainBasemap = new Basemap(mainArcGISTiledLayer);
        ArcGISMap arcGISMap = new ArcGISMap(mainBasemap);
        mMapView.setMap(arcGISMap);

        if (PermissionUtils.hasPermissions(this, permissions)) {
            startLocation();
        } else {
            PermissionUtils.requestPermissions(this, REQUEST_PERMISSION_CODE, permissions);
        }

    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);

        PermissionUtils.onRequestPermissionsResult(requestCode, permissions, grantResults, this);
    }

    @Override
    public void onPermissionsAllGranted(int requestCode, List<String> perms, boolean isAllGranted) {
        if (isAllGranted) {
            startLocation();
        }
    }

    @Override
    public void onPermissionsDenied(int requestCode, List<String> perms) {
    }

    private void startLocation() {
        mLocationDisplay = mMapView.getLocationDisplay();
        mLocationDisplay.setAutoPanMode(LocationDisplay.AutoPanMode.RECENTER);
        //当我们执行LocationDisplay.startAsync()方法时候,会在地图上显示出我们当前位置
        mLocationDisplay.startAsync();

        //获取的点是基于当前地图坐标系的点
        Point point = mLocationDisplay.getMapLocation();
        Log.e("xyh", "point: " + point.toString());

        //获取基于GPS的位置信息
        LocationDataSource.Location location = mLocationDisplay.getLocation();
        //基于WGS84的经纬度坐标。
        Point point1 = location.getPosition();
        if (point1 != null) {
            Log.e("xyh", "point1: " + point1.toString());
        }

        //如果要在LocationDisplay里进行位置信息的自动监听,方法也很简单,只需要LocationDisplay.addLocationChangedListener即可
        mLocationDisplay.addLocationChangedListener(new LocationDisplay.LocationChangedListener() {
            @Override
            public void onLocationChanged(LocationDisplay.LocationChangedEvent locationChangedEvent) {
                LocationDataSource.Location location = locationChangedEvent.getLocation();
                Log.e("xyh", "onLocationChanged: " + location.getPosition().toString());
            }
        });
    }

    @Override
    protected void onPause() {
        super.onPause();
        mMapView.pause();
    }

    @Override
    protected void onResume() {
        super.onResume();
        mMapView.resume();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        mMapView.dispose();
    }
}

结束定位

 if (mLocationDisplay.isStarted())
 mLocationDisplay.stop();

位置监听的自动扫描模式

位置监听的自动扫描模式可能有点拗口,算是对于这个功能的直译吧。这个功能的意思是当你的位置信息变化时候,如何在地图上展示出来。

使用方法为:LocationDisplay.setAutoPanMode(LocationDisplay.AutoMode)。

模式一共有四种:

COMPASS_NAVIGATION 和NAVIGATION 分别最适用于步行导航和车载导航,用户的位置符号会固定显示在屏幕的某个点上,并且指向设备的顶部(也就是地图会随着用户移动而平移,随用户转弯而旋转);

OFF 模式,用户位置符号会随位置变化而移动,但地图不会动;

RECENTER模式,当用户位置处于当前地图范围内时候,用户位置符号会随位置变化而移动,但地图不会动;当用户位置处于地图边缘时候,地图会自动平移是用户的当前位置重新居于显示地图中心。

LocationDisplay类里可以直接设置位置符号样式

当我们执行LocationDisplay.startAsync()方法时候,会在地图上显示出我们当前位置,默认的符号如下所示:

如果我们想要改变这个符号样式,只需要重新设置符号即可,代码如下所示:

locationDisplay = mMapView.getLocationDisplay();
Resources resources=getResources();
BitmapDrawable bitmapDrawable= new BitmapDrawable(BitmapFactory.decodeResource(resources,R.drawable.location));
final PictureMarkerSymbol campsiteSymbol = new PictureMarkerSymbol(bitmapDrawable);
campsiteSymbol.loadAsync();
campsiteSymbol.addDoneLoadingListener(new Runnable() {
    @Override
    public void run() {
        locationDisplay.setDefaultSymbol(campsiteSymbol);//设置默认符号
        locationDisplay.setShowAccuracy(false);//隐藏符号的缓存区域
    }
});

对于位置符号的设置有以下几种:

locationDisplay.setAcquiringSymbol(campsiteSymbol);//设置当前位置的填充符号
locationDisplay.setAccuracySymbol(campsiteSymbol);//设置最后一个已知位置的标记符号
locationDisplay.setPingAnimationSymbol(campsiteSymbol);//设置当前位置更新时候的动画
locationDisplay.setCourseSymbol(campsiteSymbol);//设置当前位置的路线符号
locationDisplay.setHeadingSymbol(campsiteSymbol);//设置当前位置设备面对方向的符号
locationDisplay.setDefaultSymbol(campsiteSymbol);//设置默认符号

位置符号隐藏

在ArcGIS Runtime 100里假如我们只是想获取位置信息,而不需要显示出来,我们只需要将位置监听的模式设置为OFF,然后执行以下代码即可。

locationDisplay.setShowLocation(false);//隐藏符号
locationDisplay.setShowAccuracy(false);//隐藏符号的缓存区域
locationDisplay.setShowPingAnimation(false);//隐藏位置更新的符号动画

PermissionUtils:

/**
 * 动态申请权限工具类
 * Created by xiaoyehai on 2018/4/25 0025.
 */

public class PermissionUtils {

    public static final int GOTO_SEETING_CODE = 152;

    /**
     * 判断是否有权限
     *
     * @param context
     * @param perms
     * @return
     */
    public static boolean hasPermissions(@NonNull Context context, @Size(min = 1) @NonNull String... perms) {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
            return true;
        }

        if (context == null) {
            throw new IllegalArgumentException("Can't check permissions for null context");
        }

        for (String perm : perms) {
            if (ContextCompat.checkSelfPermission(context, perm) != PackageManager.PERMISSION_GRANTED) {
                return false;
            }
        }
        return true;
    }


    /**
     * 申请权限
     */
    public static void requestPermissions(@NonNull Activity activity, int requestCode, String[] permissions) {

        List<String> permissionList = new ArrayList<>();
        for (String permission : permissions) {
            if (ContextCompat.checkSelfPermission(activity, permission) != PackageManager.PERMISSION_GRANTED) {
                permissionList.add(permission);
            }
        }

        String[] permissionsArray = permissionList.toArray(new String[permissionList.size()]);//将List转为数组
        if (permissionList.isEmpty()) {
            //不可能为空
        } else {
            ActivityCompat.requestPermissions(activity, permissionsArray, requestCode);
            //返回结果onRequestPermissionsResult
        }
    }


    /**
     * 申请权限的回调
     *
     * @param requestCode  请求权限时传入的请求码,用于区别是哪一次请求的
     * @param permissions  所请求的所有权限的数组
     * @param grantResults 权限授予结果,和 permissions 数组参数中的权限一一对应,元素值为两种情况,如下:
     *                     授予: PackageManager.PERMISSION_GRANTED
     *                     拒绝: PackageManager.PERMISSION_DENIED
     */
    public static void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
                                                  @NonNull int[] grantResults, @NonNull PermissionCallbacks callBack) {
        //授予的权限。
        List<String> granted = new ArrayList<>();

        //拒绝的权限
        List<String> denied = new ArrayList<>();


        for (int i = 0; i < permissions.length; i++) {
            String perm = permissions[i];
            if (grantResults[i] == PackageManager.PERMISSION_GRANTED) {
                granted.add(perm);
            } else {
                denied.add(perm);
            }
        }

        if (null != callBack) {
            if (denied.isEmpty()) {
                callBack.onPermissionsAllGranted(requestCode, granted, denied.isEmpty());
            }

            if (!denied.isEmpty()) {
                callBack.onPermissionsDenied(requestCode, denied);
            }
        }
    }

    /**
     * 用户是否拒绝权限,并检查“不要提醒”。
     *
     * @param activity
     * @param perms
     * @return
     */
    public static boolean somePermissionPermanentlyDenied(Activity activity, @NonNull List<String> perms) {
        for (String deniedPermission : perms) {
            if (permissionPermanentlyDenied(activity, deniedPermission)) {
                return true;
            }
        }

        return false;
    }

    public static boolean permissionPermanentlyDenied(Activity activity, @NonNull String perms) {
        if (!ActivityCompat.shouldShowRequestPermissionRationale(activity, perms)) {
            return true;
        }
        return false;
    }


    public static void showDialogGoToAppSettting(final Activity activity) {
        AlertDialog dialog = new AlertDialog.Builder(activity)
                .setMessage("去设置界面开启权限")
                .setPositiveButton("确定", new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int which) {
                        // 跳转到应用设置界面
                        goToAppSetting(activity);
                    }
                }).setCancelable(false).show();
    }


    /**
     * 跳转到应用设置界面
     */
    public static void goToAppSetting(Activity activity) {
        Intent intent = new Intent();
        intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
        Uri uri = Uri.fromParts("package", activity.getPackageName(), null);
        intent.setData(uri);
        activity.startActivityForResult(intent, GOTO_SEETING_CODE);
    }

    public static void showPermissionReason(final int requestCode, final Activity activity, final String[] permission, String s) {
        AlertDialog dialog = new AlertDialog.Builder(activity)
                .setMessage(s)
                .setPositiveButton("确定", new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int which) {
                        requestPermissions(activity, requestCode, permission);
                    }
                })
                .setCancelable(false).show();
    }



    public interface PermissionCallbacks {

        /**
         * @param isAllGranted 是否全部同意
         */
        void onPermissionsAllGranted(int requestCode, List<String> perms, boolean isAllGranted);

        /**
         */
        void onPermissionsDenied(int requestCode, List<String> perms);

    }
}

下面来看看官方的例子

这里写图片描述

public class DisplayDeviceLocationActivity extends AppCompatActivity {

    private MapView mMapView;

    private LocationDisplay mLocationDisplay;

    private Spinner mSpinner;

    private int requestCode = 2;

    String[] reqPermissions = new String[]{
            Manifest.permission.ACCESS_FINE_LOCATION,
            Manifest.permission.ACCESS_COARSE_LOCATION};

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_display_device_location);

        mSpinner = (Spinner) findViewById(R.id.spinner);
        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) {

                // If LocationDisplay started OK, then continue.
                if (dataSourceStatusChangedEvent.isStarted())
                    return;

                // No error is reported, then continue.
                if (dataSourceStatusChangedEvent.getError() == null)
                    return;

                // If an error is found, handle the failure to start.
                // Check permissions to see if failure may be due to lack of permissions.
                boolean permissionCheck1 = ContextCompat.checkSelfPermission(DisplayDeviceLocationActivity.this, reqPermissions[0]) ==
                        PackageManager.PERMISSION_GRANTED;
                boolean permissionCheck2 = ContextCompat.checkSelfPermission(DisplayDeviceLocationActivity.this, reqPermissions[1]) ==
                        PackageManager.PERMISSION_GRANTED;

                if (!(permissionCheck1 && permissionCheck2)) {
                    ActivityCompat.requestPermissions(DisplayDeviceLocationActivity.this, reqPermissions, requestCode);
                } else {
                    // Report other unknown failure types to the user - for example, location services may not
                    // be enabled on the device.
                    String message = String.format("Error in DataSourceStatusChangedListener: %s", dataSourceStatusChangedEvent
                            .getSource().getLocationDataSource().getError().getMessage());
                    Toast.makeText(DisplayDeviceLocationActivity.this, message, Toast.LENGTH_LONG).show();

                    // Update UI to reflect that the location display did not actually start
                    mSpinner.setSelection(0, true);
                }
            }
        });


        // Populate the list for the Location display options for the spinner's Adapter
        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));

        SpinnerAdapter adapter = new SpinnerAdapter(this, R.layout.spinner_layout, R.id.txt, list);
        mSpinner.setAdapter(adapter);
        mSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {

                switch (position) {
                    case 0:
                        // Stop Location Display
                        if (mLocationDisplay.isStarted())
                            mLocationDisplay.stop();
                        break;
                    case 1:
                        // Start Location Display
                        if (!mLocationDisplay.isStarted())
                            mLocationDisplay.startAsync();
                        break;
                    case 2:
                        // RECENTER模式,当用户位置处于当前地图范围内时候,用户位置符号会随位置变化而移动,但地图不会动;
                        // 当用户位置处于地图边缘时候,地图会自动平移是用户的当前位置重新居于显示地图中心。
                        mLocationDisplay.setAutoPanMode(LocationDisplay.AutoPanMode.RECENTER);
                        if (!mLocationDisplay.isStarted())
                            mLocationDisplay.startAsync();
                        break;
                    case 3:
                        // Start Navigation Mode
                        // 这种模式最适合于车载导航。
                        mLocationDisplay.setAutoPanMode(LocationDisplay.AutoPanMode.NAVIGATION);
                        if (!mLocationDisplay.isStarted())
                            mLocationDisplay.startAsync();
                        break;
                    case 4:
                        // Start Compass Mode
                        // 这种模式更适合用户行走时的路标导航。
                        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) {
            mLocationDisplay.startAsync();
        } else {
            Toast.makeText(DisplayDeviceLocationActivity.this, "权限被拒绝", Toast.LENGTH_SHORT).show();

            mSpinner.setSelection(0, true);
        }
    }

    @Override
    protected void onPause() {
        super.onPause();
        mMapView.pause();
    }

    @Override
    protected void onResume() {
        super.onResume();
        mMapView.resume();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        mMapView.dispose();
    }
}

猜你喜欢

转载自blog.csdn.net/qq_36699930/article/details/82463545