Skip to content

Commit

Permalink
Merge pull request #3 from akaMrNagar/dev
Browse files Browse the repository at this point in the history
Major improvements and bug fixes
  • Loading branch information
akaMrNagar authored Dec 23, 2024
2 parents cf6f6dd + b98c6a8 commit 9f3ef2b
Show file tree
Hide file tree
Showing 50 changed files with 1,352 additions and 836 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ migrate_working_dir/
.pub-cache/
.pub/
/build/
untranslated_strings.json

# Symbolication related
app.*.symbols
Expand Down
133 changes: 42 additions & 91 deletions android/app/src/main/java/com/mindful/android/MainActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,23 +12,16 @@

package com.mindful.android;

import static com.mindful.android.generics.ServiceBinder.ACTION_START_MINDFUL_SERVICE;
import static com.mindful.android.helpers.NewActivitiesLaunchHelper.INTENT_EXTRA_IS_SELF_RESTART;
import static com.mindful.android.services.EmergencyPauseService.ACTION_START_SERVICE_EMERGENCY;
import static com.mindful.android.services.FocusSessionService.ACTION_START_FOCUS_SERVICE;
import static com.mindful.android.services.OverlayDialogService.INTENT_EXTRA_PACKAGE_NAME;

import android.annotation.SuppressLint;
import android.app.AlarmManager;
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.PowerManager;
import android.provider.Settings;
import android.widget.Toast;

import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

Expand Down Expand Up @@ -66,17 +59,29 @@ public class MainActivity extends FlutterFragmentActivity implements MethodChann
private SafeServiceConnection<MindfulTrackerService> mTrackerServiceConn;
private SafeServiceConnection<MindfulVpnService> mVpnServiceConn;
private SafeServiceConnection<FocusSessionService> mFocusServiceConn;
private ActivityResultLauncher<Intent> mVpnPermissionLauncher;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

// Store uncaught exceptions
Thread.setDefaultUncaughtExceptionHandler((thread, exception) -> SharedPrefsHelper.insertCrashLogToPrefs(this, exception));

// Register notification channels
NotificationHelper.registerNotificationChannels(this);

// Schedule midnight 12 task if already not scheduled
AlarmTasksSchedulingHelper.scheduleMidnightResetTask(this, true);

// register permission launcher for result
mVpnPermissionLauncher = registerForActivityResult(
new ActivityResultContracts.StartActivityForResult(),
result -> {
// Ignored
}
);

// Initialize service connections
mTrackerServiceConn = new SafeServiceConnection<>(MindfulTrackerService.class, this);
mVpnServiceConn = new SafeServiceConnection<>(MindfulVpnService.class, this);
Expand Down Expand Up @@ -152,7 +157,15 @@ public void onMethodCall(@NonNull MethodCall call, @NonNull MethodChannel.Result
result.success(true);
break;
}

case "getNativeCrashLogs": {
result.success(SharedPrefsHelper.getCrashLogsArrayString(this));
break;
}
case "clearNativeCrashLogs": {
SharedPrefsHelper.clearCrashLogs(this);
result.success(true);
break;
}
// SECTION: Foreground service and Worker methods ---------------------------------------------------------------------------
case "updateAppRestrictions": {
HashMap<String, AppRestrictions> appRestrictions = SharedPrefsHelper.getSetAppRestrictions(this, Utils.notNullStr(call.arguments()));
Expand All @@ -172,7 +185,7 @@ public void onMethodCall(@NonNull MethodCall call, @NonNull MethodChannel.Result
mVpnServiceConn.getService().updateBlockedApps(blockedApps);
} else if (!blockedApps.isEmpty() && getAndAskVpnPermission(false)) {
mVpnServiceConn.setOnConnectedCallback(service -> service.updateBlockedApps(blockedApps));
mVpnServiceConn.startAndBind(MindfulVpnService.ACTION_START_SERVICE_VPN);
mVpnServiceConn.startAndBind();
}
result.success(true);
break;
Expand All @@ -189,6 +202,9 @@ public void onMethodCall(@NonNull MethodCall call, @NonNull MethodChannel.Result
AlarmTasksSchedulingHelper.scheduleBedtimeRoutineTasks(this, bedtimeSettings);
} else {
AlarmTasksSchedulingHelper.cancelBedtimeRoutineTasks(this);
if (bedtimeSettings.shouldStartDnd) {
NotificationHelper.toggleDnd(this, false);
}
}
result.success(true);
break;
Expand All @@ -197,7 +213,7 @@ public void onMethodCall(@NonNull MethodCall call, @NonNull MethodChannel.Result
if (!Utils.isServiceRunning(this, EmergencyPauseService.class.getName())
&& Utils.isServiceRunning(this, MindfulTrackerService.class.getName())
) {
startService(new Intent(getApplicationContext(), EmergencyPauseService.class).setAction(ACTION_START_SERVICE_EMERGENCY));
startService(new Intent(getApplicationContext(), EmergencyPauseService.class).setAction(ACTION_START_MINDFUL_SERVICE));
result.success(true);
} else {
result.success(false);
Expand All @@ -210,7 +226,7 @@ public void onMethodCall(@NonNull MethodCall call, @NonNull MethodChannel.Result
mFocusServiceConn.getService().updateFocusSession(focusSession);
} else {
mFocusServiceConn.setOnConnectedCallback(service -> service.startFocusSession(focusSession));
mFocusServiceConn.startAndBind(ACTION_START_FOCUS_SERVICE);
mFocusServiceConn.startAndBind();
}
result.success(true);
break;
Expand Down Expand Up @@ -246,19 +262,19 @@ public void onMethodCall(@NonNull MethodCall call, @NonNull MethodChannel.Result
break;
}
case "getAndAskIgnoreBatteryOptimizationPermission": {
result.success(getAndAskIgnoreBatteryOptimizationPermission(Boolean.TRUE.equals(call.arguments())));
break;
}
case "getAndAskVpnPermission": {
result.success(getAndAskVpnPermission(Boolean.TRUE.equals(call.arguments())));
result.success(PermissionsHelper.getAndAskIgnoreBatteryOptimizationPermission(this, Boolean.TRUE.equals(call.arguments())));
break;
}
case "getAndAskDisplayOverlayPermission": {
result.success(getAndAskDisplayOverlayPermission(Boolean.TRUE.equals(call.arguments())));
result.success(PermissionsHelper.getAndAskDisplayOverlayPermission(this, Boolean.TRUE.equals(call.arguments())));
break;
}
case "getAndAskExactAlarmPermission": {
result.success(getAndAskExactAlarmPermission(Boolean.TRUE.equals(call.arguments())));
result.success(PermissionsHelper.getAndAskExactAlarmPermission(this, Boolean.TRUE.equals(call.arguments())));
break;
}
case "getAndAskVpnPermission": {
result.success(getAndAskVpnPermission(Boolean.TRUE.equals(call.arguments())));
break;
}
case "disableDeviceAdmin": {
Expand All @@ -269,12 +285,12 @@ public void onMethodCall(@NonNull MethodCall call, @NonNull MethodChannel.Result

// SECTION: New Activity Launch methods ------------------------------------------------------
case "openAppWithPackage": {
NewActivitiesLaunchHelper.openAppWithPackage(this, call.arguments());
NewActivitiesLaunchHelper.openAppWithPackage(this, Utils.notNullStr(call.arguments()));
result.success(true);
break;
}
case "openAppSettingsForPackage": {
NewActivitiesLaunchHelper.openSettingsForPackage(this, call.arguments());
NewActivitiesLaunchHelper.openSettingsForPackage(this, Utils.notNullStr(call.arguments()));
result.success(true);
break;
}
Expand Down Expand Up @@ -328,7 +344,7 @@ private void updateTrackerServiceRestrictions(
|| (restrictionGroups != null && !restrictionGroups.isEmpty())
) {
mTrackerServiceConn.setOnConnectedCallback(service -> service.updateRestrictionData(appRestrictions, restrictionGroups));
mTrackerServiceConn.startAndBind(MindfulTrackerService.ACTION_START_RESTRICTION_MODE);
mTrackerServiceConn.startAndBind();
}
}

Expand All @@ -340,77 +356,12 @@ private void updateTrackerServiceRestrictions(
*/
private boolean getAndAskVpnPermission(boolean askPermissionToo) {
Intent intent = MindfulVpnService.prepare(this);
if (askPermissionToo && intent != null) {
startActivityForResult(intent, 0);
if (askPermissionToo && intent != null && mVpnPermissionLauncher != null) {
mVpnPermissionLauncher.launch(intent);
}
return intent == null;
}

/**
* Checks if the Display Over Other Apps permission is granted and optionally asks for it if not granted.
*
* @param askPermissionToo Whether to prompt the user to enable Display Over Other Apps permission if not granted.
* @return True if Display Over Other Apps permission is granted, false otherwise.
*/
private boolean getAndAskDisplayOverlayPermission(boolean askPermissionToo) {
if (Settings.canDrawOverlays(this)) return true;

if (askPermissionToo) {
Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
intent.setData(android.net.Uri.parse("package:" + getPackageName()));
startActivityForResult(intent, 0);
Toast.makeText(this, "Please allow Mindful to display overlay", Toast.LENGTH_LONG).show();
}
return false;
}

/**
* Checks if the Set Exact Alarm permission is granted and optionally asks for it if not granted.
*
* @param askPermissionToo Whether to prompt the user to enable Set Exact Alarm permission if not granted.
* @return True if Set Exact Alarm permission is granted, false otherwise.
*/
public boolean getAndAskExactAlarmPermission(boolean askPermissionToo) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) return true;

AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
if (alarmManager.canScheduleExactAlarms()) return true;

if (askPermissionToo) {
Intent intent = new Intent(Settings.ACTION_REQUEST_SCHEDULE_EXACT_ALARM);
intent.setData(android.net.Uri.parse("package:" + getPackageName()));
startActivityForResult(intent, 0);
}
return false;
}

/**
* Checks if the Ignore Battery Optimization permission is granted and optionally asks for it if not granted.
*
* @param askPermissionToo Whether to prompt the user to enable Ignore Battery Optimization permission if not granted.
* @return True if Ignore Battery Optimization permission is granted, false otherwise.
*/
public boolean getAndAskIgnoreBatteryOptimizationPermission(boolean askPermissionToo) {
PowerManager powerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
if (powerManager.isIgnoringBatteryOptimizations(getPackageName())) return true;

if (askPermissionToo) {
@SuppressLint("BatteryLife") Intent intent = new Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
intent.setData(Uri.parse("package:" + getPackageName()));
startActivityForResult(intent, 0);
}
return false;
}

@Override
protected void onStop() {
super.onStop();
// Notify VPN service that it can restart if needed
if (mVpnServiceConn.isConnected()) {
mVpnServiceConn.getService().onApplicationStop();
}
}

@Override
protected void onDestroy() {
super.onDestroy();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@

package com.mindful.android.generics;

import static com.mindful.android.generics.ServiceBinder.ACTION_BIND_TO_MINDFUL;
import static com.mindful.android.generics.ServiceBinder.ACTION_START_MINDFUL_SERVICE;

import android.app.Service;
import android.content.ComponentName;
import android.content.Context;
Expand All @@ -31,7 +34,6 @@
* @param <T> The type of Service this class is designed to connect to.
*/
public class SafeServiceConnection<T extends Service> implements ServiceConnection {

private final Class<T> mServiceClass;
private final Context mContext;
private T mService = null;
Expand All @@ -50,15 +52,19 @@ public SafeServiceConnection(Class<T> serviceClass, @NonNull Context context) {
mContext = context.getApplicationContext();
}

@SuppressWarnings("unchecked")
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mService = ((ServiceBinder<T>) service).getService();

if (mService != null) {
mIsBound = true;
if (mConnectionSuccessCallback != null) {
mConnectionSuccessCallback.onSuccess(mService);
public void onServiceConnected(ComponentName name, IBinder binder) {
try {
mService = ((ServiceBinder<T>) binder).getService();

if (mService != null) {
mIsBound = true;
if (mConnectionSuccessCallback != null) {
mConnectionSuccessCallback.onSuccess(mService);
}
}
} catch (Exception ignored) {
}
}

Expand Down Expand Up @@ -91,7 +97,9 @@ public boolean isConnected() {
public void bindService() {
if (!mIsBound && Utils.isServiceRunning(mContext, mServiceClass.getName())) {
try {
mContext.bindService(new Intent(mContext, mServiceClass), this, Context.BIND_WAIVE_PRIORITY);
Intent bindIntent = new Intent(mContext, mServiceClass);
bindIntent.setAction(ACTION_BIND_TO_MINDFUL);
mContext.bindService(bindIntent, this, Context.BIND_WAIVE_PRIORITY);
} catch (Exception e) {
Log.e("Mindful.SafeServiceConnection", "bindService: Failed to bind " + mServiceClass.getName(), e);

Expand Down Expand Up @@ -120,9 +128,9 @@ public void unBindService() {
/**
* Starts and binds the service if it is not already running.
*/
public void startAndBind(String action) {
public void startAndBind() {
if (!Utils.isServiceRunning(mContext, mServiceClass.getName())) {
mContext.startService(new Intent(mContext, mServiceClass).setAction(action));
mContext.startService(new Intent(mContext, mServiceClass).setAction(ACTION_START_MINDFUL_SERVICE));
}
bindService();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

package com.mindful.android.generics;

import android.app.Service;
import android.os.Binder;

/**
Expand All @@ -20,8 +21,9 @@
*
* @param <T> The type of the service being bound.
*/
public class ServiceBinder<T> extends Binder {
// public static final String ACTION_START_SERVICE = "com.mindful.android.service.START";
public class ServiceBinder<T extends Service> extends Binder {
public static final String ACTION_START_MINDFUL_SERVICE = "com.mindful.android.ServiceBinder.ACTION_START_MINDFUL_SERVICE";
public static final String ACTION_BIND_TO_MINDFUL = "com.mindful.android.ServiceBinder.ACTION_BIND_TO_MINDFUL";


private final T mService;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,12 @@
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.Handler;
import android.util.Log;

import androidx.annotation.NonNull;

import com.mindful.android.generics.SafeServiceConnection;
import com.mindful.android.models.BedtimeSettings;
import com.mindful.android.receivers.alarm.BedtimeRoutineReceiver;
import com.mindful.android.receivers.alarm.MidnightResetReceiver;
Expand Down Expand Up @@ -123,15 +125,13 @@ public static void cancelBedtimeRoutineTasks(@NonNull Context context) {
alarmManager.cancel(startPendingIntent);
alarmManager.cancel(stopPendingIntent);

// Turn off Dnd
NotificationHelper.toggleDnd(context, false);

// Let service know
if (Utils.isServiceRunning(context, MindfulTrackerService.class.getName())) {
Intent serviceIntent = new Intent(context.getApplicationContext(), MindfulTrackerService.class).setAction(MindfulTrackerService.ACTION_STOP_BEDTIME_MODE);
context.startService(serviceIntent);
SafeServiceConnection<MindfulTrackerService> conn = new SafeServiceConnection<>(MindfulTrackerService.class, context);
conn.setOnConnectedCallback(s -> s.startStopBedtimeMode(null));
conn.bindService();
conn.unBindService();
}

Log.d(TAG, "cancelBedtimeRoutineTasks: Bedtime routine tasks cancelled successfully");
}

Expand Down
Loading

0 comments on commit 9f3ef2b

Please sign in to comment.