Skip to content

Commit c315a7a

Browse files
committed
add shortcut to notification settings
1 parent 07c1247 commit c315a7a

File tree

7 files changed

+131
-38
lines changed

7 files changed

+131
-38
lines changed

src/main/AndroidManifest.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
package="de.j4velin.pedometer"
44
xmlns:android="http://schemas.android.com/apk/res/android"
55
xmlns:tools="http://schemas.android.com/tools"
6-
android:versionCode="157"
7-
android:versionName="1.5.7">
6+
android:versionCode="158"
7+
android:versionName="1.5.8">
88

99
<uses-sdk
1010
android:minSdkVersion="19"

src/main/java/de/j4velin/pedometer/SensorListener.java

Lines changed: 33 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
import android.app.AlarmManager;
2020
import android.app.Notification;
21+
import android.app.NotificationManager;
2122
import android.app.PendingIntent;
2223
import android.app.Service;
2324
import android.content.BroadcastReceiver;
@@ -52,7 +53,7 @@
5253
*/
5354
public class SensorListener extends Service implements SensorEventListener {
5455

55-
private final static int NOTIFICATION_ID = 1;
56+
public final static int NOTIFICATION_ID = 1;
5657
private final static long MICROSECONDS_IN_ONE_MINUTE = 60000000;
5758
private final static long SAVE_OFFSET_TIME = AlarmManager.INTERVAL_HOUR;
5859
private final static int SAVE_OFFSET_STEPS = 500;
@@ -63,8 +64,6 @@ public class SensorListener extends Service implements SensorEventListener {
6364

6465
private final BroadcastReceiver shutdownReceiver = new ShutdownRecevier();
6566

66-
public final static String ACTION_UPDATE_NOTIFICATION = "updateNotificationState";
67-
6867
@Override
6968
public void onAccuracyChanged(final Sensor sensor, int accuracy) {
7069
// nobody knows what happens here: step value might magically decrease
@@ -108,14 +107,26 @@ private boolean updateIfNecessary() {
108107
db.close();
109108
lastSaveSteps = steps;
110109
lastSaveTime = System.currentTimeMillis();
111-
startForeground(NOTIFICATION_ID, getNotification()); // update notification
110+
showNotification(); // update notification
112111
startService(new Intent(this, WidgetUpdateService.class));
113112
return true;
114113
} else {
115114
return false;
116115
}
117116
}
118117

118+
private void showNotification() {
119+
if (Build.VERSION.SDK_INT >= 26) {
120+
startForeground(NOTIFICATION_ID, getNotification(this));
121+
} else if (getSharedPreferences("pedometer", Context.MODE_PRIVATE)
122+
.getBoolean("notification", true)) {
123+
{
124+
((NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE))
125+
.notify(NOTIFICATION_ID, getNotification(this));
126+
}
127+
}
128+
}
129+
119130
@Override
120131
public IBinder onBind(final Intent intent) {
121132
return null;
@@ -126,7 +137,7 @@ public int onStartCommand(final Intent intent, int flags, int startId) {
126137
reRegisterSensor();
127138
registerBroadcastReceiver();
128139
if (!updateIfNecessary()) {
129-
startForeground(NOTIFICATION_ID, getNotification());
140+
showNotification();
130141
}
131142

132143
// restart service every hour to save the current step count
@@ -176,34 +187,35 @@ public void onDestroy() {
176187
}
177188
}
178189

179-
private Notification getNotification() {
190+
public static Notification getNotification(final Context context) {
180191
if (BuildConfig.DEBUG) Logger.log("getNotification");
181-
SharedPreferences prefs = getSharedPreferences("pedometer", Context.MODE_PRIVATE);
192+
SharedPreferences prefs = context.getSharedPreferences("pedometer", Context.MODE_PRIVATE);
182193
int goal = prefs.getInt("goal", 10000);
183-
Database db = Database.getInstance(this);
194+
Database db = Database.getInstance(context);
184195
int today_offset = db.getSteps(Util.getToday());
185196
if (steps == 0)
186197
steps = db.getCurrentSteps(); // use saved value if we haven't anything better
187198
db.close();
188199
Notification.Builder notificationBuilder =
189-
Build.VERSION.SDK_INT >= 26 ? API26Wrapper.getNotificationBuilder(this) :
190-
new Notification.Builder(this);
200+
Build.VERSION.SDK_INT >= 26 ? API26Wrapper.getNotificationBuilder(context) :
201+
new Notification.Builder(context);
191202
if (steps > 0) {
192203
if (today_offset == Integer.MIN_VALUE) today_offset = -steps;
193204
notificationBuilder.setProgress(goal, today_offset + steps, false).setContentText(
194-
today_offset + steps >= goal ? getString(R.string.goal_reached_notification,
195-
NumberFormat.getInstance(Locale.getDefault())
196-
.format((today_offset + steps))) :
197-
getString(R.string.notification_text,
205+
today_offset + steps >= goal ?
206+
context.getString(R.string.goal_reached_notification,
207+
NumberFormat.getInstance(Locale.getDefault())
208+
.format((today_offset + steps))) :
209+
context.getString(R.string.notification_text,
198210
NumberFormat.getInstance(Locale.getDefault())
199211
.format((goal - today_offset - steps))));
200212
} else { // still no step value?
201-
notificationBuilder
202-
.setContentText(getString(R.string.your_progress_will_be_shown_here_soon));
213+
notificationBuilder.setContentText(
214+
context.getString(R.string.your_progress_will_be_shown_here_soon));
203215
}
204216
notificationBuilder.setPriority(Notification.PRIORITY_MIN).setShowWhen(false)
205-
.setContentTitle(getString(R.string.notification_title)).setContentIntent(
206-
PendingIntent.getActivity(this, 0, new Intent(this, Activity_Main.class),
217+
.setContentTitle(context.getString(R.string.notification_title)).setContentIntent(
218+
PendingIntent.getActivity(context, 0, new Intent(context, Activity_Main.class),
207219
PendingIntent.FLAG_UPDATE_CURRENT)).setSmallIcon(R.drawable.ic_notification)
208220
.setOngoing(true);
209221
return notificationBuilder.build();
@@ -232,15 +244,8 @@ private void reRegisterSensor() {
232244
Logger.log("default: " + sm.getDefaultSensor(Sensor.TYPE_STEP_COUNTER).getName());
233245
}
234246

235-
if (Build.VERSION.SDK_INT >= 27) {
236-
// do not use batching on Android P and newer as we dont live long enough to recieve
237-
// those value due to aggressive power saving
238-
sm.registerListener(this, sm.getDefaultSensor(Sensor.TYPE_STEP_COUNTER),
239-
SensorManager.SENSOR_DELAY_FASTEST);
240-
} else {
241-
// enable batching with delay of max 5 min
242-
sm.registerListener(this, sm.getDefaultSensor(Sensor.TYPE_STEP_COUNTER),
243-
SensorManager.SENSOR_DELAY_NORMAL, (int) (5 * MICROSECONDS_IN_ONE_MINUTE));
244-
}
247+
// enable batching with delay of max 5 min
248+
sm.registerListener(this, sm.getDefaultSensor(Sensor.TYPE_STEP_COUNTER),
249+
SensorManager.SENSOR_DELAY_NORMAL, (int) (5 * MICROSECONDS_IN_ONE_MINUTE));
245250
}
246251
}

src/main/java/de/j4velin/pedometer/ui/Fragment_Settings.java

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import android.Manifest;
1919
import android.app.AlertDialog;
2020
import android.app.Dialog;
21+
import android.app.NotificationManager;
2122
import android.content.Context;
2223
import android.content.DialogInterface;
2324
import android.content.DialogInterface.OnClickListener;
@@ -29,7 +30,6 @@
2930
import android.os.Bundle;
3031
import android.os.Environment;
3132
import android.preference.Preference;
32-
import android.preference.Preference.OnPreferenceChangeListener;
3333
import android.preference.Preference.OnPreferenceClickListener;
3434
import android.preference.PreferenceFragment;
3535
import android.view.Menu;
@@ -54,6 +54,7 @@
5454
import de.j4velin.pedometer.R;
5555
import de.j4velin.pedometer.SensorListener;
5656
import de.j4velin.pedometer.util.API23Wrapper;
57+
import de.j4velin.pedometer.util.API26Wrapper;
5758
import de.j4velin.pedometer.util.PlaySettingsWrapper;
5859

5960
public class Fragment_Settings extends PreferenceFragment implements OnPreferenceClickListener {
@@ -67,12 +68,36 @@ public void onCreate(final Bundle savedInstanceState) {
6768
super.onCreate(savedInstanceState);
6869

6970
addPreferencesFromResource(R.xml.settings);
70-
findPreference("import").setOnPreferenceClickListener(this);
71-
findPreference("export").setOnPreferenceClickListener(this);
7271

7372
final SharedPreferences prefs =
7473
getActivity().getSharedPreferences("pedometer", Context.MODE_PRIVATE);
7574

75+
findPreference("import").setOnPreferenceClickListener(this);
76+
findPreference("export").setOnPreferenceClickListener(this);
77+
if (Build.VERSION.SDK_INT >= 26) {
78+
findPreference("notification").setOnPreferenceClickListener(this);
79+
} else {
80+
findPreference("notification")
81+
.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
82+
@Override
83+
public boolean onPreferenceChange(final Preference preference,
84+
final Object newValue) {
85+
prefs.edit().putBoolean("notification", (Boolean) newValue).apply();
86+
87+
NotificationManager manager = (NotificationManager) getActivity()
88+
.getSystemService(Context.NOTIFICATION_SERVICE);
89+
if ((Boolean) newValue) {
90+
manager.notify(SensorListener.NOTIFICATION_ID,
91+
SensorListener.getNotification(getActivity()));
92+
} else {
93+
manager.cancel(SensorListener.NOTIFICATION_ID);
94+
}
95+
96+
return true;
97+
}
98+
});
99+
}
100+
76101
Preference account = findPreference("account");
77102
PlaySettingsWrapper
78103
.setupAccountSetting(account, savedInstanceState, (Activity_Main) getActivity());
@@ -100,6 +125,10 @@ public void onSaveInstanceState(final Bundle outState) {
100125
public void onResume() {
101126
super.onResume();
102127
getActivity().getActionBar().setDisplayHomeAsUpEnabled(true);
128+
if (Build.VERSION.SDK_INT >= 26) { // notification settings might have changed
129+
API26Wrapper.startForegroundService(getActivity(),
130+
new Intent(getActivity(), SensorListener.class));
131+
}
103132
}
104133

105134
@Override
@@ -209,6 +238,9 @@ public void onClick(DialogInterface dialog, int which) {
209238
Toast.LENGTH_SHORT).show();
210239
}
211240
break;
241+
case R.string.notification_settings:
242+
API26Wrapper.launchNotificationSettings(getActivity());
243+
break;
212244
}
213245
return false;
214246
}

src/main/java/de/j4velin/pedometer/util/API26Wrapper.java

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,24 +20,49 @@
2020
import android.app.Notification;
2121
import android.app.NotificationChannel;
2222
import android.app.NotificationManager;
23+
import android.content.ActivityNotFoundException;
2324
import android.content.Context;
2425
import android.content.Intent;
2526
import android.os.Build;
27+
import android.provider.Settings;
28+
import android.widget.Toast;
2629

2730
@TargetApi(Build.VERSION_CODES.O)
2831
public class API26Wrapper {
2932

30-
public static void startForegroundService(Context context, Intent intent) {
33+
public final static String NOTIFICATION_CHANNEL_ID = "Notification";
34+
35+
public static void startForegroundService(final Context context, final Intent intent) {
3136
context.startForegroundService(intent);
3237
}
3338

34-
public static Notification.Builder getNotificationBuilder(Context context) {
39+
public static Notification.Builder getNotificationBuilder(final Context context) {
3540
NotificationManager manager =
3641
(NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
37-
manager.createNotificationChannel(
38-
new NotificationChannel("foobar", "foobar", NotificationManager.IMPORTANCE_NONE));
39-
Notification.Builder builder = new Notification.Builder(context, "foobar");
42+
NotificationChannel channel =
43+
new NotificationChannel(NOTIFICATION_CHANNEL_ID, NOTIFICATION_CHANNEL_ID,
44+
NotificationManager.IMPORTANCE_NONE);
45+
channel.setImportance(NotificationManager.IMPORTANCE_MIN); // ignored by Android O ...
46+
channel.enableLights(false);
47+
channel.enableVibration(false);
48+
channel.setBypassDnd(false);
49+
channel.setSound(null, null);
50+
manager.createNotificationChannel(channel);
51+
Notification.Builder builder = new Notification.Builder(context, NOTIFICATION_CHANNEL_ID);
4052
return builder;
4153
}
4254

55+
public static void launchNotificationSettings(final Context context) {
56+
Intent intent = new Intent(Settings.ACTION_CHANNEL_NOTIFICATION_SETTINGS);
57+
intent.putExtra(Settings.EXTRA_CHANNEL_ID, NOTIFICATION_CHANNEL_ID);
58+
intent.putExtra(Settings.EXTRA_APP_PACKAGE, context.getPackageName());
59+
try {
60+
context.startActivity(intent);
61+
} catch (ActivityNotFoundException e) {
62+
Toast.makeText(context,
63+
"Settings not found - please search for the notification settings in the Android settings manually",
64+
Toast.LENGTH_LONG).show();
65+
}
66+
}
67+
4368
}

src/main/res/values/strings.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,4 +59,5 @@
5959
<string name="no_sensor">Sensor not found</string>
6060
<string name="no_sensor_explain">This app requires a dedicated hardware step sensor - which your device does not have. This app won\'t run on your device.</string>
6161
<string name="permission_external_storage">No permission to access external storage</string>
62+
<string name="notification_settings">Notification settings</string>
6263
</resources>

src/main/res/xml-v26/settings.xml

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
3+
4+
<Preference
5+
android:key="goal"
6+
android:title="@string/goal"/>
7+
<Preference
8+
android:key="stepsize"
9+
android:title="@string/step_size"/>
10+
<Preference
11+
android:key="account"
12+
android:summary="@string/sign_in"
13+
android:title="@string/account"/>
14+
<Preference
15+
android:key="notification"
16+
android:title="@string/notification_settings"/>
17+
<Preference
18+
android:key="export"
19+
android:summary="@string/export_summary"
20+
android:title="@string/export_title"/>
21+
<Preference
22+
android:key="import"
23+
android:summary="@string/import_summary"
24+
android:title="@string/import_title"/>
25+
26+
</PreferenceScreen>

src/main/res/xml/settings.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@
1111
android:key="account"
1212
android:summary="@string/sign_in"
1313
android:title="@string/account"/>
14+
<CheckBoxPreference
15+
android:defaultValue="true"
16+
android:key="notification"
17+
android:title="@string/notification"/>
1418
<Preference
1519
android:key="export"
1620
android:summary="@string/export_summary"

0 commit comments

Comments
 (0)