| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585 |
- package com.paul.drone.activity;
- import android.annotation.SuppressLint;
- import android.app.DownloadManager;
- import android.content.BroadcastReceiver;
- import android.content.Context;
- import android.content.Intent;
- import android.content.IntentFilter;
- import android.database.Cursor;
- import android.net.Uri;
- import android.os.Build;
- import android.os.Bundle;
- import android.os.Handler;
- import android.os.Looper;
- import android.text.TextUtils;
- import android.util.Log;
- import android.view.LayoutInflater;
- import android.view.View;
- import android.widget.Button;
- import android.widget.EditText;
- import android.widget.LinearLayout;
- import android.widget.ProgressBar;
- import android.widget.TextView;
- import android.widget.Toast;
- import androidx.appcompat.app.AlertDialog;
- import androidx.appcompat.app.AppCompatActivity;
- import com.paul.drone.MainActivity;
- import com.paul.drone.R;
- import com.paul.drone.data.UpdateInfoResponse;
- import com.paul.drone.manager.DJISDKManager;
- import com.paul.drone.network.SessionManager;
- import com.paul.drone.repository.NetworkRepository;
- import com.paul.drone.util.VersionUpdateUtil;
- import java.io.File;
- import java.util.Objects;
- import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
- import io.reactivex.rxjava3.core.Single;
- import io.reactivex.rxjava3.disposables.CompositeDisposable;
- import io.reactivex.rxjava3.schedulers.Schedulers;
- public class LoginActivity extends AppCompatActivity {
- private static final String TAG = LoginActivity.class.getSimpleName();
-
- private NetworkRepository networkRepository;
- private VersionUpdateUtil updateUtil;
- private EditText editTextPhone;
- private TextView tvSdkInitStatus;
- private EditText editTextSmsCode;
- private Button buttonSendSms;
- private Button buttonLogin;
- private CompositeDisposable disposables = new CompositeDisposable();
- // 声明需要的成员变量
- private long downloadId;
- private ProgressBar progressBar;
- private TextView progressText;
- private TextView statusText;
- private Button installButton;
- private AlertDialog dialog;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- // 初始化 NetworkRepository
- networkRepository = NetworkRepository.getInstance();
- SessionManager sessionManager = new SessionManager(this);
- updateUtil = VersionUpdateUtil.getInstance(this);
- String currentVersion = updateUtil.getCurrentVersion();
- Single<UpdateInfoResponse> updateInfoResponseSingle = updateUtil.checkLatestVersion();
- disposables.add(updateInfoResponseSingle.subscribeOn(Schedulers.io())
- .observeOn(AndroidSchedulers.mainThread())
- .subscribe(
- updateInfoResponse -> {
- boolean newVersion = updateUtil.isNewVersion(currentVersion, updateInfoResponse.getData().getVersion());
- if (newVersion && updateInfoResponse.getData().isForce()) {
- // 处理强制更新逻辑 - 显示更新对话框
- showForceUpdateDialog(updateInfoResponse);
- } else {
- // 没有强制更新,继续检查登录状态
- checkLoginStatus(sessionManager);
- }
- },
- throwable -> {
- // 处理错误 - 即使检查失败也允许用户登录
- Log.e(TAG, "版本检查失败: " + throwable.getMessage(), throwable);
- checkLoginStatus(sessionManager);
- }
- ));
- // 注意:不要在这里添加其他逻辑,所有后续操作应该在subscribe回调中处理
- }
- private void checkLoginStatus(SessionManager sessionManager) {
- // 检查登录状态
- if (!sessionManager.isSessionExpired()) {
- Log.i(TAG, "用户已登录且token有效,直接进入MainActivity");
- Intent intent = new Intent(LoginActivity.this, MainActivity.class);
- startActivity(intent);
- finish();
- return;
- } else {
- Log.i(TAG, "未登录或token无效,显示登录界面");
- }
- // 未登录或token无效,加载登录界面
- setContentView(R.layout.activity_login);
- initViews();
- setupListeners();
- }
- private void initViews() {
- editTextPhone = findViewById(R.id.et_phone_number);
- editTextSmsCode = findViewById(R.id.et_sms_code);
- buttonSendSms = findViewById(R.id.btn_send_sms_code);
- buttonLogin = findViewById(R.id.btn_login);
- tvSdkInitStatus = findViewById(R.id.tv_sdk_init_status);
- }
- private void setupListeners() {
- // 发送验证码按钮点击事件
- buttonSendSms.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- tvSdkInitStatus.setText(DJISDKManager.getInstance().isSDKRegistered() ? "Dji SDK 初始化成功" : "Dji SDK 初始化中。。。。");
- String phoneNumber = editTextPhone.getText().toString().trim();
- if (TextUtils.isEmpty(phoneNumber)) {
- Toast.makeText(LoginActivity.this, "请输入手机号", Toast.LENGTH_SHORT).show();
- return;
- }
- if (phoneNumber.length() != 11) {
- Toast.makeText(LoginActivity.this, "请输入正确的手机号", Toast.LENGTH_SHORT).show();
- return;
- }
-
- sendSmsCode(phoneNumber);
- }
- });
- // 登录按钮点击事件
- buttonLogin.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- String phoneNumber = editTextPhone.getText().toString().trim();
- String smsCode = editTextSmsCode.getText().toString().trim();
-
- if (TextUtils.isEmpty(phoneNumber)) {
- Toast.makeText(LoginActivity.this, "请输入手机号", Toast.LENGTH_SHORT).show();
- return;
- }
- if (TextUtils.isEmpty(smsCode)) {
- Toast.makeText(LoginActivity.this, "请输入验证码", Toast.LENGTH_SHORT).show();
- return;
- }
- if (!DJISDKManager.getInstance().isSDKInitialized()) {
- Toast.makeText(LoginActivity.this, "SDK 未初始化,请稍后再试", Toast.LENGTH_SHORT).show();
- return;
- }
-
- performLogin(phoneNumber, smsCode);
- }
- });
- }
- /**
- * 发送验证码
- */
- private void sendSmsCode(String phoneNumber) {
- Log.i(TAG, "发送验证码到: " + phoneNumber);
-
- // 禁用发送按钮
- buttonSendSms.setEnabled(false);
- buttonSendSms.setText("发送中...");
-
- // 使用 NetworkRepository 发送验证码
- disposables.add(networkRepository.sendSmsCode(phoneNumber)
- .subscribeOn(Schedulers.io())
- .observeOn(AndroidSchedulers.mainThread())
- .subscribe(
- response -> {
- if (response.getCode() == 200){
- buttonSendSms.setEnabled(true);
- buttonSendSms.setText("发送验证码");
- Toast.makeText(LoginActivity.this, "验证码已发送", Toast.LENGTH_SHORT).show();
- }else{
- buttonSendSms.setEnabled(true);
- buttonSendSms.setText("发送验证码");
- Toast.makeText(LoginActivity.this, "发送验证码错误:"+response.getMsg(), Toast.LENGTH_SHORT).show();
- }
- },
- throwable -> {
- buttonSendSms.setEnabled(true);
- buttonSendSms.setText("发送验证码");
- String errorMessage = getErrorMessage(throwable);
- Toast.makeText(LoginActivity.this, "发送失败: " + errorMessage, Toast.LENGTH_SHORT).show();
- }
- ));
- }
- /**
- * 执行登录
- */
- private void performLogin(String phoneNumber, String smsCode) {
- Log.i(TAG, "登录: " + phoneNumber + ", 验证码: " + smsCode);
-
- // 禁用登录按钮
- buttonLogin.setEnabled(false);
- buttonLogin.setText("登录中...");
-
- // 使用 NetworkRepository 执行登录
- disposables.add(networkRepository.loginWithSmsCode(phoneNumber, smsCode)
- .subscribeOn(Schedulers.io())
- .observeOn(AndroidSchedulers.mainThread())
- .subscribe(
- response -> {
- buttonLogin.setEnabled(true);
- buttonLogin.setText("登录");
-
- if (response != null) {
- Toast.makeText(LoginActivity.this, "登录成功", Toast.LENGTH_SHORT).show();
- // 跳转到 MainActivity
- Intent intent = new Intent(LoginActivity.this, MainActivity.class);
- startActivity(intent);
- finish();
- } else {
- Toast.makeText(LoginActivity.this, "登录失败", Toast.LENGTH_SHORT).show();
- }
- },
- throwable -> {
- buttonLogin.setEnabled(true);
- buttonLogin.setText("登录");
- String errorMessage = getErrorMessage(throwable);
- Toast.makeText(LoginActivity.this, "登录失败: " + errorMessage, Toast.LENGTH_SHORT).show();
- }
- ));
- }
-
- /**
- * 统一错误处理
- */
- private String getErrorMessage(Throwable throwable) {
- if (throwable instanceof java.io.IOException) {
- return "网络连接失败,请检查网络设置";
- } else {
- return throwable.getMessage() != null ? throwable.getMessage() : "未知错误";
- }
- }
-
- private void showForceUpdateDialog(UpdateInfoResponse updateInfo) {
- AlertDialog.Builder builder = new AlertDialog.Builder(this);
- LayoutInflater inflater = LayoutInflater.from(this);
- View dialogView = inflater.inflate(R.layout.dialog_update, null);
- builder.setView(dialogView);
- AlertDialog dialog = builder.create();
- dialog.setCancelable(false);
- dialog.setCanceledOnTouchOutside(false);
- // 获取对话框中的控件
- TextView currentVersionText = dialogView.findViewById(R.id.currentVersion);
- TextView newVersionText = dialogView.findViewById(R.id.newVersion);
- ProgressBar progressBar = dialogView.findViewById(R.id.dialogProgressBar);
- TextView progressText = dialogView.findViewById(R.id.dialogProgressText);
- TextView statusText = dialogView.findViewById(R.id.dialogStatusText);
- Button cancelButton = dialogView.findViewById(R.id.dialogCancelButton);
- Button installButton = dialogView.findViewById(R.id.dialogInstallButton);
- // 设置版本信息
- String currentVersion = updateUtil.getCurrentVersion();
- currentVersionText.setText(currentVersion);
- newVersionText.setText(updateInfo.getVersion());
- // 设置状态文本
- statusText.setText("检测到重要更新,请立即升级");
- // 隐藏进度条和进度文本(初始状态)
- progressBar.setVisibility(View.GONE);
- progressText.setVisibility(View.GONE);
- // 隐藏取消按钮,显示立即更新按钮
- cancelButton.setVisibility(View.GONE);
- installButton.setVisibility(View.VISIBLE);
- installButton.setText("立即更新");
- // 设置立即更新按钮点击事件
- installButton.setOnClickListener(v -> {
- // 开始下载APK
- startDownloadApk(updateInfo, dialog, progressBar, progressText, statusText, installButton);
- });
- dialog.show();
- }
- // 修改 startDownloadApk 方法中的安装按钮点击事件
- private final Handler progressHandler = new Handler(Looper.getMainLooper());
- private Runnable progressRunnable;
- private boolean isDownloading = false;
- // 修改 startDownloadApk 方法
- @SuppressLint("UnspecifiedRegisterReceiverFlag")
- private void startDownloadApk(UpdateInfoResponse updateInfo, AlertDialog dialog,
- ProgressBar progressBar, TextView progressText,
- TextView statusText, Button installButton) {
- // 保存引用到成员变量
- this.dialog = dialog;
- this.progressBar = progressBar;
- this.progressText = progressText;
- this.statusText = statusText;
- this.installButton = installButton;
- // 显示进度条
- progressBar.setVisibility(View.VISIBLE);
- progressText.setVisibility(View.VISIBLE);
- statusText.setText("正在准备下载...");
- installButton.setEnabled(false);
- installButton.setText("下载中...");
- try {
- // 使用VersionUpdateUtil下载APK
- downloadId = updateUtil.downloadApk(updateInfo.getUpgradeurl(), updateInfo.getVersion());
- statusText.setText("开始下载,请勿关闭应用...");
- progressText.setText("下载已启动...");
- // 先检查是否已经有相同下载任务在进行或已完成
- if (isDownloadAlreadyExists(updateInfo.getUpgradeurl())) {
- Log.w(TAG, "检测到相同URL的下载任务已存在");
- }
-
- // 注册下载完成广播接收器
- IntentFilter filter = new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE);
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
- registerReceiver(downloadReceiver, filter, Context.RECEIVER_EXPORTED);
- } else {
- registerReceiver(downloadReceiver, filter);
- Log.d(TAG, "已注册广播接收器");
- }
- // 开始定期查询下载进度
- startProgressTracking();
- } catch (Exception e) {
- statusText.setText("下载失败: " + e.getMessage());
- installButton.setEnabled(true);
- installButton.setText("重试");
- installButton.setOnClickListener(v -> {
- startDownloadApk(updateInfo, dialog, progressBar, progressText, statusText, installButton);
- });
- }
- }
- // 添加检查下载任务是否已存在的方法
- private boolean isDownloadAlreadyExists(String downloadUrl) {
- DownloadManager downloadManager = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
- DownloadManager.Query query = new DownloadManager.Query();
- Cursor cursor = downloadManager.query(query);
- if (cursor != null) {
- int uriIndex = cursor.getColumnIndex(DownloadManager.COLUMN_URI);
- while (cursor.moveToNext()) {
- String uri = cursor.getString(uriIndex);
- if (downloadUrl.equals(uri)) {
- cursor.close();
- return true;
- }
- }
- cursor.close();
- }
- return false;
- }
- // 添加进度跟踪方法
- private void startProgressTracking() {
- isDownloading = true;
- progressRunnable = new Runnable() {
- @Override
- public void run() {
- if (isDownloading) {
- updateProgress();
- progressHandler.postDelayed(this, 1000); // 每秒更新一次
- }
- }
- };
- progressHandler.post(progressRunnable);
- }
- // 更新进度显示
- private void updateProgress() {
- DownloadManager downloadManager = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
- DownloadManager.Query query = new DownloadManager.Query();
- query.setFilterById(downloadId);
- Cursor cursor = downloadManager.query(query);
- if (cursor != null && cursor.moveToFirst()) {
- int statusIndex = cursor.getColumnIndex(DownloadManager.COLUMN_STATUS);
- int status = cursor.getInt(statusIndex);
- switch (status) {
- case DownloadManager.STATUS_RUNNING:
- int bytesDownloadedIndex = cursor.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR);
- int bytesTotalIndex = cursor.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES);
- long bytesDownloaded = cursor.getLong(bytesDownloadedIndex);
- long bytesTotal = cursor.getLong(bytesTotalIndex);
- if (bytesTotal > 0) {
- int progress = (int) ((bytesDownloaded * 100) / bytesTotal);
- progressBar.setProgress(progress);
- progressText.setText(String.format("下载中... %d%%", progress));
- statusText.setText("正在下载应用更新...");
- }
- break;
- case DownloadManager.STATUS_PENDING:
- statusText.setText("等待下载开始...");
- progressText.setText("准备中...");
- break;
- case DownloadManager.STATUS_PAUSED:
- statusText.setText("下载已暂停");
- progressText.setText("下载暂停");
- break;
- case DownloadManager.STATUS_FAILED:
- statusText.setText("下载失败");
- progressText.setText("下载失败,请重试");
- stopProgressTracking();
- // 显示重试按钮
- installButton.setEnabled(true);
- installButton.setText("重试");
- installButton.setOnClickListener(v -> {
- // 重新开始下载逻辑
- });
- break;
- }
- }
- if (cursor != null) {
- cursor.close();
- }
- }
- // 停止进度跟踪
- private void stopProgressTracking() {
- isDownloading = false;
- if (progressRunnable != null) {
- progressHandler.removeCallbacks(progressRunnable);
- }
- }
- // 修改 downloadReceiver 添加额外验证
- private final BroadcastReceiver downloadReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- Log.d(TAG, "收到广播: " + intent.getAction());
- if (DownloadManager.ACTION_DOWNLOAD_COMPLETE.equals(intent.getAction())) {
- long receivedDownloadId = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1);
- Log.d(TAG, "下载ID: " + receivedDownloadId + ", 期望ID: " + downloadId);
- // 额外验证:确保是当前会话的下载任务
- if (receivedDownloadId == downloadId && downloadId != 0) {
- Log.d(TAG, "下载完成,准备更新UI");
- // 停止进度跟踪
- stopProgressTracking();
- // 下载完成,更新UI
- runOnUiThread(() -> {
- if (!isFinishing() && progressText != null && statusText != null && installButton != null) {
- progressText.setText("");
- statusText.setText("下载已完成,准备安装");
- progressBar.setProgress(100);
- installButton.setEnabled(true);
- installButton.setText("立即安装");
- installButton.setVisibility(View.VISIBLE);
- // 设置安装按钮点击事件
- installButton.setOnClickListener(installView -> {
- installDownloadedApk(downloadId, dialog);
- });
- Log.d(TAG, "UI更新完成");
- } else {
- Log.w(TAG, "Activity已结束或UI组件为空");
- }
- });
- } else {
- Log.d(TAG, "收到其他下载任务的完成广播或无效下载ID");
- }
- }
- }
- };
- // 在 onDestroy 中停止进度跟踪
- @Override
- protected void onDestroy() {
- super.onDestroy();
- // 停止进度跟踪
- stopProgressTracking();
- // 清理资源
- if (disposables != null && !disposables.isDisposed()) {
- disposables.dispose();
- }
- // 注销广播接收器
- try {
- unregisterReceiver(downloadReceiver);
- Log.d(TAG, "广播接收器已注销");
- } catch (IllegalArgumentException e) {
- // 接收器未注册,忽略
- Log.w(TAG, "广播接收器未注册或已注销: " + e.getMessage());
- }
- }
- private void installDownloadedApk(long downloadId, AlertDialog dialog) {
- try {
- // 通过DownloadManager查询下载的文件
- DownloadManager downloadManager = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
- DownloadManager.Query query = new DownloadManager.Query();
- query.setFilterById(downloadId);
- Cursor cursor = downloadManager.query(query);
- if (cursor != null && cursor.moveToFirst()) {
- int statusIndex = cursor.getColumnIndex(DownloadManager.COLUMN_STATUS);
- if (DownloadManager.STATUS_SUCCESSFUL == cursor.getInt(statusIndex)) {
- // 获取下载文件的URI
- int uriIndex = cursor.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI);
- String downloadedFileUriString = cursor.getString(uriIndex);
- if (downloadedFileUriString != null) {
- Uri apkUri = Uri.parse(downloadedFileUriString);
- // Android 7.0及以上版本使用FileProvider处理file:// URI
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && "file".equals(apkUri.getScheme())) {
- // 将 file:// URI 转换为 content:// URI
- File apkFile = new File(apkUri.getPath());
- if (apkFile.exists()) {
- Uri contentUri = androidx.core.content.FileProvider.getUriForFile(
- this,
- "com.paul.drone.fileprovider",
- apkFile
- );
- // 授予临时权限给包管理器
- updateUtil.installApk(contentUri);
- } else {
- Toast.makeText(this, "APK文件不存在", Toast.LENGTH_LONG).show();
- }
- } else {
- // Android 7.0以下版本或已经是content:// URI,直接使用
- updateUtil.installApk(apkUri);
- }
- dialog.dismiss();
- finish();
- } else {
- Toast.makeText(this, "无法找到下载的文件", Toast.LENGTH_LONG).show();
- }
- } else {
- Toast.makeText(this, "下载未完成", Toast.LENGTH_LONG).show();
- }
- } else {
- Toast.makeText(this, "下载查询失败", Toast.LENGTH_LONG).show();
- }
- if (cursor != null) {
- cursor.close();
- }
- } catch (Exception e) {
- Log.e(TAG, "安装APK失败: " + e.getMessage(), e);
- Toast.makeText(this, "安装失败: " + e.getMessage(), Toast.LENGTH_LONG).show();
- }
- }
- }
|