android: VPN notification as in the Final 2026 shade: protected title, pause and change actions
Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
6652970925
commit
db6c806d58
5 files changed
+53
-2
No files matched your search
+26
-2
@@ -734,6 +734,12 @@ public class CharonVpnService extends VpnService implements Runnable, VpnStateSe
|
||||
/**
|
||||
* Build a notification matching the current state
|
||||
*/
|
||||
/** Whether «RU sites direct» is on (any mode). */
|
||||
private static boolean isRuSplitOn(Context context)
|
||||
{
|
||||
return PreferenceManager.getDefaultSharedPreferences(context).getBoolean(Constants.PREF_RUSPLIT_GEOIP_ENABLED, false);
|
||||
}
|
||||
|
||||
private Notification buildNotification(boolean publicVersion)
|
||||
{
|
||||
/* the state service may not be bound yet when startForeground() is
|
||||
@@ -818,7 +824,14 @@ public class CharonVpnService extends VpnService implements Runnable, VpnStateSe
|
||||
break;
|
||||
}
|
||||
}
|
||||
builder.setContentTitle(getString(s));
|
||||
if (state == State.CONNECTED && error == ErrorState.NO_ERROR && !publicVersion && profile != null)
|
||||
{ /* «Protected · Amsterdam» like the mockup shade */
|
||||
builder.setContentTitle(getString(R.string.notif_protected, name));
|
||||
}
|
||||
else
|
||||
{
|
||||
builder.setContentTitle(getString(s));
|
||||
}
|
||||
|
||||
int flags = PendingIntent.FLAG_UPDATE_CURRENT;
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
|
||||
@@ -827,6 +840,17 @@ public class CharonVpnService extends VpnService implements Runnable, VpnStateSe
|
||||
}
|
||||
if (!publicVersion)
|
||||
{
|
||||
if (state == State.CONNECTED && error == ErrorState.NO_ERROR && profile != null)
|
||||
{ /* «Pause 15 min» and «Change» as on the mockup shade */
|
||||
Intent pause = new Intent(getApplicationContext(), PauseReceiver.class).setAction(PauseManager.ACTION_PAUSE);
|
||||
builder.addAction(R.drawable.ic_notification_connecting, getString(R.string.notif_pause),
|
||||
PendingIntent.getBroadcast(getApplicationContext(), 1, pause, flags));
|
||||
Intent change = new Intent(getApplicationContext(), MainActivity.class)
|
||||
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP)
|
||||
.putExtra(MainActivity.EXTRA_OPEN_SERVERS, true);
|
||||
builder.addAction(R.drawable.ic_notification, getString(R.string.notif_change),
|
||||
PendingIntent.getActivity(getApplicationContext(), 2, change, flags));
|
||||
}
|
||||
if (add_action)
|
||||
{
|
||||
Intent intent = new Intent(getApplicationContext(), VpnProfileControlActivity.class);
|
||||
@@ -837,7 +861,7 @@ public class CharonVpnService extends VpnService implements Runnable, VpnStateSe
|
||||
}
|
||||
if (error == ErrorState.NO_ERROR)
|
||||
{
|
||||
builder.setContentText(name);
|
||||
builder.setContentText(state == State.CONNECTED && isRuSplitOn(this) ? getString(R.string.notif_ru_direct) : name);
|
||||
}
|
||||
builder.setPublicVersion(buildNotification(true));
|
||||
}
|
||||
|
||||
@@ -40,6 +40,8 @@ object PauseManager
|
||||
private const val PREF_UNTIL = "pref_pause_until"
|
||||
private const val PREF_PROFILE = "pref_pause_profile"
|
||||
private const val REQUEST_CODE = 45
|
||||
/** «Pause 15 min» from the VPN notification */
|
||||
const val ACTION_PAUSE = "org.strongswan.android.action.PAUSE_15"
|
||||
/* safety net of "until the network changes" */
|
||||
private const val NETWORK_PAUSE_MAX_MS = 12L * 60 * 60 * 1000
|
||||
|
||||
@@ -329,6 +331,13 @@ class PauseReceiver : BroadcastReceiver()
|
||||
{
|
||||
override fun onReceive(context: Context, intent: Intent?)
|
||||
{
|
||||
if (intent?.action == PauseManager.ACTION_PAUSE)
|
||||
{
|
||||
val service = VpnStateService.getLiveInstance() ?: return
|
||||
val profile = service.profile ?: return
|
||||
PauseManager.pause(context, service, profile.getUUID().toString(), 15)
|
||||
return
|
||||
}
|
||||
PauseManager.onAlarm(context)
|
||||
}
|
||||
}
|
||||
@@ -47,6 +47,11 @@ public class MainActivity extends AppCompatActivity
|
||||
*/
|
||||
public static final String EXTRA_ADD_SERVER = "org.strongswan.android.extra.ADD_SERVER";
|
||||
|
||||
/**
|
||||
* Set as an intent extra to open the Servers tab (the «Change» action of the notification)
|
||||
*/
|
||||
public static final String EXTRA_OPEN_SERVERS = "org.strongswan.android.extra.OPEN_SERVERS";
|
||||
|
||||
/**
|
||||
* Use "bring your own device" (BYOD) features
|
||||
*/
|
||||
@@ -111,5 +116,10 @@ public class MainActivity extends AppCompatActivity
|
||||
intent.removeExtra(EXTRA_ADD_SERVER);
|
||||
ShxNavigation.INSTANCE.requestAddServer();
|
||||
}
|
||||
if (intent != null && intent.getBooleanExtra(EXTRA_OPEN_SERVERS, false))
|
||||
{
|
||||
intent.removeExtra(EXTRA_OPEN_SERVERS);
|
||||
ShxNavigation.INSTANCE.request(ShxTab.PROFILES);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1009,4 +1009,8 @@
|
||||
<string name="perm_tag_optional">по желанию</string>
|
||||
<string name="perm_allow">Разрешить</string>
|
||||
<string name="perm_done">Готово</string>
|
||||
<string name="notif_protected">Защищено · %1$s</string>
|
||||
<string name="notif_pause">Пауза 15 м</string>
|
||||
<string name="notif_change">Сменить</string>
|
||||
<string name="notif_ru_direct">RU-сайты идут напрямую</string>
|
||||
</resources>
|
||||
@@ -994,4 +994,8 @@
|
||||
<string name="perm_tag_optional">optional</string>
|
||||
<string name="perm_allow">Allow</string>
|
||||
<string name="perm_done">Done</string>
|
||||
<string name="notif_protected">Protected · %1$s</string>
|
||||
<string name="notif_pause">Pause 15 min</string>
|
||||
<string name="notif_change">Change</string>
|
||||
<string name="notif_ru_direct">RU sites go direct</string>
|
||||
</resources>
|
||||
Reference in new issue
Block a user