Skip to content

Commit 0ff5871

Browse files
authored
Merge pull request #8 from CodeDead/release/v1.5.2
Release/v1.5.2
2 parents a7d7a8e + f027c5b commit 0ff5871

File tree

33 files changed

+255
-188
lines changed

33 files changed

+255
-188
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ https://play.google.com/store/apps/details?id=com.codedead.advancedportchecker
1515

1616
This library is maintained by CodeDead. You can find more about us using the following links:
1717
* [Website](https://codedead.com/)
18-
* [Twitter](https://twitter.com/C0DEDEAD/)
18+
* [Bluesky](https://bsky.app/profile/codedead.com)
1919
* [Facebook](https://facebook.com/deadlinecodedead/)
2020

21-
Copyright © 2023 CodeDead
21+
Copyright © 2025 CodeDead

app/build.gradle

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
apply plugin: 'com.android.application'
22

33
android {
4-
compileSdk 34
4+
compileSdk 35
55
namespace "com.codedead.advancedportchecker"
66
defaultConfig {
77
applicationId "com.codedead.advancedportchecker"
8-
minSdk 28
9-
targetSdk 34
10-
versionCode 14
11-
versionName '1.5.1'
8+
minSdk 30
9+
targetSdk 35
10+
versionCode 15
11+
versionName '1.5.2'
1212
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
1313
vectorDrawables.useSupportLibrary = true
1414
}
@@ -28,15 +28,15 @@ android {
2828

2929
dependencies {
3030
implementation fileTree(include: ['*.jar'], dir: 'libs')
31-
implementation 'androidx.core:core:1.12.0'
32-
implementation 'androidx.appcompat:appcompat:1.6.1'
33-
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
34-
implementation 'com.google.android.material:material:1.10.0'
35-
implementation 'androidx.vectordrawable:vectordrawable:1.1.0'
31+
implementation 'androidx.core:core:1.15.0'
32+
implementation 'androidx.appcompat:appcompat:1.7.0'
33+
implementation 'androidx.constraintlayout:constraintlayout:2.2.1'
34+
implementation 'com.google.android.material:material:1.12.0'
35+
implementation 'androidx.vectordrawable:vectordrawable:1.2.0'
3636
implementation 'androidx.cardview:cardview:1.0.0'
3737
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
3838
implementation 'androidx.preference:preference:1.2.1'
3939
testImplementation 'junit:junit:4.13.2'
40-
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
41-
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
40+
androidTestImplementation 'androidx.test.ext:junit:1.2.1'
41+
androidTestImplementation 'androidx.test.espresso:espresso-core:3.6.1'
4242
}

app/src/main/AndroidManifest.xml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@
3232
android:theme="@style/LoadingTheme">
3333
<intent-filter>
3434
<action android:name="android.intent.action.MAIN" />
35-
3635
<category android:name="android.intent.category.LAUNCHER" />
3736
</intent-filter>
3837
</activity>
@@ -43,5 +42,4 @@
4342
android:name=".gui.activity.AboutActivity"
4443
android:label="@string/title_activity_about" />
4544
</application>
46-
4745
</manifest>
Lines changed: 71 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package com.codedead.advancedportchecker.domain.controller;
22

33
import android.content.Context;
4-
import android.os.AsyncTask;
54

65
import com.codedead.advancedportchecker.R;
76
import com.codedead.advancedportchecker.domain.object.ScanProgress;
@@ -11,31 +10,45 @@
1110
import java.net.InetSocketAddress;
1211
import java.net.Socket;
1312
import java.net.SocketTimeoutException;
13+
import java.util.concurrent.ExecutorService;
14+
import java.util.concurrent.Executors;
15+
import java.util.concurrent.TimeUnit;
1416

15-
public final class ScanController extends AsyncTask<Void, ScanProgress, Void> {
16-
17-
private final String host;
18-
private final int startPort;
19-
private final int endPort;
20-
private final int timeOut;
17+
public final class ScanController {
2118

19+
private final Context context;
20+
private ExecutorService executorService;
21+
private final int poolSize;
2222
private final AsyncResponse response;
2323

2424
/**
2525
* Initialize a new ScanController
2626
*
27-
* @param context The context that can be used to retrieve error messages
28-
* @param host The host address that needs to be scanned
27+
* @param context The context that can be used to retrieve error messages
28+
* @param response The AsyncResponse that can be called when a scan has finished or been cancelled
29+
*/
30+
public ScanController(final Context context,
31+
final AsyncResponse response) {
32+
if (context == null)
33+
throw new NullPointerException("Context cannot be null!");
34+
35+
this.context = context;
36+
37+
final int numberOfCores = Runtime.getRuntime().availableProcessors();
38+
poolSize = Math.max(2, Math.min(numberOfCores * 2, 4));
39+
40+
this.response = response;
41+
}
42+
43+
/**
44+
* Start scanning a host for open ports
45+
*
46+
* @param host The host that needs to be scanned
2947
* @param startPort The initial port for a range of ports that need to be scanned
3048
* @param endPort The final port in a range of ports that need to be scanned
3149
* @param timeOut The time it takes before a connection is marked as timed-out
32-
* @param response The AsyncResponse that can be called when a scan has finished or been cancelled
3350
*/
34-
public ScanController(final Context context, String host, final int startPort,
35-
final int endPort, final int timeOut,
36-
final AsyncResponse response) {
37-
38-
if (context == null) throw new NullPointerException("Context cannot be null!");
51+
public void startScan(String host, final int startPort, final int endPort, final int timeOut) {
3952
if (host == null || host.isEmpty() || !UtilController.isValidAddress(host))
4053
throw new IllegalArgumentException(context.getString(R.string.string_invalid_host));
4154
if (response == null)
@@ -50,43 +63,59 @@ public ScanController(final Context context, String host, final int startPort,
5063
if (endPort > 65535)
5164
throw new IllegalArgumentException(context.getString(R.string.string_largest_possible_port));
5265

66+
final int totalNumberOfPorts = endPort - startPort + 1;
67+
// Divide the total number of ports by the number of cores
68+
final int numberOfPortsPerThread = totalNumberOfPorts / poolSize;
69+
// Calculate the remaining ports that need to be scanned
70+
final int remainingPorts = totalNumberOfPorts % poolSize;
71+
72+
executorService = Executors.newFixedThreadPool(Math.min(totalNumberOfPorts, poolSize));
73+
5374
host = host
5475
.replace("http://", "")
5576
.replace("https://", "")
56-
.replace("ftp://", "");
77+
.replace("ftp://", "")
78+
.replace("ssh://", "")
79+
.replace("telnet://", "")
80+
.replace("smtp://", "");
5781

58-
this.host = host;
59-
this.startPort = startPort;
60-
this.endPort = endPort;
61-
this.timeOut = timeOut;
62-
this.response = response;
63-
}
6482

65-
@Override
66-
protected Void doInBackground(final Void... voids) {
67-
int currentPort = startPort;
68-
while (currentPort <= endPort) {
69-
if (isCancelled()) {
70-
break;
83+
final String finalHost = host;
84+
for (int i = 0; i < poolSize; i++) {
85+
final int currentStartPort = startPort + i * numberOfPortsPerThread;
86+
int currentEndPort = currentStartPort + numberOfPortsPerThread - 1;
87+
88+
if (i == poolSize - 1) {
89+
// Add the remaining ports to the last thread
90+
currentEndPort += remainingPorts;
7191
}
72-
publishProgress(scanTcp(host, currentPort, timeOut));
73-
currentPort++;
74-
}
75-
return null;
76-
}
7792

78-
@Override
79-
protected void onPostExecute(final Void aVoid) {
80-
response.scanComplete();
81-
super.onPostExecute(aVoid);
93+
int finalCurrentEndPort = currentEndPort;
94+
executorService.execute(() -> {
95+
// Loop over the ports to scan
96+
for (int currentPort = currentStartPort; currentPort <= finalCurrentEndPort; currentPort++) {
97+
if (Thread.currentThread().isInterrupted()) {
98+
break;
99+
}
100+
final ScanProgress scan = scanTcp(finalHost, currentPort, timeOut);
101+
response.update(scan);
102+
}
103+
});
104+
}
82105
}
83106

84-
@Override
85-
protected void onProgressUpdate(final ScanProgress... values) {
86-
if (isCancelled()) return;
107+
/**
108+
* Cancel the current scan
109+
*
110+
* @throws InterruptedException If the cancellation cannot be awaited
111+
*/
112+
public void cancelScan() throws InterruptedException {
113+
if (executorService == null)
114+
return;
87115

88-
response.update(values[0]);
89-
super.onProgressUpdate(values);
116+
executorService.shutdownNow();
117+
//noinspection ResultOfMethodCallIgnored
118+
executorService.awaitTermination(30000, TimeUnit.MILLISECONDS);
90119
}
91120

92121
/**
@@ -112,10 +141,4 @@ private static ScanProgress scanTcp(final String host, final int port, final int
112141

113142
return scan;
114143
}
115-
116-
@Override
117-
protected void onCancelled() {
118-
response.scanCancelled();
119-
super.onCancelled();
120-
}
121144
}

app/src/main/java/com/codedead/advancedportchecker/domain/controller/UtilController.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
import androidx.appcompat.app.AlertDialog;
88

9+
import android.util.Log;
910
import android.util.Patterns;
1011

1112
public final class UtilController {
@@ -23,7 +24,7 @@ public static void openWebsite(final Context context, final String url) {
2324

2425
context.startActivity(intent);
2526
} catch (final Exception ex) {
26-
ex.printStackTrace();
27+
Log.e(UtilController.class.getSimpleName(), "An error occurred while trying to open the website: " + ex.getMessage());
2728
}
2829
}
2930

@@ -52,7 +53,7 @@ public static void showAlert(final Context context, final String message) {
5253
* @param address The address that needs to be verified
5354
* @return True if the input is a valid WEB URL or IP address
5455
*/
55-
static boolean isValidAddress(String address) {
56+
static boolean isValidAddress(final String address) {
5657
return Patterns.WEB_URL.matcher(address).matches() || Patterns.IP_ADDRESS.matcher(address).matches();
5758
}
5859
}

app/src/main/java/com/codedead/advancedportchecker/domain/interfaces/AsyncResponse.java

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,5 @@
33
import com.codedead.advancedportchecker.domain.object.ScanProgress;
44

55
public interface AsyncResponse {
6-
void scanComplete();
7-
8-
void scanCancelled();
9-
106
void update(final ScanProgress scanProgress);
117
}

app/src/main/java/com/codedead/advancedportchecker/gui/activity/LoadingActivity.java

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@
1313

1414
import androidx.activity.result.ActivityResultLauncher;
1515
import androidx.activity.result.contract.ActivityResultContracts;
16+
import androidx.core.view.WindowCompat;
17+
import androidx.core.view.WindowInsetsCompat;
18+
import androidx.core.view.WindowInsetsControllerCompat;
1619
import androidx.preference.PreferenceManager;
1720

1821
import android.provider.Settings;
@@ -25,6 +28,7 @@
2528

2629
import android.os.Bundle;
2730
import android.view.View;
31+
import android.view.Window;
2832
import android.widget.Toast;
2933

3034
import com.codedead.advancedportchecker.R;
@@ -55,9 +59,13 @@ protected void onCreate(final Bundle savedInstanceState) {
5559
resetTitle();
5660
super.onCreate(savedInstanceState);
5761

62+
final Window window = getWindow();
5863
final View decorView = getWindow().getDecorView();
59-
final int uiOptions = View.SYSTEM_UI_FLAG_FULLSCREEN;
60-
decorView.setSystemUiVisibility(uiOptions);
64+
65+
WindowCompat.setDecorFitsSystemWindows(window, false);
66+
final WindowInsetsControllerCompat controllerCompat = new WindowInsetsControllerCompat(window, decorView);
67+
controllerCompat.hide(WindowInsetsCompat.Type.systemBars() | WindowInsetsCompat.Type.navigationBars());
68+
controllerCompat.setSystemBarsBehavior(WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE);
6169

6270
setContentView(R.layout.activity_loading);
6371
networkUtils = new NetworkUtils(this);
@@ -172,7 +180,7 @@ public void onRequestPermissionsResult(final int requestCode, @NonNull final Str
172180
builder.setMessage(R.string.string_give_manual_permissions);
173181
builder.setCancelable(false);
174182

175-
builder.setPositiveButton(android.R.string.yes,
183+
builder.setPositiveButton(R.string.yes,
176184
(dialog, id) -> {
177185
dialog.cancel();
178186
Intent intent = new Intent();
@@ -182,7 +190,7 @@ public void onRequestPermissionsResult(final int requestCode, @NonNull final Str
182190
permissionResultLaunch.launch(intent);
183191
});
184192

185-
builder.setNegativeButton(android.R.string.no,
193+
builder.setNegativeButton(R.string.no,
186194
(dialog, id) -> {
187195
Toast.makeText(LoadingActivity.this, R.string.string_networkpermissions_required, Toast.LENGTH_SHORT).show();
188196
finish();
@@ -228,8 +236,8 @@ private void wifiConfirmationCheck() {
228236
final AlertDialog.Builder builder = new AlertDialog.Builder(LoadingActivity.this);
229237
builder.setMessage(R.string.string_enable_wifi)
230238
.setCancelable(false)
231-
.setPositiveButton(android.R.string.yes, dialogClickListener)
232-
.setNegativeButton(android.R.string.no, dialogClickListener)
239+
.setPositiveButton(R.string.yes, dialogClickListener)
240+
.setNegativeButton(R.string.no, dialogClickListener)
233241
.show();
234242
}
235243

0 commit comments

Comments
 (0)