The use of native GPS in Android

When it comes to mobile phone positioning, everyone must think of AutoNavi Maps or Baidu Maps, because these location service providers can determine our more accurate location information based on the base station data we return, WIFI data, and our GPS positioning. However, the GPS positioning is actually included in the Android native system. Although we don't use it directly most of the time, as a rigorous developer, we need to understand it accordingly. In addition, in some special environments, such as exclusive devices or exclusive networks, we may not be able to access the tripartite website or access the tripartite SDK. At this time, native GPS is required for positioning operations.

Below I will introduce GPS positioning from two pieces of related positioning tools and sample codes.

1. Introduction to related tools

<1> Criteria

The positioning condition device is used to set the preconditions for positioning, such as accuracy, speed, altitude, bearing and other information. There are the following 5 commonly used parameters.

  • setAccuracy: Set the positioning accuracy. There are two values, Criteria.ACCURACY_FINE means high precision, and Criteria.ACCURACY_COARSE means low precision.
  • setSpeedAccuracy: Set the speed accuracy. The value of speed accuracy is shown in Table 1.
Table 1
Speed ​​accuracy of the Criteria class Description
ACCURACY_HIGH High accuracy, error less than 100 meters
ACCURACY_MEDIUM The accuracy is medium, the error is between 100 meters and 500 meters
ACCURACY_LOW Low accuracy, error greater than 500 meters
  • setAltitudeRequired: Set whether altitude information is required. The value true means it is needed, and false means it is not needed.
  • setBearingRequired: Set whether bearing information is required. The value true means it is needed, and false means it is not needed.
  • setCostAllowed: Set whether to allow the operator to charge. The value true means it is allowed, and false means it is not allowed.
  • setPowerRequirement: This is the power requirement. There are 3 values. Criteria.POWER_LOW means low power consumption, Criteria.POWER_MEDIUM means medium power consumption, and Criteria.POWER_HIGH means good power.

<2>LocationManager

The location manager is used to obtain the provider of location information, set up a listener, and obtain the most recent location information. The object of the location manager is obtained from the system service LOCATION_SERVICE.

  • getBestProvider: Get the best positioning provider. The first parameter is an instance of the positioning conditioner Criteria, and the value of the second parameter is true as long as it is available. See Table 2 for the value of the location provider.
Table 2
The name of the location provider Description The open state of the positioning function
gps Satellite positioning Turn on GPS function
network Network positioning Turn on data connection or Wi-Fi
passive Unable to locate To enable positioning-related functions
  • isProviderEnabled: Determine whether the specified location provider is available.
  • getLastKnownLocation: Get the last location location.
  • requestLocationUpdates: Set the location listener. Among them, the first parameter is the location provider, the second parameter is the minimum interval time for location update, the third parameter is the minimum distance for location update, and the fourth parameter is an example of a location listener.
  • removeUpdates: Remove the positioning listener.
  • addGpsStatusListener: Add a listener for positioning status. The listener needs to implement the onGpsStatusChanged method of the GpsStatus.Listener interface.
  • removeGpsStatusListener: Remove the listener for positioning status.

<3>Locationistener

The location listener is used to monitor the change events of the location information, such as the switch of the location provider, the change of the location information, etc.

  • onLocationChanged: Called when the location location changes. Here you can get the latest location information.
  • onProviderDisabled: Called when the location provider is closed by the user.
  • onProviderEnabled: Called when the positioning provider is turned on by the user.
  • onStatusChanged: Called when the status of the positioning provider changes. See Table 3 for the value of the status of the location provider.
table 3
The status type of the LocationProvider class Description
OUT_OF_SERVICE Out of service
TEMPORARILY_UNAVAILABLE Temporarily unavailable
AVAILABLE Available status

2. Related code examples

Add permissions

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

Layout file activity_main.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="match_parent"
    android:orientation="vertical" >
    <TextView
        android:id="@+id/tv_location"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textColor="@color/black"
        android:textSize="17sp" />
</LinearLayout>

MainActivity.java

public class MainActivity extends WaterPermissionActivity {

    private final static String TAG = "LocationActivity";
    private TextView tv_location;
    private String mLocation = "";
    private LocationManager mLocationMgr; // 声明一个定位管理器对象
    private Criteria mCriteria = new Criteria(); // 声明一个定位准则对象
    private Handler mHandler = new Handler(); // 声明一个处理器
    private boolean isLocationEnable = false; // 定位服务是否可用

    @Override
    protected MvcBaseModel getModelImp() {
        return null;
    }

    @Override
    protected int getContentLayoutId() {
        return R.layout.activity_main;
    }

    @Override
    protected void initWidget() {
        tv_location = findViewById(R.id.tv_location);
        checkGpsIsOpen(this, "需要打开定位功能才能查看定位结果信息");
    }

    @Override
    protected void onResume() {
        super.onResume();
        requestPermission(ACCESS_COARSE_LOCATION);
    }

    @Override
    protected void doAccessCoarseLocation() {
        requestPermission(ACCESS_FINE_LOCATION);
    }

    @Override
    protected void doAccessFineLocation() {
        mHandler.removeCallbacks(mRefresh); // 移除定位刷新任务
        initLocation();
        mHandler.postDelayed(mRefresh, 100); // 延迟100毫秒启动定位刷新任务
    }

    // 初始化定位服务
    private void initLocation() {
        // 从系统服务中获取定位管理器
        mLocationMgr = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
        // 设置定位精确度。Criteria.ACCURACY_COARSE表示粗略,Criteria.ACCURACY_FIN表示精细
        mCriteria.setAccuracy(Criteria.ACCURACY_FINE);
        // 设置是否需要海拔信息
        mCriteria.setAltitudeRequired(true);
        // 设置是否需要方位信息
        mCriteria.setBearingRequired(true);
        // 设置是否允许运营商收费
        mCriteria.setCostAllowed(true);
        // 设置对电源的需求
        mCriteria.setPowerRequirement(Criteria.POWER_LOW);
        // 获取定位管理器的最佳定位提供者
        String bestProvider = mLocationMgr.getBestProvider(mCriteria, true);
        if (mLocationMgr.isProviderEnabled(bestProvider)) { // 定位提供者当前可用
            tv_location.setText("正在获取" + bestProvider + "定位对象");
            mLocation = String.format("定位类型=%s", bestProvider);
            beginLocation(bestProvider);
            isLocationEnable = true;
        } else { // 定位提供者暂不可用
            tv_location.setText("\n" + bestProvider + "定位不可用");
            isLocationEnable = false;
        }
    }

    // 设置定位结果文本
    private void setLocationText(Location location) {
        if (location != null) {
            String desc = String.format("%s\n定位对象信息如下: " +
                            "\n\t其中时间:%s" + "\n\t其中经度:%f,纬度:%f" +
                            "\n\t其中高度:%d米,精度:%d米",
                    mLocation, getNowDateTimeFormat(),
                    location.getLongitude(), location.getLatitude(),
                    Math.round(location.getAltitude()), Math.round(location.getAccuracy()));
            Log.d(TAG, desc);
            tv_location.setText(desc);
        } else {
            tv_location.setText(mLocation + "\n暂未获取到定位对象");
        }
    }

    // 开始定位
    @SuppressLint("MissingPermission")
    private void beginLocation(String method) {
        // 检查当前设备是否已经开启了定位功能
        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
                != PackageManager.PERMISSION_GRANTED) {
            Toast.makeText(this, "请授予定位权限并开启定位功能", Toast.LENGTH_SHORT).show();
            return;
        }
        // 设置定位管理器的位置变更监听器
        mLocationMgr.requestLocationUpdates(method, 300, 0, mLocationListener);
        // 获取最后一次成功定位的位置信息
        Location location = mLocationMgr.getLastKnownLocation(method);
        setLocationText(location);
    }

    // 定义一个位置变更监听器
    private LocationListener mLocationListener = new LocationListener() {
        @Override
        public void onLocationChanged(Location location) {
            setLocationText(location);
        }

        @Override
        public void onProviderDisabled(String arg0) {}

        @Override
        public void onProviderEnabled(String arg0) {}

        @Override
        public void onStatusChanged(String arg0, int arg1, Bundle arg2) {}
    };

    // 定义一个刷新任务,若无法定位则每隔一秒就尝试定位
    private Runnable mRefresh = new Runnable() {
        @Override
        public void run() {
            if (!isLocationEnable) {
                initLocation();
                mHandler.postDelayed(this, 1000);
            }
        }
    };

    @SuppressLint("MissingPermission")
    @Override
    protected void onDestroy() {
        if (mLocationMgr != null) {
            // 移除定位管理器的位置变更监听器
            mLocationMgr.removeUpdates(mLocationListener);
        }
        super.onDestroy();
    }

    // 获取定位功能的开关状态
    public static boolean getGpsStatus(Context ctx) {
        // 从系统服务中获取定位管理器
        LocationManager lm = (LocationManager) ctx.getSystemService(Context.LOCATION_SERVICE);
        return lm.isProviderEnabled(LocationManager.GPS_PROVIDER);
    }

    // 检查定位功能是否打开,若未打开则跳到系统的定位功能设置页面
    public static void checkGpsIsOpen(Context ctx, String hint) {
        if (!getGpsStatus(ctx)) {
            Toast.makeText(ctx, hint, Toast.LENGTH_SHORT).show();
            Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
            ctx.startActivity(intent);
        }
    }

    public static String getNowDateTimeFormat() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return sdf.format(new Date());
    }
}

Similarly, applications for dynamic permissions can use the ones in your own project.

Guess you like

Origin blog.csdn.net/weixin_38322371/article/details/115342567