package com.jsbogang.womp.android; import android.Manifest; import android.content.pm.PackageManager; import android.os.Build; import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.Toast; import androidx.activity.OnBackPressedCallback; import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; import androidx.core.app.ActivityCompat; import androidx.core.content.ContextCompat; import androidx.fragment.app.Fragment; import com.google.android.material.appbar.MaterialToolbar; import com.google.android.material.bottomnavigation.BottomNavigationView; import com.jsbogang.womp.health.ActiveMeasureRunner; import com.jsbogang.womp.health.HealthFragment; import com.jsbogang.womp.health.HealthSyncer; import com.jsbogang.womp.health.HealthUploader; import com.jsbogang.womp.workbench.WompKeepAliveService; import com.jsbogang.womp.workbench.WompSession; import com.jsbogang.womp.workbench.WompWorkbenchFragment; import java.util.ArrayList; import java.util.List; public class MainActivity extends AppCompatActivity { private static final String TAG = "MainActivity"; private View workbenchContainer; private View healthContainer; private WompWorkbenchFragment workbenchFragment; private long lastBackPressedAt; private boolean switchingTab; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); HealthSyncer.get().attach(this); HealthUploader.get().attach(this); ActiveMeasureRunner.get().attach(this); MaterialToolbar toolbar = findViewById(R.id.toolbar); toolbar.setTitle(R.string.app_name); toolbar.setTitleCentered(true); workbenchContainer = findViewById(R.id.workbench_container); healthContainer = findViewById(R.id.health_container); if (savedInstanceState == null) { workbenchFragment = new WompWorkbenchFragment(); getSupportFragmentManager().beginTransaction() .replace(R.id.workbench_container, workbenchFragment, "womp_workbench") .commit(); } else { workbenchFragment = (WompWorkbenchFragment) getSupportFragmentManager() .findFragmentByTag("womp_workbench"); } BottomNavigationView nav = findViewById(R.id.bottom_nav); nav.setOnItemSelectedListener(item -> { if (switchingTab) { return true; } if (item.getItemId() == R.id.nav_workbench) { showWorkbenchTab(); return true; } if (item.getItemId() == R.id.nav_health) { try { showHealthTab(); return true; } catch (Throwable t) { Log.e(TAG, "open health tab failed", t); Toast.makeText(this, "健康页打开失败: " + t.getMessage(), Toast.LENGTH_LONG).show(); return false; } } return false; }); getOnBackPressedDispatcher().addCallback(this, new OnBackPressedCallback(true) { @Override public void handleOnBackPressed() { if (healthContainer.getVisibility() == View.VISIBLE) { switchingTab = true; nav.setSelectedItemId(R.id.nav_workbench); switchingTab = false; showWorkbenchTab(); return; } if (workbenchFragment != null && workbenchFragment.goBack()) { return; } long now = System.currentTimeMillis(); if (now - lastBackPressedAt < 2000) { finish(); return; } lastBackPressedAt = now; Toast.makeText(MainActivity.this, R.string.womp_press_again_to_exit, Toast.LENGTH_SHORT).show(); } }); requestRuntimePermissions(); WompKeepAliveService.start(this); } public void showHealthTab() { ensureHealthFragment(); // 不要把工作台 WebView 设为 GONE,部分机型会直接 native crash 且没有 Java 堆栈 workbenchContainer.setVisibility(View.INVISIBLE); healthContainer.setVisibility(View.VISIBLE); healthContainer.bringToFront(); HealthSyncer.get().syncAll(false); BottomNavigationView nav = findViewById(R.id.bottom_nav); if (nav.getSelectedItemId() != R.id.nav_health) { switchingTab = true; nav.setSelectedItemId(R.id.nav_health); switchingTab = false; } } public void showWorkbenchTab() { healthContainer.setVisibility(View.GONE); workbenchContainer.setVisibility(View.VISIBLE); workbenchContainer.bringToFront(); } private void ensureHealthFragment() { Fragment existing = getSupportFragmentManager().findFragmentByTag("health"); if (existing != null) { return; } getSupportFragmentManager().beginTransaction() .replace(R.id.health_container, new HealthFragment(), "health") .commitNowAllowingStateLoss(); } private void requestRuntimePermissions() { List need = new ArrayList<>(); if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) { need.add(Manifest.permission.ACCESS_FINE_LOCATION); need.add(Manifest.permission.ACCESS_COARSE_LOCATION); } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { if (ContextCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_SCAN) != PackageManager.PERMISSION_GRANTED) { need.add(Manifest.permission.BLUETOOTH_SCAN); } if (ContextCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED) { need.add(Manifest.permission.BLUETOOTH_CONNECT); } } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU && ContextCompat.checkSelfPermission(this, Manifest.permission.POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED) { need.add(Manifest.permission.POST_NOTIFICATIONS); } if (!need.isEmpty()) { ActivityCompat.requestPermissions(this, need.toArray(new String[0]), 1001); } } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (WompSession.isLoggedIn(this)) { WompKeepAliveService.start(this); } } @Override protected void onResume() { super.onResume(); Fragment f = getSupportFragmentManager().findFragmentByTag("womp_workbench"); if (f instanceof WompWorkbenchFragment) { workbenchFragment = (WompWorkbenchFragment) f; } WompKeepAliveService.start(this, true); Fragment health = getSupportFragmentManager().findFragmentByTag("health"); if (health instanceof HealthFragment) { ((HealthFragment) health).reloadFromLocal(); } } }