需要全部代码请点赞关注收藏后评论区留言私信~~~
一、获取照片里的位置信息
手机拍摄的相片还保存着时间、地点、镜头参数等信息,这些信息由相片接口工具ExifInterface管理,它的常用方法说明如下:
getLatLong:获取相片拍摄时候的经纬度。
getAltitude:获取相片拍摄时候的海拔高度。
getAttribute:获取指定名称的属性值。
不过Android从9.0开始才支持获取照片的位置信息,并且增加了新的媒体位置权限,并且如果想访问存储卡的图片文件,还得给App赋予存储卡读写权限。
即照片在拍摄时会默认存储经纬度和时间等信息 可以通过对应方法来调用
代码如下
Java类
package com.example.location; import android.app.ProgressDialog; import android.database.Cursor; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.provider.MediaStore; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.GridLayout; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; import androidx.appcompat.app.AppCompatActivity; import com.example.location.bean.ImageInfo; import com.example.location.util.BitmapUtil; import com.example.location.util.ExifUtil; import com.example.location.util.FileUtil; import com.example.location.util.Utils; import java.util.ArrayList; import java.util.List; public class ImageLocationActivity extends AppCompatActivity { private final static String TAG = "ImageLocationActivity"; private GridLayout gl_appendix; // 声明一个网格布局对象 private ProgressDialog mDialog; // 声明一个进度对话框对象 private List<ImageInfo> mImageList = new ArrayList<>(); // 图片列表 private Uri mImageUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI; // 相册的Uri private String[] mImageColumn = new String[]{ // 媒体库的字段名称数组 MediaStore.Images.Media._ID, // 编号 MediaStore.Images.Media.TITLE, // 标题 MediaStore.Images.Media.SIZE, // 文件大小 MediaStore.Images.Media.DATA}; // 文件路径 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_image_location); gl_appendix = findViewById(R.id.gl_appendix); new Handler().post(() -> showImageLocation()); // // 显示图像的位置信息 } // 显示图像的位置信息 private void showImageLocation() { // 显示进度对话框 mDialog = ProgressDialog.show(this, "请稍候", "正在加载图片的位置信息"); new Thread(() -> loadImageList()).start(); // 启动线程加载图片列表 } // 加载图片列表 private void loadImageList() { Log.d(TAG, "loadImageList"); mImageList.clear(); // 清空图片列表 // 查询相册媒体库,并返回结果集的游标。“_size asc”表示按照文件大小升序排列 Cursor cursor = getContentResolver().query(mImageUri, mImageColumn, null, null, "_size desc"); if (cursor != null) { // 下面遍历结果集,并逐个添加到图片列表。简单起见只挑选前六张图片 for (int i=0; i<6 && cursor.moveToNext(); i++) { ImageInfo image = new ImageInfo(); // 创建一个图片信息对象 image.setId(cursor.getLong(0)); // 设置图片编号 image.setName(cursor.getString(1)); // 设置图片名称 image.setSize(cursor.getLong(2)); // 设置图片的文件大小 image.setPath(cursor.getString(3)); // 设置图片的文件路径 Log.d(TAG, image.getName() + " " + image.getSize() + " " + image.getPath()); // 检查该路径是否合法 if (!FileUtil.checkFileUri(this, image.getPath())) { i--; continue; // 路径非法则再来一次 } // 从指定路径解码得到位图对象 Bitmap bitmap = BitmapFactory.decodeFile(image.getPath()); // 给图像视图设置自动缩放的位图对象 image.setBitmap(BitmapUtil.getAutoZoomImage(bitmap)); mImageList.add(image); // 添加至图片列表 } cursor.close(); // 关闭数据库游标 } Log.d(TAG, "mImageList.size="+mImageList.size()); runOnUiThread(() -> showImageGrid()); // 显示图像网格 } // 显示图像网格 private void showImageGrid() { Log.d(TAG, "showImageGrid"); for (int i=0; i<mImageList.size(); i++) { final ImageInfo image = mImageList.get(i); LinearLayout ll_grid = new LinearLayout(this); // 创建一个线性布局视图 ll_grid.setLayoutParams(new LinearLayout.LayoutParams(Utils.getScreenWidth(this)/3, ViewGroup.LayoutParams.WRAP_CONTENT)); // 设置线性布局的布局参数 View view = LayoutInflater.from(this).inflate(R.layout.item_location, null); ImageView iv_photo = view.findViewById(R.id.iv_photo); iv_photo.setImageBitmap(image.getBitmap()); // 设置图像视图的位图对象 TextView tv_latlng = view.findViewById(R.id.tv_latlng); // 获取指定图片的位置信息 String location = ExifUtil.getLocationFromImage(this, image.getId()+""); tv_latlng.setText(location); // 设置文本视图的文字内容 ll_grid.addView(view); // 把视图对象添加至线性布局 gl_appendix.addView(ll_grid); // 把线性布局添加至网格布局 } mDialog.dismiss(); // 关闭进度对话框 } }
二、全球卫星导航系统(GNSS)
联合国认可的全球卫星导航系统有下列4个:
(1)美国的GPS
(2)俄罗斯的格洛纳斯
(3)中国的北斗
(4)欧洲的伽利略
通过GnssStatus对象的下列方法可获取卫星详情。
getSatelliteCount:获取卫星的数量。
getCn0DbHz:获取卫星的信号。
getAzimuthDegrees:获取卫星的方位角。
getElevationDegrees:获取卫星的仰角。
getConstellationType:获取卫星的星座类型。
实际效果如下 有中间的浑天仪显示定位信息 更加美观与精准
如果一部手机只支持GPS 那么定位响应就会很慢,定位精度一般在十米左右,而且定位高度很不准确,误差相当大,一旦有了北大与格洛纳斯参与定位,那么在室内也能很快响应,精度一般能提升至五米,并且高度数值准确了许多
代码如下
Java类
package com.example.location; import android.Manifest; import android.annotation.SuppressLint; import android.content.Context; import android.content.pm.PackageManager; import android.location.Criteria; import android.location.GnssStatus; import android.location.GpsSatellite; import android.location.GpsStatus; import android.location.Location; import android.location.LocationListener; import android.location.LocationManager; import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.util.Log; import android.widget.TextView; import android.widget.Toast; import androidx.annotation.RequiresApi; import androidx.appcompat.app.AppCompatActivity; import androidx.core.app.ActivityCompat; import com.example.location.bean.Satellite; import com.example.location.util.DateUtil; import com.example.location.util.SwitchUtil; import com.example.location.widget.CompassView; import java.util.HashMap; import java.util.Map; @SuppressLint("DefaultLocale") public class SatelliteSphereActivity extends AppCompatActivity { private final static String TAG = "SatelliteSphereActivity"; private Map<String, String> providerMap = new HashMap<>(); // 定位提供者映射 private TextView tv_satellite; // 声明一个文本视图对象 private CompassView cv_satellite; // 声明一个罗盘视图对象 private Map<Integer, Satellite> mapSatellite = new HashMap<>(); // 导航卫星映射 private LocationManager mLocationMgr; // 声明一个定位管理器对象 private Criteria mCriteria = new Criteria(); // 声明一个定位准则对象 private Handler mHandler = new Handler(Looper.myLooper()); // 声明一个处理器对象 private boolean isLocationEnable = false; // 定位服务是否可用 private String mLocationType = ""; // 定位类型。是卫星定位还是网络定位 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_satellite_sphere); providerMap.put("gps", "卫星"); providerMap.put("network", "网络"); tv_satellite = findViewById(R.id.tv_satellite); cv_satellite = findViewById(R.id.cv_satellite); SwitchUtil.checkLocationIsOpen(this, "需要打开定位功能才能查看卫星导航信息"); } @Override protected void onResume() { super.onResume(); 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)) { // 定位提供者当前可用 mLocationType = providerMap.get(bestProvider)+"定位"; beginLocation(bestProvider); // 开始定位 isLocationEnable = true; } else { // 定位提供者暂不可用 isLocationEnable = false; } } // 设置定位结果文本 private void showLocation(Location location) { if (location != null) { String desc = String.format("当前定位类型:%s,定位时间:%s" + "\n经度:%f,纬度:%f\n高度:%d米,精度:%d米", mLocationType, DateUtil.formatDate(location.getTime()), location.getLongitude(), location.getLatitude(), Math.round(location.getAltitude()), Math.round(location.getAccuracy())); tv_satellite.setText(desc); } else { Log.d(TAG, "暂未获取到定位对象"); } } // 开始定位 private void beginLocation(String method) { // 检查当前设备是否已经开启了定位功能 if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_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); // 显示定位结果文本 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { // 注册全球导航卫星系统的状态监听器 mLocationMgr.registerGnssStatusCallback(mGnssStatusListener, null); } else { // 给定位管理器添加导航状态监听器 mLocationMgr.addGpsStatusListener(mStatusListener); } } private String[] mSystemArray = new String[] {"UNKNOWN", "GPS", "SBAS", "GLONASS", "QZSS", "BEIDOU", "GALILEO", "IRNSS"}; @RequiresApi(api = Build.VERSION_CODES.N) // 定义一个GNSS状态监听器 private GnssStatus.Callback mGnssStatusListener = new GnssStatus.Callback() { @Override public void onStarted() {} @Override public void onStopped() {} @Override public void onFirstFix(int ttffMillis) {} // 在卫星导航系统的状态变更时触发 @Override public void onSatelliteStatusChanged(GnssStatus status) { mapSatellite.clear(); for (int i=0; i<status.getSatelliteCount(); i++) { Log.d(TAG, "i="+i+",getSvid="+status.getSvid(i)+",getConstellationType="+status.getConstellationType(i)); Satellite item = new Satellite(); // 创建一个卫星信息对象 item.signal = status.getCn0DbHz(i); // 获取卫星的信号 item.elevation = status.getElevationDegrees(i); // 获取卫星的仰角 item.azimuth = status.getAzimuthDegrees(i); // 获取卫星的方位角 item.time = DateUtil.getNowDateTime(); // 获取当前时间 int systemType = status.getConstellationType(i); // 获取卫星的类型 item.name = mSystemArray[systemType]; mapSatellite.put(i, item); } cv_satellite.setSatelliteMap(mapSatellite); // 设置卫星浑天仪 } }; // 定义一个位置变更监听器 private LocationListener mLocationListener = new LocationListener() { @Override public void onLocationChanged(Location location) { showLocation(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); } } }; @Override protected void onDestroy() { super.onDestroy(); if (mLocationMgr != null) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { // 注销全球导航卫星系统的状态监听器 mLocationMgr.unregisterGnssStatusCallback(mGnssStatusListener); } else { // 移除定位管理器的导航状态监听器 mLocationMgr.removeGpsStatusListener(mStatusListener); } // 移除定位管理器的位置变更监听器 mLocationMgr.removeUpdates(mLocationListener); } } // 定义一个导航状态监听器 private GpsStatus.Listener mStatusListener = new GpsStatus.Listener() { // 在卫星导航系统的状态变更时触发 @Override public void onGpsStatusChanged(int event) { if (ActivityCompat.checkSelfPermission(SatelliteSphereActivity.this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) { // 获取卫星定位的状态信息 GpsStatus gpsStatus = mLocationMgr.getGpsStatus(null); switch (event) { case GpsStatus.GPS_EVENT_SATELLITE_STATUS: // 周期性报告卫星状态 // 得到所有收到的卫星的信息,包括 卫星的高度角、方位角、信噪比、和伪随机号(及卫星编号) Iterable<GpsSatellite> satellites = gpsStatus.getSatellites(); for (GpsSatellite satellite : satellites) { /* * satellite.getElevation(); //卫星的仰角 (卫星的高度) * satellite.getAzimuth(); //卫星的方位角 * satellite.getSnr(); //卫星的信噪比 * satellite.getPrn(); //卫星的伪随机码,可以认为就是卫星的编号 * satellite.hasAlmanac(); //卫星是否有年历表 * satellite.hasEphemeris(); //卫星是否有星历表 * satellite.usedInFix(); //卫星是否被用于近期的GPS修正计算 */ Satellite item = new Satellite(); // 创建一个卫星信息对象 int prn_id = satellite.getPrn(); // 获取卫星的编号 item.signal = Math.round(satellite.getSnr()); // 获取卫星的信号 item.elevation = Math.round(satellite.getElevation()); // 获取卫星的仰角 item.azimuth = Math.round(satellite.getAzimuth()); // 获取卫星的方位角 item.time = DateUtil.getNowDateTime(); // 获取当前时间 if (prn_id <= 51) { // 美国的GPS item.name = "GPS"; } else if (prn_id >= 201 && prn_id <= 235) { // 中国的北斗 item.name = "BEIDOU"; } else if (prn_id >= 65 && prn_id <= 96) { // 俄罗斯的格洛纳斯 item.name = "GLONASS"; } else if (prn_id >= 301 && prn_id <= 336) { // 欧洲的伽利略 item.name = "GALILEO"; } else { item.name = "未知"; } Log.d(TAG, "id="+prn_id+", signal="+item.signal+", elevation="+item.elevation+", azimuth="+item.azimuth); mapSatellite.put(prn_id, item); } cv_satellite.setSatelliteMap(mapSatellite); // 设置卫星浑天仪 case GpsStatus.GPS_EVENT_FIRST_FIX: // 首次卫星定位 case GpsStatus.GPS_EVENT_STARTED: // 卫星导航服务开始 case GpsStatus.GPS_EVENT_STOPPED: // 卫星导航服务停止 default: break; } } } }; }
创作不易 觉得有帮助请点赞关注收藏~~