Skip to content

Commit a8a444a

Browse files
Merge pull request #161 from MihaiCristianCondrea/codex/restore-notifications-and-in-app-update
Restore notifications and update checks
2 parents 961a7d9 + 135e1ad commit a8a444a

File tree

3 files changed

+127
-15
lines changed

3 files changed

+127
-15
lines changed

app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/main/MainActivity.java

Lines changed: 78 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -30,14 +30,18 @@
3030
import androidx.navigation.ui.NavigationUI;
3131
import androidx.preference.PreferenceManager;
3232

33+
import com.d4rk.androidtutorials.java.BuildConfig;
3334
import com.d4rk.androidtutorials.java.R;
3435
import com.d4rk.androidtutorials.java.databinding.ActivityMainBinding;
36+
import com.d4rk.androidtutorials.java.notifications.managers.AppUpdateNotificationsManager;
37+
import com.d4rk.androidtutorials.java.notifications.managers.AppUsageNotificationsManager;
3538
import com.d4rk.androidtutorials.java.ui.components.navigation.BottomSheetMenuFragment;
3639
import com.d4rk.androidtutorials.java.ui.screens.startup.StartupActivity;
3740
import com.d4rk.androidtutorials.java.ui.screens.startup.StartupViewModel;
3841
import com.d4rk.androidtutorials.java.ui.screens.support.SupportActivity;
3942
import com.d4rk.androidtutorials.java.utils.ConsentUtils;
4043
import com.d4rk.androidtutorials.java.utils.EdgeToEdgeDelegate;
44+
import com.d4rk.androidtutorials.java.utils.ReviewHelper;
4145
import com.google.android.gms.ads.AdRequest;
4246
import com.google.android.gms.ads.MobileAds;
4347
import com.google.android.material.navigation.NavigationBarView;
@@ -48,6 +52,7 @@
4852
import com.google.android.play.core.install.InstallStateUpdatedListener;
4953
import com.google.android.play.core.install.model.AppUpdateType;
5054
import com.google.android.play.core.install.model.InstallStatus;
55+
import com.google.android.play.core.install.model.UpdateAvailability;
5156
import com.google.android.ump.ConsentInformation;
5257
import com.google.android.ump.ConsentRequestParameters;
5358
import com.google.android.ump.UserMessagingPlatform;
@@ -92,6 +97,7 @@ public void onResume(@NonNull LifecycleOwner owner) {
9297
private NavController navController;
9398
private int currentNavIndex;
9499
private AppUpdateManager appUpdateManager;
100+
private AppUpdateNotificationsManager appUpdateNotificationsManager;
95101
private InstallStateUpdatedListener installStateUpdatedListener;
96102
private long backPressedTime;
97103

@@ -134,6 +140,7 @@ protected void onCreate(Bundle savedInstanceState) {
134140
}
135141

136142
this.appUpdateManager = mainViewModel.getAppUpdateManager();
143+
setupUpdateNotifications();
137144

138145
registerInstallStateListener();
139146
getLifecycle().addObserver(lifecycleObserver);
@@ -150,6 +157,8 @@ public void handleOnBackPressed() {
150157
}
151158
}
152159
});
160+
161+
checkInAppReview();
153162
}
154163

155164
private void setupActionBar() {
@@ -238,17 +247,19 @@ private void observeViewModel() {
238247
.build();
239248

240249
if (useRail) {
241-
NavigationUI.setupWithNavController(mBinding.navRail, navController);
242-
mBinding.navRail.setOnItemSelectedListener(item -> {
243-
if (item.getItemId() == navController.getCurrentDestination().getId()) {
250+
if (mBinding.navRail != null) {
251+
NavigationUI.setupWithNavController(mBinding.navRail, navController);
252+
mBinding.navRail.setOnItemSelectedListener(item -> {
253+
if (item.getItemId() == navController.getCurrentDestination().getId()) {
254+
return true;
255+
}
256+
int newIndex = navOrder.get(item.getItemId());
257+
NavOptions options = newIndex > currentNavIndex ? forwardOptions : backwardOptions;
258+
navController.navigate(item.getItemId(), null, options);
259+
currentNavIndex = newIndex;
244260
return true;
245-
}
246-
int newIndex = navOrder.get(item.getItemId());
247-
NavOptions options = newIndex > currentNavIndex ? forwardOptions : backwardOptions;
248-
navController.navigate(item.getItemId(), null, options);
249-
currentNavIndex = newIndex;
250-
return true;
251-
});
261+
});
262+
}
252263
} else {
253264
NavigationUI.setupWithNavController(navBarView, navController);
254265
navBarView.setOnItemSelectedListener(item -> {
@@ -299,12 +310,64 @@ public boolean onOptionsItemSelected(android.view.MenuItem item) {
299310
return super.onOptionsItemSelected(item);
300311
}
301312

302-
private void startImmediateUpdate(AppUpdateInfo appUpdateInfo) {
303-
appUpdateManager.startUpdateFlowForResult(
304-
appUpdateInfo,
305-
updateActivityResultLauncher,
306-
AppUpdateOptions.newBuilder(AppUpdateType.IMMEDIATE).build()
313+
@Override
314+
protected void onResume() {
315+
super.onResume();
316+
AppUsageNotificationsManager appUsageNotificationsManager = new AppUsageNotificationsManager(this);
317+
appUsageNotificationsManager.scheduleAppUsageCheck();
318+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
319+
appUpdateNotificationsManager.checkAndSendUpdateNotification();
320+
}
321+
checkForFlexibleOrImmediateUpdate();
322+
}
323+
324+
private void checkForFlexibleOrImmediateUpdate() {
325+
appUpdateManager.getAppUpdateInfo().addOnSuccessListener(appUpdateInfo -> {
326+
boolean updateAvailable = appUpdateInfo.updateAvailability() == UpdateAvailability.UPDATE_AVAILABLE;
327+
if (updateAvailable) {
328+
startImmediateUpdate(appUpdateInfo);
329+
}
330+
})
331+
.addOnFailureListener(e -> {
332+
if (!BuildConfig.DEBUG) {
333+
Snackbar.make(
334+
findViewById(android.R.id.content),
335+
getString(R.string.snack_general_error),
336+
Snackbar.LENGTH_LONG
337+
).show();
338+
}
339+
});
340+
}
341+
342+
private void checkInAppReview() {
343+
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
344+
int sessionCount = prefs.getInt(getString(R.string.key_session_count), 0);
345+
boolean hasPrompted = prefs.getBoolean(getString(R.string.key_has_prompted_review), false);
346+
347+
ReviewHelper.launchInAppReviewIfEligible(
348+
this,
349+
sessionCount,
350+
hasPrompted,
351+
() -> prefs.edit().putBoolean(getString(R.string.key_has_prompted_review), true).apply()
307352
);
353+
354+
prefs.edit().putInt(getString(R.string.key_session_count), sessionCount + 1).apply();
355+
}
356+
357+
private void startImmediateUpdate(AppUpdateInfo appUpdateInfo) {
358+
try {
359+
appUpdateManager.startUpdateFlowForResult(
360+
appUpdateInfo,
361+
updateActivityResultLauncher,
362+
AppUpdateOptions.newBuilder(AppUpdateType.IMMEDIATE).build()
363+
);
364+
} catch (Exception e) {
365+
Log.e("MainActivity", "Error starting in-app update", e);
366+
}
367+
}
368+
369+
private void setupUpdateNotifications() {
370+
appUpdateNotificationsManager = new AppUpdateNotificationsManager(this);
308371
}
309372

310373
private void registerInstallStateListener() {
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package com.d4rk.androidtutorials.java.utils;
2+
3+
import android.app.Activity;
4+
5+
import com.google.android.play.core.review.ReviewInfo;
6+
import com.google.android.play.core.review.ReviewManager;
7+
import com.google.android.play.core.review.ReviewManagerFactory;
8+
9+
/**
10+
* Utility class for launching Google Play in-app reviews.
11+
*/
12+
public final class ReviewHelper {
13+
14+
private ReviewHelper() {
15+
// Utility class
16+
}
17+
18+
public static void launchInAppReviewIfEligible(Activity activity,
19+
int sessionCount,
20+
boolean hasPromptedBefore,
21+
Runnable onReviewLaunched) {
22+
if (sessionCount < 3 || hasPromptedBefore) {
23+
return;
24+
}
25+
launchReview(activity, onReviewLaunched);
26+
}
27+
28+
public static void forceLaunchInAppReview(Activity activity) {
29+
launchReview(activity, null);
30+
}
31+
32+
private static void launchReview(Activity activity, Runnable onReviewLaunched) {
33+
ReviewManager reviewManager = ReviewManagerFactory.create(activity);
34+
reviewManager.requestReviewFlow()
35+
.addOnCompleteListener(task -> {
36+
if (task.isSuccessful()) {
37+
ReviewInfo reviewInfo = task.getResult();
38+
reviewManager.launchReviewFlow(activity, reviewInfo)
39+
.addOnCompleteListener(flow -> {
40+
if (onReviewLaunched != null) {
41+
onReviewLaunched.run();
42+
}
43+
});
44+
}
45+
});
46+
}
47+
}

app/src/main/res/values/keys.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,6 @@
2121
<string name="key_consent_ad_user_data" translatable="false">consent_ad_user_data</string>
2222
<string name="key_consent_ad_personalization" translatable="false">consent_ad_personalization</string>
2323
<string name="key_onboarding_complete" translatable="false">onboarding_complete</string>
24+
<string name="key_session_count" translatable="false">session_count</string>
25+
<string name="key_has_prompted_review" translatable="false">has_prompted_review</string>
2426
</resources>

0 commit comments

Comments
 (0)