Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix: No prompt to enable notifications #603

Merged
merged 7 commits into from
Jul 5, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,11 @@
</intent-filter>
</activity>

<activity
android:name=".activity.PromptActivity"
android:theme="@style/Theme.MaterialComponents.NoActionBar.Onboarding"
android:exported="false" />

<service
android:name=".common.service.RunTestService"
android:icon="@drawable/notification_icon"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,30 +1,19 @@
package org.openobservatory.ooniprobe.activity;

import static org.openobservatory.ooniprobe.common.service.RunTestService.CHANNEL_ID;

import android.Manifest;
import android.app.Activity;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.PowerManager;
import android.provider.Settings;

import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatDelegate;
import androidx.core.content.ContextCompat;

import com.google.android.material.bottomnavigation.BottomNavigationView;
import com.google.android.material.snackbar.Snackbar;

import org.openobservatory.ooniprobe.R;
import org.openobservatory.ooniprobe.common.Application;
import org.openobservatory.ooniprobe.common.NotificationUtility;
import org.openobservatory.ooniprobe.common.PreferenceManager;
import org.openobservatory.ooniprobe.common.ThirdPartyServices;
import org.openobservatory.ooniprobe.common.service.ServiceUtil;
Expand All @@ -38,8 +27,6 @@

import javax.inject.Inject;

import butterknife.BindView;
import butterknife.ButterKnife;
import localhost.toolkit.app.fragment.ConfirmDialogFragment;

public class MainActivity extends AbstractActivity implements ConfirmDialogFragment.OnConfirmedListener {
Expand All @@ -56,8 +43,6 @@ public class MainActivity extends AbstractActivity implements ConfirmDialogFragm
@Inject
PreferenceManager preferenceManager;

private ActivityResultLauncher<String> requestPermissionLauncher;

public static Intent newIntent(Context context, int resItem) {
return new Intent(context, MainActivity.class).putExtra(RES_ITEM, resItem).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
}
Expand All @@ -71,7 +56,6 @@ protected void onCreate(@Nullable Bundle savedInstanceState) {
finish();
}
else {
ButterKnife.bind(this);
binding = ActivityMainBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
binding.bottomNavigation.setOnItemSelectedListener(item -> {
Expand Down Expand Up @@ -101,14 +85,11 @@ protected void onCreate(@Nullable Bundle savedInstanceState) {
.withExtra(AUTOTEST_DIALOG)
.build().show(getSupportFragmentManager(), null);
} else if (notificationManager.shouldShow()) {
new ConfirmDialogFragment.Builder()
.withTitle(getString(R.string.Modal_EnableNotifications_Title))
.withMessage(getString(R.string.Modal_EnableNotifications_Paragraph))
.withPositiveButton(getString(R.string.Modal_SoundsGreat))
.withNegativeButton(getString(R.string.Modal_NotNow))
.withNeutralButton(getString(R.string.Modal_DontAskAgain))
.withExtra(NOTIFICATION_DIALOG)
.build().show(getSupportFragmentManager(), null);
registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), result -> {
if (result.getResultCode() == Activity.RESULT_OK) {
// TODO (aanorbel) Notify Users of successful completion
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems we need to do this before merging

}
}).launch(PromptActivity.newIntent(this, PromptActivity.Prompt.CENSORSHIP_CONSENT));
}
ThirdPartyServices.checkUpdates(this);
}
Expand All @@ -122,46 +103,8 @@ protected void onCreate(@Nullable Bundle savedInstanceState) {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
}
}
requestNotificationPermission();
}

private void requestNotificationPermission() {

requestPermissionLauncher = registerForActivityResult(
new ActivityResultContracts.RequestPermission(),
(result) -> {
if (!result) {
Snackbar.make(
binding.getRoot(),
"Please grant Notification permission from App Settings",
Snackbar.LENGTH_LONG
).setAction(R.string.Settings_Title, view -> {
Intent intent = new Intent();
intent.setAction("android.settings.APP_NOTIFICATION_SETTINGS");
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

//for Android 5-7
intent.putExtra("app_package", getPackageName());
intent.putExtra("app_uid", getApplicationInfo().uid);

// for Android 8 and above
intent.putExtra("android.provider.extra.APP_PACKAGE", getPackageName());

startActivity(intent);
}).show();
}
}
);
NotificationUtility.setChannel(getApplicationContext(), CHANNEL_ID, getString(R.string.Settings_AutomatedTesting_Label), false, false, false);
if (ContextCompat.checkSelfPermission(
this,
Manifest.permission.POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED
) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
requestPermissionLauncher.launch(Manifest.permission.POST_NOTIFICATIONS);
}
}
}

@Override
protected void onNewIntent(Intent intent) {
Expand All @@ -183,17 +126,6 @@ else if (intent.getExtras().containsKey(NOTIFICATION_DIALOG)){
@Override
public void onConfirmation(Serializable extra, int i) {
if (extra == null) return;
if (extra.equals(NOTIFICATION_DIALOG)) {
notificationManager.getUpdates(i == DialogInterface.BUTTON_POSITIVE);

//If positive answer reload consents and init notification
if (i == DialogInterface.BUTTON_POSITIVE){
ThirdPartyServices.reloadConsents((Application) getApplication());
}
else if (i == DialogInterface.BUTTON_NEUTRAL){
notificationManager.disableAskNotificationDialog();
}
}
if (extra.equals(AUTOTEST_DIALOG)) {
preferenceManager.setNotificationsFromDialog(i == DialogInterface.BUTTON_POSITIVE);
if (i == DialogInterface.BUTTON_POSITIVE){
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,209 @@
package org.openobservatory.ooniprobe.activity;


import android.Manifest;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.view.View;

import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.StringRes;
import androidx.core.content.ContextCompat;

import com.google.android.material.snackbar.Snackbar;

import org.openobservatory.ooniprobe.R;
import org.openobservatory.ooniprobe.databinding.ActivityPromptBinding;
import org.openobservatory.ooniprobe.domain.UpdatesNotificationManager;

import javax.inject.Inject;

public class PromptActivity extends AbstractActivity {
private static final String PROMPT_ITEM = "promptItem";
@Inject
UpdatesNotificationManager notificationManager;
private ActivityPromptBinding binding;
private Prompt prompt;

private ActivityResultLauncher<String> requestPermissionLauncher;

public static Intent newIntent(Context context, Prompt prompt) {
return new Intent(context, PromptActivity.class).putExtra(PROMPT_ITEM, prompt);
}

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getActivityComponent().inject(this);
binding = ActivityPromptBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());

prompt = (Prompt) getIntent().getExtras().get(PROMPT_ITEM);
binding.title.setText(prompt.title);
binding.description.setText(prompt.paragraph);

registerPermissionRequest();
setUpClickListeners();
}

private void registerPermissionRequest() {
requestPermissionLauncher = registerForActivityResult(new ActivityResultContracts.RequestPermission(), (result) -> {
if (!result) {
Snackbar.make(binding.getRoot(), "Please grant Notification permission from App Settings", Snackbar.LENGTH_LONG).setAction(R.string.Settings_Title, view -> {
Intent intent = new Intent();
intent.setAction("android.settings.APP_NOTIFICATION_SETTINGS");
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

//for Android 5-7
intent.putExtra("app_package", getPackageName());
intent.putExtra("app_uid", getApplicationInfo().uid);

// for Android 8 and above
intent.putExtra("android.provider.extra.APP_PACKAGE", getPackageName());

startActivity(intent);
}).show();
}
setResult(result ? Activity.RESULT_OK : Activity.RESULT_CANCELED);
finish();
});
}

private void setUpClickListeners() {
OnPromptAction actions;
switch (prompt) {
case CENSORSHIP_CONSENT:
actions = new InternetCensorshipConsentActions();
break;
case TEST_PROGRESS_CONSENT:
actions = new TestProgressNotificationConsentActions();
break;
default:
actions = new OnPromptAction() {
@Override
public void onClickPositive(View view) {
}

@Override
public void onClickNeutral(View view) {
}

@Override
public void onClickNegative(View view) {
}
aanorbel marked this conversation as resolved.
Show resolved Hide resolved
};
}

binding.soundsGreat.setOnClickListener(actions::onClickPositive);
binding.notNow.setOnClickListener(actions::onClickNeutral);
binding.dontAskAgain.setOnClickListener(actions::onClickNegative);
}

public void requestNotificationPermission() {
if (ContextCompat.checkSelfPermission(
this, Manifest.permission.POST_NOTIFICATIONS)
!= PackageManager.PERMISSION_GRANTED) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
requestPermissionLauncher.launch(Manifest.permission.POST_NOTIFICATIONS);
}
}
}

enum Prompt {
CENSORSHIP_CONSENT(R.string.Modal_EnableNotifications_Title, R.string.Modal_EnableNotifications_Paragraph),
TEST_PROGRESS_CONSENT(R.string.Prompt_EnableTestProgressNotifications_Title, R.string.Prompt_EnableTestProgressNotifications_Paragraph);

private final int title;
private final int paragraph;

Prompt(@StringRes int title, @StringRes int paragraph) {
this.title = title;
this.paragraph = paragraph;
}
}

interface OnPromptAction {
/**
* Callback for View#onClick of `soundsGreat` button.
*
* @param view
*/
void onClickPositive(View view);

/**
* Callback for View#onClick of `notNow` button.
*
* @param view
*/
void onClickNeutral(View view);

/**
* Callback for View#onClick of `dontAskAgain` button.
*
* @param view
*/
void onClickNegative(View view);
}

public class InternetCensorshipConsentActions implements OnPromptAction {
aanorbel marked this conversation as resolved.
Show resolved Hide resolved

@Override
public void onClickPositive(View view) {
notificationManager.getUpdates(true);
if (ContextCompat.checkSelfPermission(
PromptActivity.this,
Manifest.permission.POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED){
PromptActivity.this.requestNotificationPermission();
} else {
setResult(Activity.RESULT_OK);
finish();
}
}

@Override
public void onClickNeutral(View view) {
PromptActivity.this.setResult(Activity.RESULT_CANCELED);
PromptActivity.this.finish();
}

@Override
public void onClickNegative(View view) {
notificationManager.disableAskNotificationDialog();
onClickNeutral(view);
}
}

public class TestProgressNotificationConsentActions implements OnPromptAction {
aanorbel marked this conversation as resolved.
Show resolved Hide resolved

@Override
public void onClickPositive(View view) {
notificationManager.setTestProgressNotificationConsent(true);
if (ContextCompat.checkSelfPermission(
PromptActivity.this,
Manifest.permission.POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED){
PromptActivity.this.requestNotificationPermission();
} else {
setResult(Activity.RESULT_OK);
finish();
}
}

@Override
public void onClickNeutral(View view) {
PromptActivity.this.setResult(Activity.RESULT_CANCELED);
PromptActivity.this.finish();
}

@Override
public void onClickNegative(View view) {
notificationManager.disableAskTestProgressNotificationConsent();
onClickNeutral(view);
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;

import com.airbnb.lottie.LottieAnimationView;
Expand Down Expand Up @@ -94,6 +93,11 @@ public static void runAsForegroundService(AbstractActivity context,
ArrayList<AbstractSuite> testSuites,
OnTestServiceStartedListener onTestServiceStartedListener,
PreferenceManager iPreferenceManager) {

if (iPreferenceManager.shouldShowTestProgressConsent()){
context.startActivity(PromptActivity.newIntent(context, PromptActivity.Prompt.TEST_PROGRESS_CONSENT));
}

if (ReachabilityManager.getNetworkType(context).equals(ReachabilityManager.NO_INTERNET)) {
new MessageDialogFragment.Builder()
.withTitle(context.getString(R.string.Modal_Error))
Expand Down
Loading