Skip to content

Commit ea211c5

Browse files
author
doubleangels
committed
Merge branch 'main' into dev
2 parents 58362d3 + 230443c commit ea211c5

17 files changed

Lines changed: 333 additions & 256 deletions

File tree

.github/workflows/deploy.yml

Lines changed: 83 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,12 @@ name: Release Deployment
22

33
on:
44
workflow_dispatch:
5+
inputs:
6+
skip_appsweep:
7+
description: "Skip AppSweep security scan"
8+
required: false
9+
default: false
10+
type: boolean
511

612
jobs:
713
build-gms-flavor-for-github:
@@ -17,20 +23,43 @@ jobs:
1723
distribution: "temurin"
1824
cache: gradle
1925

26+
<<<<<<< HEAD
2027
- name: Cache gradle dependencies
2128
uses: actions/cache@v5
29+
=======
30+
- name: Set up Android SDK
31+
uses: android-actions/setup-android@v3
32+
with:
33+
packages: "platform-tools platforms;android-36 build-tools;34.0.0"
34+
accept-android-sdk-licenses: true
35+
36+
- name: Cache Gradle dependencies
37+
uses: actions/cache@v4
38+
>>>>>>> main
2239
with:
2340
path: |
24-
~/.gradle
41+
~/.gradle/caches
42+
~/.gradle/wrapper
43+
~/.gradle/daemon
2544
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
2645
restore-keys: |
2746
${{ runner.os }}-gradle-
2847
48+
- name: Cache Android SDK
49+
uses: actions/cache@v4
50+
with:
51+
path: |
52+
~/.android/build-cache
53+
~/.android/cache
54+
key: ${{ runner.os }}-android-sdk-${{ hashFiles('**/build.gradle*') }}
55+
restore-keys: |
56+
${{ runner.os }}-android-sdk-
57+
2958
- name: Grant execute permission for gradlew
3059
run: chmod +x gradlew
3160

3261
- name: Build APK for Github release
33-
run: ./gradlew assembleGmsRelease
62+
run: ./gradlew assembleGmsRelease --parallel --build-cache --configuration-cache
3463

3564
- name: Sign APK for Github release
3665
uses: r0adkll/sign-android-release@v1
@@ -65,20 +94,43 @@ jobs:
6594
distribution: "temurin"
6695
cache: gradle
6796

97+
<<<<<<< HEAD
6898
- name: Cache gradle dependencies
6999
uses: actions/cache@v5
100+
=======
101+
- name: Set up Android SDK
102+
uses: android-actions/setup-android@v3
103+
with:
104+
packages: "platform-tools platforms;android-36 build-tools;34.0.0"
105+
accept-android-sdk-licenses: true
106+
107+
- name: Cache Gradle dependencies
108+
uses: actions/cache@v4
109+
>>>>>>> main
70110
with:
71111
path: |
72-
~/.gradle
112+
~/.gradle/caches
113+
~/.gradle/wrapper
114+
~/.gradle/daemon
73115
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
74116
restore-keys: |
75117
${{ runner.os }}-gradle-
76118
119+
- name: Cache Android SDK
120+
uses: actions/cache@v4
121+
with:
122+
path: |
123+
~/.android/build-cache
124+
~/.android/cache
125+
key: ${{ runner.os }}-android-sdk-${{ hashFiles('**/build.gradle*') }}
126+
restore-keys: |
127+
${{ runner.os }}-android-sdk-
128+
77129
- name: Grant execute permission for gradlew
78130
run: chmod +x gradlew
79131

80132
- name: Build APK for Github release
81-
run: ./gradlew assembleFossRelease
133+
run: ./gradlew assembleFossRelease --parallel --build-cache --configuration-cache
82134

83135
- name: Sign APK for Github release
84136
uses: r0adkll/sign-android-release@v1
@@ -113,20 +165,43 @@ jobs:
113165
distribution: "temurin"
114166
cache: gradle
115167

168+
<<<<<<< HEAD
116169
- name: Cache gradle dependencies
117170
uses: actions/cache@v5
171+
=======
172+
- name: Set up Android SDK
173+
uses: android-actions/setup-android@v3
174+
with:
175+
packages: "platform-tools platforms;android-36 build-tools;34.0.0"
176+
accept-android-sdk-licenses: true
177+
178+
- name: Cache Gradle dependencies
179+
uses: actions/cache@v4
180+
>>>>>>> main
118181
with:
119182
path: |
120-
~/.gradle
183+
~/.gradle/caches
184+
~/.gradle/wrapper
185+
~/.gradle/daemon
121186
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
122187
restore-keys: |
123188
${{ runner.os }}-gradle-
124189
190+
- name: Cache Android SDK
191+
uses: actions/cache@v4
192+
with:
193+
path: |
194+
~/.android/build-cache
195+
~/.android/cache
196+
key: ${{ runner.os }}-android-sdk-${{ hashFiles('**/build.gradle*') }}
197+
restore-keys: |
198+
${{ runner.os }}-android-sdk-
199+
125200
- name: Grant execute permission for gradlew
126201
run: chmod +x gradlew
127202

128203
- name: Build bundle for Google Play release
129-
run: ./gradlew bundleGmsRelease
204+
run: ./gradlew bundleGmsRelease --parallel --build-cache --configuration-cache
130205

131206
- name: Sign bundle for Google Play release
132207
uses: r0adkll/sign-android-release@v1
@@ -240,6 +315,7 @@ jobs:
240315
"build-gms-flavor-for-google-play",
241316
]
242317
runs-on: ubuntu-latest
318+
if: ${{ !inputs.skip_appsweep }}
243319
steps:
244320
- name: Checkout
245321
uses: actions/checkout@v6
@@ -276,6 +352,7 @@ jobs:
276352
"appsweep-scan",
277353
]
278354
runs-on: ubuntu-latest
355+
if: always()
279356
steps:
280357
- name: Delete workflow runs
281358
uses: Mattraks/delete-workflow-runs@v2

CONTRIBUTING.md

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,6 @@ There are several ways you can contribute:
1010

1111
Improving the documentation is always valuable. You can suggest edits, propose updates, or add new sections to make the project more informative and user-friendly.
1212

13-
### Translations
14-
15-
If you find any inaccuracies in translations, please open an issue to report them or contribute directly to the [translation project](https://poeditor.com/join/project/EupqZ3cGCJ).
16-
1713
### Code Contributions
1814

1915
If you'd like to contribute code, please open a pull request with your changes. Make sure that all automated tests pass before submitting your pull request.

app/src/foss/java/com/doubleangels/nextdnsmanagement/MainActivity.java

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -84,13 +84,10 @@ public class MainActivity extends AppCompatActivity {
8484
protected void onSaveInstanceState(@NonNull Bundle outState) {
8585
super.onSaveInstanceState(outState);
8686
try {
87-
// Save the WebView state if it exists
88-
if (webView != null) {
89-
Bundle webViewBundle = new Bundle();
90-
webView.saveState(webViewBundle);
91-
outState.putBundle("webViewState", webViewBundle);
92-
}
93-
// Save the dark mode flag
87+
// We consciously avoid saving the WebView state to prevent
88+
// TransactionTooLargeException which occurs when the WebView
89+
// accumulates too much data (e.g. from single-page apps like nextdns.io)
90+
// in its saved bundle.
9491
outState.putBoolean("darkModeEnabled", darkModeEnabled);
9592
} catch (Exception e) {
9693
SentryManager.captureStaticException(e);
@@ -225,11 +222,6 @@ protected void onDestroy() {
225222
sentryManager = null;
226223
} catch (Exception e) {
227224
SentryManager.captureStaticException(e);
228-
} finally {
229-
webView = null;
230-
swipeRefreshLayout = null;
231-
blurOverlay = null;
232-
sentryManager = null;
233225
}
234226
}
235227

@@ -461,6 +453,14 @@ public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request
461453
startActivity(intent);
462454
return true;
463455
}
456+
} catch (android.content.ActivityNotFoundException e) {
457+
android.widget.Toast.makeText(view.getContext(), "No browser found to open link.", android.widget.Toast.LENGTH_LONG).show();
458+
SentryManager.captureStaticException(e);
459+
return false;
460+
} catch (SecurityException e) {
461+
android.widget.Toast.makeText(view.getContext(), "Unable to open link due to security restrictions.", android.widget.Toast.LENGTH_LONG).show();
462+
SentryManager.captureStaticException(e);
463+
return false;
464464
} catch (Exception e) {
465465
SentryManager.captureStaticException(e);
466466
return false;
@@ -681,15 +681,16 @@ private void showBlurOverlay() {
681681
*/
682682
private void hideBlurOverlay() {
683683
if (blurOverlay != null) {
684-
blurOverlay.animate()
684+
View overlay = blurOverlay;
685+
overlay.animate()
685686
.alpha(0.0f)
686687
.scaleX(1.05f)
687688
.scaleY(1.05f)
688689
.setDuration(300)
689690
.withEndAction(() -> {
690-
blurOverlay.setVisibility(View.GONE);
691-
blurOverlay.setScaleX(1.0f);
692-
blurOverlay.setScaleY(1.0f);
691+
overlay.setVisibility(View.GONE);
692+
overlay.setScaleX(1.0f);
693+
overlay.setScaleY(1.0f);
693694
})
694695
.start();
695696
}

app/src/foss/java/com/doubleangels/nextdnsmanagement/PermissionActivity.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -193,8 +193,12 @@ private List<PermissionInfo> getPermissionsList(SentryManager sentryManager) {
193193
// If requested permissions are present, iterate and add them to the list
194194
if (packageInfo.requestedPermissions != null) {
195195
for (String permission : packageInfo.requestedPermissions) {
196-
PermissionInfo permissionInfo = getPackageManager().getPermissionInfo(permission, 0);
197-
permissions.add(permissionInfo);
196+
try {
197+
PermissionInfo permissionInfo = getPackageManager().getPermissionInfo(permission, 0);
198+
permissions.add(permissionInfo);
199+
} catch (PackageManager.NameNotFoundException ignored) {
200+
// Ignore permissions not found on older Android versions
201+
}
198202
}
199203
}
200204
} catch (PackageManager.NameNotFoundException e) {

app/src/gms/java/com/doubleangels/nextdnsmanagement/MainActivity.java

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -92,13 +92,10 @@ public class MainActivity extends AppCompatActivity {
9292
protected void onSaveInstanceState(@NonNull Bundle outState) {
9393
super.onSaveInstanceState(outState);
9494
try {
95-
// Save the WebView state if it exists
96-
if (webView != null) {
97-
Bundle webViewBundle = new Bundle();
98-
webView.saveState(webViewBundle);
99-
outState.putBundle("webViewState", webViewBundle);
100-
}
101-
// Save the dark mode flag
95+
// We consciously avoid saving the WebView state to prevent
96+
// TransactionTooLargeException which occurs when the WebView
97+
// accumulates too much data (e.g. from single-page apps like nextdns.io)
98+
// in its saved bundle.
10299
outState.putBoolean("darkModeEnabled", darkModeEnabled);
103100
} catch (Exception e) {
104101
SentryManager.captureStaticException(e);
@@ -235,11 +232,6 @@ protected void onDestroy() {
235232
sentryManager = null;
236233
} catch (Exception e) {
237234
SentryManager.captureStaticException(e);
238-
} finally {
239-
webView = null;
240-
swipeRefreshLayout = null;
241-
blurOverlay = null;
242-
sentryManager = null;
243235
}
244236
}
245237

@@ -471,6 +463,14 @@ public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request
471463
startActivity(intent);
472464
return true;
473465
}
466+
} catch (android.content.ActivityNotFoundException e) {
467+
android.widget.Toast.makeText(view.getContext(), "No browser found to open link.", android.widget.Toast.LENGTH_LONG).show();
468+
SentryManager.captureStaticException(e);
469+
return false;
470+
} catch (SecurityException e) {
471+
android.widget.Toast.makeText(view.getContext(), "Unable to open link due to security restrictions.", android.widget.Toast.LENGTH_LONG).show();
472+
SentryManager.captureStaticException(e);
473+
return false;
474474
} catch (Exception e) {
475475
SentryManager.captureStaticException(e);
476476
return false;
@@ -691,15 +691,16 @@ private void showBlurOverlay() {
691691
*/
692692
private void hideBlurOverlay() {
693693
if (blurOverlay != null) {
694-
blurOverlay.animate()
694+
View overlay = blurOverlay;
695+
overlay.animate()
695696
.alpha(0.0f)
696697
.scaleX(1.05f)
697698
.scaleY(1.05f)
698699
.setDuration(300)
699700
.withEndAction(() -> {
700-
blurOverlay.setVisibility(View.GONE);
701-
blurOverlay.setScaleX(1.0f);
702-
blurOverlay.setScaleY(1.0f);
701+
overlay.setVisibility(View.GONE);
702+
overlay.setScaleX(1.0f);
703+
overlay.setScaleY(1.0f);
703704
})
704705
.start();
705706
}

app/src/gms/java/com/doubleangels/nextdnsmanagement/PermissionActivity.java

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -198,11 +198,14 @@ private List<PermissionInfo> getPermissionsList(SentryManager sentryManager) {
198198
PackageInfo packageInfo = getPackageManager().getPackageInfo(
199199
getPackageName(),
200200
PackageManager.GET_PERMISSIONS);
201-
// If there are any requested permissions, add them to the list
202201
if (packageInfo.requestedPermissions != null) {
203202
for (String permission : packageInfo.requestedPermissions) {
204-
PermissionInfo permissionInfo = getPackageManager().getPermissionInfo(permission, 0);
205-
permissions.add(permissionInfo);
203+
try {
204+
PermissionInfo permissionInfo = getPackageManager().getPermissionInfo(permission, 0);
205+
permissions.add(permissionInfo);
206+
} catch (PackageManager.NameNotFoundException ignored) {
207+
// Ignore permissions not found on older Android versions
208+
}
206209
}
207210
}
208211
} catch (PackageManager.NameNotFoundException e) {

0 commit comments

Comments
 (0)