如何给网站做地图,wordpress 页面伪静态页面,迁西网站建设,免费网站可以做cpa?前段时间#xff0c;我在学习鸿蒙应用开发的过程中#xff0c;在鸿蒙系统的手机上实现了获取经纬度及地理位置描述信息#xff08;鸿蒙应用开发学习#xff1a;手机位置信息进阶#xff0c;从经纬度数据获取地理位置描述信息#xff09;。反而学习时间更长的安卓应用开发… 前段时间我在学习鸿蒙应用开发的过程中在鸿蒙系统的手机上实现了获取经纬度及地理位置描述信息鸿蒙应用开发学习手机位置信息进阶从经纬度数据获取地理位置描述信息。反而学习时间更长的安卓应用开发还未实现获取经纬度及地理位置描述。这几天我正在看《Android App 开发进阶与项目实战》一书正好看到了第9章是讲定位导航的。这一章里正好有获取经纬度和详细地址的内容随书还附带有源码。我照着做很轻松的实现了用安卓手机获取经纬度和详细地址的功能。特此记录以备忘。 我的安卓手机上实现了获取经纬度和详细地址 稍微有点不足的就是我的手机上显示的定位类型为 null而书中显示的是卫星定位。这边书是几年前的基于安卓11的而我的手机系统已经是安卓13可能操作系统的不同使得同样的代码运行效果有所不同吧。 我的这个应用中与获取经纬度及详细地址有关的代码如下
1.获取经纬度及详细地址的Activity文件
src\main\java\......\LocationPageActivity.java
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;import android.Manifest;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;import com.bahamutjapp.task.GetAddressTask;
import com.bahamutjapp.util.DateUtil;
import com.bahamutjapp.util.SwitchUtil;import java.util.HashMap;
import java.util.Locale;
import java.util.Map;SuppressLint(value{DefaultLocale,SetTextI18n})
public class LocationPageActivity extends AppCompatActivity {private final static String TAG myDebug;private MapString,String providerMap new HashMap();private TextView tv_location; // 声明一个文本视图对象private String mLocationDesc ; // 定位说明private LocationManager mLocationMgr; // 声明一个定位管理器对象private Handler mHandler new Handler(Looper.myLooper()); // 声明一个处理器对象private boolean isLocationEnable false; // 定位服务是否可用Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_location_page);tv_location findViewById(R.id.tv_location);providerMap.put(gps, 卫星定位);providerMap.put(network, 网络定位);SwitchUtil.checkLocationIsOpen(this, 需要打开定位功能才能查看定位信息);}Overrideprotected void onResume() {super.onResume();mHandler.removeCallbacks(mRefresh); // 移除定位刷新任务initLocation(); // 初始化定位服务mHandler.postDelayed(mRefresh, 100); // 延迟100毫秒启动定位刷新任务}// 初始化定位服务private void initLocation() {// 从系统服务中获取定位管理器mLocationMgr (LocationManager) getSystemService(Context.LOCATION_SERVICE);Criteria criteria new Criteria(); // 创建一个定位准则对象// 设置定位精确度。Criteria.ACCURACY_COARSE表示粗略Criteria.ACCURACY_FIN表示精细criteria.setAccuracy(Criteria.ACCURACY_FINE);criteria.setAltitudeRequired(true); // 设置是否需要海拔信息criteria.setBearingRequired(true); // 设置是否需要方位信息criteria.setCostAllowed(true); // 设置是否允许运营商收费criteria.setPowerRequirement(Criteria.POWER_LOW); // 设置对电源的需求// Log.d(TAG, 初始化定位服务, 准备获取定位管理器的最佳定位提供者);// 获取定位管理器的最佳定位提供者String bestProvider mLocationMgr.getBestProvider(criteria, true);if (mLocationMgr.isProviderEnabled(bestProvider)) { // 定位提供者当前可用tv_location.setText(正在获取 providerMap.get(bestProvider) 对象);mLocationDesc String.format(【定位信息】\n定位类型为%s, providerMap.get(bestProvider));beginLocation(bestProvider); // 开始定位isLocationEnable true;} else { // 定位提供者暂不可用tv_location.setText(providerMap.get(bestProvider) 不可用);isLocationEnable false;}}// 显示定位结果文本private void showLocation(Location location) {if (location ! null) {// 创建一个根据经纬度查询详细地址的任务GetAddressTask task new GetAddressTask(this, location, address - {String desc String.format(Locale.CHINESE,%s \n\t定位时间为%s \n\t经度为%f纬度为%f \n\t高度为%d米精度为%d米 \n\t详细地址为%s。,mLocationDesc, DateUtil.formatDate(location.getTime()),location.getLongitude(), location.getLatitude(),Math.round(location.getAltitude()), Math.round(location.getAccuracy()),address);tv_location.setText(desc);});task.start(); // 启动地址查询任务} else {tv_location.setText(mLocationDesc \n暂未获取到定位对象);}}// 开始定位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);showLocation(location); // 显示定位结果文本}// 定义一个位置变更监听器private LocationListener mLocationListener new LocationListener() {Overridepublic void onLocationChanged(Location location) {showLocation(location); // 显示定位结果文本}Overridepublic void onProviderDisabled(String arg0) {}Overridepublic void onProviderEnabled(String arg0) {}Overridepublic void onStatusChanged(String arg0, int arg1, Bundle arg2) {}};// 定义一个刷新任务若无法定位则每隔一秒就尝试定位private Runnable mRefresh new Runnable() {Overridepublic void run() {if (!isLocationEnable) {initLocation(); // 初始化定位服务mHandler.postDelayed(this, 1000);}}};Overrideprotected void onDestroy() {super.onDestroy();mLocationMgr.removeUpdates(mLocationListener); // 移除定位管理器的位置变更监听器}} 2.Activity文件对应的xml文件
src\main\res\layout\activity_location_page.xml
?xml version1.0 encodingutf-8?
androidx.constraintlayout.widget.ConstraintLayout xmlns:androidhttp://schemas.android.com/apk/res/androidxmlns:apphttp://schemas.android.com/apk/res-autoxmlns:toolshttp://schemas.android.com/toolsandroid:layout_widthmatch_parentandroid:layout_heightmatch_parenttools:context.LocationPageActivityTextViewandroid:idid/tv_locationTitleandroid:layout_widthwrap_contentandroid:layout_height30dpandroid:text定位导航android:textSize24spandroid:textStyleboldapp:layout_constraintEnd_toEndOfparentapp:layout_constraintStart_toStartOfparentapp:layout_constraintTop_toTopOfparent /TextViewandroid:idid/tv_locationandroid:layout_widthwrap_contentandroid:layout_heightwrap_contentandroid:layout_marginStart10dpandroid:layout_marginTop50dpandroid:layout_marginEnd10dpandroid:paddingStart10dpandroid:paddingEnd10dpandroid:text【定位信息】android:textSize16spapp:layout_constraintEnd_toEndOfparentapp:layout_constraintStart_toStartOfparentapp:layout_constraintTop_toBottomOfid/tv_locationTitle //androidx.constraintlayout.widget.ConstraintLayout
3.GetAddressTask.java文件此文件根据经纬度数据获取详细地址信息
src\main\java\......\task\GetAddressTask.java
import android.app.Activity;
import android.location.Location;
import android.util.Log;
import android.widget.Toast;import androidx.annotation.NonNull;import org.json.JSONException;
import org.json.JSONObject;import java.io.IOException;
import java.util.Objects;import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;// 根据经纬度获取详细地址的线程
public class GetAddressTask extends Thread {private static final String TAG GetAddressTask;private String mQueryUrl https://api.tianditu.gov.cn/geocoder?postStr{lon:%f,lat:%f,ver:1}typegeocodetk253b3bd69713d4bdfdc116255f379841;private Activity mAct; // 声明一个活动实例private OnAddressListener mListener; // 声明一个获取地址的监听器对象private Location mLocation; // 声明一个定位对象public GetAddressTask(Activity act, Location location, OnAddressListener listener) {mAct act;mListener listener;mLocation location;}Overridepublic void run() {String url String.format(mQueryUrl, mLocation.getLongitude(), mLocation.getLatitude());Log.d(TAG, urlurl);OkHttpClient client new OkHttpClient(); // 创建一个okhttp客户端对象// 创建一个GET方式的请求结构Request request new Request.Builder().url(url).build();Call call client.newCall(request); // 根据请求结构创建调用对象// 加入HTTP请求队列。异步调用并设置接口应答的回调方法call.enqueue(new Callback() {Overridepublic void onFailure(NonNull Call call, NonNull IOException e) { // 请求失败// 回到主线程操纵界面mAct.runOnUiThread(() - Toast.makeText(mAct,查询详细地址出错e.getMessage(), Toast.LENGTH_SHORT).show());}Overridepublic void onResponse(NonNull Call call, NonNull final Response response) throws IOException { // 请求成功String resp Objects.requireNonNull(response.body()).string();Log.d(TAG, respresp);// 下面从json串中逐级解析formatted_address字段获得详细地址描述try {JSONObject obj new JSONObject(resp);JSONObject result obj.getJSONObject(result);String address result.getString(formatted_address);// 回到主线程操纵界面mAct.runOnUiThread(() - mListener.onFindAddress(address));} catch (JSONException e) {e.printStackTrace();}}});}// 定义一个查询详细地址的监听器接口public interface OnAddressListener {void onFindAddress(String address);}}
4.DateUtil.java文件对日期数据进行格式化
src\main\java\......\util\DateUtil.java
import android.annotation.SuppressLint;import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;SuppressLint(SimpleDateFormat)
public class DateUtil {// 获取当前的日期时间public static String getNowDateTime() {SimpleDateFormat sdf new SimpleDateFormat(yyyyMMddHHmmss);return sdf.format(new Date());}// 将长整型的时间数值格式化为日期时间字符串public static String formatDate(long time) {Date date new Date(time);SimpleDateFormat sdf new SimpleDateFormat(yyyy-MM-dd HH:mm:ss);return sdf.format(date);}}
5.SwitchUtil.java文件获取定位功能开关状态
src\main\java\......\util\SwitchUtil.java
import android.content.Context;
import android.content.Intent;
import android.location.LocationManager;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.wifi.WifiManager;
import android.provider.Settings;
import android.telephony.TelephonyManager;
import android.util.Log;
import android.widget.Toast;import java.lang.reflect.Method;public class SwitchUtil {private static final String TAG SwitchUtil;// 获取定位功能的开关状态public static boolean getLocationStatus(Context ctx) {// 从系统服务中获取定位管理器LocationManager lm (LocationManager) ctx.getSystemService(Context.LOCATION_SERVICE);return lm.isProviderEnabled(LocationManager.GPS_PROVIDER);}// 检查定位功能是否打开若未打开则跳到系统的定位功能设置页面public static void checkLocationIsOpen(Context ctx, String hint) {if (!getLocationStatus(ctx)) {Toast.makeText(ctx, hint, Toast.LENGTH_SHORT).show();Intent intent new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);ctx.startActivity(intent);}}}6月25日补充
今天代码进一步研究发现导致页面上定位类型显示为null的原因是在LocationPageActivity.java文件中的源代码“ String bestProvider mLocationMgr.getBestProvider(criteria, true); ” 的返回值是“fused”。通过搜寻资料才知道这是一种定位类型融合定位介绍资料见下面的链接
Fused定位
再对代码进行仔细研究发现上面的代码的返回值赋值给“bestProvider”后通过执行以下语句获取在页面上显示定位类型的字符串
mLocationDesc String.format(【定位信息】\n\t定位类型为%s, providerMap.get(bestProvider)); 这个语句是将“bestProvider”作为参数从providerMap对象中获取对应的值。而providerMap对象是在onCreate方法中赋值的
providerMap.put(gps, 卫星定位);
providerMap.put(network, 网络定位);
因为只put了两个键值对没有fused的键值对因此得到的结果是null。解决方法就是再加入下面这条即可。
providerMap.put(fused, 融合);