diff options
8 files changed, 91 insertions, 16 deletions
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 4b97efb8..53394d05 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -24,6 +24,8 @@ <uses-permission android:name="android.permission.WAKE_LOCK" /> + <uses-permission android:name="android.permission.POST_NOTIFICATIONS"/> + <application android:name=".Infinity" android:allowBackup="false" diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/AppModule.java b/app/src/main/java/ml/docilealligator/infinityforreddit/AppModule.java index 6fac70b3..44d4486f 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/AppModule.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/AppModule.java @@ -137,6 +137,13 @@ abstract class AppModule { } @Provides + @Named("internal") + @Singleton + static SharedPreferences provideInternalSharedPreferences(Application application) { + return application.getSharedPreferences(SharedPreferencesUtils.INTERNAL_SHARED_PREFERENCES_FILE, Context.MODE_PRIVATE); + } + + @Provides @Singleton static CustomThemeWrapper provideCustomThemeWrapper(@Named("light_theme") SharedPreferences lightThemeSharedPreferences, @Named("dark_theme") SharedPreferences darkThemeSharedPreferences, diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/PullNotificationWorker.java b/app/src/main/java/ml/docilealligator/infinityforreddit/PullNotificationWorker.java index 9a36071d..5c54be73 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/PullNotificationWorker.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/PullNotificationWorker.java @@ -72,6 +72,12 @@ public class PullNotificationWorker extends Worker { @NonNull @Override public Result doWork() { + NotificationManagerCompat notificationManager = NotificationUtils.getNotificationManager(context); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU && !notificationManager.areNotificationsEnabled()) { + return Result.success(); + } + try { List<Account> accounts = mRedditDataRoomDatabase.accountDao().getAllAccounts(); int color = mCustomThemeWrapper.getColorPrimaryLightTheme(); @@ -89,8 +95,6 @@ public class PullNotificationWorker extends Worker { context.getResources().getConfiguration().locale, FetchMessage.MESSAGE_TYPE_NOTIFICATION); if (!messages.isEmpty()) { - NotificationManagerCompat notificationManager = NotificationUtils.getNotificationManager(context); - NotificationCompat.Builder summaryBuilder = NotificationUtils.buildSummaryNotification(context, notificationManager, accountName, context.getString(R.string.notification_new_messages, messages.size()), diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/MainActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/MainActivity.java index ef3f6858..43d41e8a 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/MainActivity.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/MainActivity.java @@ -3,16 +3,19 @@ package ml.docilealligator.infinityforreddit.activities; import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_NO; import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_YES; +import android.Manifest; import android.app.Activity; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; +import android.content.pm.PackageManager; import android.graphics.Color; import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.text.Editable; import android.text.TextWatcher; +import android.util.Log; import android.view.Gravity; import android.view.KeyEvent; import android.view.Menu; @@ -24,12 +27,16 @@ import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputMethodManager; import android.widget.Toast; +import androidx.activity.result.ActivityResultCallback; +import androidx.activity.result.ActivityResultLauncher; +import androidx.activity.result.contract.ActivityResultContracts; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.appcompat.app.ActionBarDrawerToggle; import androidx.appcompat.app.AppCompatDelegate; import androidx.coordinatorlayout.widget.CoordinatorLayout; import androidx.core.app.ActivityCompat; +import androidx.core.content.ContextCompat; import androidx.drawerlayout.widget.DrawerLayout; import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentActivity; @@ -200,6 +207,9 @@ public class MainActivity extends BaseActivity implements SortTypeSelectionCallb @Named("security") SharedPreferences mSecuritySharedPreferences; @Inject + @Named("internal") + SharedPreferences mInternalSharedPreferences; + @Inject CustomThemeWrapper mCustomThemeWrapper; @Inject Executor mExecutor; @@ -351,6 +361,16 @@ public class MainActivity extends BaseActivity implements SortTypeSelectionCallb } private void initializeNotificationAndBindView() { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + ActivityResultLauncher<String> requestNotificationPermissionLauncher = registerForActivityResult(new ActivityResultContracts.RequestPermission(), result -> mInternalSharedPreferences.edit().putBoolean(SharedPreferencesUtils.HAS_REQUESTED_NOTIFICATION_PERMISSION, true).apply()); + + if (ContextCompat.checkSelfPermission(this, Manifest.permission.POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED) { + if (!mInternalSharedPreferences.getBoolean(SharedPreferencesUtils.HAS_REQUESTED_NOTIFICATION_PERMISSION, false)) { + requestNotificationPermissionLauncher.launch(Manifest.permission.POST_NOTIFICATIONS); + } + } + } + boolean enableNotification = mSharedPreferences.getBoolean(SharedPreferencesUtils.ENABLE_NOTIFICATION_KEY, true); long notificationInterval = Long.parseLong(mSharedPreferences.getString(SharedPreferencesUtils.NOTIFICATION_INTERVAL_KEY, "1")); TimeUnit timeUnit = (notificationInterval == 15 || notificationInterval == 30) ? TimeUnit.MINUTES : TimeUnit.HOURS; diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/SettingsActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/SettingsActivity.java index 5705e3eb..e0b584b4 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/SettingsActivity.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/SettingsActivity.java @@ -4,16 +4,16 @@ import android.content.SharedPreferences; import android.os.Build; import android.os.Bundle; import android.view.MenuItem; +import android.view.View; import androidx.annotation.NonNull; -import androidx.appcompat.widget.Toolbar; import androidx.core.app.ActivityCompat; import androidx.fragment.app.Fragment; import androidx.preference.Preference; import androidx.preference.PreferenceFragmentCompat; -import com.google.android.material.appbar.AppBarLayout; -import com.google.android.material.appbar.CollapsingToolbarLayout; +import com.google.android.material.snackbar.BaseTransientBottomBar; +import com.google.android.material.snackbar.Snackbar; import org.greenrobot.eventbus.EventBus; import org.greenrobot.eventbus.Subscribe; @@ -22,11 +22,11 @@ import org.greenrobot.eventbus.ThreadMode; import javax.inject.Inject; import javax.inject.Named; -import butterknife.BindView; import butterknife.ButterKnife; import ml.docilealligator.infinityforreddit.Infinity; import ml.docilealligator.infinityforreddit.R; import ml.docilealligator.infinityforreddit.customtheme.CustomThemeWrapper; +import ml.docilealligator.infinityforreddit.databinding.ActivitySettingsBinding; import ml.docilealligator.infinityforreddit.events.RecreateActivityEvent; import ml.docilealligator.infinityforreddit.settings.AboutPreferenceFragment; import ml.docilealligator.infinityforreddit.settings.AdvancedPreferenceFragment; @@ -46,12 +46,7 @@ public class SettingsActivity extends BaseActivity implements private static final String TITLE_STATE = "TS"; - @BindView(R.id.appbar_layout_settings_activity) - AppBarLayout appBarLayout; - @BindView(R.id.collapsing_toolbar_layout_settings_activity) - CollapsingToolbarLayout collapsingToolbarLayout; - @BindView(R.id.toolbar_settings_activity) - Toolbar toolbar; + private ActivitySettingsBinding binding; private String mAccountName; @Inject @@ -71,7 +66,8 @@ public class SettingsActivity extends BaseActivity implements super.onCreate(savedInstanceState); - setContentView(R.layout.activity_settings); + binding = ActivitySettingsBinding.inflate(getLayoutInflater()); + setContentView(binding.getRoot()); ButterKnife.bind(this); @@ -80,10 +76,10 @@ public class SettingsActivity extends BaseActivity implements applyCustomTheme(); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && isChangeStatusBarIconColor()) { - addOnOffsetChangedListener(appBarLayout); + addOnOffsetChangedListener(binding.appbarLayoutSettingsActivity); } - setSupportActionBar(toolbar); + setSupportActionBar(binding.toolbarSettingsActivity); mAccountName = mCurrentAccountSharedPreferences.getString(SharedPreferencesUtils.ACCOUNT_NAME, null); @@ -130,7 +126,8 @@ public class SettingsActivity extends BaseActivity implements @Override protected void applyCustomTheme() { - applyAppBarLayoutAndCollapsingToolbarLayoutAndToolbarTheme(appBarLayout, collapsingToolbarLayout, toolbar); + applyAppBarLayoutAndCollapsingToolbarLayoutAndToolbarTheme(binding.appbarLayoutSettingsActivity, + binding.collapsingToolbarLayoutSettingsActivity, binding.toolbarSettingsActivity); } @Override @@ -190,6 +187,10 @@ public class SettingsActivity extends BaseActivity implements EventBus.getDefault().unregister(this); } + public void showSnackbar(int stringId, int actionStringId, View.OnClickListener onClickListener) { + Snackbar.make(binding.getRoot(), stringId, BaseTransientBottomBar.LENGTH_SHORT).setAction(actionStringId, onClickListener).show(); + } + @Subscribe(threadMode = ThreadMode.MAIN) public void onRecreateActivityEvent(RecreateActivityEvent recreateActivityEvent) { ActivityCompat.recreate(this); diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/settings/NotificationPreferenceFragment.java b/app/src/main/java/ml/docilealligator/infinityforreddit/settings/NotificationPreferenceFragment.java index 5316a4fc..7ba9e869 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/settings/NotificationPreferenceFragment.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/settings/NotificationPreferenceFragment.java @@ -1,9 +1,19 @@ package ml.docilealligator.infinityforreddit.settings; +import android.Manifest; +import android.content.Intent; import android.content.SharedPreferences; +import android.content.pm.PackageManager; +import android.net.Uri; +import android.os.Build; import android.os.Bundle; +import android.provider.Settings; +import android.view.View; +import androidx.activity.result.ActivityResultLauncher; +import androidx.activity.result.contract.ActivityResultContracts; +import androidx.core.content.ContextCompat; import androidx.fragment.app.Fragment; import androidx.preference.ListPreference; import androidx.preference.SwitchPreference; @@ -32,6 +42,9 @@ public class NotificationPreferenceFragment extends CustomFontPreferenceFragment @Inject @Named("default") SharedPreferences sharedPreferences; + @Inject + @Named("internal") + SharedPreferences mInternalSharedPreferences; private boolean enableNotification; private long notificationInterval; private WorkManager workManager; @@ -113,5 +126,27 @@ public class NotificationPreferenceFragment extends CustomFontPreferenceFragment return true; }); } + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + ActivityResultLauncher<String> requestNotificationPermissionLauncher = registerForActivityResult(new ActivityResultContracts.RequestPermission(), result -> { + mInternalSharedPreferences.edit().putBoolean(SharedPreferencesUtils.HAS_REQUESTED_NOTIFICATION_PERMISSION, true).apply(); + if (!result) { + activity.showSnackbar(R.string.denied_notification_permission, R.string.go_to_settings, new View.OnClickListener() { + @Override + public void onClick(View view) { + Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + Uri uri = Uri.fromParts("package", activity.getPackageName(), null); + intent.setData(uri); + startActivity(intent); + } + }); + } + }); + + if (ContextCompat.checkSelfPermission(activity, Manifest.permission.POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED) { + requestNotificationPermissionLauncher.launch(Manifest.permission.POST_NOTIFICATIONS); + } + } } } diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/utils/SharedPreferencesUtils.java b/app/src/main/java/ml/docilealligator/infinityforreddit/utils/SharedPreferencesUtils.java index 389bcf83..e530b853 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/utils/SharedPreferencesUtils.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/utils/SharedPreferencesUtils.java @@ -364,6 +364,9 @@ public class SharedPreferencesUtils { public static final String APP_LOCK_TIMEOUT = "app_lock_timeout"; public static final String LAST_FOREGROUND_TIME = "last_foreground_time"; + public static final String INTERNAL_SHARED_PREFERENCES_FILE = "ml.docilealligator.infinityforreddit.internal"; + public static final String HAS_REQUESTED_NOTIFICATION_PERMISSION = "has_requested_notification_permission"; + //Legacy Settings public static final String MAIN_PAGE_TAB_1_TITLE_LEGACY = "main_page_tab_1_title"; public static final String MAIN_PAGE_TAB_2_TITLE_LEGACY = "main_page_tab_2_title"; diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 41c1bcb2..51f70012 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1318,4 +1318,7 @@ <string name="image_index_in_gallery">%1$d/%2$d</string> + <string name="denied_notification_permission">Notification permission is not granted</string> + <string name="go_to_settings">Settings</string> + </resources> |