增加位置实时显示窗口

This commit is contained in:
ZhanGSKen
2025-09-29 18:41:46 +08:00
parent fbd6f70b36
commit 14abd9edd8
7 changed files with 286 additions and 4 deletions

View File

@@ -46,6 +46,9 @@ android {
dependencies {
api fileTree(dir: 'libs', include: ['*.jar'])
// 谷歌定位服务核心依赖FusedLocationProviderClient所在库
api 'com.google.android.gms:play-services-location:21.0.1'
// SSH
api 'com.jcraft:jsch:0.1.55'
// Html 解析

View File

@@ -1,8 +1,8 @@
#Created by .winboll/winboll_app_build.gradle
#Mon Sep 29 18:02:11 HKT 2025
#Mon Sep 29 10:40:51 GMT 2025
stageCount=2
libraryProject=
baseVersion=15.0
publishVersion=15.0.1
buildCount=0
buildCount=2
baseBetaVersion=15.0.2

View File

@@ -3,6 +3,19 @@
xmlns:android="http://schemas.android.com/apk/res/android"
package="cc.winboll.studio.positions">
<!-- 1. 定位必需权限声明 -->
<!-- 精确定位权限GPS+网络定位,核心) -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<!-- 粗略定位权限仅安卓12+需要,兼容低版本可加) -->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<!-- 网络权限(可选,用于网络定位,提升室内定位精度) -->
<uses-permission android:name="android.permission.INTERNET" />
<!-- 2. 声明定位硬件支持(可选,告诉系统应用需要定位功能) -->
<uses-feature
android:name="android.hardware.location.gps"
android:required="false" /> <!-- false=无GPS也能使用网络定位 -->
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
@@ -31,6 +44,12 @@
<activity android:name=".GlobalApplication$CrashActivity"/>
<activity android:name="cc.winboll.studio.positions.activities.LocationActivity"/>
<!-- 4. 谷歌定位服务版本声明(避免版本兼容问题) -->
<meta-data
android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version" />
</application>
</manifest>

View File

@@ -5,6 +5,9 @@ import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import cc.winboll.studio.libappbase.LogView;
import com.hjq.toast.ToastUtils;
import android.view.View;
import cc.winboll.studio.positions.activities.LocationActivity;
import android.content.Intent;
public class MainActivity extends AppCompatActivity {
@@ -28,4 +31,8 @@ public class MainActivity extends AppCompatActivity {
super.onResume();
mLogView.start();
}
public void onPositions(View view) {
startActivity(new Intent(this, LocationActivity.class));
}
}

View File

@@ -0,0 +1,219 @@
package cc.winboll.studio.positions.activities;
/**
* @Author ZhanGSKen&豆包大模型<zhangsken@qq.com>
* @Date 2025/09/29 18:22
* @Describe 当前位置实时显示
*/
import android.Manifest;
import android.content.pm.PackageManager;
import android.location.Location;
import android.os.Bundle;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import com.google.android.gms.location.FusedLocationProviderClient;
import com.google.android.gms.location.LocationCallback;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationResult;
import com.google.android.gms.location.LocationServices;
import com.google.android.gms.tasks.OnSuccessListener;
import cc.winboll.studio.positions.R;
/**
* 实时定位活动窗口:
* 1. 申请定位必需权限(精确定位+粗略定位)
* 2. 初始化FusedLocationProviderClient谷歌官方定位服务兼容所有安卓版本
* 3. 实时监听位置变化,更新显示经度、纬度
*/
public class LocationActivity extends AppCompatActivity {
public static final String TAG = "LocationActivity";
// 1. 核心组件与常量定义
private static final int REQUEST_LOCATION_PERMISSIONS = 1004; // 定位权限请求码
private FusedLocationProviderClient fusedLocationClient; // 定位核心客户端
private LocationCallback locationCallback; // 位置变化监听器
private LocationRequest locationRequest; // 定位请求配置(频率、精度等)
// UI控件用于显示经纬度需在布局中定义对应ID
private TextView tvLongitude; // 经度显示
private TextView tvLatitude; // 纬度显示
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 2. 加载布局(需手动创建对应布局文件,见下方说明)
setContentView(R.layout.activity_location);
// 3. 绑定UI控件与布局文件中的TextView ID对应
tvLongitude = findViewById(R.id.tv_longitude);
tvLatitude = findViewById(R.id.tv_latitude);
// 4. 初始化定位相关组件
initLocationConfig();
// 5. 检查并申请定位权限(无权限则申请,有权限则直接启动定位)
if (checkLocationPermissions()) {
startRealTimeLocation(); // 权限已授予 → 启动实时定位
} else {
requestLocationPermissions(); // 权限未授予 → 申请权限
}
}
/**
* 初始化定位配置:设置定位精度、更新频率等
*/
private void initLocationConfig() {
// 初始化定位客户端谷歌官方推荐替代旧的LocationManager
fusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
// 配置定位请求实时更新1秒请求一次最小间隔500毫秒最高精度
locationRequest = new LocationRequest.Builder(1000) // 定位更新间隔(毫秒)
.setMinUpdateIntervalMillis(500) // 最小更新间隔(避免频繁更新耗电)
.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY) // 高精度定位优先GPS
.build();
// 初始化位置变化监听器位置更新时触发实时更新UI
locationCallback = new LocationCallback() {
@Override
public void onLocationResult(@NonNull LocationResult locationResult) {
super.onLocationResult(locationResult);
// 获取最新位置信息locationResult包含最近一次或多次位置
Location latestLocation = locationResult.getLastLocation();
if (latestLocation != null) {
// 6. 提取经纬度并更新UI实时显示
double longitude = latestLocation.getLongitude(); // 经度(东经为正,西经为负)
double latitude = latestLocation.getLatitude(); // 纬度(北纬为正,南纬为负)
// 更新TextView显示保留6位小数精度足够日常使用
tvLongitude.setText(String.format("当前经度:%.6f", longitude));
tvLatitude.setText(String.format("当前纬度:%.6f", latitude));
}
}
};
}
/**
* 检查定位必需权限是否已授予(精确定位+粗略定位,覆盖所有安卓版本)
*/
private boolean checkLocationPermissions() {
// 安卓12+API31+新增精确定位权限需同时检查2个权限低版本只需检查1个
/*if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S) {
return ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED
&& ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED;
} else {*/
return ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED;
//}
}
/**
* 申请定位必需权限(弹系统授权弹窗)
*/
private void requestLocationPermissions() {
/*if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S) {
// 安卓12+:同时申请精确定位+粗略定位
ActivityCompat.requestPermissions(
this,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION},
REQUEST_LOCATION_PERMISSIONS
);
} else {*/
// 安卓12以下仅申请精确定位包含粗略定位能力
ActivityCompat.requestPermissions(
this,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
REQUEST_LOCATION_PERMISSIONS
);
//}
}
/**
* 启动实时定位:注册位置监听器,开始接收位置更新
*/
private void startRealTimeLocation() {
// 权限兜底检查(避免异常)
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
Toast.makeText(this, "定位权限未授予,无法启动定位", Toast.LENGTH_SHORT).show();
return;
}
// 1. 先获取一次当前位置(快速显示初始经纬度)
fusedLocationClient.getLastLocation()
.addOnSuccessListener(this, new OnSuccessListener<Location>() {
@Override
public void onSuccess(Location location) {
if (location != null) {
// 显示初始经纬度
tvLongitude.setText(String.format("当前经度:%.6f", location.getLongitude()));
tvLatitude.setText(String.format("当前纬度:%.6f", location.getLatitude()));
} else {
// 无历史位置(如首次启动),提示“等待定位更新”
tvLongitude.setText("当前经度:等待更新...");
tvLatitude.setText("当前纬度:等待更新...");
}
}
});
// 2. 注册监听器,接收实时位置更新(持续监听)
fusedLocationClient.requestLocationUpdates(
locationRequest,
locationCallback,
getMainLooper() // 在主线程更新UI避免线程异常
);
}
/**
* 处理权限申请结果(用户同意/拒绝后触发)
*/
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == REQUEST_LOCATION_PERMISSIONS) {
// 检查是否所有必需权限都已授予
boolean allGranted = true;
for (int result : grantResults) {
if (result != PackageManager.PERMISSION_GRANTED) {
allGranted = false;
break;
}
}
if (allGranted) {
// 权限同意 → 启动实时定位
startRealTimeLocation();
} else {
// 权限拒绝 → 提示用户(无法定位)
Toast.makeText(this, "定位权限被拒绝,无法显示位置信息", Toast.LENGTH_SHORT).show();
tvLongitude.setText("当前经度:无权限");
tvLatitude.setText("当前纬度:无权限");
}
}
}
/**
* 活动销毁时:停止定位监听(避免内存泄漏、减少耗电)
*/
@Override
protected void onDestroy() {
super.onDestroy();
// 移除定位监听器核心防止Activity销毁后仍在监听导致内存泄漏
if (fusedLocationClient != null && locationCallback != null) {
fusedLocationClient.removeLocationUpdates(locationCallback);
}
}
}

View File

@@ -0,0 +1,34 @@
<?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:gravity="center_horizontal|center_vertical"
android:orientation="vertical"
android:padding="20dp">
<!-- 标题 -->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="实时位置信息"
android:textSize="22sp"
android:textStyle="bold"/>
<!-- 经度显示(大字体,清晰可见) -->
<TextView
android:id="@+id/tv_longitude"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="当前经度:等待更新..."
android:textSize="18sp"/>
<!-- 纬度显示(大字体,清晰可见) -->
<TextView
android:id="@+id/tv_latitude"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="当前纬度:等待更新..."
android:textSize="18sp"/>
</LinearLayout>

View File

@@ -26,11 +26,11 @@
android:layout_weight="1.0"
android:gravity="center_vertical|center_horizontal">
<TextView
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Positions"
android:textAppearance="?android:attr/textAppearanceLarge"/>
android:onClick="onPositions"/>
</LinearLayout>