This repository has been archived on 2025-12-05. You can view files and clone it, but cannot push or open issues or pull requests.
Files
APPBase-jitpack.io/positions/src/main/java/cc/winboll/studio/positions/MainActivity.java
2025-10-02 10:14:14 +08:00

267 lines
12 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package cc.winboll.studio.positions;
import android.Manifest;
import android.app.Activity;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.CompoundButton;
import android.widget.Switch;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.appcompat.widget.Toolbar;
import androidx.core.content.ContextCompat;
import cc.winboll.studio.libaes.interfaces.IWinBoLLActivity;
import cc.winboll.studio.libaes.utils.WinBoLLActivityManager;
import cc.winboll.studio.libappbase.LogUtils;
import cc.winboll.studio.positions.activities.LocationActivity;
import cc.winboll.studio.positions.activities.WinBoLLActivity;
import cc.winboll.studio.positions.services.MainService;
import cc.winboll.studio.positions.utils.AppConfigsUtil;
/**
* 主页面:仅负责
* 1. 位置服务启动/停止(通过 Switch 开关控制)
* 2. 跳转至“位置管理页LocationActivity”和“日志页LogActivity
* 3. Java 7 语法适配:无 Lambda、显式接口实现、兼容低版本
*/
public class MainActivity extends WinBoLLActivity implements IWinBoLLActivity {
public static final String TAG = "MainActivity";
// 权限请求码(建议定义为类常量,避免魔法值)
private static final int REQUEST_LOCATION_PERMISSIONS = 1001;
private static final int REQUEST_BACKGROUND_LOCATION_PERMISSION = 1002;
// UI 控件:服务控制开关、顶部工具栏
private Switch mServiceSwitch;
private Button mManagePositionsButton;
private Toolbar mToolbar;
// 服务相关:服务实例、绑定状态标记
//private DistanceRefreshService mDistanceService;
private boolean isServiceBound = false;
@Override
public Activity getActivity() {
return this;
}
@Override
public String getTag() {
return TAG;
}
// ---------------------- 服务连接回调(仅用于获取服务状态,不依赖服务执行核心逻辑) ----------------------
// private final ServiceConnection mServiceConn = new ServiceConnection() {
// /**
// * 服务绑定成功:获取服务实例,同步开关状态(以服务实际状态为准)
// */
// @Override
// public void onServiceConnected(ComponentName name, IBinder service) {
// // Java 7 显式强转 Binder 实例确保类型匹配避免ClassCastException
// DistanceRefreshService.DistanceBinder binder = (DistanceRefreshService.DistanceBinder) service;
// mDistanceService = binder.getService();
// isServiceBound = true;
// }
//
// /**
// * 服务意外断开(如服务崩溃):重置服务实例和绑定状态
// */
// @Override
// public void onServiceDisconnected(ComponentName name) {
// mDistanceService = null;
// isServiceBound = false;
// }
// };
// ---------------------- Activity 生命周期核心初始化UI、申请权限、绑定服务、释放资源 ----------------------
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); // 关联主页面布局
// 1. 初始化顶部 Toolbar保留原逻辑设置页面标题
initToolbar();
// 2. 初始化其他控件
initViews();
// 3. 检查并申请位置权限含后台GPS权限确保服务启动前权限就绪
if (!checkLocationPermissions()) {
requestLocationPermissions();
}
// 4. 绑定服务(仅用于获取服务实时状态,不影响服务独立运行)
//bindDistanceService();
}
@Override
protected void onDestroy() {
super.onDestroy();
// 页面销毁时解绑服务避免Activity与服务相互引用导致内存泄漏
// if (isServiceBound) {
// unbindService(mServiceConn);
// isServiceBound = false;
// mDistanceService = null;
// }
}
// ---------------------- 核心功能1初始化UI组件Toolbar + 服务开关) ----------------------
/**
* 初始化顶部 Toolbar设置页面标题
*/
private void initToolbar() {
mToolbar = (Toolbar) findViewById(R.id.toolbar); // Java 7 显式 findViewById + 强转
setSupportActionBar(mToolbar);
// 给ActionBar设置标题先判断非空避免空指针异常
if (getSupportActionBar() != null) {
getSupportActionBar().setTitle(getString(R.string.app_name));
}
}
/**
* 初始化服务控制开关读取SP状态、绑定点击事件含权限检查
*/
private void initViews() {
mServiceSwitch = (Switch) findViewById(R.id.switch_service_control); // 显式强转
mServiceSwitch.setChecked(AppConfigsUtil.getInstance(this).isEnableMainService(true));
mManagePositionsButton = (Button) findViewById(R.id.btn_manage_positions);
mManagePositionsButton.setEnabled(mServiceSwitch.isChecked());
// Java 7 用匿名内部类实现 CompoundButton.OnCheckedChangeListener
mServiceSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
// 开关打开前先检查权限:无权限则终止操作、重置开关、引导申请
if (isChecked && !checkLocationPermissions()) {
requestLocationPermissions();
return;
}
// 权限就绪:执行服务启停逻辑
if (isChecked) {
LogUtils.d(TAG, "设置启动服务");
AppConfigsUtil.getInstance(MainActivity.this).setIsEnableMainService(true);
// 启动服务startService确保服务独立运行不受Activity绑定影响
startService(new Intent(MainActivity.this, MainService.class));
} else {
LogUtils.d(TAG, "设置关闭服务");
AppConfigsUtil.getInstance(MainActivity.this).setIsEnableMainService(false);
// 停止服务前先解绑避免服务被Activity持有
// if (isServiceBound) {
// unbindService(mServiceConn);
// isServiceBound = false;
// }
stopService(new Intent(MainActivity.this, MainService.class));
}
mManagePositionsButton.setEnabled(isChecked);
}
});
}
/**
* 绑定服务(仅用于获取服务状态,不启动服务)
*/
// private void bindDistanceService() {
// Intent serviceIntent = new Intent(this, MainService.class);
// // BIND_AUTO_CREATE服务未启动则创建仅为获取状态启停由开关控制
// bindService(serviceIntent, mServiceConn, Context.BIND_AUTO_CREATE);
// }
// ---------------------- 核心功能3页面跳转位置管理页+日志页) ----------------------
/**
* 跳转至“位置管理页LocationActivity按钮点击触发需在布局中设置 android:onClick="onPositions"
* 服务未启动时提示不允许跳转避免LocationActivity无数据
*/
public void onPositions(View view) {
//ToastUtils.show("onPositions");
// 服务已启动:跳转到位置管理页
startActivity(new Intent(MainActivity.this, LocationActivity.class));
}
/**
* 跳转至“日志页LogActivity按钮点击触发需在布局中设置 android:onClick="onLog"
* 无服务状态限制,直接跳转
*/
public void onLog(View view) {
WinBoLLActivityManager.getInstance().startLogActivity(this); // 调用LogActivity静态方法跳转保留原逻辑
}
// ---------------------- 新增位置权限处理适配Java7 + 后台GPS权限 ----------------------
/**
* 检查是否拥有「前台+后台」位置权限适配Android版本差异
* Java7 特性显式类型判断、无Lambda、兼容低版本API
*/
private boolean checkLocationPermissions() {
// 1. 检查前台精确定位权限Android 6.0+ 必需,显式强转权限常量)
int foregroundPermResult = checkSelfPermission(android.Manifest.permission.ACCESS_FINE_LOCATION);
boolean hasForegroundPerm = (foregroundPermResult == PackageManager.PERMISSION_GRANTED);
// 2. 检查后台定位权限仅Android 10+ 需要Java7 显式用Build.VERSION判断版本
boolean hasBackgroundPerm = true;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
int backgroundPermResult = checkSelfPermission(android.Manifest.permission.ACCESS_BACKGROUND_LOCATION);
hasBackgroundPerm = (backgroundPermResult == PackageManager.PERMISSION_GRANTED);
}
// 前台+后台权限均满足才返回true
return hasForegroundPerm && hasBackgroundPerm;
}
private void requestLocationPermissions() {
// 1. 先判断前台定位权限ACCESS_FINE_LOCATION是否已授予
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
// 1.1 未授予前台权限先申请前台权限API 30+ 后台权限依赖前台权限)
String[] foregroundPermissions = new String[]{Manifest.permission.ACCESS_FINE_LOCATION};
// 对API 23+Android 6.0)动态申请,低版本会直接授予(清单已声明前提下)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
requestPermissions(foregroundPermissions, REQUEST_LOCATION_PERMISSIONS);
}
} else {
// 2. 已授予前台权限判断是否需要申请后台权限仅API 29+需要)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
// 2.1 检查后台权限是否未授予
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_BACKGROUND_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
// 2.2 API 30+ 必须单独申请后台权限(不能和前台权限一起弹框)
requestPermissions(
new String[]{Manifest.permission.ACCESS_BACKGROUND_LOCATION},
REQUEST_BACKGROUND_LOCATION_PERMISSION
);
}
}
// 3. 前台权限已授予(+ 后台权限按需授予):此处可执行定位相关逻辑
// doLocationRelatedLogic();
}
}
// 【必须补充】权限申请结果回调(处理用户同意/拒绝逻辑)
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
// 处理前台权限申请结果
if (requestCode == REQUEST_LOCATION_PERMISSIONS) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// 前台权限同意自动尝试申请后台权限如果是API 29+
requestLocationPermissions();
} else {
// 前台权限拒绝:提示用户(可选:引导跳转到应用设置页)
Toast.makeText(this, "需要前台定位权限才能使用该功能", Toast.LENGTH_SHORT).show();
}
} else if (requestCode == REQUEST_BACKGROUND_LOCATION_PERMISSION) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// 后台权限同意:可执行后台定位逻辑
Toast.makeText(this, "已获得后台定位权限", Toast.LENGTH_SHORT).show();
} else {
// 后台权限拒绝:提示用户(可选:说明后台定位的用途,引导手动开启)
Toast.makeText(this, "拒绝后台权限将无法在后台持续定位", Toast.LENGTH_SHORT).show();
}
}
}
}