From 0022b01b34a290b27f859f3e8e231d504d473898 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Wed, 30 Aug 2023 18:56:42 +0200 Subject: fix notification permission handling, also covering the case of an app update for which the user has a provider already configured and only needs to give the lacking permissions --- .../se/leap/bitmaskclient/base/StartActivity.java | 16 ++++++--- .../base/fragments/NavigationDrawerFragment.java | 4 ++- .../base/models/FeatureVersionCode.java | 1 + .../providersetup/SetupViewPagerAdapter.java | 17 ++++++--- .../providersetup/activities/SetupActivity.java | 42 +++++++++++++++------- app/src/main/res/layout/activity_setup.xml | 29 +++++++++++++++ 6 files changed, 85 insertions(+), 24 deletions(-) (limited to 'app/src/main') diff --git a/app/src/main/java/se/leap/bitmaskclient/base/StartActivity.java b/app/src/main/java/se/leap/bitmaskclient/base/StartActivity.java index 715367f5..8372b6ad 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/StartActivity.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/StartActivity.java @@ -21,7 +21,6 @@ import static se.leap.bitmaskclient.base.MainActivity.ACTION_SHOW_VPN_FRAGMENT; import static se.leap.bitmaskclient.base.models.Constants.APP_ACTION_CONFIGURE_ALWAYS_ON_PROFILE; import static se.leap.bitmaskclient.base.models.Constants.EIP_RESTART_ON_BOOT; import static se.leap.bitmaskclient.base.models.Constants.EXTRA_MOTD_MSG; -import static se.leap.bitmaskclient.base.models.Constants.PREFERENCES_APP_VERSION; import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_EIP_DEFINITION; import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_KEY; import static se.leap.bitmaskclient.base.models.Constants.REQUEST_CODE_CONFIGURE_LEAP; @@ -74,6 +73,9 @@ public class StartActivity extends Activity{ private int versionCode; private int previousVersionCode; + // flag indicating that the provider configuration UI should show up, + // to configure the lacking permissions + private boolean configurePermissions = false; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { @@ -87,8 +89,6 @@ public class StartActivity extends Activity{ case FIRST: storeAppVersion(); - // TODO start ProfileCreation & replace below code - // (new Intent(getActivity(), ProviderListActivity.class), Constants.REQUEST_CODE_SWITCH_PROVIDER); break; case UPGRADE: @@ -195,6 +195,10 @@ public class StartActivity extends Activity{ if (hasNewFeature(FeatureVersionCode.ENCRYPTED_SHARED_PREFS)) { PreferenceHelper.migrateToEncryptedPrefs(this); } + if (hasNewFeature(FeatureVersionCode.NOTIFICATION_PREMISSION_API_UPDATE)) { + // if the provider is not configured, permissions will be configured automatically during the provider setup + configurePermissions = ProviderObservable.getInstance().getCurrentProvider().isConfigured(); + } // always check if manual gateway selection feature switch has been disabled if (!BuildConfig.allow_manual_gateway_selection && PreferenceHelper.getPreferredCity() != null) { @@ -220,7 +224,7 @@ public class StartActivity extends Activity{ private void prepareEIP() { Provider provider = ProviderObservable.getInstance().getCurrentProvider(); - if (provider.isConfigured()) { + if (provider.isConfigured() && !configurePermissions) { Log.d(TAG, "vpn provider is configured"); if (getIntent() != null && getIntent().getBooleanExtra(EIP_RESTART_ON_BOOT, false)) { EipCommand.startVPN(this, true); @@ -244,7 +248,9 @@ public class StartActivity extends Activity{ getIntent().removeExtra(APP_ACTION_CONFIGURE_ALWAYS_ON_PROFILE); } if (isDefaultBitmask()) { - startActivityForResult(new Intent(this, SetupActivity.class), REQUEST_CODE_CONFIGURE_LEAP); + Intent intent = new Intent(this, SetupActivity.class); + intent.putExtra(SetupActivity.EXTRA_SWITCH_PROVIDER, false); + startActivityForResult(intent, REQUEST_CODE_CONFIGURE_LEAP); } else { // custom branded app startActivityForResult(new Intent(this, CustomProviderSetupActivity.class), REQUEST_CODE_CONFIGURE_LEAP); } diff --git a/app/src/main/java/se/leap/bitmaskclient/base/fragments/NavigationDrawerFragment.java b/app/src/main/java/se/leap/bitmaskclient/base/fragments/NavigationDrawerFragment.java index 18f20a6f..a06fee5d 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/fragments/NavigationDrawerFragment.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/fragments/NavigationDrawerFragment.java @@ -236,7 +236,9 @@ public class NavigationDrawerFragment extends Fragment implements SharedPreferen switchProvider.setVisibility(VISIBLE); switchProvider.setOnClickListener(v -> { closeDrawer(); - getActivity().startActivityForResult(new Intent(getActivity(), SetupActivity.class), REQUEST_CODE_SWITCH_PROVIDER); + Intent intent = new Intent(getActivity(), SetupActivity.class); + intent.putExtra(SetupActivity.EXTRA_SWITCH_PROVIDER, true); + getActivity().startActivityForResult(intent, REQUEST_CODE_SWITCH_PROVIDER); }); } } diff --git a/app/src/main/java/se/leap/bitmaskclient/base/models/FeatureVersionCode.java b/app/src/main/java/se/leap/bitmaskclient/base/models/FeatureVersionCode.java index c2eb9694..8b78c966 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/models/FeatureVersionCode.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/models/FeatureVersionCode.java @@ -7,4 +7,5 @@ public interface FeatureVersionCode { int RISEUP_PROVIDER_LILYPAD_UPDATE = 165000; int ENCRYPTED_SHARED_PREFS = 170000; + int NOTIFICATION_PREMISSION_API_UPDATE = 170000; } diff --git a/app/src/main/java/se/leap/bitmaskclient/providersetup/SetupViewPagerAdapter.java b/app/src/main/java/se/leap/bitmaskclient/providersetup/SetupViewPagerAdapter.java index 39122572..a4a8fabd 100644 --- a/app/src/main/java/se/leap/bitmaskclient/providersetup/SetupViewPagerAdapter.java +++ b/app/src/main/java/se/leap/bitmaskclient/providersetup/SetupViewPagerAdapter.java @@ -1,9 +1,13 @@ package se.leap.bitmaskclient.providersetup; -import static se.leap.bitmaskclient.providersetup.fragments.SetupFragmentFactory.*; import static se.leap.bitmaskclient.providersetup.fragments.SetupFragmentFactory.CIRCUMVENTION_SETUP_FRAGMENT; import static se.leap.bitmaskclient.providersetup.fragments.SetupFragmentFactory.CONFIGURE_PROVIDER_FRAGMENT; +import static se.leap.bitmaskclient.providersetup.fragments.SetupFragmentFactory.NOTIFICATION_PERMISSON_EDUCATIONAL_FRAGMENT; +import static se.leap.bitmaskclient.providersetup.fragments.SetupFragmentFactory.NOTIFICATION_PERMISSON_FRAGMENT; import static se.leap.bitmaskclient.providersetup.fragments.SetupFragmentFactory.PROVIDER_SELECTION_FRAGMENT; +import static se.leap.bitmaskclient.providersetup.fragments.SetupFragmentFactory.SUCCESS_FRAGMENT; +import static se.leap.bitmaskclient.providersetup.fragments.SetupFragmentFactory.VPN_PERMISSON_EDUCATIONAL_FRAGMENT; +import static se.leap.bitmaskclient.providersetup.fragments.SetupFragmentFactory.VPN_PERMISSON_FRAGMENT; import android.content.Intent; @@ -25,12 +29,15 @@ public class SetupViewPagerAdapter extends FragmentStateAdapter { super(fragmentManager, lifecycle); } - public SetupViewPagerAdapter(@NonNull FragmentManager fragmentManager, @NonNull Lifecycle lifecycle, Intent vpnPermissionRequest, Boolean showNotificationPermission) { + public SetupViewPagerAdapter(@NonNull FragmentManager fragmentManager, @NonNull Lifecycle lifecycle, boolean providerSetup, Intent vpnPermissionRequest, Boolean showNotificationPermission) { this(fragmentManager, lifecycle); ArrayList fragments = new ArrayList<>(); - fragments.add(PROVIDER_SELECTION_FRAGMENT); - fragments.add(CIRCUMVENTION_SETUP_FRAGMENT); - fragments.add(CONFIGURE_PROVIDER_FRAGMENT); + if (providerSetup) { + fragments.add(PROVIDER_SELECTION_FRAGMENT); + fragments.add(CIRCUMVENTION_SETUP_FRAGMENT); + fragments.add(CONFIGURE_PROVIDER_FRAGMENT); + } + if (vpnPermissionRequest != null) { fragments.add(VPN_PERMISSON_EDUCATIONAL_FRAGMENT); fragments.add(VPN_PERMISSON_FRAGMENT); diff --git a/app/src/main/java/se/leap/bitmaskclient/providersetup/activities/SetupActivity.java b/app/src/main/java/se/leap/bitmaskclient/providersetup/activities/SetupActivity.java index 27ca6658..a6e50769 100644 --- a/app/src/main/java/se/leap/bitmaskclient/providersetup/activities/SetupActivity.java +++ b/app/src/main/java/se/leap/bitmaskclient/providersetup/activities/SetupActivity.java @@ -21,7 +21,6 @@ import android.view.Gravity; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; -import android.widget.Toast; import androidx.annotation.ColorInt; import androidx.annotation.NonNull; @@ -56,10 +55,12 @@ public class SetupActivity extends AppCompatActivity implements SetupActivityCal public static final String EXTRA_PROVIDER = "EXTRA_PROVIDER"; public static final String EXTRA_CURRENT_POSITION = "EXTRA_CURRENT_POSITION"; + public static final String EXTRA_SWITCH_PROVIDER = "EXTRA_SWITCH_PROVIDER"; private static final String TAG = SetupActivity.class.getSimpleName(); ActivitySetupBinding binding; Provider provider; private int currentPosition = 0; + private boolean switchProvider = false; private final HashSet cancelCallbacks = new HashSet<>(); private FragmentManagerEnhanced fragmentManager; @@ -72,6 +73,10 @@ public class SetupActivity extends AppCompatActivity implements SetupActivityCal if (savedInstanceState != null) { provider = savedInstanceState.getParcelable(EXTRA_PROVIDER); currentPosition = savedInstanceState.getInt(EXTRA_CURRENT_POSITION); + switchProvider = savedInstanceState.getBoolean(EXTRA_SWITCH_PROVIDER); + } + if (getIntent() != null && getIntent().hasExtra(EXTRA_SWITCH_PROVIDER)) { + switchProvider = getIntent().getBooleanExtra(EXTRA_SWITCH_PROVIDER, false); } binding = ActivitySetupBinding.inflate(getLayoutInflater()); @@ -79,28 +84,35 @@ public class SetupActivity extends AppCompatActivity implements SetupActivityCal fragmentManager = new FragmentManagerEnhanced(getSupportFragmentManager()); ArrayList indicatorViews = new ArrayList<>(); - for (int i = 0; i < 4; i++) { - addIndicatorView(indicatorViews); + // indicator views for provider selection and config setup + boolean basicProviderSetup = !ProviderObservable.getInstance().getCurrentProvider().isConfigured() || switchProvider; + if (basicProviderSetup) { + for (int i = 0; i < 3; i++) { + addIndicatorView(indicatorViews); + } } + // indicator views for VPN permission Intent requestVpnPermission = VpnService.prepare(this); if (requestVpnPermission != null) { addIndicatorView(indicatorViews); addIndicatorView(indicatorViews); } - boolean showNotificationPermissionFragments = false; + // indicator views for notification permission + boolean requestNotificationPermission = false; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { if (ContextCompat.checkSelfPermission(getApplication(), Manifest.permission.POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED) { - showNotificationPermissionFragments = shouldShowRequestPermissionRationale(Manifest.permission.POST_NOTIFICATIONS); - if (showNotificationPermissionFragments) { - addIndicatorView(indicatorViews); - addIndicatorView(indicatorViews); - } + requestNotificationPermission = true; + addIndicatorView(indicatorViews); + addIndicatorView(indicatorViews); } } - adapter = new SetupViewPagerAdapter(getSupportFragmentManager(), getLifecycle(), requestVpnPermission, showNotificationPermissionFragments); + // indicator views for "all set" Fragment + addIndicatorView(indicatorViews); + + adapter = new SetupViewPagerAdapter(getSupportFragmentManager(), getLifecycle(), basicProviderSetup, requestVpnPermission, requestNotificationPermission); binding.viewPager.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() { @Override @@ -114,7 +126,7 @@ public class SetupActivity extends AppCompatActivity implements SetupActivityCal } ActionBar actionBar = getSupportActionBar(); if (actionBar != null) { - getSupportActionBar().setDisplayHomeAsUpEnabled(position == 0 && ProviderObservable.getInstance().getCurrentProvider().isConfigured()); + getSupportActionBar().setDisplayHomeAsUpEnabled(position == 0 && switchProvider); } } }); @@ -126,7 +138,6 @@ public class SetupActivity extends AppCompatActivity implements SetupActivityCal int currentPos = binding.viewPager.getCurrentItem(); int newPos = currentPos + 1; if (newPos >= binding.viewPager.getAdapter().getItemCount()) { - Toast.makeText(SetupActivity.this, "SetupFinished \\o/", Toast.LENGTH_LONG).show(); return; } binding.viewPager.setCurrentItem(newPos); @@ -143,6 +154,7 @@ public class SetupActivity extends AppCompatActivity implements SetupActivityCal if (provider != null) { outState.putParcelable(EXTRA_PROVIDER, provider); outState.putInt(EXTRA_CURRENT_POSITION, currentPosition); + outState.putBoolean(EXTRA_SWITCH_PROVIDER, switchProvider); } } @@ -184,7 +196,7 @@ public class SetupActivity extends AppCompatActivity implements SetupActivityCal final Drawable upArrow = ResourcesCompat.getDrawable(getResources(), R.drawable.ic_back, getTheme()); actionBar.setHomeAsUpIndicator(upArrow); - actionBar.setDisplayHomeAsUpEnabled(currentPosition == 0 && ProviderObservable.getInstance().getCurrentProvider().isConfigured()); + actionBar.setDisplayHomeAsUpEnabled(currentPosition == 0 && switchProvider); ViewHelper.setActivityBarColor(this, R.color.bg_setup_status_bar, R.color.bg_setup_action_bar, R.color.colorActionBarTitleFont); @ColorInt int titleColor = ContextCompat.getColor(context, R.color.colorActionBarTitleFont); actionBarTitle.setTitleTextColor(titleColor); @@ -270,6 +282,10 @@ public class SetupActivity extends AppCompatActivity implements SetupActivityCal @Override public void onSetupFinished() { Intent intent = getIntent(); + if (provider == null && ProviderObservable.getInstance().getCurrentProvider().isConfigured()) { + // only permissions were requested, no new provider configured, so reuse previously configured one + provider = ProviderObservable.getInstance().getCurrentProvider(); + } intent.putExtra(Provider.KEY, provider); setResult(RESULT_OK, intent); finish(); diff --git a/app/src/main/res/layout/activity_setup.xml b/app/src/main/res/layout/activity_setup.xml index 5fff1154..6a2c5209 100644 --- a/app/src/main/res/layout/activity_setup.xml +++ b/app/src/main/res/layout/activity_setup.xml @@ -46,6 +46,7 @@ app:cardCornerRadius="6dp" app:cardElevation="0dp" android:layout_margin="4dp" + android:visibility="gone" > + + + + + +