Panagiotis Triantafyllou

steps for android 13 and up fixes

...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
16 <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" /> 16 <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
17 <uses-permission android:name="android.permission.FOREGROUND_SERVICE_HEALTH" /> 17 <uses-permission android:name="android.permission.FOREGROUND_SERVICE_HEALTH" />
18 <uses-permission android:name="android.permission.HIGH_SAMPLING_RATE_SENSORS" /> 18 <uses-permission android:name="android.permission.HIGH_SAMPLING_RATE_SENSORS" />
19 + <uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
19 20
20 <application android:largeHeap="true"> 21 <application android:largeHeap="true">
21 <!-- <meta-data--> 22 <!-- <meta-data-->
......
1 package ly.warp.sdk.activities; 1 package ly.warp.sdk.activities;
2 2
3 +import android.app.AlertDialog;
3 import android.content.Context; 4 import android.content.Context;
5 +import android.content.pm.PackageManager;
6 +import android.os.Build;
4 import android.os.Bundle; 7 import android.os.Bundle;
5 import android.view.MenuItem; 8 import android.view.MenuItem;
6 import android.widget.Toast; 9 import android.widget.Toast;
7 10
8 import androidx.annotation.NonNull; 11 import androidx.annotation.NonNull;
12 +import androidx.core.app.ActivityCompat;
13 +import androidx.core.content.ContextCompat;
9 import androidx.fragment.app.Fragment; 14 import androidx.fragment.app.Fragment;
10 import androidx.fragment.app.FragmentActivity; 15 import androidx.fragment.app.FragmentActivity;
11 16
...@@ -37,6 +42,7 @@ public class BaseFragmentActivity extends FragmentActivity implements Navigation ...@@ -37,6 +42,7 @@ public class BaseFragmentActivity extends FragmentActivity implements Navigation
37 42
38 private BottomNavigationView mBottomNavigationView; 43 private BottomNavigationView mBottomNavigationView;
39 private Fragment mFragmentToSet = null; 44 private Fragment mFragmentToSet = null;
45 + private static final int REQUEST_NOTIFICATION_PERMISSION = 5000;
40 46
41 // =========================================================== 47 // ===========================================================
42 // Methods for/from SuperClass/Interfaces 48 // Methods for/from SuperClass/Interfaces
...@@ -52,6 +58,12 @@ public class BaseFragmentActivity extends FragmentActivity implements Navigation ...@@ -52,6 +58,12 @@ public class BaseFragmentActivity extends FragmentActivity implements Navigation
52 WarplyManager.getUserCouponsWithCouponsets(mUserCouponsReceiver); 58 WarplyManager.getUserCouponsWithCouponsets(mUserCouponsReceiver);
53 WarplyManager.getCampaigns(mCampaignsCallback); 59 WarplyManager.getCampaigns(mCampaignsCallback);
54 WarplyManager.getUnifiedCouponsDeals(mUnifiedCallback); 60 WarplyManager.getUnifiedCouponsDeals(mUnifiedCallback);
61 +
62 + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
63 + if (!hasNotificationPermission()) {
64 + requestNotificationPermission();
65 + }
66 + }
55 } 67 }
56 68
57 @Override 69 @Override
...@@ -103,6 +115,18 @@ public class BaseFragmentActivity extends FragmentActivity implements Navigation ...@@ -103,6 +115,18 @@ public class BaseFragmentActivity extends FragmentActivity implements Navigation
103 super.attachBaseContext(ViewPumpContextWrapper.wrap(newBase)); 115 super.attachBaseContext(ViewPumpContextWrapper.wrap(newBase));
104 } 116 }
105 117
118 + @Override
119 + public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
120 + super.onRequestPermissionsResult(requestCode, permissions, grantResults);
121 + if (requestCode == REQUEST_NOTIFICATION_PERMISSION) {
122 + if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
123 + Toast.makeText(BaseFragmentActivity.this, "Notifications Permission Granted", Toast.LENGTH_SHORT).show();
124 + } else {
125 + Toast.makeText(BaseFragmentActivity.this, "Notifications Permission Denied", Toast.LENGTH_SHORT).show();
126 + }
127 + }
128 + }
129 +
106 // =========================================================== 130 // ===========================================================
107 // Methods 131 // Methods
108 // =========================================================== 132 // ===========================================================
...@@ -114,6 +138,24 @@ public class BaseFragmentActivity extends FragmentActivity implements Navigation ...@@ -114,6 +138,24 @@ public class BaseFragmentActivity extends FragmentActivity implements Navigation
114 mBottomNavigationView.setSelectedItemId(R.id.menu_home); 138 mBottomNavigationView.setSelectedItemId(R.id.menu_home);
115 } 139 }
116 140
141 + private boolean hasNotificationPermission() {
142 + return ContextCompat.checkSelfPermission(this, android.Manifest.permission.POST_NOTIFICATIONS) == PackageManager.PERMISSION_GRANTED;
143 + }
144 +
145 + private void requestNotificationPermission() {
146 + if (ActivityCompat.shouldShowRequestPermissionRationale(this, android.Manifest.permission.POST_NOTIFICATIONS)) {
147 + new AlertDialog.Builder(this)
148 + .setTitle("Notification Permission Needed")
149 + .setMessage("This app needs the Notification permission to keep you updated.")
150 + .setPositiveButton("OK", (dialog, which) -> ActivityCompat.requestPermissions(this, new String[]{android.Manifest.permission.POST_NOTIFICATIONS}, REQUEST_NOTIFICATION_PERMISSION))
151 + .setNegativeButton("Cancel", (dialog, which) -> dialog.dismiss())
152 + .create()
153 + .show();
154 + } else {
155 + ActivityCompat.requestPermissions(this, new String[]{android.Manifest.permission.POST_NOTIFICATIONS}, REQUEST_NOTIFICATION_PERMISSION);
156 + }
157 + }
158 +
117 // =========================================================== 159 // ===========================================================
118 // Inner and Anonymous Classes 160 // Inner and Anonymous Classes
119 // =========================================================== 161 // ===========================================================
......
...@@ -14,6 +14,7 @@ import android.hardware.SensorEvent; ...@@ -14,6 +14,7 @@ import android.hardware.SensorEvent;
14 import android.hardware.SensorEventListener; 14 import android.hardware.SensorEventListener;
15 import android.hardware.SensorManager; 15 import android.hardware.SensorManager;
16 import android.os.Build; 16 import android.os.Build;
17 +import android.os.Handler;
17 import android.os.IBinder; 18 import android.os.IBinder;
18 19
19 import androidx.annotation.Nullable; 20 import androidx.annotation.Nullable;
...@@ -86,12 +87,10 @@ public class WarplyHealthService extends Service implements SensorEventListener ...@@ -86,12 +87,10 @@ public class WarplyHealthService extends Service implements SensorEventListener
86 87
87 mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); 88 mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
88 mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); 89 mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
89 -// registerStepSensor();
90 Warply.getInitializer(getApplicationContext()).init(); 90 Warply.getInitializer(getApplicationContext()).init();
91 WarplyManager.getPacingDetails(new PacingDetailsRequest(), mPacingCallback); 91 WarplyManager.getPacingDetails(new PacingDetailsRequest(), mPacingCallback);
92 } 92 }
93 93
94 - // @RequiresApi(api = Build.VERSION_CODES.O)
95 @Override 94 @Override
96 public int onStartCommand(Intent intent, int flags, int startId) { 95 public int onStartCommand(Intent intent, int flags, int startId) {
97 NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); 96 NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
...@@ -103,45 +102,59 @@ public class WarplyHealthService extends Service implements SensorEventListener ...@@ -103,45 +102,59 @@ public class WarplyHealthService extends Service implements SensorEventListener
103 b.setDefaults(Notification.DEFAULT_VIBRATE | Notification.DEFAULT_LIGHTS); 102 b.setDefaults(Notification.DEFAULT_VIBRATE | Notification.DEFAULT_LIGHTS);
104 b.setChannelId(STEPS_CHANNEL_ID); 103 b.setChannelId(STEPS_CHANNEL_ID);
105 b.setContentTitle(getString(R.string.cos_steps_for_good_notification_title)); 104 b.setContentTitle(getString(R.string.cos_steps_for_good_notification_title));
106 -// b.setContentText(getString(R.string.cos_steps_for_good_notification_subtitle));
107 b.setStyle(new NotificationCompat.BigTextStyle().bigText(getString(R.string.cos_steps_for_good_notification_subtitle))); 105 b.setStyle(new NotificationCompat.BigTextStyle().bigText(getString(R.string.cos_steps_for_good_notification_subtitle)));
108 b.setContentIntent(pbIntent); 106 b.setContentIntent(pbIntent);
109 - b.setAutoCancel(true); 107 + b.setAutoCancel(false); //it was true
110 b.setOngoing(true); 108 b.setOngoing(true);
111 -// b.setCategory(Notification.CATEGORY_SERVICE); 109 + b.setPriority(NotificationCompat.PRIORITY_HIGH);
112 b.setSmallIcon(R.drawable.ic_launcher); 110 b.setSmallIcon(R.drawable.ic_launcher);
113 111
114 if (notificationManager != null) { 112 if (notificationManager != null) {
115 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) { 113 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
116 - NotificationChannel notificationChannel = new NotificationChannel(STEPS_CHANNEL_ID, "steps_notification_channel", NotificationManager.IMPORTANCE_DEFAULT); 114 + NotificationChannel notificationChannel = new NotificationChannel(STEPS_CHANNEL_ID, "steps_notification_channel", NotificationManager.IMPORTANCE_HIGH);
117 notificationManager.createNotificationChannel(notificationChannel); 115 notificationManager.createNotificationChannel(notificationChannel);
118 Notification notification_build = b.setChannelId(STEPS_CHANNEL_ID).build(); 116 Notification notification_build = b.setChannelId(STEPS_CHANNEL_ID).build();
117 + notification_build.flags = Notification.FLAG_ONGOING_EVENT | Notification.FLAG_NO_CLEAR;
119 this.startForeground(2001, notification_build, ServiceInfo.FOREGROUND_SERVICE_TYPE_HEALTH); 118 this.startForeground(2001, notification_build, ServiceInfo.FOREGROUND_SERVICE_TYPE_HEALTH);
120 } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { 119 } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
121 - NotificationChannel notificationChannel = new NotificationChannel(STEPS_CHANNEL_ID, "steps_notification_channel", NotificationManager.IMPORTANCE_DEFAULT); 120 + NotificationChannel notificationChannel = new NotificationChannel(STEPS_CHANNEL_ID, "steps_notification_channel", NotificationManager.IMPORTANCE_HIGH);
122 notificationManager.createNotificationChannel(notificationChannel); 121 notificationManager.createNotificationChannel(notificationChannel);
123 Notification notification_build = b.setChannelId(STEPS_CHANNEL_ID).build(); 122 Notification notification_build = b.setChannelId(STEPS_CHANNEL_ID).build();
123 + notification_build.flags = Notification.FLAG_ONGOING_EVENT | Notification.FLAG_NO_CLEAR;
124 this.startForeground(2001, notification_build); 124 this.startForeground(2001, notification_build);
125 } else { 125 } else {
126 Notification notification_build = b.build(); 126 Notification notification_build = b.build();
127 + notification_build.flags = Notification.FLAG_ONGOING_EVENT | Notification.FLAG_NO_CLEAR;
127 this.startForeground(2001, notification_build); 128 this.startForeground(2001, notification_build);
128 } 129 }
129 } 130 }
130 131
131 - new Thread( 132 + /** Old Implementation */
132 - () -> { 133 +// new Thread(
133 - while (true) { 134 +// () -> {
134 - sendSteps(); 135 +// while (true) {
135 - try { 136 +// sendSteps();
136 - Thread.sleep(900000); 137 +// try {
137 - } catch (InterruptedException e) { 138 +// Thread.sleep(900000);
138 - e.printStackTrace(); 139 +// } catch (InterruptedException e) {
139 - } 140 +// e.printStackTrace();
140 - } 141 +// }
141 - } 142 +// }
142 - ).start(); 143 +// }
144 +// ).start();
145 +
146 + /** New Implementation */
147 + // Use Handler instead of Thread for periodic tasks
148 + final Handler handler = new Handler();
149 + Runnable runnable = new Runnable() {
150 + @Override
151 + public void run() {
152 + sendSteps();
153 + handler.postDelayed(this, 900000);
154 + }
155 + };
156 + handler.post(runnable);
143 157
144 -// return super.onStartCommand(intent, flags, startId);
145 return Service.START_STICKY; 158 return Service.START_STICKY;
146 } 159 }
147 160
...@@ -158,22 +171,6 @@ public class WarplyHealthService extends Service implements SensorEventListener ...@@ -158,22 +171,6 @@ public class WarplyHealthService extends Service implements SensorEventListener
158 sendSteps(); 171 sendSteps();
159 } 172 }
160 173
161 -// @Override
162 -// public void onTaskRemoved(Intent rootIntent) {
163 -// Intent restartServiceIntent = new Intent(getApplicationContext(), WarplyHealthService.class);
164 -// restartServiceIntent.setPackage(getPackageName());
165 -//
166 -// PendingIntent restartServicePendingIntent = PendingIntent.getService(getApplicationContext(), 2002, restartServiceIntent, PendingIntent.FLAG_ONE_SHOT);
167 -// AlarmManager alarmService = (AlarmManager) getApplicationContext().getSystemService(Context.ALARM_SERVICE);
168 -// alarmService.set(
169 -// AlarmManager.ELAPSED_REALTIME,
170 -// SystemClock.elapsedRealtime() + 1000,
171 -// restartServicePendingIntent
172 -// );
173 -//
174 -// super.onTaskRemoved(rootIntent);
175 -// }
176 -
177 @Nullable 174 @Nullable
178 @Override 175 @Override
179 public IBinder onBind(Intent intent) { 176 public IBinder onBind(Intent intent) {
......