2654 lines
108 KiB
Java
2654 lines
108 KiB
Java
package sh.ftp.rocketninelabs.meditationassistant;
|
|
|
|
import android.annotation.SuppressLint;
|
|
import android.app.Activity;
|
|
import android.app.AlarmManager;
|
|
import android.app.AlertDialog;
|
|
import android.app.Application;
|
|
import android.app.DatePickerDialog;
|
|
import android.app.NotificationChannel;
|
|
import android.app.NotificationManager;
|
|
import android.app.PendingIntent;
|
|
import android.app.job.JobInfo;
|
|
import android.app.job.JobScheduler;
|
|
import android.appwidget.AppWidgetManager;
|
|
import android.content.ComponentName;
|
|
import android.content.Context;
|
|
import android.content.DialogInterface;
|
|
import android.content.Intent;
|
|
import android.content.IntentFilter;
|
|
import android.content.SharedPreferences;
|
|
import android.content.pm.PackageInfo;
|
|
import android.content.pm.PackageManager;
|
|
import android.media.AudioAttributes;
|
|
import android.media.AudioManager;
|
|
import android.media.MediaPlayer;
|
|
import android.net.Uri;
|
|
import android.os.AsyncTask;
|
|
import android.os.Build;
|
|
import android.os.Environment;
|
|
import android.os.Handler;
|
|
import android.os.Looper;
|
|
import android.os.Vibrator;
|
|
import android.preference.PreferenceManager;
|
|
import android.provider.Settings;
|
|
import android.util.Log;
|
|
import android.util.TypedValue;
|
|
import android.view.LayoutInflater;
|
|
import android.view.View;
|
|
import android.widget.Button;
|
|
import android.widget.DatePicker;
|
|
import android.widget.EditText;
|
|
import android.widget.Toast;
|
|
|
|
import androidx.annotation.RequiresApi;
|
|
import androidx.core.app.NotificationCompat;
|
|
import androidx.multidex.MultiDex;
|
|
|
|
import com.nononsenseapps.filepicker.FilePickerActivity;
|
|
import com.nononsenseapps.filepicker.Utils;
|
|
import com.opencsv.CSVReader;
|
|
import com.opencsv.CSVWriter;
|
|
|
|
import net.openid.appauth.AuthorizationRequest;
|
|
import net.openid.appauth.AuthorizationService;
|
|
import net.openid.appauth.AuthorizationServiceConfiguration;
|
|
import net.openid.appauth.ResponseTypeValues;
|
|
|
|
import org.apache.commons.lang3.ArrayUtils;
|
|
import org.apache.commons.lang3.StringUtils;
|
|
|
|
import java.io.BufferedReader;
|
|
import java.io.File;
|
|
import java.io.FileNotFoundException;
|
|
import java.io.FileOutputStream;
|
|
import java.io.IOException;
|
|
import java.io.InputStream;
|
|
import java.io.InputStreamReader;
|
|
import java.io.OutputStream;
|
|
import java.io.OutputStreamWriter;
|
|
import java.io.UnsupportedEncodingException;
|
|
import java.net.CookieHandler;
|
|
import java.net.CookieManager;
|
|
import java.net.URLEncoder;
|
|
import java.text.DateFormat;
|
|
import java.text.SimpleDateFormat;
|
|
import java.util.ArrayList;
|
|
import java.util.Arrays;
|
|
import java.util.Calendar;
|
|
import java.util.Date;
|
|
import java.util.GregorianCalendar;
|
|
import java.util.HashMap;
|
|
import java.util.List;
|
|
import java.util.Locale;
|
|
import java.util.Map;
|
|
import java.util.TimeZone;
|
|
import java.util.concurrent.TimeUnit;
|
|
import java.util.concurrent.locks.Lock;
|
|
import java.util.concurrent.locks.ReentrantLock;
|
|
import java.util.regex.Pattern;
|
|
|
|
public class MeditationAssistant extends Application {
|
|
public static String URL_ROCKETNINELABS = "https://rocketnine.space";
|
|
public static String URL_MEDINET = "https://medinet.rocketnine.space";
|
|
public static String URL_SOURCE = "https://code.rocketnine.space/tslocum/meditationassistant";
|
|
|
|
public static String ACTION_PRESET = "sh.ftp.rocketninelabs.meditationassistant.PRESET";
|
|
public static String ACTION_REMINDER = "sh.ftp.rocketninelabs.meditationassistant.DAILY_NOTIFICATION";
|
|
public static String ACTION_UPDATED = "sh.ftp.rocketninelabs.meditationassistant.DAILY_NOTIFICATION_UPDATED";
|
|
|
|
public static String LOG_TAG = "MeditationAssistant";
|
|
|
|
public static int CSV_COLUMN_COUNT = 5;
|
|
|
|
public static int dailyReminderJobID = 108;
|
|
public static int dailyReminderNotificationID = 1946; // Terence McKenna's year of birth
|
|
public static int sessionNotificationID = 1990;
|
|
public static int bellNotificationID = 1991;
|
|
|
|
public boolean ispaused = false;
|
|
public long pausestart = 0;
|
|
public long pausetime = 0;
|
|
public int previousRingerFilter = -1;
|
|
public int previousRingerMode = -1;
|
|
public String pendingNotificationAction = "";
|
|
public Boolean asktorate = false;
|
|
public Boolean asktodonate = false;
|
|
public DatabaseHandler db = null;
|
|
public PendingIntent reminderPendingIntent = null;
|
|
public String theme = null;
|
|
public String marketName = null;
|
|
public Integer previous_volume = null;
|
|
private String appVersion = null;
|
|
private long timeToStopMeditate = 0;
|
|
private long timeStartMeditate = 0;
|
|
public boolean hideConnectedMsg;
|
|
private MediNET medinet = null;
|
|
private boolean screenoff = false;
|
|
private boolean runnablestopped = true;
|
|
private boolean sessrunnablestopped = true;
|
|
private String medinetkey = null;
|
|
private String medinetprovider = null;
|
|
private boolean connectedonce = false;
|
|
private boolean editingduration = false;
|
|
private Boolean rememberduration = null;
|
|
private Integer meditationstreak = null;
|
|
private long meditationstreakexpires = 0;
|
|
public ArrayList<Integer> streaktime = new ArrayList<>();
|
|
public long streakbuffer = -1;
|
|
private long sessrunnablestarttime = 0;
|
|
private boolean sesswassignedout = false;
|
|
private long sessionduration = 0;
|
|
private Integer webview_scale = null;
|
|
private String timerMode = null;
|
|
private SharedPreferences prefs = null;
|
|
private AlarmManager am;
|
|
private WakeLocker wakeLocker = new WakeLocker();
|
|
private Lock wakeLockerLock = new ReentrantLock();
|
|
String pausedTimerHoursMinutes;
|
|
String pausedTimerSeconds;
|
|
private HashMap<String, MediaPlayer> mediaPlayers = new HashMap<String, MediaPlayer>();
|
|
|
|
private AlertDialog sessionDialog = null;
|
|
private int sessionDialogStartedYear = -1;
|
|
private int sessionDialogStartedMonth = -1;
|
|
private int sessionDialogStartedDay = -1;
|
|
private int sessionDialogStartedHour = -1;
|
|
private int sessionDialogStartedMinute = -1;
|
|
private int sessionDialogCompletedYear = -1;
|
|
private int sessionDialogCompletedMonth = -1;
|
|
private int sessionDialogCompletedDay = -1;
|
|
private int sessionDialogCompletedHour = -1;
|
|
private int sessionDialogCompletedMinute = -1;
|
|
private boolean sessionDialogLengthSetManually = false;
|
|
private int sessionDialogLengthHour = -1;
|
|
private int sessionDialogLengthMinute = -1;
|
|
private long sessionDialogUpdateSessionStarted = 0;
|
|
private Activity sessionDialogActivity = null;
|
|
private String sessionDialogCurrentOption = "";
|
|
private Button sessionDialogStartedDateButton = null;
|
|
private Button sessionDialogStartedTimeButton = null;
|
|
private Button sessionDialogCompletedDateButton = null;
|
|
private Button sessionDialogCompletedTimeButton = null;
|
|
private Button sessionDialogLengthButton = null;
|
|
private EditText sessionDialogMessage = null;
|
|
private DailyReminderReceiver dailyReminderReceiver = null;
|
|
private JobScheduler jobScheduler = null;
|
|
private DatePickerDialog.OnDateSetListener sessionDialogDateSetListener =
|
|
new DatePickerDialog.OnDateSetListener() {
|
|
@Override
|
|
public void onDateSet(DatePicker view, int year,
|
|
int monthOfYear, int dayOfMonth) {
|
|
if (sessionDialogCurrentOption.equals("started")) {
|
|
sessionDialogStartedYear = year;
|
|
sessionDialogStartedMonth = monthOfYear;
|
|
sessionDialogStartedDay = dayOfMonth;
|
|
|
|
if (sessionDialogCompletedYear == -1 || sessionDialogCompletedMonth == -1 || sessionDialogCompletedDay == -1) {
|
|
sessionDialogCompletedYear = sessionDialogStartedYear;
|
|
sessionDialogCompletedMonth = sessionDialogStartedMonth;
|
|
sessionDialogCompletedDay = sessionDialogStartedDay;
|
|
} else {
|
|
Calendar c_started = Calendar.getInstance();
|
|
c_started.set(Calendar.YEAR, sessionDialogStartedYear);
|
|
c_started.set(Calendar.MONTH, sessionDialogStartedMonth);
|
|
c_started.set(Calendar.DAY_OF_MONTH, sessionDialogStartedDay);
|
|
c_started.set(Calendar.HOUR_OF_DAY, 0);
|
|
c_started.set(Calendar.MINUTE, 0);
|
|
c_started.set(Calendar.SECOND, 0);
|
|
c_started.set(Calendar.MILLISECOND, 0);
|
|
|
|
Calendar c_completed = Calendar.getInstance();
|
|
c_completed.set(Calendar.YEAR, sessionDialogCompletedYear);
|
|
c_completed.set(Calendar.MONTH, sessionDialogCompletedMonth);
|
|
c_completed.set(Calendar.DAY_OF_MONTH, sessionDialogCompletedDay);
|
|
c_completed.set(Calendar.HOUR_OF_DAY, 0);
|
|
c_completed.set(Calendar.MINUTE, 0);
|
|
c_completed.set(Calendar.SECOND, 0);
|
|
c_completed.set(Calendar.MILLISECOND, 0);
|
|
|
|
if (c_started.getTimeInMillis() > c_completed.getTimeInMillis()) {
|
|
sessionDialogCompletedYear = sessionDialogStartedYear;
|
|
sessionDialogCompletedMonth = sessionDialogStartedMonth;
|
|
sessionDialogCompletedDay = sessionDialogStartedDay;
|
|
}
|
|
}
|
|
} else {
|
|
sessionDialogCompletedYear = year;
|
|
sessionDialogCompletedMonth = monthOfYear;
|
|
sessionDialogCompletedDay = dayOfMonth;
|
|
}
|
|
|
|
updateSessionDialog();
|
|
}
|
|
};
|
|
private TimePickerDialog.OnTimeSetListener sessionDialogTimeSetListener =
|
|
new TimePickerDialog.OnTimeSetListener() {
|
|
@Override
|
|
public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
|
|
if (sessionDialogCurrentOption.equals("started")) {
|
|
sessionDialogStartedHour = hourOfDay;
|
|
sessionDialogStartedMinute = minute;
|
|
|
|
if (sessionDialogCompletedHour == -1 && sessionDialogCompletedMinute == -1) {
|
|
sessionDialogCompletedHour = sessionDialogStartedHour;
|
|
sessionDialogCompletedMinute = sessionDialogStartedMinute;
|
|
}
|
|
} else if (sessionDialogCurrentOption.equals("length")) {
|
|
if (hourOfDay > 0 || minute > 0) {
|
|
sessionDialogLengthSetManually = true;
|
|
sessionDialogLengthHour = hourOfDay;
|
|
sessionDialogLengthMinute = minute;
|
|
} else {
|
|
sessionDialogLengthSetManually = false;
|
|
sessionDialogLengthHour = -1;
|
|
sessionDialogLengthMinute = -1;
|
|
}
|
|
} else {
|
|
sessionDialogCompletedHour = hourOfDay;
|
|
sessionDialogCompletedMinute = minute;
|
|
}
|
|
|
|
updateSessionDialog();
|
|
}
|
|
};
|
|
|
|
SharedPreferences.OnSharedPreferenceChangeListener sharedPrefslistener = new SharedPreferences.OnSharedPreferenceChangeListener() {
|
|
public void onSharedPreferenceChanged(SharedPreferences newprefs, String key) {
|
|
if (key.equals("pref_meditationstreakbuffer")) {
|
|
streakbuffer = -1;
|
|
streaktime = new ArrayList<>();
|
|
}
|
|
}
|
|
};
|
|
|
|
public static void setAlphaCompat(View view, float alpha) {
|
|
view.setAlpha(alpha);
|
|
}
|
|
|
|
public int dpToPixels(float dp) {
|
|
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp,
|
|
getResources().getDisplayMetrics());
|
|
}
|
|
|
|
public int pixelsToDP(float px) {
|
|
return (int) (px * getResources().getDisplayMetrics().density + 0.5f);
|
|
}
|
|
|
|
public String getMarketName() {
|
|
if (marketName == null) {
|
|
String osname = System.getProperty("os.name");
|
|
if (osname != null && osname.equals("qnx")) {
|
|
marketName = "bb"; // BlackBerry
|
|
} else if (BuildConfig.FLAVOR.equals("opensource")) {
|
|
marketName = "fdroid";
|
|
} else { // To be uncommented based upon target market
|
|
marketName = "google";
|
|
//marketName = "amazon";
|
|
//marketName = "getjar";
|
|
//marketName = "slideme";
|
|
}
|
|
}
|
|
|
|
return marketName;
|
|
}
|
|
|
|
public String capitalizeFirst(String string) {
|
|
if (string == null) {
|
|
return "";
|
|
}
|
|
|
|
return string.substring(0, 1).toUpperCase() + string.substring(1).toLowerCase();
|
|
}
|
|
|
|
public int audioStream() {
|
|
switch (getPrefs().getString("pref_audio_stream", "")) {
|
|
case "media":
|
|
return AudioManager.STREAM_MUSIC;
|
|
case "ringtone":
|
|
return AudioManager.STREAM_RING;
|
|
case "notification":
|
|
return AudioManager.STREAM_NOTIFICATION;
|
|
default:
|
|
return AudioManager.STREAM_ALARM;
|
|
}
|
|
}
|
|
|
|
public int audioUsage() {
|
|
switch (getPrefs().getString("pref_audio_stream", "")) {
|
|
case "media":
|
|
return AudioAttributes.USAGE_MEDIA;
|
|
case "ringtone":
|
|
return AudioAttributes.USAGE_NOTIFICATION_RINGTONE;
|
|
case "notification":
|
|
return AudioAttributes.USAGE_NOTIFICATION;
|
|
default:
|
|
return AudioAttributes.USAGE_ALARM;
|
|
}
|
|
}
|
|
|
|
public void restoreVolume() {
|
|
if (previous_volume != null) {
|
|
try {
|
|
AudioManager mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
|
|
mAudioManager.setStreamVolume(audioStream(), previous_volume, 0);
|
|
} catch (java.lang.SecurityException e) {
|
|
// Do nothing
|
|
}
|
|
previous_volume = null;
|
|
}
|
|
}
|
|
|
|
public void connectOnce() {
|
|
if (!connectedonce) {
|
|
getMediNET().connect();
|
|
connectedonce = true;
|
|
}
|
|
}
|
|
|
|
public void rateApp() {
|
|
if (getMarketName().equals("bb")) {
|
|
startActivity(Intent.createChooser(new Intent(Intent.ACTION_VIEW, Uri.parse("https://appworld.blackberry.com/webstore/content/" + (BuildConfig.FLAVOR.equals("free") ? "59939924" : "59939922") + "/")), getString(R.string.openWith)).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
|
|
} else if (getMarketName().equals("google")) {
|
|
startActivity(Intent.createChooser(new Intent(Intent.ACTION_VIEW, Uri.parse("http://play.google.com/store/apps/details?id=" + getApplicationContext().getPackageName())), getString(R.string.openWith)).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
|
|
} else if (getMarketName().equals("amazon")) {
|
|
startActivity(Intent.createChooser(new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.amazon.com/gp/mas/dl/android?p=" + getApplicationContext().getPackageName())), getString(R.string.openWith)).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
|
|
}
|
|
}
|
|
|
|
public AlarmManager getAlarmManager() {
|
|
if (am == null) {
|
|
am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
|
|
}
|
|
|
|
return am;
|
|
}
|
|
|
|
public void setAlarm(boolean allowAlarmClock, long triggerAtMillis, PendingIntent pendingIntent) {
|
|
if (Build.VERSION.SDK_INT >= 21 && allowAlarmClock) {
|
|
getAlarmManager().setAlarmClock(new AlarmManager.AlarmClockInfo(triggerAtMillis, PendingIntent.getActivity(this, 0, new Intent(getApplicationContext(), MainActivity.class), PendingIntent.FLAG_UPDATE_CURRENT | MeditationAssistant.extraPendingIntentFlags())), pendingIntent);
|
|
} else if (Build.VERSION.SDK_INT >= 19) {
|
|
getAlarmManager().setExact(AlarmManager.RTC_WAKEUP, triggerAtMillis, pendingIntent);
|
|
} else {
|
|
getAlarmManager().set(AlarmManager.RTC_WAKEUP, triggerAtMillis, pendingIntent);
|
|
}
|
|
}
|
|
|
|
public void setNotificationControl() {
|
|
previousRingerFilter = getRingerFilter();
|
|
AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
|
|
previousRingerMode = audioManager.getRingerMode();
|
|
|
|
if ((getPrefs().getString("pref_notificationcontrol", "").equals("priority") || getPrefs().getString("pref_notificationcontrol", "").equals("alarms")) && Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
|
if (!haveNotificationPermission()) {
|
|
return;
|
|
}
|
|
|
|
NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
|
|
mNotificationManager.setInterruptionFilter(getPrefs().getString("pref_notificationcontrol", "").equals("priority") ? NotificationManager.INTERRUPTION_FILTER_PRIORITY : NotificationManager.INTERRUPTION_FILTER_ALARMS);
|
|
} else if (getPrefs().getString("pref_notificationcontrol", "").equals("vibrate")) {
|
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
|
NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
|
|
int currentfilter = mNotificationManager.getCurrentInterruptionFilter();
|
|
if (!haveNotificationPermission() && currentfilter != 0 && currentfilter != 1) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
audioManager.setRingerMode(AudioManager.RINGER_MODE_VIBRATE);
|
|
}
|
|
}
|
|
|
|
@SuppressLint("WrongConstant")
|
|
public void unsetNotificationControl() {
|
|
if (previousRingerFilter > 0 && (getPrefs().getString("pref_notificationcontrol", "").equals("priority") || getPrefs().getString("pref_notificationcontrol", "").equals("alarms")) && Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
|
if (!haveNotificationPermission()) {
|
|
return;
|
|
}
|
|
|
|
NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
|
|
mNotificationManager.setInterruptionFilter(previousRingerFilter);
|
|
}
|
|
|
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
|
NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
|
|
int currentfilter = mNotificationManager.getCurrentInterruptionFilter();
|
|
if (!haveNotificationPermission() && currentfilter != 0 && currentfilter != 1) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
|
|
if (previousRingerMode >= 0 && getPrefs().getString("pref_notificationcontrol", "").equals("vibrate")) {
|
|
audioManager.setRingerMode(previousRingerMode);
|
|
}
|
|
|
|
previousRingerFilter = -1;
|
|
previousRingerMode = -1;
|
|
}
|
|
|
|
public int getRingerFilter() {
|
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
|
if (!haveNotificationPermission()) {
|
|
return 0;
|
|
}
|
|
|
|
NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
|
|
return mNotificationManager.getCurrentInterruptionFilter();
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
public boolean getEditingDuration() {
|
|
return editingduration;
|
|
}
|
|
|
|
public void setEditingDuration(boolean bool) {
|
|
editingduration = bool;
|
|
}
|
|
|
|
public int getMATextColor(Boolean enabled) {
|
|
if (enabled) {
|
|
if (getMAThemeIsLight()) {
|
|
return android.R.color.primary_text_light;
|
|
} else {
|
|
return android.R.color.primary_text_dark;
|
|
}
|
|
} else {
|
|
if (getMAThemeIsLight()) {
|
|
return android.R.color.secondary_text_light;
|
|
} else {
|
|
return android.R.color.secondary_text_dark;
|
|
}
|
|
}
|
|
}
|
|
|
|
public int getMATheme() {
|
|
return getMATheme(false);
|
|
}
|
|
|
|
public int getMATheme(Boolean dialogue) {
|
|
if (theme == null) {
|
|
theme = getPrefs().getString("pref_theme", "dark");
|
|
}
|
|
|
|
if (theme.equals("buddhism")) {
|
|
return dialogue ? R.style.BuddhismDialogue : R.style.Buddhism;
|
|
}
|
|
|
|
if (dialogue) {
|
|
if (theme.equals("dark")) {
|
|
return R.style.MeditationDarkDialogTheme;
|
|
} else if (theme.equals("black")) {
|
|
return R.style.MeditationBlackDialogTheme;
|
|
} else {
|
|
return R.style.MeditationLightDialogTheme;
|
|
}
|
|
} else {
|
|
if (theme.equals("light")) {
|
|
return R.style.MeditationLightTheme;
|
|
} else if (theme.equals("lightdark")) {
|
|
return R.style.MeditationLightDarkTheme;
|
|
} else if (theme.equals("black")) {
|
|
return R.style.MeditationBlackTheme;
|
|
} else {
|
|
return R.style.MeditationDarkTheme;
|
|
}
|
|
}
|
|
}
|
|
|
|
public String getMAThemeString() {
|
|
if (theme == null) {
|
|
theme = getPrefs().getString("pref_theme", "dark");
|
|
}
|
|
return theme;
|
|
}
|
|
|
|
public boolean getMAThemeIsLight() {
|
|
String currentTheme = getMAThemeString();
|
|
switch (currentTheme) {
|
|
case "buddhism":
|
|
case "dark":
|
|
case "black":
|
|
return false;
|
|
default:
|
|
return true;
|
|
}
|
|
}
|
|
|
|
public MediNET getMediNET() {
|
|
if (medinet == null) {
|
|
//
|
|
}
|
|
return medinet;
|
|
}
|
|
|
|
public void setMediNET(MediNET medi) {
|
|
medinet = medi;
|
|
Log.d("MeditationAssistant", "Session: " + medinet);
|
|
}
|
|
|
|
public String getMediNETKey() {
|
|
Log.d("MeditationAssistant", "getMediNETKey() - medinetkey: " + medinetkey + " prefs: " + getPrefs().getString("key", ""));
|
|
if (medinetkey == null) {
|
|
medinetkey = getPrefs().getString("key", "");
|
|
}
|
|
return medinetkey;
|
|
}
|
|
|
|
public String getMediNETProvider() {
|
|
if (medinetprovider == null) {
|
|
medinetprovider = getPrefs().getString("provider", "");
|
|
}
|
|
if (medinetprovider.trim().equals("")) {
|
|
return "Unknown";
|
|
}
|
|
return medinetprovider;
|
|
}
|
|
|
|
public void cacheSound(int soundresource, String soundpath) {
|
|
String cacheKey = soundpath;
|
|
if (cacheKey.equals("")) {
|
|
cacheKey = Integer.toString(soundresource);
|
|
}
|
|
if (mediaPlayers.containsKey(cacheKey)) {
|
|
return;
|
|
}
|
|
|
|
MediaPlayer mp = new MediaPlayer();
|
|
|
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
|
AudioAttributes audioAttributes = new AudioAttributes.Builder()
|
|
.setUsage(audioUsage())
|
|
.build();
|
|
mp.setAudioAttributes(audioAttributes);
|
|
} else {
|
|
mp.setAudioStreamType(audioStream());
|
|
}
|
|
try {
|
|
if (!soundpath.equals("")) {
|
|
mp.setDataSource(getApplicationContext(), Uri.parse(soundpath));
|
|
} else {
|
|
mp.setDataSource(getApplicationContext(), Uri.parse("android.resource://" + getPackageName() + "/" + soundresource));
|
|
}
|
|
|
|
mp.prepareAsync();
|
|
} catch (Exception e) {
|
|
e.printStackTrace();
|
|
|
|
String soundLabel = soundpath;
|
|
if (soundLabel.equals("")) {
|
|
soundLabel = String.valueOf(soundresource);
|
|
}
|
|
Log.e("MeditationAssistant", "Failed to load sound: " + soundLabel);
|
|
return;
|
|
}
|
|
|
|
mediaPlayers.put(cacheKey, mp);
|
|
}
|
|
|
|
public void cacheSessionSounds() {
|
|
String label;
|
|
for (int i = 0; i < 4; i++) {
|
|
switch (i) {
|
|
case 0:
|
|
label = "start";
|
|
break;
|
|
case 1:
|
|
label = "interval";
|
|
break;
|
|
case 2:
|
|
label = "finish";
|
|
break;
|
|
case 3:
|
|
label = "bell";
|
|
break;
|
|
default:
|
|
return;
|
|
}
|
|
|
|
SharedPreferences prefs = getPrefs();
|
|
String soundPath = prefs.getString("pref_meditation_sound_" + label, "");
|
|
if (!soundPath.equals("none")) {
|
|
if (soundPath.equals("custom")) {
|
|
cacheSound(0, getFilesDir().getAbsolutePath() + "/" + prefs.getString("pref_meditation_sound_" + label + "_custom", ""));
|
|
} else {
|
|
cacheSound(MeditationSounds.getMeditationSound(soundPath), "");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public void clearSoundCache() {
|
|
for (MediaPlayer mp : mediaPlayers.values()) {
|
|
try {
|
|
mp.stop();
|
|
} catch (Exception e) {
|
|
// Do nothing
|
|
}
|
|
try {
|
|
mp.release();
|
|
} catch (Exception e) {
|
|
// Do nothing
|
|
}
|
|
}
|
|
|
|
mediaPlayers.clear();
|
|
}
|
|
|
|
public void playSound(int soundresource, String soundpath, boolean restoreVolume) {
|
|
String wakeLockID = acquireWakeLock(false);
|
|
|
|
String cacheKey = soundpath;
|
|
if (cacheKey.equals("")) {
|
|
cacheKey = Integer.toString(soundresource);
|
|
}
|
|
if (!mediaPlayers.containsKey(cacheKey)) {
|
|
cacheSound(soundresource, soundpath);
|
|
}
|
|
if (!mediaPlayers.containsKey(cacheKey)) {
|
|
Log.d("MeditationAssistant", "Failed to cache sound");
|
|
return; // Failed to load sound
|
|
}
|
|
MediaPlayer mp = mediaPlayers.get(cacheKey);
|
|
|
|
if (mp.isPlaying()) {
|
|
Log.d("MeditationAssistant", "Failed to play sound: already playing");
|
|
releaseWakeLock(wakeLockID);
|
|
return;
|
|
}
|
|
|
|
mp.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
|
|
@Override
|
|
public void onCompletion(MediaPlayer mp) {
|
|
if (restoreVolume) {
|
|
MeditationAssistant.this.restoreVolume();
|
|
}
|
|
|
|
try {
|
|
mp.stop();
|
|
} catch (Exception e) {
|
|
// Do nothing
|
|
}
|
|
try {
|
|
mp.prepareAsync();
|
|
} catch (Exception e) {
|
|
// Do nothing
|
|
}
|
|
|
|
MeditationAssistant.this.releaseWakeLock(wakeLockID);
|
|
}
|
|
});
|
|
|
|
try {
|
|
mp.start();
|
|
} catch (Exception e) {
|
|
e.printStackTrace();
|
|
|
|
if (restoreVolume) {
|
|
restoreVolume();
|
|
}
|
|
|
|
releaseWakeLock(wakeLockID);
|
|
}
|
|
}
|
|
|
|
public void notifySession(int phase, boolean skipVibration, boolean restoreVolume) {
|
|
String label;
|
|
switch (phase) {
|
|
case 0:
|
|
label = "start";
|
|
break;
|
|
case 1:
|
|
label = "interval";
|
|
break;
|
|
case 2:
|
|
label = "finish";
|
|
break;
|
|
case 3:
|
|
label = "bell";
|
|
break;
|
|
default:
|
|
return;
|
|
}
|
|
SharedPreferences prefs = getPrefs();
|
|
|
|
// Play sound
|
|
String soundPath = prefs.getString("pref_meditation_sound_" + label, "");
|
|
if (!soundPath.equals("none")) {
|
|
if (soundPath.equals("custom")) {
|
|
playSound(0, getFilesDir().getAbsolutePath() + "/" + prefs.getString("pref_meditation_sound_" + label + "_custom", ""), restoreVolume);
|
|
} else {
|
|
playSound(MeditationSounds.getMeditationSound(soundPath), "", restoreVolume);
|
|
}
|
|
}
|
|
|
|
// Vibrate device
|
|
if (!skipVibration) {
|
|
String vibration = prefs.getString("pref_meditation_vibrate_" + label, "");
|
|
if (!vibration.isEmpty()) {
|
|
if (vibration.equals("custom")) {
|
|
vibrateDevice(prefs.getString("pref_meditation_vibrate_" + label + "_custom", ""));
|
|
} else {
|
|
vibrateDevice(vibration);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public void startAuth(Context context, boolean showToast) {
|
|
String trace = Arrays.toString(Thread.currentThread().getStackTrace());
|
|
Log.d("MeditationAssistant", "startAuth called, current stack trace: " + trace);
|
|
hideConnectedMsg = !showToast;
|
|
|
|
if (showToast) {
|
|
shortToast(getString(R.string.signInToMediNET));
|
|
}
|
|
|
|
AsyncTask.execute(() -> {
|
|
AuthorizationServiceConfiguration serviceConfiguration = new AuthorizationServiceConfiguration(
|
|
Uri.parse("https://accounts.google.com/o/oauth2/v2/auth") /* auth endpoint */,
|
|
Uri.parse("https://www.googleapis.com/oauth2/v4/token") /* token endpoint */
|
|
);
|
|
|
|
String clientId = BuildConfig.GOOGLEOAUTHKEY;
|
|
Uri redirectUri = Uri.parse(BuildConfig.APPLICATION_ID + ":/oauth");
|
|
AuthorizationRequest.Builder builder = new AuthorizationRequest.Builder(
|
|
serviceConfiguration,
|
|
clientId,
|
|
ResponseTypeValues.CODE,
|
|
redirectUri
|
|
);
|
|
builder.setScopes("profile");
|
|
AuthorizationRequest request = builder.build();
|
|
|
|
AuthorizationService authorizationService = new AuthorizationService(context);
|
|
|
|
PendingIntent authIntent = PendingIntent.getActivity(MeditationAssistant.this, 0, new Intent(context, AuthResultActivity.class).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK), PendingIntent.FLAG_CANCEL_CURRENT | MeditationAssistant.extraPendingIntentFlags());
|
|
|
|
authorizationService.performAuthorizationRequest(
|
|
request,
|
|
authIntent,
|
|
authIntent);
|
|
});
|
|
}
|
|
|
|
public ArrayList<Integer> getStreakBufferTime() {
|
|
if (streaktime.isEmpty()) {
|
|
String[] bufferSplit = getPrefs().getString("pref_meditationstreakbuffer", "4:00").split(":");
|
|
streaktime.add(Integer.valueOf(bufferSplit[0]));
|
|
streaktime.add(Integer.valueOf(bufferSplit[1]));
|
|
}
|
|
|
|
return streaktime;
|
|
}
|
|
|
|
public long getStreakBufferSeconds() {
|
|
if (streakbuffer < 0) {
|
|
ArrayList<Integer> streakbuffertime = getStreakBufferTime();
|
|
streakbuffer = (streakbuffertime.get(0) * 3600) + (streakbuffertime.get(1) * 60);
|
|
}
|
|
|
|
return streakbuffer;
|
|
}
|
|
|
|
public void recalculateMeditationStreak(Activity activity) {
|
|
Calendar dayCalendar = new GregorianCalendar();
|
|
Integer daysback = 0;
|
|
Integer recalculatedstreak = 0;
|
|
Boolean sessionexiststoday = false;
|
|
|
|
while (true) {
|
|
Log.d("MeditationAssistant", "Checking (" + daysback + ") " + dayCalendar);
|
|
if (db.numSessionsByDate(dayCalendar) > 0) {
|
|
recalculatedstreak++;
|
|
|
|
if (daysback == 0) {
|
|
sessionexiststoday = true;
|
|
}
|
|
} else if (daysback > 0) {
|
|
break;
|
|
}
|
|
|
|
daysback++;
|
|
dayCalendar.add(Calendar.DATE, -1);
|
|
}
|
|
|
|
Long currentStreak = getMeditationStreak().get(0);
|
|
if (currentStreak < recalculatedstreak) {
|
|
setMeditationStreak(recalculatedstreak, sessionexiststoday ? getStreakExpiresTwoDaysTimestamp() : getStreakExpiresOneDayTimestamp());
|
|
} else if (currentStreak > recalculatedstreak) {
|
|
showStreakDifferenceWarning(currentStreak.intValue(), recalculatedstreak, sessionexiststoday, activity);
|
|
}
|
|
}
|
|
|
|
public ArrayList<Long> getMeditationStreak() {
|
|
long timestamp = System.currentTimeMillis() / 1000;
|
|
|
|
if (meditationstreak == null || meditationstreakexpires < 1) {
|
|
meditationstreak = getPrefs().getInt("meditationstreak", 0);
|
|
meditationstreakexpires = getPrefs().getLong("meditationstreakexpires", 0);
|
|
}
|
|
|
|
if (meditationstreakexpires > 0 && meditationstreakexpires < timestamp) {
|
|
// Streak window has passed
|
|
meditationstreak = 0;
|
|
meditationstreakexpires = 0;
|
|
|
|
getPrefs().edit().putInt("meditationstreak", meditationstreak)
|
|
.putLong("meditationstreakexpires", meditationstreakexpires)
|
|
.putBoolean("meditationstreakwarningshown", false).apply();
|
|
}
|
|
|
|
ArrayList<Long> streak = new ArrayList<>();
|
|
streak.add((long) meditationstreak);
|
|
streak.add(meditationstreakexpires);
|
|
return streak;
|
|
}
|
|
|
|
public void addMeditationStreak() {
|
|
addMeditationStreak(true);
|
|
}
|
|
|
|
public void addMeditationStreak(Boolean twodays) {
|
|
ArrayList<Long> streak = getMeditationStreak();
|
|
Long streakday = streak.get(0);
|
|
Long streakexpires = streak.get(1);
|
|
Log.d("MeditationAssistant", "addMeditationStreak() - Streak: " + streakday + " Expires: in " + (streakexpires - getTimestamp()) + " seconds");
|
|
if (streakday == 0 || streakexpires - getTimestamp() < 86400) {
|
|
streakday++;
|
|
|
|
if (twodays) {
|
|
setMeditationStreak(streakday.intValue(),
|
|
getStreakExpiresTwoDaysTimestamp());
|
|
} else {
|
|
setMeditationStreak(streakday.intValue(),
|
|
getStreakExpiresOneDayTimestamp());
|
|
}
|
|
}
|
|
}
|
|
|
|
public int getLongestMeditationStreak() {
|
|
return getPrefs().getInt("longeststreak", 0);
|
|
}
|
|
|
|
public void setLongestMeditationStreak(int ms) {
|
|
getPrefs().edit().putInt("longeststreak", ms).apply();
|
|
}
|
|
|
|
public long getStreakExpiresOneDayTimestamp() {
|
|
Calendar c_midnight_oneday = new GregorianCalendar();
|
|
c_midnight_oneday.setTime(new Date());
|
|
c_midnight_oneday.set(Calendar.HOUR_OF_DAY, 0);
|
|
c_midnight_oneday.set(Calendar.MINUTE, 0);
|
|
c_midnight_oneday.set(Calendar.SECOND, 0);
|
|
c_midnight_oneday.set(Calendar.MILLISECOND, 0);
|
|
c_midnight_oneday.add(Calendar.DATE, 1); // One day
|
|
|
|
return (c_midnight_oneday.getTimeInMillis() / 1000) + getStreakBufferSeconds();
|
|
}
|
|
|
|
public long getStreakExpiresTwoDaysTimestamp() {
|
|
Calendar c_midnight_twodays = new GregorianCalendar();
|
|
c_midnight_twodays.setTime(new Date());
|
|
c_midnight_twodays.set(Calendar.HOUR_OF_DAY, 0);
|
|
c_midnight_twodays.set(Calendar.MINUTE, 0);
|
|
c_midnight_twodays.set(Calendar.SECOND, 0);
|
|
c_midnight_twodays.set(Calendar.MILLISECOND, 0);
|
|
c_midnight_twodays.add(Calendar.DATE, 2); // Two days
|
|
|
|
return (c_midnight_twodays.getTimeInMillis() / 1000) + getStreakBufferSeconds();
|
|
}
|
|
|
|
public void notifySessionsUpdated() {
|
|
Log.d("MeditationAssistant", "Sending session update notification");
|
|
getPrefs().edit().putLong("sessionsupdate", getTimestamp()).apply();
|
|
}
|
|
|
|
public void notifyMediNETUpdated() {
|
|
Log.d("MeditationAssistant", "Sending MediNET update notification");
|
|
getPrefs().edit().putLong("medinetupdate", getTimestamp()).apply();
|
|
}
|
|
|
|
public Integer timePreferenceValueToSeconds(String timePreferenceValue, String defaultValue) {
|
|
try {
|
|
String[] timeValueSplit = ((timePreferenceValue != null && timePreferenceValue != "") ? timePreferenceValue : defaultValue).split(":");
|
|
return (Integer.valueOf(timeValueSplit[0]) * 60) + Integer.valueOf(timeValueSplit[1]);
|
|
} catch (Exception e) {
|
|
e.printStackTrace();
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
public ArrayList<String> formatDuration(String duration) {
|
|
if (!duration.equals("")) {
|
|
String[] duration_separated = duration.split(":");
|
|
String newHours = "-1";
|
|
String newMinutes = "-1";
|
|
|
|
if (duration_separated.length > 1) {
|
|
if (!duration_separated[0].trim().equals("")) {
|
|
try {
|
|
newHours = String.valueOf(Integer
|
|
.valueOf(duration_separated[0]));
|
|
} catch (Exception e) {
|
|
e.printStackTrace();
|
|
}
|
|
} else {
|
|
newHours = "0";
|
|
}
|
|
if (!duration_separated[1].trim().equals("")) {
|
|
try {
|
|
newMinutes = String.valueOf(Integer
|
|
.valueOf(duration_separated[1]));
|
|
} catch (Exception e) {
|
|
e.printStackTrace();
|
|
}
|
|
} else {
|
|
newMinutes = "0";
|
|
}
|
|
} else {
|
|
try {
|
|
newMinutes = String.valueOf(Integer.valueOf(duration));
|
|
newHours = "0";
|
|
} catch (Exception e) {
|
|
e.printStackTrace();
|
|
}
|
|
}
|
|
|
|
if (Integer.valueOf(newMinutes) >= 60) {
|
|
newHours = String.format("%d",
|
|
(int) (Integer.valueOf(newHours) + Math.floor(Integer
|
|
.valueOf(newMinutes) / 60))
|
|
);
|
|
newMinutes = String.format("%02d",
|
|
Integer.valueOf(newMinutes) % 60);
|
|
}
|
|
|
|
if (!newHours.equals("-1") && !newMinutes.equals("-1")
|
|
&& !(newHours.equals("0") && newMinutes.equals("0"))) {
|
|
ArrayList<String> formatted_duration = new ArrayList<>();
|
|
formatted_duration.add(newHours);
|
|
formatted_duration.add(String.format("%02d",
|
|
Integer.valueOf(newMinutes)));
|
|
|
|
return formatted_duration;
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
public ArrayList<String> formatDurationEndAt(String duration) {
|
|
if (!duration.equals("")) {
|
|
String[] duration_separated = duration.split(":");
|
|
String newHours = "-1";
|
|
String newMinutes = "-1";
|
|
Boolean shorthand = false;
|
|
|
|
if (duration_separated.length > 1) {
|
|
if (!duration_separated[0].trim().equals("")) {
|
|
try {
|
|
newHours = String.valueOf(Integer
|
|
.valueOf(duration_separated[0]));
|
|
} catch (Exception e) {
|
|
e.printStackTrace();
|
|
}
|
|
} else {
|
|
newHours = "0";
|
|
}
|
|
if (!duration_separated[1].trim().equals("")) {
|
|
try {
|
|
newMinutes = String.valueOf(Integer
|
|
.valueOf(duration_separated[1]));
|
|
if (duration_separated[1].trim().length() < 2) {
|
|
shorthand = true;
|
|
}
|
|
} catch (Exception e) {
|
|
e.printStackTrace();
|
|
}
|
|
} else {
|
|
newMinutes = "0";
|
|
}
|
|
} else {
|
|
try {
|
|
newHours = String.valueOf(Integer.valueOf(duration));
|
|
newMinutes = "0";
|
|
} catch (Exception e) {
|
|
e.printStackTrace();
|
|
}
|
|
}
|
|
|
|
Log.d("MeditationAssistant", "Formatted end at duration newMinutes: " + newMinutes);
|
|
if (shorthand && Integer.valueOf(newMinutes) > 0 && Integer.valueOf(newMinutes) <= 5) { // shorthand 3 -> 30, 4 -> 40...
|
|
newMinutes = String.format("%02d",
|
|
Integer.valueOf(newMinutes) * 10);
|
|
} else if (Integer.valueOf(newMinutes) >= 60) {
|
|
newHours = String.format("%d",
|
|
(int) (Integer.valueOf(newHours) + Math.floor(Integer
|
|
.valueOf(newMinutes) / 60))
|
|
);
|
|
newMinutes = String.format("%02d",
|
|
Integer.valueOf(newMinutes) % 60);
|
|
}
|
|
|
|
if (Integer.valueOf(newHours) == 0 || Integer.valueOf(newHours) > 24) {
|
|
return null; // Invalid hour for time
|
|
} else if (Integer.valueOf(newHours) > 12) {
|
|
newHours = String.valueOf(Integer.valueOf(newHours) - 12); // Subtract 12 hours if 24 hour time was provided
|
|
}
|
|
|
|
if (!newHours.equals("-1") && !newMinutes.equals("-1")
|
|
&& !(newHours.equals("0") && newMinutes.equals("0"))) {
|
|
ArrayList<String> formatted_duration = new ArrayList<>();
|
|
formatted_duration.add(newHours);
|
|
formatted_duration.add(String.format("%02d",
|
|
Integer.valueOf(newMinutes)));
|
|
|
|
return formatted_duration;
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
public SharedPreferences getPrefs() {
|
|
if (prefs == null) {
|
|
prefs = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
|
|
}
|
|
return prefs;
|
|
}
|
|
|
|
public boolean getRememberDuration() {
|
|
if (rememberduration == null) {
|
|
rememberduration = getPrefs().getBoolean("pref_rememberlasttimer", true);
|
|
}
|
|
return rememberduration;
|
|
}
|
|
|
|
public boolean getRunnableStopped() {
|
|
return runnablestopped;
|
|
}
|
|
|
|
public void setRunnableStopped(boolean bool) {
|
|
runnablestopped = bool;
|
|
}
|
|
|
|
public boolean getScreenOff() {
|
|
return screenoff;
|
|
}
|
|
|
|
public void setScreenOff(boolean bool) {
|
|
screenoff = bool;
|
|
}
|
|
|
|
public long getSessionDuration() {
|
|
return sessionduration;
|
|
}
|
|
|
|
public void setSessionDuration(long duration) {
|
|
sessionduration = duration;
|
|
}
|
|
|
|
public long getSessionsRunnableStartTime() {
|
|
return sessrunnablestarttime;
|
|
}
|
|
|
|
public void setSessionsRunnableStartTime(long l) {
|
|
sessrunnablestarttime = l;
|
|
}
|
|
|
|
public boolean getSessionsRunnableStopped() {
|
|
return sessrunnablestopped;
|
|
}
|
|
|
|
public void setSessionsRunnableStopped(boolean bool) {
|
|
sessrunnablestopped = bool;
|
|
}
|
|
|
|
public boolean getSessionsRunnableWasSignedOut() {
|
|
return sesswassignedout;
|
|
}
|
|
|
|
public void setSessionsRunnableWasSignedOut(boolean bool) {
|
|
sesswassignedout = bool;
|
|
}
|
|
|
|
public Long getTimestamp() {
|
|
return System.currentTimeMillis() / 1000;
|
|
}
|
|
|
|
public long getTimeStartMeditate() {
|
|
return timeStartMeditate;
|
|
}
|
|
|
|
public void setTimeStartMeditate(long l) {
|
|
timeStartMeditate = l;
|
|
pendingNotificationAction = "";
|
|
// Log.d("MeditationAssistant", String.valueOf(timeToStopMeditate));
|
|
}
|
|
|
|
public long getTimeToStopMeditate() {
|
|
return timeToStopMeditate;
|
|
}
|
|
|
|
public void setTimeToStopMeditate(long l) {
|
|
timeToStopMeditate = l;
|
|
getPrefs().edit().putLong("last_reminder", getTimestamp()).apply();
|
|
//(new Exception()).printStackTrace();
|
|
Log.d("MeditationAssistant", "Setting time to stop meditating: "
|
|
+ timeToStopMeditate);
|
|
}
|
|
|
|
public String getTimerMode() {
|
|
if (timerMode == null) {
|
|
timerMode = getPrefs().getString("pref_timer_mode", "timed");
|
|
}
|
|
return timerMode;
|
|
}
|
|
|
|
public void setTimerMode(String tm) {
|
|
timerMode = tm;
|
|
|
|
getPrefs().edit().putString("pref_timer_mode", timerMode).apply();
|
|
}
|
|
|
|
public Integer getWebViewScale() {
|
|
if (webview_scale == null) {
|
|
webview_scale = getPrefs().getInt("webviewscale", 100);
|
|
}
|
|
return webview_scale;
|
|
}
|
|
|
|
public void setWebViewScale(int scale) {
|
|
webview_scale = scale;
|
|
|
|
getPrefs().edit().putInt("webviewscale", webview_scale).apply();
|
|
}
|
|
|
|
public void hideBellNotification() {
|
|
NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
|
|
notificationManager.cancel(bellNotificationID);
|
|
}
|
|
|
|
public void hideSessionNotification() {
|
|
NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
|
|
notificationManager.cancel(sessionNotificationID);
|
|
}
|
|
|
|
public void longToast(String text) {
|
|
new Handler(Looper.getMainLooper()).post(() -> {
|
|
Toast.makeText(getApplicationContext(), text, Toast.LENGTH_LONG).show();
|
|
});
|
|
}
|
|
|
|
@Override
|
|
public void onCreate() {
|
|
super.onCreate();
|
|
|
|
CookieManager cookieManager = new CookieManager();
|
|
CookieHandler.setDefault(cookieManager);
|
|
|
|
Integer applaunches = getPrefs().getInt("applaunches", 0) + 1;
|
|
if (applaunches == 1) {
|
|
getPrefs().edit().putBoolean("askedtodonate156", true).apply();
|
|
} else if (!getPrefs().getBoolean("askedtodonate156", false)) {
|
|
asktodonate = true;
|
|
getPrefs().edit().putBoolean("askedtodonate156", true).apply();
|
|
}
|
|
getPrefs().edit().putInt("applaunches", applaunches).apply();
|
|
|
|
Log.d("MeditationAssistant",
|
|
"Meditation Assistant running (" + applaunches + " launches) on API level "
|
|
+ Build.VERSION.SDK_INT
|
|
);
|
|
|
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
jobScheduler = (JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE);
|
|
|
|
dailyReminderReceiver = new DailyReminderReceiver();
|
|
IntentFilter reminderFilter = new IntentFilter();
|
|
reminderFilter.addAction(ACTION_REMINDER);
|
|
reminderFilter.addAction(ACTION_UPDATED);
|
|
registerReceiver(dailyReminderReceiver, reminderFilter);
|
|
}
|
|
|
|
if (Build.VERSION.SDK_INT >= 23) {
|
|
PackageManager pm = getPackageManager();
|
|
pm.setComponentEnabledSetting(new ComponentName(this, FilePickerActivity.class),
|
|
PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);
|
|
}
|
|
|
|
if (getPrefs().getBoolean("pref_vibrate", false)) {
|
|
getPrefs()
|
|
.edit()
|
|
.putString("pref_meditation_vibrate_start", "medium")
|
|
.putString("pref_meditation_vibrate_interval", "medium")
|
|
.putString("pref_meditation_vibrate_finish", "medium")
|
|
.putBoolean("pref_vibrate", false)
|
|
.apply();
|
|
}
|
|
|
|
getPrefs().registerOnSharedPreferenceChangeListener(sharedPrefslistener);
|
|
|
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
createNotificationChannels();
|
|
}
|
|
|
|
// Reset timer to default values
|
|
if (!getPrefs().getBoolean("pref_rememberlasttimer", true)) {
|
|
SharedPreferences.Editor editor = getPrefs().edit();
|
|
editor.putString("timerHours",
|
|
getPrefs().getString("timerDefaultHours", "15"));
|
|
editor.putString("timerMinutes",
|
|
getPrefs().getString("timerDefaultMinutes", "15"));
|
|
editor.apply();
|
|
}
|
|
|
|
// Upgrade to the new full screen preference
|
|
try {
|
|
boolean oldFullScreenPref = getPrefs().getBoolean("pref_full_screen", false);
|
|
|
|
// We didn't encounter an exception, upgrade the preference
|
|
String newFullScreenPref = "";
|
|
if (oldFullScreenPref) {
|
|
newFullScreenPref = "session";
|
|
}
|
|
|
|
getPrefs().edit().remove("pref_full_screen").apply();
|
|
getPrefs().edit().putString("pref_full_screen", newFullScreenPref).apply();
|
|
} catch (Exception e) {
|
|
// Do nothing
|
|
}
|
|
|
|
db = DatabaseHandler.getInstance(getApplicationContext());
|
|
|
|
setDailyReminder(getApplicationContext());
|
|
}
|
|
|
|
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
|
|
public JobInfo.Builder buildDailyReminderJob(Context context, Calendar calendar) {
|
|
long delay = calendar.getTimeInMillis() - System.currentTimeMillis();
|
|
|
|
JobInfo.Builder builder = new JobInfo.Builder(dailyReminderJobID, new ComponentName(context, DailyReminderService.class));
|
|
builder.setPersisted(true);
|
|
builder.setMinimumLatency(delay);
|
|
builder.setOverrideDeadline(delay);
|
|
return builder;
|
|
}
|
|
|
|
public void setDailyReminder(Context context) {
|
|
String reminderTime = getPrefs().getString("pref_daily_reminder_time", "19:00");
|
|
String[] reminderTimeSplit = ((reminderTime != null && reminderTime != "") ? reminderTime : "19:00").split(":");
|
|
Integer reminderHour = Integer.valueOf(reminderTimeSplit[0]);
|
|
Integer reminderMinute = Integer.valueOf(reminderTimeSplit[1]);
|
|
|
|
Calendar calendar = Calendar.getInstance();
|
|
calendar.set(Calendar.HOUR_OF_DAY, reminderHour);
|
|
calendar.set(Calendar.MINUTE, reminderMinute);
|
|
calendar.set(Calendar.SECOND, 0);
|
|
|
|
if (Calendar.getInstance().getTimeInMillis() > calendar.getTimeInMillis()) {
|
|
calendar.add(Calendar.DATE, 1); // Tomorrow
|
|
}
|
|
|
|
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
|
|
cancelDailyReminder(context);
|
|
|
|
reminderPendingIntent = PendingIntent.getBroadcast(context, dailyReminderNotificationID, new Intent(MeditationAssistant.ACTION_REMINDER), PendingIntent.FLAG_CANCEL_CURRENT | MeditationAssistant.extraPendingIntentFlags());
|
|
|
|
/* Don't use setAlarmClock here as it will always place an alarm icon in the status bar */
|
|
setAlarm(false, calendar.getTimeInMillis(), reminderPendingIntent);
|
|
} else {
|
|
long lastJobScheduled = getPrefs().getLong("last_job_scheduled", 0);
|
|
if (System.currentTimeMillis() - lastJobScheduled < 250) {
|
|
Log.d("MeditationAssistant", "Rate limiting daily reminder job scheduling");
|
|
return;
|
|
}
|
|
|
|
JobInfo.Builder builder = buildDailyReminderJob(context, calendar);
|
|
int result = jobScheduler.schedule(builder.build());
|
|
|
|
getPrefs().edit().putLong("last_job_scheduled", System.currentTimeMillis()).apply();
|
|
|
|
String resultLabel = (result == JobScheduler.RESULT_SUCCESS) ? "successfully" : "unsuccessfully";
|
|
Log.d("MeditationAssistant", "Scheduled daily reminder job " + resultLabel);
|
|
}
|
|
|
|
Log.d("MeditationAssistant", "Set daily reminder alarm for " + calendar);
|
|
}
|
|
|
|
public void cancelDailyReminder(Context context) {
|
|
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
|
|
if (reminderPendingIntent == null) {
|
|
return;
|
|
}
|
|
|
|
try {
|
|
getAlarmManager().cancel(reminderPendingIntent);
|
|
} catch (Exception e) {
|
|
Log.e("MeditationAssistant", "AlarmManager update was not canceled. " + e.toString());
|
|
}
|
|
try {
|
|
PendingIntent.getBroadcast(context, 0, new Intent(MeditationAssistant.ACTION_REMINDER), PendingIntent.FLAG_CANCEL_CURRENT | MeditationAssistant.extraPendingIntentFlags()).cancel();
|
|
} catch (Exception e) {
|
|
Log.e("MeditationAssistant", "PendingIntent broadcast was not canceled. " + e.toString());
|
|
}
|
|
try {
|
|
reminderPendingIntent.cancel();
|
|
} catch (Exception e) {
|
|
Log.e("MeditationAssistant", "PendingIntent was not canceled. " + e.toString());
|
|
}
|
|
} else {
|
|
jobScheduler.cancel(dailyReminderJobID);
|
|
Log.d("MeditationAssistant", "Canceled daily reminder job");
|
|
}
|
|
}
|
|
public String getPostDataString(HashMap<String, String> params) throws UnsupportedEncodingException {
|
|
StringBuilder result = new StringBuilder();
|
|
boolean first = true;
|
|
for (Map.Entry<String, String> entry : params.entrySet()) {
|
|
if (first)
|
|
first = false;
|
|
else
|
|
result.append("&");
|
|
|
|
result.append(URLEncoder.encode(entry.getKey(), "UTF-8"));
|
|
result.append("=");
|
|
result.append(URLEncoder.encode(entry.getValue(), "UTF-8"));
|
|
}
|
|
|
|
return result.toString();
|
|
}
|
|
|
|
public void setMediNETKey(String key, String provider) {
|
|
Log.d("MeditationAssistant", "Setting medinet key: " + key + " - " + provider);
|
|
medinetkey = key;
|
|
medinetprovider = provider;
|
|
long timestamp = System.currentTimeMillis() / 1000;
|
|
|
|
SharedPreferences.Editor editor = getPrefs().edit();
|
|
if (getPrefs().getBoolean("pref_rememberme", true)) {
|
|
Log.d("MeditationAssistant", "Storing medinet key: " + key + " - " + provider);
|
|
editor.putString("key", key);
|
|
editor.putString("provider", provider);
|
|
}
|
|
if (!key.equals("")) {
|
|
editor.putString("keyupdate", String.valueOf(timestamp));
|
|
}
|
|
editor.apply();
|
|
}
|
|
|
|
public void setMeditationStreak(Integer ms, long expires) {
|
|
meditationstreak = ms;
|
|
meditationstreakexpires = expires;
|
|
|
|
Calendar date = new GregorianCalendar();
|
|
date.setTimeZone(TimeZone.getDefault());
|
|
long timestamp = date.getTimeInMillis() / 1000;
|
|
Log.d("MeditationAssistant",
|
|
"Streak: " + meditationstreak + ", expires: "
|
|
+ expires + " (in "
|
|
+ (expires - timestamp) + " seconds)"
|
|
);
|
|
|
|
getPrefs().edit().putInt("meditationstreak", meditationstreak).putLong("meditationstreakexpires", meditationstreakexpires).apply();
|
|
|
|
if (meditationstreak == 1) {
|
|
getPrefs().edit().putBoolean("meditationstreakwarningshown", false).apply();
|
|
}
|
|
if (meditationstreak > getLongestMeditationStreak()) {
|
|
setLongestMeditationStreak(meditationstreak);
|
|
}
|
|
|
|
updateWidgets();
|
|
|
|
/* Update all widgets */
|
|
Intent update_widgets = new Intent(getApplicationContext(), WidgetStreakProvider.class);
|
|
update_widgets.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
|
|
sendBroadcast(update_widgets);
|
|
}
|
|
|
|
public void pauseSession() {
|
|
pausestart = getTimestamp();
|
|
ispaused = true;
|
|
}
|
|
|
|
public long unPauseSession() {
|
|
if (!ispaused) {
|
|
return 0;
|
|
}
|
|
|
|
long thispausetime;
|
|
if (getTimerMode().equals("endat")) {
|
|
thispausetime = Math.min(getTimeToStopMeditate(), getTimestamp()) - pausestart;
|
|
} else {
|
|
thispausetime = Math.max(0, getTimestamp() - pausestart);
|
|
}
|
|
pausetime += thispausetime;
|
|
|
|
Log.d("MeditationAssistant", "PAUSE: Un-paused. Paused for " + thispausetime + " seconds (" + pausetime + " total)");
|
|
|
|
ispaused = false;
|
|
|
|
return thispausetime;
|
|
}
|
|
|
|
public void shortToast(String text) {
|
|
new Handler(Looper.getMainLooper()).post(() -> {
|
|
Toast.makeText(getApplicationContext(), text, Toast.LENGTH_SHORT).show();
|
|
});
|
|
}
|
|
|
|
public AlertDialog showAnnouncementDialog(String title) {
|
|
try {
|
|
Looper.prepare();
|
|
} catch (Exception e) {
|
|
//e.printStackTrace();
|
|
}
|
|
|
|
if (getMediNET().activity != null
|
|
&& !getMediNET().announcement.equals("")) {
|
|
AlertDialog announceDialog = new AlertDialog.Builder(getMediNET().activity)
|
|
.setPositiveButton(R.string.dismiss,
|
|
new DialogInterface.OnClickListener() {
|
|
@Override
|
|
public void onClick(DialogInterface dialog,
|
|
int id) {
|
|
|
|
}
|
|
}
|
|
)
|
|
.setTitle(title == null ? getString(R.string.announcement) : title)
|
|
.setMessage(medinet.announcement)
|
|
.setIcon(getMediNET().activity.getResources().getDrawable(getTheme().obtainStyledAttributes(getMATheme(true), new int[]{R.attr.actionIconGoToToday}).getResourceId(0, 0)))
|
|
.setCancelable(false)
|
|
.create();
|
|
|
|
announceDialog.show();
|
|
return announceDialog;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
public void showDonationDialog(Activity activity) {
|
|
AlertDialog donateDialog = new AlertDialog.Builder(activity)
|
|
.setTitle(getString(R.string.donate))
|
|
.setMessage(R.string.chooseDonationMethod)
|
|
.setPositiveButton("Liberapay",
|
|
(dialog, id) -> startActivity(new Intent(
|
|
Intent.ACTION_VIEW,
|
|
Uri.parse("https://liberapay.com/~968545")).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)))
|
|
.setNegativeButton("PayPal",
|
|
(dialog, id) -> startActivity(new Intent(
|
|
Intent.ACTION_VIEW,
|
|
Uri.parse(MeditationAssistant.URL_ROCKETNINELABS + "/donate")).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)))
|
|
.create();
|
|
|
|
donateDialog.show();
|
|
}
|
|
|
|
public void showStreakDifferenceWarning(int oldstreak, int newstreak, boolean twodays, Activity activity) {
|
|
try {
|
|
Looper.prepare();
|
|
} catch (Exception e) {
|
|
//e.printStackTrace();
|
|
}
|
|
|
|
if (activity == null) {
|
|
return;
|
|
}
|
|
|
|
if (getPrefs().getBoolean("meditationstreakwarningshown", false)) {
|
|
return;
|
|
}
|
|
getPrefs().edit().putBoolean("meditationstreakwarningshown", true).apply();
|
|
|
|
AlertDialog streakDifferenceDialog = new AlertDialog.Builder(activity)
|
|
.setPositiveButton(R.string.yes,
|
|
(dialog, id) -> {
|
|
setMeditationStreak(newstreak, twodays ? getStreakExpiresTwoDaysTimestamp() : getStreakExpiresOneDayTimestamp());
|
|
}
|
|
)
|
|
.setNegativeButton(R.string.no,
|
|
(dialog, id) -> {
|
|
// Do nothing
|
|
}
|
|
)
|
|
.setTitle(R.string.warning)
|
|
.setMessage(String.format(getString(R.string.streakdifferencewarning), oldstreak, newstreak))
|
|
.setIcon(activity.getResources().getDrawable(getTheme().obtainStyledAttributes(getMATheme(true), new int[]{R.attr.actionIconGoToToday}).getResourceId(0, 0)))
|
|
.setCancelable(false)
|
|
.create();
|
|
|
|
streakDifferenceDialog.show();
|
|
}
|
|
|
|
@RequiresApi(api = Build.VERSION_CODES.O)
|
|
public void createNotificationChannels() {
|
|
NotificationChannel sessionChannel = new NotificationChannel("session", getString(R.string.session), NotificationManager.IMPORTANCE_LOW);
|
|
sessionChannel.enableLights(false);
|
|
sessionChannel.enableVibration(false);
|
|
|
|
NotificationChannel bellChannel = new NotificationChannel("bell", getString(R.string.session), NotificationManager.IMPORTANCE_LOW);
|
|
bellChannel.enableLights(false);
|
|
bellChannel.enableVibration(false);
|
|
|
|
NotificationChannel reminderChannel = new NotificationChannel("reminder", getString(R.string.pref_daily_reminder), NotificationManager.IMPORTANCE_DEFAULT);
|
|
reminderChannel.enableLights(true);
|
|
reminderChannel.enableVibration(true);
|
|
|
|
NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
|
|
notificationManager.createNotificationChannel(sessionChannel);
|
|
notificationManager.createNotificationChannel(bellChannel);
|
|
notificationManager.createNotificationChannel(reminderChannel);
|
|
}
|
|
|
|
public void showMindfulnessBellNotification() {
|
|
Intent intent = new Intent(this, MainActivity.class);
|
|
intent.setAction("notification");
|
|
// intent.putExtra("notificationButton", "notification");
|
|
// intent.putExtra("notificationButton", "");
|
|
PendingIntent pIntent = PendingIntent.getActivity(this, 0, intent,
|
|
PendingIntent.FLAG_UPDATE_CURRENT | MeditationAssistant.extraPendingIntentFlags());
|
|
|
|
Intent intent3 = new Intent(this, MainActivity.class);
|
|
// intent3.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
|
|
// intent3.putExtra("notificationButton", "end");
|
|
intent3.setAction("notificationEndBell");
|
|
PendingIntent pIntentEnd = PendingIntent.getActivity(this, 0, intent3,
|
|
PendingIntent.FLAG_UPDATE_CURRENT | MeditationAssistant.extraPendingIntentFlags());
|
|
|
|
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
|
|
.setOngoing(true)
|
|
.setSmallIcon(R.drawable.ic_notification)
|
|
.setContentTitle(getString(R.string.mindfulnessBellActive))
|
|
.setPriority(NotificationCompat.PRIORITY_LOW)
|
|
.setContentIntent(pIntent)
|
|
.addAction(R.drawable.ic_action_stop,
|
|
getString(R.string.deactivate), pIntentEnd);
|
|
|
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
notificationBuilder.setChannelId("bell");
|
|
}
|
|
|
|
NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
|
|
notificationManager.notify(bellNotificationID, notificationBuilder.build());
|
|
}
|
|
|
|
public void showSessionNotification() {
|
|
if (!getPrefs().getBoolean("pref_notification", true)
|
|
|| getTimeStartMeditate() < 1) {
|
|
hideSessionNotification();
|
|
return;
|
|
}
|
|
|
|
Intent intent = new Intent(this, MainActivity.class);
|
|
intent.setAction("notification");
|
|
// intent.putExtra("notificationButton", "notification");
|
|
// intent.putExtra("notificationButton", "");
|
|
PendingIntent pIntent = PendingIntent.getActivity(this, 0, intent,
|
|
PendingIntent.FLAG_UPDATE_CURRENT | MeditationAssistant.extraPendingIntentFlags());
|
|
|
|
Intent intent2 = new Intent(this, MainActivity.class);
|
|
// intent2.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
|
|
intent2.setAction("notificationPause");
|
|
PendingIntent pIntentPause = PendingIntent.getActivity(this, 0, intent2,
|
|
PendingIntent.FLAG_UPDATE_CURRENT | MeditationAssistant.extraPendingIntentFlags());
|
|
|
|
Intent intent3 = new Intent(this, MainActivity.class);
|
|
// intent3.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
|
|
// intent3.putExtra("notificationButton", "end");
|
|
intent3.setAction("notificationEnd");
|
|
PendingIntent pIntentEnd = PendingIntent.getActivity(this, 0, intent3,
|
|
PendingIntent.FLAG_UPDATE_CURRENT | MeditationAssistant.extraPendingIntentFlags());
|
|
|
|
String streaktext = "";
|
|
if (getMeditationStreak().get(0) > 1) {
|
|
streaktext = String.valueOf(getMeditationStreak().get(0));
|
|
}
|
|
|
|
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
|
|
.setOngoing(true)
|
|
.setSmallIcon(R.drawable.ic_notification)
|
|
.setContentTitle(getString(!ispaused ? R.string.sessionInProgress : R.string.sessionPaused))
|
|
.setPriority(NotificationCompat.PRIORITY_LOW)
|
|
.setContentInfo(streaktext)
|
|
.setContentIntent(pIntent)
|
|
.addAction(R.drawable.ic_action_pause,
|
|
getString(!ispaused ? R.string.pause : R.string.resume), pIntentPause)
|
|
.addAction(R.drawable.ic_action_stop,
|
|
getString(R.string.end), pIntentEnd);
|
|
|
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
notificationBuilder.setChannelId("session");
|
|
}
|
|
|
|
NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
|
|
notificationManager.notify(sessionNotificationID, notificationBuilder.build());
|
|
}
|
|
|
|
public void showSessionDialog(final SessionSQL session, Activity activity) {
|
|
if (sessionDialog != null) {
|
|
try {
|
|
if (sessionDialog.isShowing()) {
|
|
sessionDialog.dismiss();
|
|
}
|
|
} catch (Exception e) {
|
|
// Activity is not in the foreground
|
|
}
|
|
}
|
|
|
|
if (getTimeStartMeditate() > 0) {
|
|
shortToast(getString(session._id == 0 ? R.string.addSessionMeditating : R.string.editSessionMeditating));
|
|
return;
|
|
}
|
|
|
|
sessionDialogUpdateSessionStarted = 0;
|
|
sessionDialogActivity = activity;
|
|
|
|
sessionDialogStartedYear = -1;
|
|
sessionDialogStartedMonth = -1;
|
|
sessionDialogStartedDay = -1;
|
|
sessionDialogStartedHour = -1;
|
|
sessionDialogStartedMinute = -1;
|
|
|
|
sessionDialogCompletedYear = -1;
|
|
sessionDialogCompletedMonth = -1;
|
|
sessionDialogCompletedDay = -1;
|
|
sessionDialogCompletedHour = -1;
|
|
sessionDialogCompletedMinute = -1;
|
|
|
|
sessionDialogLengthSetManually = false;
|
|
sessionDialogLengthHour = -1;
|
|
sessionDialogLengthMinute = -1;
|
|
|
|
View sessionDialogView = LayoutInflater.from(sessionDialogActivity).inflate(R.layout.session_dialog, sessionDialogActivity.findViewById(R.id.sessionDialog));
|
|
sessionDialogStartedDateButton = sessionDialogView.findViewById(R.id.sessionDialogSetDateStarted);
|
|
sessionDialogStartedTimeButton = sessionDialogView.findViewById(R.id.sessionDialogSetTimeStarted);
|
|
sessionDialogCompletedDateButton = sessionDialogView.findViewById(R.id.sessionDialogSetDateCompleted);
|
|
sessionDialogCompletedTimeButton = sessionDialogView.findViewById(R.id.sessionDialogSetTimeCompleted);
|
|
sessionDialogLengthButton = sessionDialogView.findViewById(R.id.sessionDialogSetLength);
|
|
sessionDialogMessage = sessionDialogView.findViewById(R.id.sessionDialogSetMessage);
|
|
|
|
if (session._id > 0) {
|
|
sessionDialogUpdateSessionStarted = session._started;
|
|
|
|
Calendar c_session_started = Calendar.getInstance();
|
|
c_session_started.setTimeInMillis(session._started * 1000);
|
|
sessionDialogStartedYear = c_session_started.get(Calendar.YEAR);
|
|
sessionDialogStartedMonth = c_session_started.get(Calendar.MONTH);
|
|
sessionDialogStartedDay = c_session_started.get(Calendar.DAY_OF_MONTH);
|
|
sessionDialogStartedHour = c_session_started.get(Calendar.HOUR_OF_DAY);
|
|
sessionDialogStartedMinute = c_session_started.get(Calendar.MINUTE);
|
|
|
|
Calendar c_session_completed = Calendar.getInstance();
|
|
c_session_completed.setTimeInMillis(session._completed * 1000);
|
|
sessionDialogCompletedYear = c_session_completed.get(Calendar.YEAR);
|
|
sessionDialogCompletedMonth = c_session_completed.get(Calendar.MONTH);
|
|
sessionDialogCompletedDay = c_session_completed.get(Calendar.DAY_OF_MONTH);
|
|
sessionDialogCompletedHour = c_session_completed.get(Calendar.HOUR_OF_DAY);
|
|
sessionDialogCompletedMinute = c_session_completed.get(Calendar.MINUTE);
|
|
|
|
sessionDialogLengthSetManually = true;
|
|
sessionDialogLengthHour = Long.valueOf(session._length / 3600).intValue();
|
|
sessionDialogLengthMinute = Long.valueOf((session._length % 3600) / 60).intValue();
|
|
if (sessionDialogLengthHour == 0 && sessionDialogLengthMinute == 0) {
|
|
sessionDialogLengthMinute = 1;
|
|
}
|
|
|
|
sessionDialogMessage.setText(session._message);
|
|
}
|
|
|
|
sessionDialogStartedDateButton.setOnClickListener(new View.OnClickListener() {
|
|
@Override
|
|
public void onClick(View view) {
|
|
sessionDialogCurrentOption = "started";
|
|
DatePickerDialog dateDialog = null;
|
|
|
|
if (sessionDialogStartedYear == -1 || sessionDialogStartedMonth == -1 || sessionDialogStartedDay == -1) {
|
|
Calendar c = Calendar.getInstance();
|
|
dateDialog = new DatePickerDialog(sessionDialogActivity,
|
|
sessionDialogDateSetListener,
|
|
c.get(Calendar.YEAR), c.get(Calendar.MONTH), c.get(Calendar.DAY_OF_MONTH));
|
|
} else {
|
|
dateDialog = new DatePickerDialog(sessionDialogActivity,
|
|
sessionDialogDateSetListener,
|
|
sessionDialogStartedYear, sessionDialogStartedMonth, sessionDialogStartedDay);
|
|
}
|
|
|
|
dateDialog.show();
|
|
}
|
|
});
|
|
sessionDialogStartedTimeButton.setOnClickListener(new View.OnClickListener() {
|
|
@Override
|
|
public void onClick(View view) {
|
|
sessionDialogCurrentOption = "started";
|
|
TimePickerDialog timeDialog = null;
|
|
|
|
if (sessionDialogStartedHour == -1 || sessionDialogStartedMinute == -1) {
|
|
Calendar c = Calendar.getInstance();
|
|
timeDialog = new TimePickerDialog(sessionDialogActivity,
|
|
sessionDialogTimeSetListener,
|
|
c.get(Calendar.HOUR_OF_DAY), c.get(Calendar.MINUTE), false);
|
|
} else {
|
|
timeDialog = new TimePickerDialog(sessionDialogActivity,
|
|
sessionDialogTimeSetListener,
|
|
sessionDialogStartedHour, sessionDialogStartedMinute, false);
|
|
}
|
|
|
|
timeDialog.show();
|
|
}
|
|
});
|
|
sessionDialogCompletedDateButton.setOnClickListener(new View.OnClickListener() {
|
|
@Override
|
|
public void onClick(View view) {
|
|
sessionDialogCurrentOption = "completed";
|
|
DatePickerDialog dateDialog = null;
|
|
|
|
if (sessionDialogCompletedYear == -1 || sessionDialogCompletedMonth == -1 || sessionDialogCompletedDay == -1) {
|
|
Calendar c = Calendar.getInstance();
|
|
dateDialog = new DatePickerDialog(sessionDialogActivity,
|
|
sessionDialogDateSetListener,
|
|
c.get(Calendar.YEAR), c.get(Calendar.MONTH), c.get(Calendar.DAY_OF_MONTH));
|
|
} else {
|
|
dateDialog = new DatePickerDialog(sessionDialogActivity,
|
|
sessionDialogDateSetListener,
|
|
sessionDialogCompletedYear, sessionDialogCompletedMonth, sessionDialogCompletedDay);
|
|
}
|
|
|
|
dateDialog.show();
|
|
}
|
|
});
|
|
sessionDialogCompletedTimeButton.setOnClickListener(new View.OnClickListener() {
|
|
@Override
|
|
public void onClick(View view) {
|
|
sessionDialogCurrentOption = "completed";
|
|
TimePickerDialog timeDialog = null;
|
|
|
|
if (sessionDialogCompletedHour == -1 || sessionDialogCompletedMinute == -1) {
|
|
Calendar c = Calendar.getInstance();
|
|
timeDialog = new TimePickerDialog(sessionDialogActivity,
|
|
sessionDialogTimeSetListener,
|
|
c.get(Calendar.HOUR_OF_DAY), c.get(Calendar.MINUTE), false);
|
|
} else {
|
|
timeDialog = new TimePickerDialog(sessionDialogActivity,
|
|
sessionDialogTimeSetListener,
|
|
sessionDialogCompletedHour, sessionDialogCompletedMinute, false);
|
|
}
|
|
|
|
timeDialog.show();
|
|
}
|
|
});
|
|
sessionDialogLengthButton.setOnClickListener(new View.OnClickListener() {
|
|
@Override
|
|
public void onClick(View view) {
|
|
sessionDialogCurrentOption = "length";
|
|
TimePickerDialog timeDialog = null;
|
|
|
|
if (sessionDialogLengthHour == -1 || sessionDialogLengthMinute == -1) {
|
|
timeDialog = new TimePickerDialog(sessionDialogActivity,
|
|
sessionDialogTimeSetListener,
|
|
0, 0, true);
|
|
} else {
|
|
timeDialog = new TimePickerDialog(sessionDialogActivity,
|
|
sessionDialogTimeSetListener,
|
|
sessionDialogLengthHour, sessionDialogLengthMinute, true);
|
|
}
|
|
|
|
timeDialog.show();
|
|
}
|
|
});
|
|
|
|
sessionDialog = new AlertDialog.Builder(sessionDialogActivity)
|
|
.setIcon(getResources().getDrawable(getTheme().obtainStyledAttributes(getMATheme(true), new int[]{session._id == 0 ? R.attr.actionIconNew : R.attr.actionIconGoToToday}).getResourceId(0, 0)))
|
|
.setTitle(getString(session._id == 0 ? R.string.addSession : R.string.editSession))
|
|
.setView(sessionDialogView)
|
|
.setPositiveButton(getString(session._id == 0 ? R.string.add : R.string.edit), new DialogInterface.OnClickListener() {
|
|
@Override
|
|
public void onClick(DialogInterface dialogInterface,
|
|
int which) {
|
|
// Overridden later
|
|
}
|
|
})
|
|
.setNegativeButton(getString(R.string.cancel), new DialogInterface.OnClickListener() {
|
|
@Override
|
|
public void onClick(DialogInterface dialogInterface,
|
|
int which) {
|
|
dialogInterface.dismiss();
|
|
}
|
|
})
|
|
.create();
|
|
|
|
updateSessionDialog();
|
|
sessionDialog.show();
|
|
|
|
Button saveButton = sessionDialog.getButton(AlertDialog.BUTTON_POSITIVE);
|
|
saveButton.setOnClickListener(new View.OnClickListener() {
|
|
@Override
|
|
public void onClick(View view) {
|
|
if (sessionDialogStartedYear == -1 || sessionDialogStartedMonth == -1 || sessionDialogStartedDay == -1 || sessionDialogStartedHour == -1 || sessionDialogStartedMinute == -1 || sessionDialogCompletedYear == -1 || sessionDialogCompletedMonth == -1 || sessionDialogCompletedDay == -1 || sessionDialogCompletedHour == -1 || sessionDialogCompletedMinute == -1) {
|
|
shortToast(getString(R.string.invalidDateOrTime));
|
|
} else {
|
|
Calendar c_started = Calendar.getInstance();
|
|
c_started.set(Calendar.YEAR, sessionDialogStartedYear);
|
|
c_started.set(Calendar.MONTH, sessionDialogStartedMonth);
|
|
c_started.set(Calendar.DAY_OF_MONTH, sessionDialogStartedDay);
|
|
c_started.set(Calendar.HOUR_OF_DAY, sessionDialogStartedHour);
|
|
c_started.set(Calendar.MINUTE, sessionDialogStartedMinute);
|
|
c_started.set(Calendar.SECOND, 0);
|
|
c_started.set(Calendar.MILLISECOND, 0);
|
|
|
|
Calendar c_completed = Calendar.getInstance();
|
|
c_completed.set(Calendar.YEAR, sessionDialogCompletedYear);
|
|
c_completed.set(Calendar.MONTH, sessionDialogCompletedMonth);
|
|
c_completed.set(Calendar.DAY_OF_MONTH, sessionDialogCompletedDay);
|
|
c_completed.set(Calendar.HOUR_OF_DAY, sessionDialogCompletedHour);
|
|
c_completed.set(Calendar.MINUTE, sessionDialogCompletedMinute);
|
|
c_completed.set(Calendar.SECOND, 0);
|
|
c_completed.set(Calendar.MILLISECOND, 0);
|
|
|
|
if (c_started.getTimeInMillis() > Calendar.getInstance().getTimeInMillis() || c_completed.getTimeInMillis() > Calendar.getInstance().getTimeInMillis() || c_started.getTimeInMillis() >= c_completed.getTimeInMillis()) {
|
|
shortToast(getString(R.string.invalidDateOrTime));
|
|
return;
|
|
}
|
|
|
|
if (((sessionDialogLengthHour * 3600) + (sessionDialogLengthMinute * 60)) > ((c_completed.getTimeInMillis() - c_started.getTimeInMillis()) / 1000)) {
|
|
shortToast(getString(R.string.invalidLength));
|
|
return;
|
|
}
|
|
|
|
final SessionSQL existingSession = db.getSessionByStarted(c_started.getTimeInMillis() / 1000);
|
|
if (existingSession != null && existingSession._id > 0 && (session._id == 0 || !existingSession._id.equals(session._id))) {
|
|
shortToast(getString(R.string.sessionExists));
|
|
return;
|
|
}
|
|
|
|
AlertDialog postSessionDialog = new AlertDialog.Builder(activity)
|
|
.setIcon(getResources().getDrawable(getTheme().obtainStyledAttributes(getMATheme(true), new int[]{R.attr.actionIconInfo}).getResourceId(0, 0)))
|
|
.setTitle(getString(R.string.sessionPosted))
|
|
.setMessage(getString(R.string.postUpdatedSession))
|
|
.setPositiveButton(getString(R.string.yes), new DialogInterface.OnClickListener() {
|
|
@Override
|
|
public void onClick(DialogInterface dialogInterface,
|
|
int which) {
|
|
dialogInterface.dismiss();
|
|
completeSessionDialog(session, true);
|
|
}
|
|
})
|
|
.setNegativeButton(getString(R.string.no), new DialogInterface.OnClickListener() {
|
|
@Override
|
|
public void onClick(DialogInterface dialogInterface,
|
|
int which) {
|
|
dialogInterface.dismiss();
|
|
completeSessionDialog(session, false);
|
|
}
|
|
})
|
|
.setCancelable(true)
|
|
.create();
|
|
postSessionDialog.show();
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
public void updateSessionDialog() {
|
|
if (sessionDialogStartedDateButton == null || sessionDialogCompletedDateButton == null || sessionDialogStartedTimeButton == null || sessionDialogCompletedTimeButton == null || sessionDialogLengthButton == null) {
|
|
return;
|
|
}
|
|
|
|
fillSessionDialogLength();
|
|
|
|
SimpleDateFormat sdf_date = new SimpleDateFormat("MMMM d",
|
|
Locale.getDefault());
|
|
SimpleDateFormat sdf_time = new SimpleDateFormat("h:mm a",
|
|
Locale.getDefault());
|
|
|
|
sdf_date.setTimeZone(TimeZone.getDefault());
|
|
sdf_time.setTimeZone(TimeZone.getDefault());
|
|
|
|
if (sessionDialogStartedYear == -1 || sessionDialogStartedMonth == -1 || sessionDialogStartedDay == -1) {
|
|
sessionDialogStartedDateButton.setText(getString(R.string.setDate));
|
|
} else {
|
|
Calendar c = Calendar.getInstance();
|
|
c.set(Calendar.YEAR, sessionDialogStartedYear);
|
|
c.set(Calendar.MONTH, sessionDialogStartedMonth);
|
|
c.set(Calendar.DAY_OF_MONTH, sessionDialogStartedDay);
|
|
c.set(Calendar.HOUR_OF_DAY, 0);
|
|
c.set(Calendar.MINUTE, 0);
|
|
c.set(Calendar.SECOND, 0);
|
|
c.set(Calendar.MILLISECOND, 0);
|
|
|
|
sessionDialogStartedDateButton.setText(sdf_date.format(c.getTime()));
|
|
}
|
|
if (sessionDialogCompletedYear == -1 || sessionDialogCompletedMonth == -1 || sessionDialogCompletedDay == -1) {
|
|
sessionDialogCompletedDateButton.setText(getString(R.string.setDate));
|
|
} else {
|
|
Calendar c = Calendar.getInstance();
|
|
c.set(Calendar.YEAR, sessionDialogCompletedYear);
|
|
c.set(Calendar.MONTH, sessionDialogCompletedMonth);
|
|
c.set(Calendar.DAY_OF_MONTH, sessionDialogCompletedDay);
|
|
c.set(Calendar.HOUR_OF_DAY, 0);
|
|
c.set(Calendar.MINUTE, 0);
|
|
c.set(Calendar.SECOND, 0);
|
|
c.set(Calendar.MILLISECOND, 0);
|
|
|
|
sessionDialogCompletedDateButton.setText(sdf_date.format(c.getTime()));
|
|
}
|
|
|
|
if (sessionDialogStartedHour == -1 || sessionDialogStartedMinute == -1) {
|
|
sessionDialogStartedTimeButton.setText(getString(R.string.setTime));
|
|
} else {
|
|
Calendar c = Calendar.getInstance();
|
|
c.set(Calendar.HOUR_OF_DAY, sessionDialogStartedHour);
|
|
c.set(Calendar.MINUTE, sessionDialogStartedMinute);
|
|
c.set(Calendar.SECOND, 0);
|
|
c.set(Calendar.MILLISECOND, 0);
|
|
|
|
sessionDialogStartedTimeButton.setText(sdf_time.format(c.getTime()));
|
|
}
|
|
if (sessionDialogCompletedHour == -1 || sessionDialogCompletedMinute == -1) {
|
|
sessionDialogCompletedTimeButton.setText(getString(R.string.setTime));
|
|
} else {
|
|
Calendar c = Calendar.getInstance();
|
|
c.set(Calendar.HOUR_OF_DAY, sessionDialogCompletedHour);
|
|
c.set(Calendar.MINUTE, sessionDialogCompletedMinute);
|
|
c.set(Calendar.SECOND, 0);
|
|
c.set(Calendar.MILLISECOND, 0);
|
|
|
|
sessionDialogCompletedTimeButton.setText(sdf_time.format(c.getTime()));
|
|
}
|
|
|
|
if (sessionDialogLengthHour == -1 || sessionDialogLengthMinute == -1) {
|
|
sessionDialogLengthButton.setText(getString(R.string.setTime));
|
|
} else {
|
|
String summary = "";
|
|
if (sessionDialogLengthHour > 0) {
|
|
summary += sessionDialogLengthHour + " hour";
|
|
if (sessionDialogLengthHour > 1) {
|
|
summary += "s";
|
|
}
|
|
}
|
|
if (sessionDialogLengthMinute > 0) {
|
|
summary += " " + sessionDialogLengthMinute + " minute";
|
|
if (sessionDialogLengthMinute > 1) {
|
|
summary += "s";
|
|
}
|
|
}
|
|
|
|
sessionDialogLengthButton.setText(summary.trim());
|
|
}
|
|
}
|
|
|
|
public void fillSessionDialogLength() {
|
|
if (sessionDialogLengthSetManually) {
|
|
return;
|
|
}
|
|
|
|
if (sessionDialogStartedYear == -1 || sessionDialogStartedMonth == -1 || sessionDialogStartedDay == -1
|
|
|| sessionDialogStartedHour == -1 || sessionDialogStartedMinute == -1
|
|
|| sessionDialogCompletedYear == -1 || sessionDialogCompletedMonth == -1 || sessionDialogCompletedDay == -1
|
|
|| sessionDialogCompletedHour == -1 || sessionDialogCompletedMinute == -1) {
|
|
return;
|
|
}
|
|
|
|
Calendar sc = Calendar.getInstance();
|
|
sc.set(Calendar.YEAR, sessionDialogStartedYear);
|
|
sc.set(Calendar.MONTH, sessionDialogStartedMonth);
|
|
sc.set(Calendar.DAY_OF_MONTH, sessionDialogStartedDay);
|
|
sc.set(Calendar.HOUR_OF_DAY, sessionDialogStartedHour);
|
|
sc.set(Calendar.MINUTE, sessionDialogStartedMinute);
|
|
sc.set(Calendar.SECOND, 0);
|
|
sc.set(Calendar.MILLISECOND, 0);
|
|
|
|
Calendar cc = Calendar.getInstance();
|
|
cc.set(Calendar.YEAR, sessionDialogCompletedYear);
|
|
cc.set(Calendar.MONTH, sessionDialogCompletedMonth);
|
|
cc.set(Calendar.DAY_OF_MONTH, sessionDialogCompletedDay);
|
|
cc.set(Calendar.HOUR_OF_DAY, sessionDialogCompletedHour);
|
|
cc.set(Calendar.MINUTE, sessionDialogCompletedMinute);
|
|
cc.set(Calendar.SECOND, 0);
|
|
cc.set(Calendar.MILLISECOND, 0);
|
|
|
|
long length = (cc.getTimeInMillis() / 1000) - (sc.getTimeInMillis() / 1000);
|
|
if (length <= 0) {
|
|
return;
|
|
}
|
|
|
|
sessionDialogLengthHour = (int) length / 3600;
|
|
sessionDialogLengthMinute = (int) (length % 3600) / 60;
|
|
|
|
if (sessionDialogLengthHour == 0 && sessionDialogLengthMinute == 0) {
|
|
sessionDialogLengthMinute = 1;
|
|
}
|
|
}
|
|
|
|
public ArrayList<Long> getSessionDialogValues() {
|
|
Calendar c_started = Calendar.getInstance();
|
|
c_started.set(Calendar.YEAR, sessionDialogStartedYear);
|
|
c_started.set(Calendar.MONTH, sessionDialogStartedMonth);
|
|
c_started.set(Calendar.DAY_OF_MONTH, sessionDialogStartedDay);
|
|
c_started.set(Calendar.HOUR_OF_DAY, sessionDialogStartedHour);
|
|
c_started.set(Calendar.MINUTE, sessionDialogStartedMinute);
|
|
c_started.set(Calendar.SECOND, 0);
|
|
c_started.set(Calendar.MILLISECOND, 0);
|
|
|
|
Calendar c_completed = Calendar.getInstance();
|
|
c_completed.set(Calendar.YEAR, sessionDialogCompletedYear);
|
|
c_completed.set(Calendar.MONTH, sessionDialogCompletedMonth);
|
|
c_completed.set(Calendar.DAY_OF_MONTH, sessionDialogCompletedDay);
|
|
c_completed.set(Calendar.HOUR_OF_DAY, sessionDialogCompletedHour);
|
|
c_completed.set(Calendar.MINUTE, sessionDialogCompletedMinute);
|
|
c_completed.set(Calendar.SECOND, 0);
|
|
c_completed.set(Calendar.MILLISECOND, 0);
|
|
|
|
ArrayList<Long> sc = new ArrayList<>();
|
|
sc.add(c_started.getTimeInMillis() / 1000);
|
|
sc.add(c_completed.getTimeInMillis() / 1000);
|
|
sc.add((long) ((sessionDialogLengthHour * 3600) + (sessionDialogLengthMinute * 60)));
|
|
return sc;
|
|
}
|
|
|
|
public void completeSessionDialog(SessionSQL session, boolean postSession) {
|
|
ArrayList<Long> sc = getSessionDialogValues();
|
|
Long started = sc.get(0);
|
|
Long completed = sc.get(1);
|
|
Long length = sc.get(2);
|
|
|
|
if (postSession) {
|
|
getMediNET().resetSession();
|
|
getMediNET().session.started = started;
|
|
getMediNET().session.length = length;
|
|
getMediNET().session.completed = completed;
|
|
getMediNET().session.message = sessionDialogMessage.getText().toString().trim();
|
|
getMediNET().session.modified = getTimestamp();
|
|
|
|
getMediNET().status = "";
|
|
getMediNET().postSession(sessionDialogUpdateSessionStarted, sessionDialogActivity, () -> {
|
|
if (getMediNET().status.equals("success")) {
|
|
notifySessionsUpdated();
|
|
sessionDialog.dismiss();
|
|
}
|
|
});
|
|
} else {
|
|
if (db.addSession(new SessionSQL((long) 0, started, completed, length, sessionDialogMessage.getText().toString().trim(), (long) 0, (long) 0, getTimestamp()), sessionDialogUpdateSessionStarted)) {
|
|
if (session._id == 0) { // Add session
|
|
shortToast(getString(R.string.sessionAdded));
|
|
} else {
|
|
shortToast(getString(R.string.sessionEdited));
|
|
}
|
|
|
|
notifySessionsUpdated();
|
|
sessionDialog.dismiss();
|
|
}
|
|
}
|
|
}
|
|
|
|
public AlertDialog showStaleDataDialog() {
|
|
Log.d("MeditationAssistant", "Showing stale data dialog");
|
|
|
|
try {
|
|
Looper.prepare();
|
|
} catch (Exception e) {
|
|
//e.printStackTrace();
|
|
}
|
|
|
|
if (getMediNET().activity != null) {
|
|
AlertDialog staleDataDialog = new AlertDialog.Builder(
|
|
getMediNET().activity)
|
|
.setPositiveButton(R.string.download,
|
|
new DialogInterface.OnClickListener() {
|
|
@Override
|
|
public void onClick(DialogInterface dialog,
|
|
int id) {
|
|
getMediNET().downloadSessions();
|
|
}
|
|
}
|
|
)
|
|
.setNegativeButton(R.string.dismiss,
|
|
new DialogInterface.OnClickListener() {
|
|
@Override
|
|
public void onClick(DialogInterface dialog,
|
|
int id) {
|
|
// Do nothing
|
|
}
|
|
}
|
|
)
|
|
.setTitle(R.string.downloadsessionstitle)
|
|
.setMessage(R.string.downloadsessionsmessage)
|
|
.setIcon(getMediNET().activity.getResources().getDrawable(getTheme().obtainStyledAttributes(getMATheme(true), new int[]{R.attr.actionIconDownCloud}).getResourceId(0, 0)))
|
|
.create();
|
|
|
|
staleDataDialog.show();
|
|
|
|
return staleDataDialog;
|
|
} else {
|
|
longToast(getString(R.string.downloadSessionsHint));
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
public void showFilePickerDialog(Activity activity, int requestCode, String action, String defaultName) {
|
|
if (Build.VERSION.SDK_INT >= 23) {
|
|
Intent intent = new Intent()
|
|
.setType("*/*");
|
|
|
|
if (action.equals("openfile")) {
|
|
intent.setAction(Intent.ACTION_OPEN_DOCUMENT);
|
|
} else if (action.equals("newfile")) {
|
|
intent.setAction(Intent.ACTION_CREATE_DOCUMENT);
|
|
intent.putExtra(Intent.EXTRA_TITLE, defaultName);
|
|
}
|
|
|
|
activity.startActivityForResult(Intent.createChooser(intent, "Select a file"), requestCode);
|
|
} else {
|
|
Intent i = new Intent(activity, FilePickerActivity.class);
|
|
i.putExtra(FilePickerActivity.EXTRA_ALLOW_MULTIPLE, false);
|
|
i.putExtra(FilePickerActivity.EXTRA_ALLOW_CREATE_DIR, true);
|
|
i.putExtra(FilePickerActivity.EXTRA_START_PATH, Environment.getExternalStorageDirectory().getPath());
|
|
|
|
if (action.equals("openfile")) {
|
|
i.putExtra(FilePickerActivity.EXTRA_MODE, FilePickerActivity.MODE_FILE);
|
|
i.putExtra(FilePickerActivity.EXTRA_PATHS, FilePickerActivity.MODE_FILE);
|
|
} else if (action.equals("newfile")) {
|
|
i.putExtra(FilePickerActivity.EXTRA_MODE, FilePickerActivity.MODE_NEW_FILE);
|
|
i.putExtra(FilePickerActivity.EXTRA_PATHS, FilePickerActivity.MODE_NEW_FILE);
|
|
}
|
|
|
|
activity.startActivityForResult(i, requestCode);
|
|
}
|
|
}
|
|
|
|
public Uri filePickerResult(Intent intent) {
|
|
if (Build.VERSION.SDK_INT >= 23) {
|
|
return intent.getData();
|
|
} else {
|
|
List<Uri> files = Utils.getSelectedFilesFromResult(intent);
|
|
for (Uri uri : files) {
|
|
return uri;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public void askToDonate(Activity activity) {
|
|
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
|
|
builder
|
|
.setIcon(getResources().getDrawable(getTheme().obtainStyledAttributes(getMATheme(true), new int[]{R.attr.actionIconInfo}).getResourceId(0, 0)))
|
|
.setTitle(getString(R.string.announcement))
|
|
.setMessage(getString(R.string.donate156))
|
|
.setPositiveButton(getString(R.string.donate),
|
|
new DialogInterface.OnClickListener() {
|
|
@Override
|
|
public void onClick(DialogInterface dialogInterface, int i) {
|
|
showDonationDialog(activity);
|
|
}
|
|
})
|
|
.setNegativeButton(getString(R.string.dismiss),
|
|
new DialogInterface.OnClickListener() {
|
|
@Override
|
|
public void onClick(DialogInterface dialogInterface, int i) {
|
|
}
|
|
})
|
|
.show();
|
|
}
|
|
|
|
public void showImportSessionsDialog(Activity activity) {
|
|
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
|
|
builder
|
|
.setIcon(getResources().getDrawable(getTheme().obtainStyledAttributes(getMATheme(true), new int[]{R.attr.actionIconForward}).getResourceId(0, 0)))
|
|
.setTitle(getString(R.string.importsessions))
|
|
.setMessage(getString(R.string.importsessions_utc_or_local))
|
|
.setPositiveButton(getString(R.string.utc),
|
|
new DialogInterface.OnClickListener() {
|
|
@Override
|
|
public void onClick(DialogInterface dialogInterface, int i) {
|
|
showFilePickerDialog(activity, SettingsActivity.FILEPICKER_IMPORT_SESSIONS_UTC, "openfile", "");
|
|
}
|
|
})
|
|
.setNegativeButton(getString(R.string.local),
|
|
new DialogInterface.OnClickListener() {
|
|
@Override
|
|
public void onClick(DialogInterface dialogInterface, int i) {
|
|
showFilePickerDialog(activity, SettingsActivity.FILEPICKER_IMPORT_SESSIONS_LOCAL, "openfile", "");
|
|
}
|
|
})
|
|
.show();
|
|
}
|
|
|
|
public void importSessions(Activity activity, Uri uri, boolean useLocalTimeZone) {
|
|
final Pattern lengthPattern = Pattern.compile("^[0-9]{1,2}:[0-9][0-9]$");
|
|
|
|
InputStreamReader inputfile;
|
|
try {
|
|
inputfile = new InputStreamReader(getContentResolver().openInputStream(uri));
|
|
} catch (FileNotFoundException e) {
|
|
e.printStackTrace();
|
|
return;
|
|
}
|
|
CSVReader reader = new CSVReader(inputfile);
|
|
|
|
long lengthHours, lengthMinutes;
|
|
Date startedDate, completedDate;
|
|
String[] lengthSplit;
|
|
|
|
DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm", Locale.getDefault());
|
|
TimeZone tz;
|
|
if (useLocalTimeZone) {
|
|
Calendar cal = Calendar.getInstance();
|
|
tz = cal.getTimeZone();
|
|
} else {
|
|
tz = TimeZone.getTimeZone("UTC");
|
|
}
|
|
df.setTimeZone(tz);
|
|
|
|
ArrayList<SessionSQL> sessions = new ArrayList<>();
|
|
int existingSessions = 0;
|
|
|
|
try {
|
|
List<String[]> data = reader.readAll();
|
|
int i = 0;
|
|
boolean foundHeader = false;
|
|
for (String[] d : data) {
|
|
i++;
|
|
if (d.length != CSV_COLUMN_COUNT) {
|
|
longToast("Invalid row on line #" + i + ": expected " + CSV_COLUMN_COUNT + " columns, found " + d.length);
|
|
closeCSVReader(reader, inputfile);
|
|
return;
|
|
} else if (d[0].trim().toLowerCase().equals("id")) {
|
|
if (foundHeader) {
|
|
longToast("Invalid row on line #" + i + ": header appears twice");
|
|
closeCSVReader(reader, inputfile);
|
|
return;
|
|
}
|
|
|
|
foundHeader = true;
|
|
continue;
|
|
}
|
|
|
|
SessionSQL s = new SessionSQL();
|
|
|
|
try {
|
|
if (!lengthPattern.matcher(d[1].trim()).matches()) {
|
|
throw new Exception();
|
|
}
|
|
|
|
lengthSplit = d[1].trim().split(":");
|
|
if (lengthSplit.length != 2) {
|
|
throw new Exception();
|
|
}
|
|
|
|
lengthHours = Long.parseLong(lengthSplit[0]);
|
|
lengthMinutes = Long.parseLong(lengthSplit[1]);
|
|
|
|
if (lengthHours < 0 || lengthMinutes < 0 || lengthHours > 24 || lengthMinutes > 59) {
|
|
throw new Exception();
|
|
}
|
|
|
|
s._length = (lengthHours * 3600) + (lengthMinutes * 60);
|
|
} catch (Exception e) {
|
|
longToast("Invalid row on line #" + i + ": invalid session length");
|
|
closeCSVReader(reader, inputfile);
|
|
return;
|
|
}
|
|
|
|
try {
|
|
if (d[2].trim().equals("")) {
|
|
throw new Exception();
|
|
}
|
|
|
|
startedDate = df.parse(d[2].trim());
|
|
s._started = startedDate.getTime() / 1000;
|
|
} catch (Exception e) {
|
|
longToast("Invalid row on line #" + i + ": invalid session started date/time");
|
|
closeCSVReader(reader, inputfile);
|
|
return;
|
|
}
|
|
|
|
try {
|
|
if (d[3].trim().equals("")) {
|
|
throw new Exception();
|
|
}
|
|
|
|
completedDate = df.parse(d[3].trim());
|
|
s._completed = completedDate.getTime() / 1000;
|
|
} catch (Exception e) {
|
|
longToast("Invalid row on line #" + i + ": invalid session completed date/time");
|
|
closeCSVReader(reader, inputfile);
|
|
return;
|
|
}
|
|
|
|
s._message = d[4].trim();
|
|
|
|
boolean existing = false;
|
|
for (int searchStarted = 0; searchStarted <= 59; searchStarted++) {
|
|
if (db.numSessionsByStarted(s._started + searchStarted) != 0) {
|
|
existing = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (existing) {
|
|
existingSessions++;
|
|
} else {
|
|
sessions.add(s);
|
|
}
|
|
}
|
|
|
|
closeCSVReader(reader, inputfile);
|
|
} catch (Exception e) {
|
|
e.printStackTrace();
|
|
longToast("Failed to write CSV file: " + e.toString());
|
|
}
|
|
|
|
if (sessions.size() == 0) {
|
|
longToast(getString(R.string.sessionsUpToDate));
|
|
return;
|
|
}
|
|
|
|
AlertDialog sessionsImportedDialog = new AlertDialog.Builder(activity)
|
|
.setIcon(getResources().getDrawable(getTheme().obtainStyledAttributes(getMATheme(true), new int[]{R.attr.actionIconForward}).getResourceId(0, 0)))
|
|
.setTitle(getString(R.string.importsessions))
|
|
.setMessage(String.format(getString(R.string.importsessions_complete), existingSessions, sessions.size()))
|
|
.setPositiveButton(getString(R.string.wordimport), new DialogInterface.OnClickListener() {
|
|
@Override
|
|
public void onClick(DialogInterface dialogInterface,
|
|
int which) {
|
|
for (SessionSQL s : sessions) {
|
|
db.addSession(s, (long) 0);
|
|
}
|
|
recalculateMeditationStreak(activity);
|
|
|
|
dialogInterface.dismiss();
|
|
}
|
|
})
|
|
.setNegativeButton(getString(R.string.cancel), new DialogInterface.OnClickListener() {
|
|
@Override
|
|
public void onClick(DialogInterface dialogInterface,
|
|
int which) {
|
|
dialogInterface.dismiss();
|
|
}
|
|
})
|
|
.create();
|
|
sessionsImportedDialog.show();
|
|
}
|
|
|
|
private void closeCSVReader(CSVReader reader, InputStreamReader file) {
|
|
try {
|
|
reader.close();
|
|
} catch (IOException e) {
|
|
// Do nothing
|
|
}
|
|
|
|
try {
|
|
file.close();
|
|
} catch (IOException e) {
|
|
// Do nothing
|
|
}
|
|
}
|
|
|
|
public void exportSessions(Activity activity, Uri uri) {
|
|
try {
|
|
FileOutputStream outputStream = (FileOutputStream) getContentResolver().openOutputStream(uri);
|
|
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream);
|
|
CSVWriter writer = new CSVWriter(outputStreamWriter);
|
|
List<String[]> data = new ArrayList<>();
|
|
|
|
ArrayList<SessionSQL> sessions = db.getAllSessions();
|
|
|
|
DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm", Locale.getDefault());
|
|
df.setTimeZone(TimeZone.getTimeZone("UTC"));
|
|
|
|
data.add(new String[]{"ID", "Length", "Started", "Completed", "Message"});
|
|
for (SessionSQL s : sessions) {
|
|
data.add(new String[]{Long.toString(s._id), String.format(Locale.getDefault(), "%02d:%02d", TimeUnit.SECONDS.toHours(s._length), TimeUnit.SECONDS.toMinutes(s._length) % TimeUnit.HOURS.toMinutes(1)), df.format(s._started * 1000), df.format(s._completed * 1000), s._message});
|
|
}
|
|
|
|
writer.writeAll(data);
|
|
writer.close();
|
|
} catch (IOException e) {
|
|
longToast(getString(R.string.sessionExportFailed) + ": " + e.toString() + " - " + uri.toString());
|
|
Log.e("MeditationAssistant", "Error exporting sessions to " + uri.toString(), e);
|
|
return;
|
|
}
|
|
longToast(getString(R.string.sessionExportWasSuccessful));
|
|
}
|
|
|
|
public void updateWidgets() {
|
|
Intent updateIntent = new Intent();
|
|
updateIntent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
|
|
getApplicationContext().sendBroadcast(updateIntent);
|
|
}
|
|
|
|
public void vibrateDevice(String pattern) {
|
|
ArrayList<Long> p = new ArrayList<Long>();
|
|
if (pattern.equals("short")) {
|
|
p.add((long) 110);
|
|
p.add((long) 225);
|
|
p.add((long) 110);
|
|
} else if (pattern.equals("medium")) {
|
|
p.add((long) 420);
|
|
p.add((long) 375);
|
|
p.add((long) 420);
|
|
} else if (pattern.equals("long")) {
|
|
p.add((long) 840);
|
|
p.add((long) 550);
|
|
p.add((long) 840);
|
|
} else {
|
|
String[] patternSplit = pattern.split(",");
|
|
for (String pp : patternSplit) {
|
|
pp = pp.trim();
|
|
if (pp.isEmpty() || !StringUtils.isNumeric(pp)) {
|
|
continue;
|
|
}
|
|
|
|
long ppv = Long.parseLong(pp);
|
|
if (ppv < 0L) {
|
|
ppv = 0L;
|
|
} else if (ppv > 15000L) {
|
|
ppv = 15000L;
|
|
}
|
|
p.add(ppv);
|
|
}
|
|
}
|
|
p.add(0, 0L);
|
|
|
|
try {
|
|
Vibrator vi = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
|
|
vi.vibrate(ArrayUtils.toPrimitive(p.toArray(new Long[p.size()])), -1);
|
|
} catch (Exception e) {
|
|
e.printStackTrace();
|
|
}
|
|
}
|
|
|
|
public boolean haveNotificationPermission() {
|
|
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
|
|
return true;
|
|
}
|
|
|
|
NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
|
|
return mNotificationManager.isNotificationPolicyAccessGranted();
|
|
}
|
|
|
|
public void checkNotificationControl(Activity activity, String prefValue) {
|
|
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
|
|
return;
|
|
}
|
|
|
|
String prefnotificationcontrol = prefValue;
|
|
if (prefnotificationcontrol.equals("")) {
|
|
prefnotificationcontrol = getPrefs().getString("pref_notificationcontrol", "");
|
|
}
|
|
if (!prefnotificationcontrol.equals("priority") && !prefnotificationcontrol.equals("alarms")) {
|
|
return; // Notification filter will not be changed
|
|
}
|
|
|
|
if (haveNotificationPermission()) {
|
|
return;
|
|
}
|
|
|
|
AlertDialog accountsAlertDialog = new AlertDialog.Builder(activity)
|
|
.setTitle(R.string.permissionRequest)
|
|
.setMessage(R.string.permissionRequestNotificationControl)
|
|
.setPositiveButton(android.R.string.ok, (dialogInterface, i) -> {
|
|
@SuppressLint("InlinedApi") Intent intent = new Intent(Settings.ACTION_NOTIFICATION_POLICY_ACCESS_SETTINGS);
|
|
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
|
startActivity(intent);
|
|
})
|
|
.create();
|
|
accountsAlertDialog.show();
|
|
}
|
|
|
|
public ArrayList<Long> dateToSessionWindow(Calendar c) {
|
|
ArrayList<Long> sessionWindow = new ArrayList<>();
|
|
ArrayList<Integer> streakbuffertime = getStreakBufferTime();
|
|
Calendar sessionWindowCalendar = (Calendar) c.clone();
|
|
|
|
sessionWindowCalendar.set(Calendar.HOUR_OF_DAY, streakbuffertime.get(0));
|
|
sessionWindowCalendar.set(Calendar.MINUTE, streakbuffertime.get(1));
|
|
sessionWindow.add(sessionWindowCalendar.getTimeInMillis() / 1000);
|
|
|
|
sessionWindowCalendar.add(Calendar.DATE, 1);
|
|
sessionWindowCalendar.set(Calendar.HOUR_OF_DAY, streakbuffertime.get(0));
|
|
sessionWindowCalendar.set(Calendar.MINUTE, streakbuffertime.get(1));
|
|
sessionWindow.add(sessionWindowCalendar.getTimeInMillis() / 1000);
|
|
|
|
return sessionWindow;
|
|
}
|
|
|
|
public String sessionToDate(SessionSQL session) {
|
|
if (session._completed != null) {
|
|
return timestampToDate(session._completed * 1000);
|
|
} else {
|
|
return timestampToDate((session._started + session._length) * 1000);
|
|
}
|
|
}
|
|
|
|
private String timestampToDate(long timestamp) {
|
|
SimpleDateFormat sdf = new SimpleDateFormat("d-M-yyyy", Locale.US);
|
|
|
|
Calendar cal = Calendar.getInstance();
|
|
cal.setTimeInMillis(timestamp);
|
|
Date api_date = cal.getTime();
|
|
|
|
return sdf.format(api_date);
|
|
}
|
|
|
|
public void sendLogcat() {
|
|
StringBuilder logcat = new StringBuilder();
|
|
Runtime rt = Runtime.getRuntime();
|
|
String[] commands = {"logcat", "-d"};
|
|
Process proc;
|
|
try {
|
|
proc = rt.exec(commands);
|
|
|
|
BufferedReader stdInput = new BufferedReader(new
|
|
InputStreamReader(proc.getInputStream()));
|
|
|
|
BufferedReader stdError = new BufferedReader(new
|
|
InputStreamReader(proc.getErrorStream()));
|
|
|
|
String s;
|
|
while ((s = stdError.readLine()) != null) {
|
|
logcat.append("Logcat error: ").append(s).append("\n");
|
|
}
|
|
logcat.append("Logcat output:\n");
|
|
while ((s = stdInput.readLine()) != null) {
|
|
logcat.append(s).append("\n");
|
|
}
|
|
} catch (IOException e) {
|
|
e.printStackTrace();
|
|
shortToast("Failed to retrieve logcat");
|
|
return;
|
|
}
|
|
|
|
Intent e = new Intent(Intent.ACTION_SENDTO, Uri.fromParts("mailto", getString(R.string.myEmailAddress), null));
|
|
String[] to = {getString(R.string.myEmailAddress)};
|
|
e.putExtra(Intent.EXTRA_EMAIL, to);
|
|
e.putExtra(Intent.EXTRA_SUBJECT, "Meditation Assistant Debug Log");
|
|
e.putExtra(Intent.EXTRA_TEXT, logcat.toString());
|
|
startActivity(Intent.createChooser(e, getString(R.string.sendEmail)));
|
|
}
|
|
|
|
public String getMAAppVersion() {
|
|
if (appVersion == null) {
|
|
appVersion = "";
|
|
try {
|
|
PackageInfo pInfo = getPackageManager().getPackageInfo(
|
|
getPackageName(), 0);
|
|
appVersion = pInfo.versionName;
|
|
} catch (PackageManager.NameNotFoundException e) {
|
|
e.printStackTrace();
|
|
}
|
|
}
|
|
|
|
return appVersion;
|
|
}
|
|
|
|
public int getMAAppVersionNumber() {
|
|
return BuildConfig.VERSION_CODE;
|
|
}
|
|
|
|
public String acquireWakeLock(Boolean fullWakeUp) {
|
|
wakeLockerLock.lock();
|
|
String wakelockID = wakeLocker.acquire(getApplicationContext(), fullWakeUp);
|
|
wakeLockerLock.unlock();
|
|
|
|
return wakelockID;
|
|
}
|
|
|
|
public void releaseWakeLock(String wakeLockID) {
|
|
wakeLockerLock.lock();
|
|
wakeLocker.release(wakeLockID);
|
|
wakeLockerLock.unlock();
|
|
}
|
|
|
|
public void releaseAllWakeLocks() {
|
|
wakeLockerLock.lock();
|
|
wakeLocker.releaseAll();
|
|
wakeLockerLock.unlock();
|
|
}
|
|
|
|
public static boolean writeInputStreamToFile(InputStream in, File file) {
|
|
OutputStream out = null;
|
|
try {
|
|
out = new FileOutputStream(file);
|
|
byte[] buf = new byte[1024];
|
|
int len;
|
|
while ((len = in.read(buf)) > 0) {
|
|
out.write(buf, 0, len);
|
|
}
|
|
} catch (Exception e) {
|
|
e.printStackTrace();
|
|
return false;
|
|
} finally {
|
|
try {
|
|
if (out != null) {
|
|
out.close();
|
|
}
|
|
in.close();
|
|
} catch (IOException e) {
|
|
e.printStackTrace();
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
@Override
|
|
protected void attachBaseContext(Context base) {
|
|
super.attachBaseContext(base);
|
|
MultiDex.install(this);
|
|
}
|
|
|
|
public static int extraPendingIntentFlags() {
|
|
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) {
|
|
return 0;
|
|
}
|
|
return PendingIntent.FLAG_MUTABLE;
|
|
}
|
|
}
|