• 【Android Developers Training】 103. 查询当前地点


    注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好。

    原文链接:http://developer.android.com/training/location/retrieve-current.html


    地点服务自动维护用户当前的地点,所以你的应用所要做的事情就是在需要时去获取它。地点的精确度是基于你所申请的地点查询权限,以及当前设备上激活的的位置传感器。

    地点服务会通过定位客户端(定位服务类的一个实例:LocationClient),将当前的位置发送给你的应用,所有地点信息的请求都通过这一客户端。

    Note:

    在你开始这节课之前,请确定你的开发环境和测试设备都已经配置正确。可以阅读Setup获取更多这方面的信息。


    一). 指定应用权限

    使用位置服务的应用必须请求定位权限。Android有两个定位权限:ACCESS_COARSE_LOCATION(粗定位)和ACCESS_FINE_LOCATION(精定位)。你所选择的权限决定了定位的精度。如果你只请求粗定位,位置服务所范围的地点信息大致会精确到一个城市街区。

    如果请求ACCESS_FINE_LOCATION,它也暗含了ACCESS_COARSE_LOCATION的权限。

    例如,要添加ACCESS_COARSE_LOCATION,将下面的代码作为<manifest>元素的子元素:

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

    二). 检查Google Play服务

    位置服务是Google Play服务APK的其中一部分。由于用户设备的状态时难以预料的,你应该一直在你尝试连接定位服务之前,检查APK是否已经安装。要检查APK是否安装,可以调用GooglePlayServicesUtil.isGooglePlayServicesAvailable(),它会返回一个整形的结果码,其含义可以参阅:ConnectionResult。如果你遇到了一个错误,可以调用GooglePlayServicesUtil.getErrorDialog(),来获取一个本地的对话框,引导用户执行正确地行为,之后将这一对话框显示在一个DialogFragment上。这一对话框可能允许用户解决当前的问题,此时Google Play服务会发回一个结果到你的activity中。要处理这一结果,需要覆写onActivityResult()方法。

    由于你一直需要在你的代码多个地方检查Google Play服务,所以应该定义一个方法将检查行为进行封装,之后在每次连接尝试之前进行检查。下面的代码片段包含了检查Google Play服务所需要的代码:

    public class MainActivity extends FragmentActivity {
        ...
        // Global constants
        /*
         * Define a request code to send to Google Play services
         * This code is returned in Activity.onActivityResult
         */
        private final static int
                CONNECTION_FAILURE_RESOLUTION_REQUEST = 9000;
        ...
        // Define a DialogFragment that displays the error dialog
        public static class ErrorDialogFragment extends DialogFragment {
            // Global field to contain the error dialog
            private Dialog mDialog;
            // Default constructor. Sets the dialog field to null
            public ErrorDialogFragment() {
                super();
                mDialog = null;
            }
            // Set the dialog to display
            public void setDialog(Dialog dialog) {
                mDialog = dialog;
            }
            // Return a Dialog to the DialogFragment.
            @Override
            public Dialog onCreateDialog(Bundle savedInstanceState) {
                return mDialog;
            }
        }
        ...
        /*
         * Handle results returned to the FragmentActivity
         * by Google Play services
         */
        @Override
        protected void onActivityResult(
                int requestCode, int resultCode, Intent data) {
            // Decide what to do based on the original request code
            switch (requestCode) {
                ...
                case CONNECTION_FAILURE_RESOLUTION_REQUEST :
                /*
                 * If the result code is Activity.RESULT_OK, try
                 * to connect again
                 */
                    switch (resultCode) {
                        case Activity.RESULT_OK :
                        /*
                         * Try the request again
                         */
                        ...
                        break;
                    }
                ...
            }
         }
        ...
        private boolean servicesConnected() {
            // Check that Google Play services is available
            int resultCode =
                    GooglePlayServicesUtil.
                            isGooglePlayServicesAvailable(this);
            // If Google Play services is available
            if (ConnectionResult.SUCCESS == resultCode) {
                // In debug mode, log the status
                Log.d("Location Updates",
                        "Google Play services is available.");
                // Continue
                return true;
            // Google Play services was not available for some reason
            } else {
                // Get the error code
                int errorCode = connectionResult.getErrorCode();
                // Get the error dialog from Google Play services
                Dialog errorDialog = GooglePlayServicesUtil.getErrorDialog(
                        errorCode,
                        this,
                        CONNECTION_FAILURE_RESOLUTION_REQUEST);
    
                // If Google Play services can provide an error dialog
                if (errorDialog != null) {
                    // Create a new DialogFragment for the error dialog
                    ErrorDialogFragment errorFragment =
                            new ErrorDialogFragment();
                    // Set the dialog in the DialogFragment
                    errorFragment.setDialog(errorDialog);
                    // Show the error dialog in the DialogFragment
                    errorFragment.show(getSupportFragmentManager(),
                            "Location Updates");
                }
            }
        }
        ...
    }

    在后续章节的代码片段中,都会调用这一方法来验证是否可获取Google Play服务。


    三). 定义位置服务回调函数

    要获取当前的地点,创建一个地点客户端,将它连接至定位服务,之后调用它的getLastLocation()方法。返回的值是最佳最新的地理位置,它基于你应用所请求的权限以及当前设备上已激活的定位传感器。

    在你创建定位客户端之前,实现定位服务的接口,以和你的应用进行交互:

    ConnectionCallbacks

    指定当定位连接上或者没有连接上时,定位服务调用的方法。

    OnConnectionFailedListener

    指定当尝试连接到定位客户端时,如果出现了错误,定位服务调用的方法。这一方法使用之前定义的showErrorDialog方法来显示一个错误对话框,它尝试使用Google Play服务来解决这一问题。

    下面的样例代码展示了如何指定接口和定义相关的函数:

    public class MainActivity extends FragmentActivity implements
            GooglePlayServicesClient.ConnectionCallbacks,
            GooglePlayServicesClient.OnConnectionFailedListener {
        ...
        /*
         * Called by Location Services when the request to connect the
         * client finishes successfully. At this point, you can
         * request the current location or start periodic updates
         */
        @Override
        public void onConnected(Bundle dataBundle) {
            // Display the connection status
            Toast.makeText(this, "Connected", Toast.LENGTH_SHORT).show();
    
        }
        ...
        /*
         * Called by Location Services if the connection to the
         * location client drops because of an error.
         */
        @Override
        public void onDisconnected() {
            // Display the connection status
            Toast.makeText(this, "Disconnected. Please re-connect.",
                    Toast.LENGTH_SHORT).show();
        }
        ...
        /*
         * Called by Location Services if the attempt to
         * Location Services fails.
         */
        @Override
        public void onConnectionFailed(ConnectionResult connectionResult) {
            /*
             * Google Play services can resolve some errors it detects.
             * If the error has a resolution, try sending an Intent to
             * start a Google Play services activity that can resolve
             * error.
             */
            if (connectionResult.hasResolution()) {
                try {
                    // Start an Activity that tries to resolve the error
                    connectionResult.startResolutionForResult(
                            this,
                            CONNECTION_FAILURE_RESOLUTION_REQUEST);
                    /*
                     * Thrown if Google Play services canceled the original
                     * PendingIntent
                     */
                } catch (IntentSender.SendIntentException e) {
                    // Log the error
                    e.printStackTrace();
                }
            } else {
                /*
                 * If no resolution is available, display a dialog to the
                 * user with the error.
                 */
                showErrorDialog(connectionResult.getErrorCode());
            }
        }
        ...
    }

    四). 连接定位客户端

    现在回调函数已经就位了,创建定位客户端并且连接它至定位服务。

    你应该在onCreate()方法中创建定位客户端,之后再onStart()方法中进行连接。这样定位服务就能在你的应用完全可见时维护当前的定位信息。在onStop()方法中关闭连接,这样当应用不可见时,定位服务就会停止更新地点。这样的连接方式还能节省电量。

    Note:

    只有在定位客户端连接到了定位服务后,当前的地点才能维护。假设没有其他应用连接到定位服务,如果你关闭了客户端,过一段时间后,调用了getLastLocation(),获得的结果可能将是过期的。

    例如:

    public class MainActivity extends FragmentActivity implements
            GooglePlayServicesClient.ConnectionCallbacks,
            GooglePlayServicesClient.OnConnectionFailedListener {
        ...
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            ...
            /*
             * Create a new location client, using the enclosing class to
             * handle callbacks.
             */
            mLocationClient = new LocationClient(this, this, this);
            ...
        }
        ...
        /*
         * Called when the Activity becomes visible.
         */
        @Override
        protected void onStart() {
            super.onStart();
            // Connect the client.
            mLocationClient.connect();
        }
        ...
        /*
         * Called when the Activity is no longer visible.
         */
        @Override
        protected void onStop() {
            // Disconnecting the client invalidates it.
            mLocationClient.disconnect();
            super.onStop();
        }
        ...
    }

    五). 获取当前地点

    要获取当前地点,调用getLastLocation(),例如:

    public class MainActivity extends FragmentActivity implements
            GooglePlayServicesClient.ConnectionCallbacks,
            GooglePlayServicesClient.OnConnectionFailedListener {
        ...
        // Global variable to hold the current location
        Location mCurrentLocation;
        ...
        mCurrentLocation = mLocationClient.getLastLocation();
        ...
    }

    在下一节课中,将会向你展示从定位服务定期地接受地点更新的方法。

  • 相关阅读:
    结对第二次作业——某次疫情统计可视化的实现
    结对第一次—疫情统计可视化(原型设计)
    个人作业——软件工程实践总结&个人技术博客
    虚拟列表(VirtualList)在Taro3中的使用
    结对第二次作业—某次疫情统计可视化的实现
    结对第一次—疫情统计可视化(原型设计)
    软工实践寒假作业(2/2)
    软工实践寒假作业(1/2)
    个人作业——软件工程实践总结&个人技术博客
    Spring Boot
  • 原文地址:https://www.cnblogs.com/jdneo/p/3713826.html
Copyright © 2020-2023  润新知