Notification permission.

This commit is contained in:
Docile-Alligator 2022-12-04 06:15:13 +11:00
parent 4af9e3d161
commit 605129517e
8 changed files with 91 additions and 16 deletions

View File

@ -24,6 +24,8 @@
<uses-permission android:name="android.permission.WAKE_LOCK" /> <uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
<application <application
android:name=".Infinity" android:name=".Infinity"
android:allowBackup="false" android:allowBackup="false"

View File

@ -136,6 +136,13 @@ abstract class AppModule {
return application.getSharedPreferences(SharedPreferencesUtils.SECURITY_SHARED_PREFERENCES_FILE, Context.MODE_PRIVATE); return application.getSharedPreferences(SharedPreferencesUtils.SECURITY_SHARED_PREFERENCES_FILE, Context.MODE_PRIVATE);
} }
@Provides
@Named("internal")
@Singleton
static SharedPreferences provideInternalSharedPreferences(Application application) {
return application.getSharedPreferences(SharedPreferencesUtils.INTERNAL_SHARED_PREFERENCES_FILE, Context.MODE_PRIVATE);
}
@Provides @Provides
@Singleton @Singleton
static CustomThemeWrapper provideCustomThemeWrapper(@Named("light_theme") SharedPreferences lightThemeSharedPreferences, static CustomThemeWrapper provideCustomThemeWrapper(@Named("light_theme") SharedPreferences lightThemeSharedPreferences,

View File

@ -72,6 +72,12 @@ public class PullNotificationWorker extends Worker {
@NonNull @NonNull
@Override @Override
public Result doWork() { public Result doWork() {
NotificationManagerCompat notificationManager = NotificationUtils.getNotificationManager(context);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU && !notificationManager.areNotificationsEnabled()) {
return Result.success();
}
try { try {
List<Account> accounts = mRedditDataRoomDatabase.accountDao().getAllAccounts(); List<Account> accounts = mRedditDataRoomDatabase.accountDao().getAllAccounts();
int color = mCustomThemeWrapper.getColorPrimaryLightTheme(); int color = mCustomThemeWrapper.getColorPrimaryLightTheme();
@ -89,8 +95,6 @@ public class PullNotificationWorker extends Worker {
context.getResources().getConfiguration().locale, FetchMessage.MESSAGE_TYPE_NOTIFICATION); context.getResources().getConfiguration().locale, FetchMessage.MESSAGE_TYPE_NOTIFICATION);
if (!messages.isEmpty()) { if (!messages.isEmpty()) {
NotificationManagerCompat notificationManager = NotificationUtils.getNotificationManager(context);
NotificationCompat.Builder summaryBuilder = NotificationUtils.buildSummaryNotification(context, NotificationCompat.Builder summaryBuilder = NotificationUtils.buildSummaryNotification(context,
notificationManager, accountName, notificationManager, accountName,
context.getString(R.string.notification_new_messages, messages.size()), context.getString(R.string.notification_new_messages, messages.size()),

View File

@ -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_NO;
import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_YES; import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_YES;
import android.Manifest;
import android.app.Activity; import android.app.Activity;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.graphics.Color; import android.graphics.Color;
import android.os.Build; import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.text.Editable; import android.text.Editable;
import android.text.TextWatcher; import android.text.TextWatcher;
import android.util.Log;
import android.view.Gravity; import android.view.Gravity;
import android.view.KeyEvent; import android.view.KeyEvent;
import android.view.Menu; import android.view.Menu;
@ -24,12 +27,16 @@ import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager; import android.view.inputmethod.InputMethodManager;
import android.widget.Toast; 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.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.appcompat.app.ActionBarDrawerToggle; import androidx.appcompat.app.ActionBarDrawerToggle;
import androidx.appcompat.app.AppCompatDelegate; import androidx.appcompat.app.AppCompatDelegate;
import androidx.coordinatorlayout.widget.CoordinatorLayout; import androidx.coordinatorlayout.widget.CoordinatorLayout;
import androidx.core.app.ActivityCompat; import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.drawerlayout.widget.DrawerLayout; import androidx.drawerlayout.widget.DrawerLayout;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity; import androidx.fragment.app.FragmentActivity;
@ -200,6 +207,9 @@ public class MainActivity extends BaseActivity implements SortTypeSelectionCallb
@Named("security") @Named("security")
SharedPreferences mSecuritySharedPreferences; SharedPreferences mSecuritySharedPreferences;
@Inject @Inject
@Named("internal")
SharedPreferences mInternalSharedPreferences;
@Inject
CustomThemeWrapper mCustomThemeWrapper; CustomThemeWrapper mCustomThemeWrapper;
@Inject @Inject
Executor mExecutor; Executor mExecutor;
@ -351,6 +361,16 @@ public class MainActivity extends BaseActivity implements SortTypeSelectionCallb
} }
private void initializeNotificationAndBindView() { 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); boolean enableNotification = mSharedPreferences.getBoolean(SharedPreferencesUtils.ENABLE_NOTIFICATION_KEY, true);
long notificationInterval = Long.parseLong(mSharedPreferences.getString(SharedPreferencesUtils.NOTIFICATION_INTERVAL_KEY, "1")); long notificationInterval = Long.parseLong(mSharedPreferences.getString(SharedPreferencesUtils.NOTIFICATION_INTERVAL_KEY, "1"));
TimeUnit timeUnit = (notificationInterval == 15 || notificationInterval == 30) ? TimeUnit.MINUTES : TimeUnit.HOURS; TimeUnit timeUnit = (notificationInterval == 15 || notificationInterval == 30) ? TimeUnit.MINUTES : TimeUnit.HOURS;

View File

@ -4,16 +4,16 @@ import android.content.SharedPreferences;
import android.os.Build; import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.View;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.appcompat.widget.Toolbar;
import androidx.core.app.ActivityCompat; import androidx.core.app.ActivityCompat;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.preference.Preference; import androidx.preference.Preference;
import androidx.preference.PreferenceFragmentCompat; import androidx.preference.PreferenceFragmentCompat;
import com.google.android.material.appbar.AppBarLayout; import com.google.android.material.snackbar.BaseTransientBottomBar;
import com.google.android.material.appbar.CollapsingToolbarLayout; import com.google.android.material.snackbar.Snackbar;
import org.greenrobot.eventbus.EventBus; import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe; import org.greenrobot.eventbus.Subscribe;
@ -22,11 +22,11 @@ import org.greenrobot.eventbus.ThreadMode;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Named; import javax.inject.Named;
import butterknife.BindView;
import butterknife.ButterKnife; import butterknife.ButterKnife;
import ml.docilealligator.infinityforreddit.Infinity; import ml.docilealligator.infinityforreddit.Infinity;
import ml.docilealligator.infinityforreddit.R; import ml.docilealligator.infinityforreddit.R;
import ml.docilealligator.infinityforreddit.customtheme.CustomThemeWrapper; import ml.docilealligator.infinityforreddit.customtheme.CustomThemeWrapper;
import ml.docilealligator.infinityforreddit.databinding.ActivitySettingsBinding;
import ml.docilealligator.infinityforreddit.events.RecreateActivityEvent; import ml.docilealligator.infinityforreddit.events.RecreateActivityEvent;
import ml.docilealligator.infinityforreddit.settings.AboutPreferenceFragment; import ml.docilealligator.infinityforreddit.settings.AboutPreferenceFragment;
import ml.docilealligator.infinityforreddit.settings.AdvancedPreferenceFragment; import ml.docilealligator.infinityforreddit.settings.AdvancedPreferenceFragment;
@ -46,12 +46,7 @@ public class SettingsActivity extends BaseActivity implements
private static final String TITLE_STATE = "TS"; private static final String TITLE_STATE = "TS";
@BindView(R.id.appbar_layout_settings_activity) private ActivitySettingsBinding binding;
AppBarLayout appBarLayout;
@BindView(R.id.collapsing_toolbar_layout_settings_activity)
CollapsingToolbarLayout collapsingToolbarLayout;
@BindView(R.id.toolbar_settings_activity)
Toolbar toolbar;
private String mAccountName; private String mAccountName;
@Inject @Inject
@ -71,7 +66,8 @@ public class SettingsActivity extends BaseActivity implements
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
setContentView(R.layout.activity_settings); binding = ActivitySettingsBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
ButterKnife.bind(this); ButterKnife.bind(this);
@ -80,10 +76,10 @@ public class SettingsActivity extends BaseActivity implements
applyCustomTheme(); applyCustomTheme();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && isChangeStatusBarIconColor()) { 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); mAccountName = mCurrentAccountSharedPreferences.getString(SharedPreferencesUtils.ACCOUNT_NAME, null);
@ -130,7 +126,8 @@ public class SettingsActivity extends BaseActivity implements
@Override @Override
protected void applyCustomTheme() { protected void applyCustomTheme() {
applyAppBarLayoutAndCollapsingToolbarLayoutAndToolbarTheme(appBarLayout, collapsingToolbarLayout, toolbar); applyAppBarLayoutAndCollapsingToolbarLayoutAndToolbarTheme(binding.appbarLayoutSettingsActivity,
binding.collapsingToolbarLayoutSettingsActivity, binding.toolbarSettingsActivity);
} }
@Override @Override
@ -190,6 +187,10 @@ public class SettingsActivity extends BaseActivity implements
EventBus.getDefault().unregister(this); 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) @Subscribe(threadMode = ThreadMode.MAIN)
public void onRecreateActivityEvent(RecreateActivityEvent recreateActivityEvent) { public void onRecreateActivityEvent(RecreateActivityEvent recreateActivityEvent) {
ActivityCompat.recreate(this); ActivityCompat.recreate(this);

View File

@ -1,9 +1,19 @@
package ml.docilealligator.infinityforreddit.settings; package ml.docilealligator.infinityforreddit.settings;
import android.Manifest;
import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle; 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.fragment.app.Fragment;
import androidx.preference.ListPreference; import androidx.preference.ListPreference;
import androidx.preference.SwitchPreference; import androidx.preference.SwitchPreference;
@ -32,6 +42,9 @@ public class NotificationPreferenceFragment extends CustomFontPreferenceFragment
@Inject @Inject
@Named("default") @Named("default")
SharedPreferences sharedPreferences; SharedPreferences sharedPreferences;
@Inject
@Named("internal")
SharedPreferences mInternalSharedPreferences;
private boolean enableNotification; private boolean enableNotification;
private long notificationInterval; private long notificationInterval;
private WorkManager workManager; private WorkManager workManager;
@ -113,5 +126,27 @@ public class NotificationPreferenceFragment extends CustomFontPreferenceFragment
return true; 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);
}
}
} }
} }

View File

@ -364,6 +364,9 @@ public class SharedPreferencesUtils {
public static final String APP_LOCK_TIMEOUT = "app_lock_timeout"; public static final String APP_LOCK_TIMEOUT = "app_lock_timeout";
public static final String LAST_FOREGROUND_TIME = "last_foreground_time"; 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 //Legacy Settings
public static final String MAIN_PAGE_TAB_1_TITLE_LEGACY = "main_page_tab_1_title"; 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"; public static final String MAIN_PAGE_TAB_2_TITLE_LEGACY = "main_page_tab_2_title";

View File

@ -1318,4 +1318,7 @@
<string name="image_index_in_gallery">%1$d/%2$d</string> <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> </resources>