Android安卓毕业设计实战项目(15)—Fast健身 APP【锻炼,计划列表,体重跟踪,身体追踪,导入导出健身记录】包括登陆注册页面+开机动画+个人信息页面(源码在文末🐕🐕🐕)
一.项目运行介绍
//
//
//
视频演示:https://www.bilibili.com/video/BV1Hh4y1Y7S2/
//
//
//
二.具体实现
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)。下面是对代码的详细解释:
-
包名和导入:
package com.easyfitness;
:这是 Java 包声明,表示这个类位于com.easyfitness
包中。- 导入必要的 Android 类和库,例如
android.app.Dialog
、android.os.Bundle
、androidx.fragment.app.DialogFragment
以及com.ikovac.timepickerwithseconds.MyTimePickerDialog
。
-
注释:
//@SuppressLint("ValidFragment")
:这是一个注释,用于告诉编译器忽略与此类相关的特定警告。在这种情况下,它似乎是关于ValidFragment
的,但是这个注释在代码中被注释掉了,所以不会生效。
-
类定义:
TimePickerDialogFragment
是一个继承自DialogFragment
的自定义类,表示时间选择对话框的片段。
-
类的成员变量:
Hours
、Minutes
和Seconds
是用于表示小时、分钟和秒钟的常量。这些常量的值都被初始化为0。onTimeSetListener
是一个MyTimePickerDialog.OnTimeSetListener
的接口对象,用于监听时间选择的事件。
-
newInstance
静态方法:- 这是一个静态工厂方法,用于创建
TimePickerDialogFragment
的新实例。 - 接受
MyTimePickerDialog.OnTimeSetListener
对象以及小时、分钟和秒钟作为参数。 - 在方法内部,创建了一个新的
TimePickerDialogFragment
实例,并为其设置onTimeSetListener
。 - 创建一个 Bundle 对象,将小时、分钟和秒钟作为数据放入 Bundle 中。
- 最后,将 Bundle 设置为
pickerFragment
的参数,并返回pickerFragment
。
- 这是一个静态工厂方法,用于创建
-
onCreateDialog
方法:- 该方法在创建对话框时被调用。
- 从参数
savedInstanceState
中获取保存的数据(如果有)。 - 从 Bundle 中获取小时、分钟和秒钟的值。
- 使用这些值创建一个新的
MyTimePickerDialog
对话框,并传入上下文、onTimeSetListener
、小时、分钟、秒钟以及一个布尔值来指示是否显示秒钟选择。 - 返回创建的对话框。
-
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)代码,它是一个健身跟踪应用的主界面。我将逐步解释这段代码的主要部分和功能:
- 导入库和包:
package com.easyfitness;
// 导入一些必要的Android库和自定义的类
- 定义MainActivity类,它继承自AppCompatActivity类:
public class MainActivity extends AppCompatActivity {
- 在类中声明各种成员变量,包括常量、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()) {
// 处理弹出菜单项的点击事件
}
};
- 实现
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);
}
}
- 实现
onStart
方法,用于Activity的启动操作:
@Override
protected void onStart() {
super.onStart();
// 初始化Activity和DEBUG数据(如果是DEBUG模式)
// ...
// 数据库迁移到Scoped存储(如果需要)
// ...
// 检查是否显示MP3工具栏(根据应用设置)
// ...
// 检查最后一次备份时间,并根据设置执行自动备份操作
// ...
}
- 实现其他方法,用于处理各种操作,如数据库迁移、数据备份、菜单点击等。
这段代码的主要功能是创建一个健身跟踪应用的主界面,其中包括多个Fragment用于不同的功能模块,并支持导航抽屉、菜单操作、夜间模式切换等功能。这是一个较大的Android应用代码,包含了多个功能和操作,需要更多的上下文来理解其具体功能。如果有特定的问题或需要进一步了解特定部分的代码,请提出具体的问题。
//
//
//
//
//
//
三.项目源码
链接:https://pan.baidu.com/s/1nWmYs-h6mc3jAQY6UbjU7g
提取码:1569
创作不易,项目已加密,有偿(仅一杯奶茶钱…)
+v15135757306
或者下面的微信名片联系我~