Android安卓毕业设计实战项目(15)---Fast健身 APP【锻炼,计划列表,体重跟踪,身体追踪,导入导出健身记录】包括登陆注册页面+开机动画+个人信息页面(源码在文末)

Android安卓毕业设计实战项目(15)—Fast健身 APP【锻炼,计划列表,体重跟踪,身体追踪,导入导出健身记录】包括登陆注册页面+开机动画+个人信息页面(源码在文末🐕🐕🐕)

一.项目运行介绍

//
//
//
视频演示:https://www.bilibili.com/video/BV1Hh4y1Y7S2/
//
//
//

a980778bdda584b5ee043980d9f9480

61402713245e9950cfa38509bcc408e

d804d1cef76695702ef2dfe71d925a34fe9f3461d3e48df6c21c49013ada3f61c5e22371771c91fece57753ad9df09a19d773a52d2849656e592380972c857bcfcfe28f157bc6dca5f582ae3153a02845bb8a9397f71bd736bfcb37d00a7948f2f81fabf819d456fbcfbf7c0a5ac068b8db2ad5253fb93b6f28e2e7415bedd0b30903e222ea276fc0d73e6b357cf7e2f186025d8f370229d4331d7c02bd6b1554c1093ea4c78a6ae5717edd18d8f4567247b1bf306ccf1397033

二.具体实现

TimePickerDialogFragment.java
package com.easyfitness;

import android.app.Dialog;
import android.os.Bundle;

import androidx.fragment.app.DialogFragment;

import com.ikovac.timepickerwithseconds.MyTimePickerDialog;

//@SuppressLint("ValidFragment")
public class TimePickerDialogFragment extends DialogFragment {

    private final int Hours = 0;
    private final int Minutes = 0;
    private final int Seconds = 0;
    private MyTimePickerDialog.OnTimeSetListener onTimeSetListener;

    static public TimePickerDialogFragment newInstance(MyTimePickerDialog.OnTimeSetListener onTimeSetListener, int hour, int min, int sec) {
        TimePickerDialogFragment pickerFragment = new TimePickerDialogFragment();
        pickerFragment.setOnTimeSetListener(onTimeSetListener);

        //Pass the date in a bundle.
        Bundle bundle = new Bundle();
        bundle.putInt("HOUR", hour);
        bundle.putInt("MINUTE", min);
        bundle.putInt("SECOND", sec);
        pickerFragment.setArguments(bundle);
        return pickerFragment;
    }

    public Dialog onCreateDialog(Bundle savedInstanceState) {
        Bundle bundle = getArguments();
        int hour = bundle.getInt("HOUR");
        int min = bundle.getInt("MINUTE");
        int sec = bundle.getInt("SECOND");

        // Create a new instance of TimePickerDialog and return it
        return new MyTimePickerDialog(getActivity(), onTimeSetListener, hour, min, sec, true);
    }

    private void setOnTimeSetListener(MyTimePickerDialog.OnTimeSetListener listener) {
        this.onTimeSetListener = listener;
    }
}

这段代码是一个 Android 应用中的 Java 类,用于创建一个时间选择对话框(TimePickerDialogFragment)。下面是对代码的详细解释:

  1. 包名和导入:

    • package com.easyfitness;:这是 Java 包声明,表示这个类位于 com.easyfitness 包中。
    • 导入必要的 Android 类和库,例如 android.app.Dialogandroid.os.Bundleandroidx.fragment.app.DialogFragment 以及 com.ikovac.timepickerwithseconds.MyTimePickerDialog
  2. 注释:

    • //@SuppressLint("ValidFragment"):这是一个注释,用于告诉编译器忽略与此类相关的特定警告。在这种情况下,它似乎是关于 ValidFragment 的,但是这个注释在代码中被注释掉了,所以不会生效。
  3. 类定义:

    • TimePickerDialogFragment 是一个继承自 DialogFragment 的自定义类,表示时间选择对话框的片段。
  4. 类的成员变量:

    • HoursMinutesSeconds 是用于表示小时、分钟和秒钟的常量。这些常量的值都被初始化为0。
    • onTimeSetListener 是一个 MyTimePickerDialog.OnTimeSetListener 的接口对象,用于监听时间选择的事件。
  5. newInstance 静态方法:

    • 这是一个静态工厂方法,用于创建 TimePickerDialogFragment 的新实例。
    • 接受 MyTimePickerDialog.OnTimeSetListener 对象以及小时、分钟和秒钟作为参数。
    • 在方法内部,创建了一个新的 TimePickerDialogFragment 实例,并为其设置 onTimeSetListener
    • 创建一个 Bundle 对象,将小时、分钟和秒钟作为数据放入 Bundle 中。
    • 最后,将 Bundle 设置为 pickerFragment 的参数,并返回 pickerFragment
  6. onCreateDialog 方法:

    • 该方法在创建对话框时被调用。
    • 从参数 savedInstanceState 中获取保存的数据(如果有)。
    • 从 Bundle 中获取小时、分钟和秒钟的值。
    • 使用这些值创建一个新的 MyTimePickerDialog 对话框,并传入上下文、onTimeSetListener、小时、分钟、秒钟以及一个布尔值来指示是否显示秒钟选择。
    • 返回创建的对话框。
  7. setOnTimeSetListener 方法:

    • 这是一个私有方法,用于设置 onTimeSetListener
    • 用于在 newInstance 方法内部设置监听器的回调。

总之,这段代码定义了一个用于创建时间选择对话框的 TimePickerDialogFragment 类,它允许你传入小时、分钟和秒钟的初始值,并监听用户对时间的选择。这对于在 Android 应用中实现时间选择功能非常有用。

MainActivity.java
package com.easyfitness;

import android.Manifest;
import android.app.AlertDialog;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.view.Gravity;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.PopupMenu;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.appcompat.app.ActionBarDrawerToggle;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.app.AppCompatDelegate;
import androidx.appcompat.content.res.AppCompatResources;
import androidx.appcompat.widget.Toolbar;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.drawerlayout.widget.DrawerLayout;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentTransaction;
import androidx.lifecycle.ViewModelProvider;
import androidx.preference.PreferenceManager;

import com.easyfitness.DAO.DAOMachine;
import com.easyfitness.DAO.DAOProfile;
import com.easyfitness.DAO.DatabaseHelper;
import com.easyfitness.DAO.Machine;
import com.easyfitness.DAO.Profile;
import com.easyfitness.DAO.cardio.DAOOldCardio;
import com.easyfitness.DAO.cardio.OldCardio;
import com.easyfitness.DAO.export.CVSManager;
import com.easyfitness.DAO.program.DAOProgram;
import com.easyfitness.DAO.program.Program;
import com.easyfitness.DAO.record.DAOCardio;
import com.easyfitness.DAO.record.DAOFonte;
import com.easyfitness.DAO.record.DAORecord;
import com.easyfitness.DAO.record.DAOStatic;
import com.easyfitness.DAO.record.Record;
import com.easyfitness.bodymeasures.BodyPartListFragment;
import com.easyfitness.enums.DistanceUnit;
import com.easyfitness.enums.ExerciseType;
import com.easyfitness.enums.WeightUnit;
import com.easyfitness.fonte.FontesPagerFragment;
import com.easyfitness.intro.MainIntroActivity;
import com.easyfitness.machines.MachineFragment;
import com.easyfitness.programs.ProgramListFragment;
import com.easyfitness.utils.DateConverter;
import com.easyfitness.utils.ImageUtil;
import com.easyfitness.utils.MusicController;
import com.easyfitness.utils.UnitConverter;
import com.mikhaellopez.circularimageview.CircularImageView;
import com.onurkaganaldemir.ktoastlib.KToast;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;

import cn.pedant.SweetAlert.SweetAlertDialog;

public class MainActivity extends AppCompatActivity {

    private static final int TIME_INTERVAL = 2000; // # milliseconds, desired time passed between two back presses.

    public static String FONTESPAGER = "FontePager";
    public static String WEIGHT = "Weight";
    public static String PROFILE = "Profile";
    public static String BODYTRACKING = "BodyTracking";
    public static String BODYTRACKINGDETAILS = "BodyTrackingDetail";
    public static String ABOUT = "About";
    public static String SETTINGS = "Settings";
    public static String MACHINES = "Machines";
    public static String MACHINESDETAILS = "MachinesDetails";
    public static String WORKOUTS = "Workouts";
    public static String WORKOUTPAGER = "WorkoutPager";
    public static String PREFS_NAME = "prefsfile";
    private final int REQUEST_CODE_INTRO = 111;
    private final int PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE_FOR_EXPORT = 1001;
    private final int PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE_FOR_IMPORT = 1002;
    private final int MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE = 103;


    private static final int IMPORT_DATABASE = 2;
    public static final int OPEN_MUSIC_FILE = 3;

    private final MusicController musicController = new MusicController(this);
    CustomDrawerAdapter mDrawerAdapter;
    List<DrawerItem> dataList;
    /* Fragments */
    private FontesPagerFragment mpFontesPagerFrag = null;
    private WeightFragment mpWeightFrag = null;
    private ProfileFragment mpProfileFrag = null;
    private MachineFragment mpMachineFrag = null;
    private SettingsFragment mpSettingFrag = null;
    private AboutFragment mpAboutFrag = null;
    private BodyPartListFragment mpBodyPartListFrag = null;
    private ProgramListFragment mpWorkoutListFrag;
    private String currentFragmentName = "";
    private DAOProfile mDbProfils = null;
    private Profile mCurrentProfile = null;
    private long mCurrentProfilID = -1;
    private Toolbar top_toolbar = null;
    /* Navigation Drawer */
    private DrawerLayout mDrawerLayout = null;
    private ListView mDrawerList = null;
    private ActionBarDrawerToggle mDrawerToggle = null;
    private CircularImageView roundProfile = null;
    private String mCurrentMachine = "";
    private boolean mIntro014Launched = false;
    private boolean mMigrationBD15done = false;
    private boolean mMigrationToScopedStoragedone = false;
    private long mBackPressed;
    private AppViMo appViMo;

    private final PopupMenu.OnMenuItemClickListener onMenuItemClick = item -> {
        switch (item.getItemId()) {
            case R.id.create_newprofil:
                getActivity().CreateNewProfile();
                return true;
            case R.id.change_profil:
                String[] profilListArray = getActivity().mDbProfils.getAllProfile();

                AlertDialog.Builder changeProfilbuilder = new AlertDialog.Builder(getActivity());
                changeProfilbuilder.setTitle(getActivity().getResources().getText(R.string.profil_select_profil))
                        .setItems(profilListArray, (dialog, which) -> {
                            ListView lv = ((AlertDialog) dialog).getListView();
                            Object checkedItem = lv.getAdapter().getItem(which);
                            setCurrentProfile(checkedItem.toString());
                            KToast.infoToast(getActivity(), getActivity().getResources().getText(R.string.profileSelected) + " : " + checkedItem.toString(), Gravity.BOTTOM, KToast.LENGTH_LONG);
                            //Toast.makeText(getApplicationContext(), getActivity().getResources().getText(R.string.profileSelected) + " : " + checkedItem.toString(), Toast.LENGTH_LONG).show();
                        });
                changeProfilbuilder.show();
                return true;
            case R.id.delete_profil:
                String[] profildeleteListArray = getActivity().mDbProfils.getAllProfile();

                AlertDialog.Builder deleteProfilbuilder = new AlertDialog.Builder(getActivity());
                deleteProfilbuilder.setTitle(getActivity().getResources().getText(R.string.profil_select_profil_to_delete))
                        .setItems(profildeleteListArray, (dialog, which) -> {
                            ListView lv = ((AlertDialog) dialog).getListView();
                            Object checkedItem = lv.getAdapter().getItem(which);
                            if (getCurrentProfile().getName().equals(checkedItem.toString())) {
                                KToast.errorToast(getActivity(), getActivity().getResources().getText(R.string.impossibleToDeleteProfile).toString(), Gravity.BOTTOM, KToast.LENGTH_LONG);
                            } else {
                                Profile profileToDelete = mDbProfils.getProfile(checkedItem.toString());
                                mDbProfils.deleteProfile(profileToDelete);
                                KToast.infoToast(getActivity(), getString(R.string.profileDeleted) + ":" + checkedItem.toString(), Gravity.BOTTOM, KToast.LENGTH_LONG);
                            }
                        });
                deleteProfilbuilder.show();
                return true;
            case R.id.rename_profil:
                getActivity().renameProfil();
                return true;
            case R.id.param_profil:
                showFragment(PROFILE);
                return true;
            default:
                return false;
        }
    };

    @Override
    public void onCreate(Bundle savedInstanceState) {
        SharedPreferences SP = PreferenceManager.getDefaultSharedPreferences(getBaseContext());
        String dayNightAuto = SP.getString("dayNightAuto", "2");
        int dayNightAutoValue;
        try {
            dayNightAutoValue = Integer.parseInt(dayNightAuto);
        } catch (NumberFormatException e) {
            dayNightAutoValue = 2;
        }
        if (dayNightAutoValue == getResources().getInteger(R.integer.dark_mode_value)) {
            AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);
            SweetAlertDialog.DARK_STYLE = true;
        } else if (dayNightAutoValue == getResources().getInteger(R.integer.light_mode_value)) {
            AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
            SweetAlertDialog.DARK_STYLE = false;
        } else {
            AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM);
            int currentNightMode = getResources().getConfiguration().uiMode
                    & Configuration.UI_MODE_NIGHT_MASK;
            switch (currentNightMode) {
                case Configuration.UI_MODE_NIGHT_YES:
                    SweetAlertDialog.DARK_STYLE = true;
                    break;
                case Configuration.UI_MODE_NIGHT_NO:
                default:
                    SweetAlertDialog.DARK_STYLE = false;
            }
        }

        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);

        loadPreferences();

        top_toolbar = this.findViewById(R.id.actionToolbar);
        setSupportActionBar(top_toolbar);
        top_toolbar.setTitle(getResources().getText(R.string.app_name));

        if (savedInstanceState == null) {
            if (mpFontesPagerFrag == null)
                mpFontesPagerFrag = FontesPagerFragment.newInstance(FONTESPAGER, 6);
            if (mpWeightFrag == null) mpWeightFrag = WeightFragment.newInstance(WEIGHT, 5);
            if (mpProfileFrag == null) mpProfileFrag = ProfileFragment.newInstance(PROFILE, 10);
            if (mpSettingFrag == null) mpSettingFrag = SettingsFragment.newInstance(SETTINGS, 8);
            if (mpAboutFrag == null) mpAboutFrag = AboutFragment.newInstance(ABOUT, 4);
            if (mpMachineFrag == null) mpMachineFrag = MachineFragment.newInstance(MACHINES, 7);
            if (mpBodyPartListFrag == null)
                mpBodyPartListFrag = BodyPartListFragment.newInstance(BODYTRACKING, 9);
            if (mpWorkoutListFrag == null)
                mpWorkoutListFrag = ProgramListFragment.newInstance(WORKOUTS, 11);
        } else {
            mpFontesPagerFrag = (FontesPagerFragment) getSupportFragmentManager().getFragment(savedInstanceState, FONTESPAGER);
            mpWeightFrag = (WeightFragment) getSupportFragmentManager().getFragment(savedInstanceState, WEIGHT);
            mpProfileFrag = (ProfileFragment) getSupportFragmentManager().getFragment(savedInstanceState, PROFILE);
            mpSettingFrag = (SettingsFragment) getSupportFragmentManager().getFragment(savedInstanceState, SETTINGS);
            mpAboutFrag = (AboutFragment) getSupportFragmentManager().getFragment(savedInstanceState, ABOUT);
            mpMachineFrag = (MachineFragment) getSupportFragmentManager().getFragment(savedInstanceState, MACHINES);
            mpBodyPartListFrag = (BodyPartListFragment) getSupportFragmentManager().getFragment(savedInstanceState, BODYTRACKING);
            mpWorkoutListFrag = (ProgramListFragment) getSupportFragmentManager().getFragment(savedInstanceState, WORKOUTS);
        }

        appViMo = new ViewModelProvider(this).get(AppViMo.class);
        appViMo.getProfile().observe(this, profile -> {
            // Update UI
            setDrawerTitle(profile.getName());
            setPhotoProfile(profile.getPhoto());
            mCurrentProfilID = profile.getId();
            savePreferences();
        });

        DatabaseHelper.renameOldDatabase(this);

        if (DatabaseHelper.DATABASE_VERSION >= 15 && !mMigrationBD15done) {
            DAOOldCardio mDbOldCardio = new DAOOldCardio(this);
            DAOMachine lDAOMachine = new DAOMachine(this);
            if (mDbOldCardio.tableExists()) {
                DAOCardio mDbCardio = new DAOCardio(this);
                List<OldCardio> mList = mDbOldCardio.getAllRecords();
                for (OldCardio record : mList) {
                    Machine m = lDAOMachine.getMachine(record.getExercice());
                    String exerciseName = record.getExercice();
                    if (m != null) { // if a machine exists
                        if (m.getType() == ExerciseType.STRENGTH) { // if it is not a Cardio type
                            exerciseName = exerciseName + "-Cardio"; // add a suffix to
                        }
                    }

                    mDbCardio.addCardioRecordToFreeWorkout(record.getDate(), exerciseName, record.getDistance(), record.getDuration(), record.getProfil().getId(), DistanceUnit.KM);
                }
                mDbOldCardio.dropTable();

                DAORecord daoRecord = new DAORecord(this);
                List<Record> mFonteList = daoRecord.getAllRecords();
                for (Record record : mFonteList) {
                    record.setExerciseType(ExerciseType.STRENGTH);
                    daoRecord.updateRecord(record); // Automatically update record Type
                }
                List<Machine> machineList = lDAOMachine.getAllMachinesArray();
                for (Machine record : machineList) {
                    lDAOMachine.updateMachine(record); // Reset all the fields on machines.
                }
            }
            mMigrationBD15done = true;
            savePreferences();
        }



        if (savedInstanceState == null) {
            showFragment(FONTESPAGER); // Create fragment, do not add to backstack
            currentFragmentName = FONTESPAGER;
        }

        dataList = new ArrayList<>();
        mDrawerLayout = findViewById(R.id.drawer_layout);
        mDrawerList = findViewById(R.id.left_drawer);

        DrawerItem drawerTitleItem = new DrawerItem("TITLE", R.drawable.ic_person, true);

        dataList.add(drawerTitleItem);
        dataList.add(new DrawerItem(this.getResources().getString(R.string.menu_Workout), R.drawable.ic_fitness_center, true));
        dataList.add(new DrawerItem(this.getResources().getString(R.string.MachinesLabel), R.drawable.ic_exercises, true));
        dataList.add(new DrawerItem(this.getResources().getString(R.string.ProgramListLabel), R.drawable.ic_exam, true));
        dataList.add(new DrawerItem(this.getResources().getString(R.string.weightMenuLabel), R.drawable.ic_bathroom_scale, true));
        dataList.add(new DrawerItem(this.getResources().getString(R.string.bodytracking), R.drawable.ic_ruler, true));
        dataList.add(new DrawerItem(this.getResources().getString(R.string.SettingLabel), R.drawable.ic_settings, true));
        dataList.add(new DrawerItem(this.getResources().getString(R.string.AboutLabel), R.drawable.ic_info_outline, true));

        mDrawerAdapter = new CustomDrawerAdapter(this, R.layout.custom_drawer_item,
                dataList);

        mDrawerList.setAdapter(mDrawerAdapter);

        roundProfile = top_toolbar.findViewById(R.id.imageProfile);

        mDrawerToggle = new ActionBarDrawerToggle(
                this,                  /* host Activity */
                mDrawerLayout,         /* DrawerLayout object */
                top_toolbar,  /* nav drawer icon to replace 'Up' caret */
                R.string.drawer_open, R.string.drawer_close
        );

        // Set the list's click listener
        mDrawerList.setOnItemClickListener(new DrawerItemClickListener());

        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        getSupportActionBar().setHomeButtonEnabled(true);

        musicController.initView();

        // Test if intro has been launched already
        if (!mIntro014Launched) {
            Intent intent = new Intent(this, MainIntroActivity.class);
            startActivityForResult(intent, REQUEST_CODE_INTRO);
        }


    }

    @Override
    protected void onStart() {
        super.onStart();  // Always call the superclass method first

        if (mIntro014Launched) {
            initActivity();
            initDEBUGdata();
        }

        if ( !mMigrationToScopedStoragedone) { //do the migration only once.
            migrateDatabase();
        }

        SharedPreferences SP = PreferenceManager.getDefaultSharedPreferences(getBaseContext());
        boolean bShowMP3 = SP.getBoolean("prefShowMP3", false);
        this.showMP3Toolbar(bShowMP3);
        this.checkLastBackup(SP);
    }

    private void checkLastBackup(SharedPreferences SP) {
        int milliSecondsOfDay = 86400000; // 24 * 60 * 60 * 1000
        int milliSecondsOfWeek = 604800000; // 7 * 24 * 60 * 60 * 1000
        long milliSecondsOfMonth = 2419200000L; // 4 * 7 * 24 * 60 * 60 * 1000

        long lastBackupUTCTime = SP.getLong("上次备份UTC时间", -1);
        int prefBackupSetting = Integer.parseInt(SP.getString("默认备份设置", "0"));
        if (lastBackupUTCTime == -1 && prefBackupSetting > 0) {
            //KToast.warningToast(getActivity(), getActivity().getResources().getText(R.string.backup_warning_never).toString(), Gravity.BOTTOM, KToast.LENGTH_LONG);
            exportDatabase(getActivity().getResources().getText(R.string.backup_warning_never).toString());
        } else {
            if (prefBackupSetting == 1 && System.currentTimeMillis() - lastBackupUTCTime > milliSecondsOfDay) {
                //KToast.warningToast(getActivity(), getActivity().getResources().getText(R.string.backup_warning_day).toString(), Gravity.BOTTOM, KToast.LENGTH_LONG);
                exportDatabase(getActivity().getResources().getText(R.string.backup_warning_day).toString());
            } else if (prefBackupSetting == 2 && System.currentTimeMillis() - lastBackupUTCTime > milliSecondsOfWeek) {
                //KToast.warningToast(getActivity(), getActivity().getResources().getText(R.string.backup_warning_week).toString(), Gravity.BOTTOM, KToast.LENGTH_LONG);
                exportDatabase(getActivity().getResources().getText(R.string.backup_warning_week).toString());
            } else if (prefBackupSetting == 3 && System.currentTimeMillis() - lastBackupUTCTime > milliSecondsOfMonth) {
                //KToast.warningToast(getActivity(), getActivity().getResources().getText(R.string.backup_warning_month).toString(), Gravity.BOTTOM, KToast.LENGTH_LONG);
                exportDatabase(getActivity().getResources().getText(R.string.backup_warning_month).toString());
            }
        }
    }

    private void initDEBUGdata() {
        if (BuildConfig.DEBUG_MODE) {
            // do something for a debug build
            DAOFonte lDbFonte = new DAOFonte(this);
            if (lDbFonte.getCount() == 0) {
                lDbFonte.addStrengthRecordToFreeWorkout(DateConverter.dateToDate(2019, 7, 1, 12, 34, 56), "锻炼 1", 1, 10, 40, WeightUnit.KG, "", this.getCurrentProfile().getId());
                lDbFonte.addStrengthRecordToFreeWorkout(DateConverter.dateToDate(2019, 6, 30, 12, 34, 56), "锻炼 2", 1, 10, UnitConverter.LbstoKg(60), WeightUnit.LBS, "", this.getCurrentProfile().getId());
            }
            DAOCardio lDbCardio = new DAOCardio(this);
            if (lDbCardio.getCount() == 0) {
                lDbCardio.addCardioRecordToFreeWorkout(DateConverter.dateToDate(2019, 7, 1), "跑步锻炼", 1, 10000, this.getCurrentProfile().getId(), DistanceUnit.KM);
                lDbCardio.addCardioRecordToFreeWorkout(DateConverter.dateToDate(2019, 7, 31), "有氧运动", UnitConverter.MilesToKm(2), 20000, this.getCurrentProfile().getId(), DistanceUnit.MILES);
            }
            DAOStatic lDbStatic = new DAOStatic(this);
            if (lDbStatic.getCount() == 0) {
                lDbStatic.addStaticRecordToFreeWorkout(DateConverter.dateToDate(2019, 7, 1, 12, 34, 56), "锻炼 ISO 1", 1, 50, 40, this.getCurrentProfile().getId(), WeightUnit.KG, "");
                lDbStatic.addStaticRecordToFreeWorkout(DateConverter.dateToDate(2019, 7, 31, 12, 34, 56), "锻炼 ISO 2", 1, 60, UnitConverter.LbstoKg(40), this.getCurrentProfile().getId(), WeightUnit.LBS, "");
            }
            DAOProgram lDbWorkout = new DAOProgram(this);
            if (lDbWorkout.getCount() == 0) {
                lDbWorkout.populate();
            }
        }
    }

    public void onRestoreInstanceState(Bundle savedInstanceState) {
        // Always call the superclass so it can restore the view hierarchy
        super.onRestoreInstanceState(savedInstanceState);
    }

    @Override
    protected void onSaveInstanceState(@NonNull Bundle outState) {
        super.onSaveInstanceState(outState);

        //Save the fragment's instance
        if (getFontesPagerFragment().isAdded())
            getSupportFragmentManager().putFragment(outState, FONTESPAGER, mpFontesPagerFrag);
        if (getWeightFragment().isAdded())
            getSupportFragmentManager().putFragment(outState, WEIGHT, mpWeightFrag);
        if (getProfileFragment().isAdded())
            getSupportFragmentManager().putFragment(outState, PROFILE, mpProfileFrag);
        if (getMachineFragment().isAdded())
            getSupportFragmentManager().putFragment(outState, MACHINES, mpMachineFrag);
        if (getAboutFragment().isAdded())
            getSupportFragmentManager().putFragment(outState, ABOUT, mpAboutFrag);
        if (getSettingsFragment().isAdded())
            getSupportFragmentManager().putFragment(outState, SETTINGS, mpSettingFrag);
        if (getBodyPartFragment().isAdded())
            getSupportFragmentManager().putFragment(outState, BODYTRACKING, mpBodyPartListFrag);
        if (getWorkoutListFragment().isAdded())
            getSupportFragmentManager().putFragment(outState, WORKOUTS, mpWorkoutListFrag);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu items for use in the action bar
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.main_activity_actions, menu);

        // restore the profile picture in case it was overwritten during the menu inflate
        if (mCurrentProfile != null) setPhotoProfile(mCurrentProfile.getPhoto());

        return super.onCreateOptionsMenu(menu);
    }

    @Override
    public boolean onPrepareOptionsMenu(Menu menu) {
        roundProfile.setOnClickListener(v -> {
            PopupMenu popup = new PopupMenu(getActivity(), v);
            MenuInflater inflater = popup.getMenuInflater();
            inflater.inflate(R.menu.profile_actions, popup.getMenu());
            popup.setOnMenuItemClickListener(onMenuItemClick);
            popup.show();
        });

        return super.onPrepareOptionsMenu(menu);
    }

    @SuppressWarnings("deprecation")
    private boolean migrateToScopedStorage() {
        boolean success = true;
        File folder = new File(Environment.getExternalStorageDirectory() + "/FastnFitness");

        if (folder.exists()) { //migrate all pictures
            //Migrate profile pictures
            DAOProfile daoProfile = new DAOProfile(getBaseContext());
            List<Profile> profileList = daoProfile.getAllProfiles(daoProfile.getWritableDatabase());
            for (Profile profile:profileList) {
                if(profile.getPhoto()!=null && !profile.getPhoto().isEmpty()) {
                    File sourceFile = new File(profile.getPhoto());
                    File storageDir = getActivity().getExternalFilesDir(Environment.DIRECTORY_PICTURES);
                    if (sourceFile.exists()) {
                        try {
                            File destFile = ImageUtil.copyFile(sourceFile, storageDir);
                            profile.setPhoto(destFile.getAbsolutePath());
                            ImageUtil.saveThumb(destFile.getAbsolutePath());
                            daoProfile.updateProfile(profile);
                        } catch (IOException e) {
                            e.printStackTrace();
                            profile.setPhoto("");
                            daoProfile.updateProfile(profile);
                            success = false;
                        }
                    } else {
                        profile.setPhoto("");
                        daoProfile.updateProfile(profile);
                    }
                }
            }

            //Migrate exercises pictures
            DAOMachine daoMachine = new DAOMachine(getBaseContext());
            List<Machine> machineList = daoMachine.getAllMachinesArray();
            for (Machine machine:machineList) {
                if(machine.getPicture()!=null && !machine.getPicture().isEmpty()) {
                    File sourceFile = new File(machine.getPicture());
                    File storageDir = getActivity().getExternalFilesDir(Environment.DIRECTORY_PICTURES);
                    if (sourceFile.exists()) {
                        machine.setPicture("");
                        try {
                            File destFile = ImageUtil.copyFile(sourceFile, storageDir);
                            ImageUtil.saveThumb(destFile.getAbsolutePath());
                            machine.setPicture(destFile.getAbsolutePath());
                            daoMachine.updateMachine(machine);
                        } catch (Exception e) {
                            e.printStackTrace();
                            success = false;
                        }
                    }
                    daoMachine.updateMachine(machine);
                }
            }
        }
        return success;
    }

    @SuppressWarnings("deprecation")
    private void migrateDatabase() {
        File folder = new File(Environment.getExternalStorageDirectory() + "/FastnFitness");
        if (!folder.exists()) {
            mMigrationToScopedStoragedone = true;
            savePreferences();
            return;
        }

        AlertDialog.Builder exportDbBuilder = new AlertDialog.Builder(this);
        exportDbBuilder.setTitle(getActivity().getResources().getText(R.string.database_migration));
        exportDbBuilder.setMessage(R.string.disclaimer_scoped_storage);
        exportDbBuilder.setPositiveButton(getActivity().getResources().getText(R.string.global_yes), (dialog, which) -> {
            if (!migrateToScopedStorage()) {
                // Display error box for information
                AlertDialog.Builder errorDialogBuilder = new AlertDialog.Builder(this);
                errorDialogBuilder.setTitle(R.string.database_migration);
                errorDialogBuilder.setMessage(R.string.something_went_wrong);
                AlertDialog errorDialog = errorDialogBuilder.create();
                errorDialog.show();
            } else {
                KToast.infoToast(this, getString(R.string.database_migration_success), Gravity.BOTTOM, KToast.LENGTH_SHORT);
            }
            mMigrationToScopedStoragedone = true;
            savePreferences();
        });

        AlertDialog exportDbDialog = exportDbBuilder.create();
        exportDbDialog.show();
    }

    private void openExportDatabaseDialog(String autoExportMessage) {
        AlertDialog.Builder exportDbBuilder = new AlertDialog.Builder(this);

        exportDbBuilder.setTitle(getActivity().getResources().getText(R.string.export_database));
        exportDbBuilder.setMessage(autoExportMessage + " " + getActivity().getResources().getText(R.string.export_question) + " " + getCurrentProfile().getName() + "?");
        exportDbBuilder.setPositiveButton(getActivity().getResources().getText(R.string.global_yes), (dialog, which) -> {
            CVSManager cvsMan = new CVSManager(getActivity().getBaseContext());
            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy_MM_dd_H_m_s", Locale.getDefault());
            Date date = new Date();
            String folderName = Environment.DIRECTORY_DOWNLOADS + "/FastnFitness/export/" +  dateFormat.format(date);
            if (cvsMan.exportDatabase(getCurrentProfile(),folderName)) {
                SharedPreferences SP = PreferenceManager.getDefaultSharedPreferences(getBaseContext());
                long currentTime = System.currentTimeMillis();
                SP.edit().putLong("prefLastTimeBackupUTCTime", currentTime).apply();
                if (mpSettingFrag.getContext() != null) {
                    mpSettingFrag.updateLastBackupSummary(SP, currentTime);
                }
                KToast.successToast(getActivity(), getCurrentProfile().getName() + ": " + getActivity().getResources().getText(R.string.export_success) + " - " + folderName, Gravity.BOTTOM, KToast.LENGTH_LONG);
            } else {
                KToast.errorToast(getActivity(), getCurrentProfile().getName() + ": " + getActivity().getResources().getText(R.string.export_failed), Gravity.BOTTOM, KToast.LENGTH_LONG);
            }
            dialog.dismiss();
        });

        exportDbBuilder.setNegativeButton(getActivity().getResources().getText(R.string.global_no), (dialog, which) -> dialog.dismiss());

        AlertDialog exportDbDialog = exportDbBuilder.create();
        exportDbDialog.show();
    }

    private void exportDatabase(String autoExportMessage) {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
            if (ContextCompat.checkSelfPermission(this,
                    Manifest.permission.WRITE_EXTERNAL_STORAGE)
                    != PackageManager.PERMISSION_GRANTED) {
                ActivityCompat.requestPermissions(this,
                        new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
                        PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE_FOR_EXPORT);
            } else {
                openExportDatabaseDialog(autoExportMessage);
            }
        } else {
            openExportDatabaseDialog(autoExportMessage);
        }
    }

    private void importDatabase() {
        Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
        intent.addCategory(Intent.CATEGORY_OPENABLE);
        intent.setType("text/*");
        startActivityForResult(intent, IMPORT_DATABASE);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // The action bar home/up action should open or close the drawer.
        // ActionBarDrawerToggle will take care of this.
        if (mDrawerToggle.onOptionsItemSelected(item)) {
            return true;
        }

        // Handle presses on the action bar items
        switch (item.getItemId()) {
            case R.id.export_database:
                exportDatabase("");
                return true;
            case R.id.import_database:
                importDatabase();
                return true;
            case R.id.action_deleteDB:
                // Afficher une boite de dialogue pour confirmer
                AlertDialog.Builder deleteDbBuilder = new AlertDialog.Builder(this);

                deleteDbBuilder.setTitle(getActivity().getResources().getText(R.string.global_confirm));
                deleteDbBuilder.setMessage(getActivity().getResources().getText(R.string.deleteDB_warning));

                // Si oui, supprimer la base de donnee et refaire un Start.
                deleteDbBuilder.setPositiveButton(getActivity().getResources().getText(R.string.global_yes), (dialog, which) -> {
                    List<Profile> lList = mDbProfils.getAllProfiles(mDbProfils.getReadableDatabase());
                    for (int i = 0; i < lList.size(); i++) {
                        Profile mTempProfile = lList.get(i);
                        mDbProfils.deleteProfile(mTempProfile.getId());
                    }

                    DAOMachine mDbMachines = new DAOMachine(getActivity());
                    List<Machine> lList2 = mDbMachines.getAllMachinesArray();
                    for (int i = 0; i < lList2.size(); i++) {
                        Machine mTemp = lList2.get(i);
                        mDbMachines.delete(mTemp.getId());
                    }

                    DAOProgram mDbPrograms = new DAOProgram(getActivity());
                    List<Program> programList = mDbPrograms.getAll();
                    for (int i = 0; i < programList.size(); i++) {
                        Program mTemp = programList.get(i);
                        mDbPrograms.delete(mTemp.getId());

                        DAORecord mDbRecords = new DAORecord(getActivity());
                        List<Record> recordList = mDbRecords.getAllTemplateRecordByProgramArray(mTemp.getId());
                        for (int j = 0; j < recordList.size(); j++) {
                            Record mTempRecord = recordList.get(j);
                            mDbRecords.deleteRecord(mTempRecord.getId());
                        }
                    }

                    mIntro014Launched = false; // redisplay the intro

                    dialog.dismiss(); // Close the dialog
                    finish(); // Close app
                });

                deleteDbBuilder.setNegativeButton(getActivity().getResources().getText(R.string.global_no), (dialog, which) -> {
                    // Do nothing
                    dialog.dismiss();
                });

                AlertDialog deleteDbDialog = deleteDbBuilder.create();
                deleteDbDialog.show();

                return true;
            case R.id.action_apropos:
                // Display the fragment as the main content.
                showFragment(ABOUT);
                //getAboutFragment().setHasOptionsMenu(true);
                return true;
            //case android.R.id.home:
            //onBackPressed();
            // return true;
            case R.id.action_chrono:
                ChronoDialogbox cdd = new ChronoDialogbox(MainActivity.this);
                cdd.show();
                return true;
            default:
                return super.onOptionsItemSelected(item);
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode,
                                           @NonNull String[] permissions, @NonNull int[] grantResults) {
        // If request is cancelled, the result arrays are empty.
        if (requestCode == PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE_FOR_EXPORT) {
            if (grantResults.length > 0
                    && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                KToast.infoToast(this, getString(R.string.access_granted), Gravity.BOTTOM, KToast.LENGTH_SHORT);
                openExportDatabaseDialog("");
            } else {
                KToast.infoToast(this, getString(R.string.another_time_maybe), Gravity.BOTTOM, KToast.LENGTH_SHORT);
            }
        } else if (requestCode == PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE_FOR_IMPORT) {
            if (grantResults.length > 0
                    && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                KToast.infoToast(this, getString(R.string.access_granted), Gravity.BOTTOM, KToast.LENGTH_SHORT);
                importDatabase();
            } else {
                KToast.infoToast(this, getString(R.string.another_time_maybe), Gravity.BOTTOM, KToast.LENGTH_SHORT);
            }
        } else if (requestCode == MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE) {
            if (grantResults.length > 0
                    && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                KToast.infoToast(this, getString(R.string.access_granted), Gravity.BOTTOM, KToast.LENGTH_SHORT);
                musicController.chooseDirectory();
            } else {
                KToast.infoToast(this, getString(R.string.another_time_maybe), Gravity.BOTTOM, KToast.LENGTH_SHORT);
            }
        }
    }

        public boolean CreateNewProfile() {
        AlertDialog.Builder newProfilBuilder = new AlertDialog.Builder(this);

        newProfilBuilder.setTitle(getActivity().getResources().getText(R.string.createProfilTitle));
        newProfilBuilder.setMessage(getActivity().getResources().getText(R.string.createProfilQuestion));

        // Set an EditText view to get user input
        final EditText input = new EditText(this);
        newProfilBuilder.setView(input);

        newProfilBuilder.setPositiveButton(getActivity().getResources().getText(android.R.string.ok), (dialog, whichButton) -> {
            String value = input.getText().toString();

            if (value.isEmpty()) {
                CreateNewProfile();
            } else {
                // Create the new profil
                mDbProfils.addProfile(value);
                // Make it the current.
                setCurrentProfile(value);
            }
        });

        newProfilBuilder.setNegativeButton(getActivity().getResources().getText(android.R.string.cancel), (dialog, whichButton) -> {
            if (getCurrentProfile() == null) {
                CreateNewProfile();
            }
        });

        newProfilBuilder.show();

        return true;
    }

    public boolean renameProfil() {
        AlertDialog.Builder newBuilder = new AlertDialog.Builder(this);

        newBuilder.setTitle(getActivity().getResources().getText(R.string.renameProfilTitle));
        newBuilder.setMessage(getActivity().getResources().getText(R.string.renameProfilQuestion));

        // Set an EditText view to get user input
        final EditText input = new EditText(this);
        input.setText(getCurrentProfile().getName());
        newBuilder.setView(input);

        newBuilder.setPositiveButton(getActivity().getResources().getText(android.R.string.ok), (dialog, whichButton) -> {
            String value = input.getText().toString();

            if (!value.isEmpty()) {
                // Get current profile
                Profile temp = getCurrentProfile();
                // Rename it
                temp.setName(value);
                // Commit it
                mDbProfils.updateProfile(temp);
                // Make it the current.
                setCurrentProfile(value);
            }
        });

        newBuilder.setNegativeButton(getActivity().getResources().getText(android.R.string.cancel), (dialog, whichButton) -> {
        });

        newBuilder.show();

        return true;
    }

    private void setDrawerTitle(String pProfilName) {
        mDrawerAdapter.getItem(0).setTitle(pProfilName);
        mDrawerAdapter.notifyDataSetChanged();
        mDrawerLayout.invalidate();
    }

    /**
     * Swaps fragments in the main content view
     */
    private void selectItem(int position) {
        // Highlight the selected item, update the title, and close the drawer
        mDrawerList.setItemChecked(position, true);
        //setTitle(mPlanetTitles[position]);
        mDrawerLayout.closeDrawer(mDrawerList);
    }

    @Override
    public void setTitle(CharSequence title) {
        getSupportActionBar().setTitle(title);
    }

    @Override
    protected void onPostCreate(Bundle savedInstanceState) {
        super.onPostCreate(savedInstanceState);
        // Sync the toggle state after onRestoreInstanceState has occurred.
        mDrawerToggle.syncState();
    }

    @Override
    public void onConfigurationChanged(@NonNull Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        mDrawerToggle.onConfigurationChanged(newConfig);
    }

    private void showFragment(String pFragmentName) {

        if (currentFragmentName.equals(pFragmentName))
            return; // If this is already the current fragment, do no replace.

        FragmentManager fragmentManager = getSupportFragmentManager();
        FragmentTransaction ft = fragmentManager.beginTransaction();

        // Then show the fragments
        if (pFragmentName.equals(FONTESPAGER)) {
            ft.replace(R.id.fragment_container, getFontesPagerFragment(), FONTESPAGER);
        } else if (pFragmentName.equals(WEIGHT)) {
            ft.replace(R.id.fragment_container, getWeightFragment(), WEIGHT);
        } else if (pFragmentName.equals(SETTINGS)) {
            ft.replace(R.id.fragment_container, getSettingsFragment(), SETTINGS);
        } else if (pFragmentName.equals(MACHINES)) {
            ft.replace(R.id.fragment_container, getMachineFragment(), MACHINES);
        } else if (pFragmentName.equals(WORKOUTS)) {
            ft.replace(R.id.fragment_container, getWorkoutListFragment(), WORKOUTS);
        } else if (pFragmentName.equals(ABOUT)) {
            ft.replace(R.id.fragment_container, getAboutFragment(), ABOUT);
        } else if (pFragmentName.equals(BODYTRACKING)) {
            ft.replace(R.id.fragment_container, getBodyPartFragment(), BODYTRACKING);
        } else if (pFragmentName.equals(PROFILE)) {
            ft.replace(R.id.fragment_container, getProfileFragment(), PROFILE);
        }
        currentFragmentName = pFragmentName;
        ft.commit();

    }

    @Override
    protected void onStop() {
        super.onStop();
        savePreferences();
    }

    public Profile getCurrentProfile() {
        return appViMo.getProfile().getValue();
    }

    public void setCurrentProfile(String newProfileName) {
        Profile newProfile = this.mDbProfils.getProfile(newProfileName);
        setCurrentProfile(newProfile);
    }

    public void setCurrentProfile(Profile newProfil) {
        appViMo.setProfile(newProfil);
    }

    private void setPhotoProfile(String path) {
        ImageUtil imgUtil = new ImageUtil();

        // Check if path is pointing to a thumb else create it and use it.
        String thumbPath = imgUtil.getThumbPath(path);
        boolean success = false;
        if (thumbPath != null) {
            success = ImageUtil.setPic(roundProfile, thumbPath);
            mDrawerAdapter.getItem(0).setImg(thumbPath);
        }

        if (!success) {
            roundProfile.setImageDrawable(AppCompatResources.getDrawable(getActivity(), R.drawable.ic_person));
            mDrawerAdapter.getItem(0).setImg(null); // Img has priority over Resource so it needs to be reset
            mDrawerAdapter.getItem(0).setImgResID(R.drawable.ic_person);
        }

        mDrawerAdapter.notifyDataSetChanged();
        mDrawerLayout.invalidate();
    }

    public String getCurrentMachine() {
        return mCurrentMachine;
    }

    public void setCurrentMachine(String newMachine) {
        mCurrentMachine = newMachine;
    }

    public MainActivity getActivity() {
        return this;
    }

    private void loadPreferences() {
        // Restore preferences
        SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);
        mCurrentProfilID = settings.getLong("currentProfil", -1); // return -1 if it doesn't exist
        mIntro014Launched = settings.getBoolean("intro014Launched", false);
        mMigrationBD15done = settings.getBoolean("migrationBD15done", false);
        mMigrationToScopedStoragedone = settings.getBoolean("migrationToScopedStoragedone", false);
    }

    private void savePreferences() {
        // Restore preferences
        SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);
        SharedPreferences.Editor editor = settings.edit();
        editor.putLong("currentProfil", mCurrentProfilID);
        editor.putBoolean("intro014Launched", mIntro014Launched);
        editor.putBoolean("migrationBD15done", mMigrationBD15done);
        editor.putBoolean("migrationToScopedStoragedone", mMigrationToScopedStoragedone);
        editor.apply();
    }

    private FontesPagerFragment getFontesPagerFragment() {
        if (mpFontesPagerFrag == null)
            mpFontesPagerFrag = (FontesPagerFragment) getSupportFragmentManager().findFragmentByTag(FONTESPAGER);
        if (mpFontesPagerFrag == null)
            mpFontesPagerFrag = FontesPagerFragment.newInstance(FONTESPAGER, 6);

        return mpFontesPagerFrag;
    }

    private WeightFragment getWeightFragment() {
        if (mpWeightFrag == null)
            mpWeightFrag = (WeightFragment) getSupportFragmentManager().findFragmentByTag(WEIGHT);
        if (mpWeightFrag == null) mpWeightFrag = WeightFragment.newInstance(WEIGHT, 5);

        return mpWeightFrag;
    }

    private ProfileFragment getProfileFragment() {
        if (mpProfileFrag == null)
            mpProfileFrag = (ProfileFragment) getSupportFragmentManager().findFragmentByTag(PROFILE);
        if (mpProfileFrag == null) mpProfileFrag = ProfileFragment.newInstance(PROFILE, 10);

        return mpProfileFrag;
    }

    private MachineFragment getMachineFragment() {
        if (mpMachineFrag == null)
            mpMachineFrag = (MachineFragment) getSupportFragmentManager().findFragmentByTag(MACHINES);
        if (mpMachineFrag == null) mpMachineFrag = MachineFragment.newInstance(MACHINES, 7);
        return mpMachineFrag;
    }

    private AboutFragment getAboutFragment() {
        if (mpAboutFrag == null)
            mpAboutFrag = (AboutFragment) getSupportFragmentManager().findFragmentByTag(ABOUT);
        if (mpAboutFrag == null) mpAboutFrag = AboutFragment.newInstance(ABOUT, 6);

        return mpAboutFrag;
    }

    private BodyPartListFragment getBodyPartFragment() {
        if (mpBodyPartListFrag == null)
            mpBodyPartListFrag = (BodyPartListFragment) getSupportFragmentManager().findFragmentByTag(BODYTRACKING);
        if (mpBodyPartListFrag == null)
            mpBodyPartListFrag = BodyPartListFragment.newInstance(BODYTRACKING, 9);

        return mpBodyPartListFrag;
    }


    private ProgramListFragment getWorkoutListFragment() {
        if (mpWorkoutListFrag == null)
            mpWorkoutListFrag = (ProgramListFragment) getSupportFragmentManager().findFragmentByTag(WORKOUTS);
        if (mpWorkoutListFrag == null)
            mpWorkoutListFrag = ProgramListFragment.newInstance(WORKOUTS, 10);

        return mpWorkoutListFrag;
    }

    private SettingsFragment getSettingsFragment() {
        if (mpSettingFrag == null)
            mpSettingFrag = (SettingsFragment) getSupportFragmentManager().findFragmentByTag(SETTINGS);
        if (mpSettingFrag == null) mpSettingFrag = SettingsFragment.newInstance(SETTINGS, 8);

        return mpSettingFrag;
    }

    public Toolbar getActivityToolbar() {
        return top_toolbar;
    }

    public void showMP3Toolbar(boolean show) {
        Toolbar mp3toolbar = this.findViewById(R.id.musicToolbar);
        if (!show) {
            mp3toolbar.setVisibility(View.GONE);
        } else {
            mp3toolbar.setVisibility(View.VISIBLE);
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == REQUEST_CODE_INTRO) {
            if (resultCode == RESULT_OK) {
                initActivity();
                mIntro014Launched = true;
                initDEBUGdata();
                this.savePreferences();
            } else {
                // Cancelled the intro. You can then e.g. finish this activity too.
                finish();
            }
        } else if (resultCode == RESULT_OK && requestCode == IMPORT_DATABASE) {
            Uri file;
            if (data != null) {
                file = data.getData();
                CVSManager cvsMan = new CVSManager(getActivity().getBaseContext());
                InputStream inputStream;
                try {
                    inputStream = getContentResolver().openInputStream(file);
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                    inputStream = null;
                }

                if (cvsMan.importDatabase(inputStream, appViMo.getProfile().getValue())) {
                    KToast.successToast(getActivity(), getCurrentProfile().getName() + ": " + getActivity().getResources().getText(R.string.imported_successfully), Gravity.BOTTOM, KToast.LENGTH_LONG);
                } else {
                    KToast.errorToast(getActivity(), getCurrentProfile().getName() + ": " + getActivity().getResources().getText(R.string.import_failed), Gravity.BOTTOM, KToast.LENGTH_LONG);
                }
            }
        } else if (resultCode == RESULT_OK && requestCode == OPEN_MUSIC_FILE) {
            Uri uri;
            if (data != null) {
                uri = data.getData();
                // Return for MusicController Choose file
                musicController.OpenMusicFileIntentResult(uri);
                int takeFlags = data.getFlags();
                takeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
                        | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
                // Check for the freshest data.
                getContentResolver().takePersistableUriPermission(uri, takeFlags);
            }
        }
    }

    @Override
    public void onBackPressed() {
        int index = getActivity().getSupportFragmentManager().getBackStackEntryCount() - 1;
        if (index >= 0) { // Si on est dans une sous activité
            super.onBackPressed();
            getActivity().getSupportActionBar().show();
        } else { // Si on est la racine, avec il faut cliquer deux fois
            if (mBackPressed + TIME_INTERVAL > System.currentTimeMillis()) {
                super.onBackPressed();
                return;
            } else {
                Toast.makeText(getBaseContext(), R.string.pressBackAgain, Toast.LENGTH_SHORT).show();
            }

            mBackPressed = System.currentTimeMillis();
        }
    }

    public void initActivity() {
        // Initialisation des objets DB
        mDbProfils = new DAOProfile(this.getApplicationContext());

        // Pour la base de donnee profil, il faut toujours qu'il y ai au moins un profil
        mCurrentProfile = mDbProfils.getProfile(mCurrentProfilID);
        if (mCurrentProfile == null) { // au cas ou il y aurait un probleme de synchro
            try {
                List<Profile> lList = mDbProfils.getAllProfiles(mDbProfils.getReadableDatabase());
                mCurrentProfile = lList.get(0);
            } catch (IndexOutOfBoundsException e) {
                this.CreateNewProfile();
            }
        }

        if (mCurrentProfile != null) setCurrentProfile(mCurrentProfile.getName());

    }

    private class DrawerItemClickListener implements ListView.OnItemClickListener {
        @Override
        public void onItemClick(AdapterView parent, View view, int position, long id) {

            selectItem(position);

            // Insert the fragment by replacing any existing fragment
            switch (position) {
                case 0:
                    showFragment(PROFILE);
                    setTitle(getString(R.string.ProfileLabel));
                    break;
                case 1:
                    showFragment(FONTESPAGER);
                    setTitle(getResources().getText(R.string.menu_Workout));
                    break;
                case 2:
                    showFragment(MACHINES);
                    setTitle(getResources().getText(R.string.MachinesLabel));
                    break;
                case 3:
                    showFragment(WORKOUTS);
                    setTitle(getString(R.string.workout_list_menu_item));
                    break;
                case 4:
                    showFragment(WEIGHT);
                    setTitle(getResources().getText(R.string.weightMenuLabel));
                    break;
                case 5:
                    showFragment(BODYTRACKING);
                    setTitle(getResources().getText(R.string.bodytracking));
                    break;
                case 6:
                    showFragment(SETTINGS);
                    setTitle(getResources().getText(R.string.SettingLabel));
                    break;
                case 7:
                    showFragment(ABOUT);
                    setTitle(getResources().getText(R.string.AboutLabel));
                    break;
                default:
                    showFragment(FONTESPAGER);
                    setTitle(getResources().getText(R.string.FonteLabel));
            }
        }
    }
}

这是一个Android应用的主要活动(Activity)代码,它是一个健身跟踪应用的主界面。我将逐步解释这段代码的主要部分和功能:

  1. 导入库和包:
package com.easyfitness;

// 导入一些必要的Android库和自定义的类
  1. 定义MainActivity类,它继承自AppCompatActivity类:
public class MainActivity extends AppCompatActivity {
  1. 在类中声明各种成员变量,包括常量、UI元素、数据库操作对象等:
private static final int TIME_INTERVAL = 2000; // 两次返回键按下的时间间隔
public static String FONTESPAGER = "FontePager";
// ... 其他常量

private FontesPagerFragment mpFontesPagerFrag = null;
private WeightFragment mpWeightFrag = null;
// ... 其他Fragment对象

private DAOProfile mDbProfils = null;
private Profile mCurrentProfile = null;
private long mCurrentProfilID = -1;
private Toolbar top_toolbar = null;
// ... 其他UI元素和操作对象

private final PopupMenu.OnMenuItemClickListener onMenuItemClick = item -> {
    switch (item.getItemId()) {
        // 处理弹出菜单项的点击事件
    }
};
  1. 实现onCreate方法,用于Activity的初始化操作:
@Override
protected void onCreate(Bundle savedInstanceState) {
    // 从SharedPreferences获取设置,如夜间模式
    // ...

    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main); // 设置布局

    loadPreferences(); // 加载应用程序设置

    top_toolbar = this.findViewById(R.id.actionToolbar);
    setSupportActionBar(top_toolbar); // 设置工具栏

    // 创建或恢复各个Fragment
    if (savedInstanceState == null) {
        // 如果没有保存的实例状态,创建新的Fragment
    } else {
        // 恢复已存在的Fragment
    }

    // 初始化ViewModel和观察Profile数据变化
    appViMo = new ViewModelProvider(this).get(AppViMo.class);
    appViMo.getProfile().observe(this, profile -> {
        // 更新UI以反映Profile的变化
    });

    // 重命名旧数据库(如果需要)
    DatabaseHelper.renameOldDatabase(this);

    // 数据库迁移操作(如果需要)
    // ...

    if (savedInstanceState == null) {
        showFragment(FONTESPAGER); // 显示FontesPagerFragment
        currentFragmentName = FONTESPAGER;
    }

    // 设置导航抽屉和菜单项
    // ...
    
    // 初始化音乐控制器(如果有的话)
    // ...
    
    // 检查是否已启动介绍界面
    if (!mIntro014Launched) {
        Intent intent = new Intent(this, MainIntroActivity.class);
        startActivityForResult(intent, REQUEST_CODE_INTRO);
    }
}
  1. 实现onStart方法,用于Activity的启动操作:
@Override
protected void onStart() {
    super.onStart();

    // 初始化Activity和DEBUG数据(如果是DEBUG模式)
    // ...

    // 数据库迁移到Scoped存储(如果需要)
    // ...

    // 检查是否显示MP3工具栏(根据应用设置)
    // ...

    // 检查最后一次备份时间,并根据设置执行自动备份操作
    // ...
}
  1. 实现其他方法,用于处理各种操作,如数据库迁移、数据备份、菜单点击等。

这段代码的主要功能是创建一个健身跟踪应用的主界面,其中包括多个Fragment用于不同的功能模块,并支持导航抽屉、菜单操作、夜间模式切换等功能。这是一个较大的Android应用代码,包含了多个功能和操作,需要更多的上下文来理解其具体功能。如果有特定的问题或需要进一步了解特定部分的代码,请提出具体的问题。

//
//
//
//
//
//

三.项目源码

链接:https://pan.baidu.com/s/1nWmYs-h6mc3jAQY6UbjU7g
提取码:1569

创作不易,项目已加密,有偿(仅一杯奶茶钱…)
+v15135757306

或者下面的微信名片联系我~

  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值