Skip to content

Commit b6030eb

Browse files
committed
feat: built-in ads blocker
thanks to https://github.com/islamdidarmd/AdBlockerWebview
1 parent 6ad4a1c commit b6030eb

3 files changed

Lines changed: 100 additions & 10 deletions

File tree

.github/workflows/build.yaml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ on:
2020
description: 'Block images'
2121
type: boolean
2222
default: false
23+
block_ads:
24+
description: 'Block ads'
25+
type: boolean
26+
default: true
2327
view_mode:
2428
description: 'View Mode'
2529
required: true
@@ -98,6 +102,8 @@ jobs:
98102
if [ -n "${{ inputs.icon_url }}" ]; then
99103
npm install && node create_mipmap_images.js "${{ inputs.icon_url }}"
100104
fi
105+
- name: Download AdBlock List
106+
run: curl "https://pgl.yoyo.org/adservers/serverlist.php?hostformat=plain&showintro=1&mimetype=plaintext" -o app/src/main/assets/adblock.txt
101107
- name: Set up JDK 17
102108
uses: actions/setup-java@v4
103109
with:
@@ -124,6 +130,7 @@ jobs:
124130
STARTUP_URL: ${{ inputs.startup_url }}
125131
ALLOWED_DOMAINS: ${{ env.ALLOWED_DOMAINS }}
126132
BLOCK_MEDIA: ${{ inputs.block_media }}
133+
BLOCK_ADS: ${{ inputs.block_ads }}
127134
- name: Rename APK
128135
run: mv app/build/outputs/apk/release/app-release.apk app/build/outputs/apk/release/webview-${{ env.PRIMARY_DOMAIN }}.apk
129136
- name: Create Release
@@ -144,6 +151,7 @@ jobs:
144151
App Name: ${{ inputs.app_name }}
145152
View Mode: ${{ inputs.view_mode }}
146153
Block Media: ${{ inputs.block_media }}
154+
Block Ads: ${{ inputs.block_ads }}
147155
Custom Icon: ${{ inputs.icon_url }}
148156
- name: Get the APK URL
149157
run: |

app/build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ android {
2020
buildConfigField "String", "STARTUP_URL", "\"${System.getenv('STARTUP_URL') ?: '' }\""
2121
buildConfigField "String", "VIEW_MODE", "\"${System.getenv('VIEW_MODE') ?: 'AUTO'}\""
2222
buildConfigField "boolean", "BLOCK_MEDIA", "${System.getenv('BLOCK_MEDIA') ?: 'false'}"
23+
buildConfigField "boolean", "BLOCK_ADS", "${System.getenv('BLOCK_ADS') ?: 'true'}"
2324
resValue "string", "app_name", System.getenv('APP_NAME') ?: "My Application"
2425
applicationId System.getenv('APPLICATION_ID') ?: "com.webview.myapplication"
2526

app/src/main/java/com/webview/myapplication/MainActivity.java

Lines changed: 91 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,40 +6,110 @@
66
import android.app.AlertDialog;
77
import android.app.DownloadManager;
88
import android.content.Context;
9+
import android.content.Intent;
910
import android.content.pm.ActivityInfo;
11+
import android.content.pm.PackageManager;
1012
import android.net.Uri;
13+
import android.net.http.SslError;
1114
import android.os.Build;
1215
import android.os.Bundle;
1316
import android.os.Environment;
1417
import android.view.View;
1518
import android.webkit.CookieManager;
19+
import android.webkit.SslErrorHandler;
1620
import android.webkit.URLUtil;
21+
import android.webkit.ValueCallback;
1722
import android.webkit.WebChromeClient;
1823
import android.webkit.WebChromeClient.CustomViewCallback;
24+
import android.webkit.WebResourceResponse;
1925
import android.webkit.WebSettings;
26+
import android.webkit.WebSettings.PluginState;
2027
import android.webkit.WebView;
2128
import android.webkit.WebViewClient;
2229
import android.widget.FrameLayout;
2330
import android.widget.ProgressBar;
2431
import android.widget.Toast;
25-
import android.content.pm.PackageManager;
26-
import androidx.core.content.ContextCompat;
2732

2833
import androidx.annotation.RequiresApi;
2934
import androidx.core.app.ActivityCompat;
30-
import android.webkit.SslErrorHandler;
31-
import android.net.http.SslError;
32-
import android.webkit.WebSettings.PluginState;
33-
import java.util.Objects;
35+
import androidx.core.content.ContextCompat;
36+
37+
import java.io.BufferedReader;
38+
import java.io.ByteArrayInputStream;
39+
import java.io.IOException;
40+
import java.io.InputStream;
41+
import java.io.InputStreamReader;
3442
import java.util.Arrays;
35-
import android.content.Intent;
36-
import android.webkit.ValueCallback;
43+
import java.util.HashSet;
44+
import java.util.Objects;
45+
46+
class AdBlockerUtil {
47+
private final HashSet<String> adHosts = new HashSet<>();
48+
49+
private static AdBlockerUtil mInstance;
50+
51+
public static AdBlockerUtil getInstance() {
52+
if (mInstance == null) {
53+
mInstance = new AdBlockerUtil();
54+
}
55+
return mInstance;
56+
}
57+
58+
public void initialize(Context context) {
59+
try {
60+
InputStream inputStream = context.getAssets().open("adblock.txt");
61+
loadHostsFromInputStream(inputStream);
62+
} catch (IOException e) {
63+
e.printStackTrace();
64+
}
65+
}
66+
67+
public boolean isAd(String url) {
68+
if (url == null) {
69+
return false;
70+
}
71+
72+
String requestHost = Uri.parse(url).getHost();
73+
74+
if (requestHost == null) {
75+
return false;
76+
}
77+
78+
if (adHosts.contains(requestHost)) {
79+
return true;
80+
}
81+
82+
String[] subDomains = requestHost.split("\\.");
83+
84+
for (int i = subDomains.length - 1; i >= 0; i--) {
85+
String domain = String.join(".", Arrays.copyOfRange(subDomains, i, subDomains.length));
86+
87+
if (adHosts.contains(domain)) {
88+
return true;
89+
}
90+
}
91+
92+
return false;
93+
}
94+
95+
private void loadHostsFromInputStream(InputStream inputStream) {
96+
try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) {
97+
String line;
98+
while ((line = reader.readLine()) != null) {
99+
adHosts.add(line);
100+
}
101+
} catch (Exception e) {
102+
e.printStackTrace();
103+
}
104+
}
105+
}
37106

38107
public class MainActivity extends Activity {
39108
private final int STORAGE_PERMISSION_CODE = 1;
40-
private static final String[] ALLOWED_DOMAINS = BuildConfig.ALLOWED_DOMAINS.split("\\,");
109+
private static final String[] ALLOWED_DOMAINS = BuildConfig.ALLOWED_DOMAINS.split(",");
41110
private static final String STARTUP_URL = BuildConfig.STARTUP_URL;
42111
private static final boolean BLOCK_MEDIA = BuildConfig.BLOCK_MEDIA;
112+
private static final boolean BLOCK_ADS = BuildConfig.BLOCK_ADS;
43113
private static final String VIEW_MODE = BuildConfig.VIEW_MODE;
44114
private WebView mWebView;
45115
private View mCustomView;
@@ -85,7 +155,8 @@ protected void onActivityResult(int requestCode, int resultCode, Intent intent)
85155
@SuppressLint("SetJavaScriptEnabled")
86156
protected void onCreate(Bundle savedInstanceState) {
87157
super.onCreate(savedInstanceState);
88-
158+
AdBlockerUtil adBlockerUtil = AdBlockerUtil.getInstance();
159+
adBlockerUtil.initialize(this);
89160
if (VIEW_MODE == "PORTRAIT") {
90161
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
91162
} else if (VIEW_MODE == "LANDSCAPE") {
@@ -225,6 +296,16 @@ public boolean shouldOverrideUrlLoading(final WebView view, final String url) {
225296
}
226297
}
227298

299+
@Override
300+
public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
301+
if (BLOCK_ADS && AdBlockerUtil.getInstance().isAd(url)) {
302+
WebResourceResponse emptyResponse = new WebResourceResponse("text/plain", "utf-8", new ByteArrayInputStream("".getBytes()));
303+
return emptyResponse;
304+
} else {
305+
return super.shouldInterceptRequest(view, url);
306+
}
307+
}
308+
228309
@Override
229310
public void onPageFinished(WebView view, String url) {
230311
super.onPageFinished(view, url);

0 commit comments

Comments
 (0)