Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit b9d1e94

Browse files
committedNov 20, 2024··
Update Android target API and lots of deps
Target update required Gradle updated required Kotlin plugin update required Kotlin update required Android Studio update required...
1 parent a4c9b23 commit b9d1e94

25 files changed

+258
-124
lines changed
 

‎.github/workflows/ci.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,11 @@ jobs:
1010
- name: Set up JDK
1111
uses: actions/setup-java@v4
1212
with:
13-
java-version: 11
13+
java-version: 21
1414
distribution: adopt-hotspot
1515

1616
- name: Setup Android SDK
17-
uses: android-actions/setup-android@v2
17+
uses: android-actions/setup-android@v3
1818

1919
- name: Build release APK
2020
run: ./gradlew assembleRelease

‎.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ captures/
4343
.idea/dictionaries
4444
.idea/libraries
4545
.idea/caches
46+
.idea/deploymentTargetDropDown.xml
47+
.idea/deploymentTargetSelector.xml
4648

4749
# Keystore files
4850
*.jks

‎.idea/compiler.xml

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎.idea/dynamic.xml

Lines changed: 37 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎.idea/gradle.xml

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎.idea/jarRepositories.xml

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎.idea/kotlinc.xml

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎.idea/migrations.xml

Lines changed: 10 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎.idea/misc.xml

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎.idea/other.xml

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎.idea/runConfigurations.xml

Lines changed: 17 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎app/build.gradle

Lines changed: 45 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,58 @@
1-
apply plugin: 'com.android.application'
2-
apply plugin: 'kotlin-android'
3-
apply plugin: 'kotlin-android-extensions'
1+
plugins {
2+
id 'com.android.application'
3+
id 'kotlin-android'
4+
id 'kotlin-parcelize'
5+
}
46

57
android {
6-
compileSdkVersion 33
8+
compileSdkVersion 35
9+
10+
namespace "tech.httptoolkit.android"
711

812
defaultConfig {
913
applicationId "tech.httptoolkit.android.v1"
1014
minSdkVersion 21
11-
targetSdkVersion 33
15+
targetSdkVersion 34
1216
versionCode 33
1317
versionName "1.4.0"
1418

1519
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
1620

17-
buildConfigField "String", "SENTRY_DSN", "null"
21+
manifestPlaceholders = [
22+
sentryEnabled: "false",
23+
sentryDsn: "null"
24+
]
1825
}
1926

2027
buildTypes {
2128
release {
2229
minifyEnabled false
2330
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
24-
buildConfigField "String", "SENTRY_DSN", "\"https://6943ce7476d54485a5998ad45289a9bc@sentry.io/1809979\""
31+
32+
manifestPlaceholders = [
33+
sentryEnabled: "true",
34+
sentryDsn: "https://6943ce7476d54485a5998ad45289a9bc@sentry.io/1809979"
35+
]
2536
}
2637
}
38+
2739
lintOptions {
2840
lintConfig file("./lint.xml")
2941
}
42+
43+
compileOptions {
44+
sourceCompatibility JavaVersion.VERSION_11
45+
targetCompatibility JavaVersion.VERSION_11
46+
}
47+
48+
kotlinOptions {
49+
jvmTarget = '11'
50+
}
51+
52+
buildFeatures {
53+
viewBinding true
54+
buildConfig true
55+
}
3056
}
3157

3258
repositories {
@@ -38,22 +64,22 @@ dependencies {
3864
implementation fileTree(dir: 'libs', include: ['*.jar'])
3965
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
4066
implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
41-
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.3"
42-
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.3"
43-
implementation 'androidx.appcompat:appcompat:1.3.0'
44-
implementation 'androidx.core:core-ktx:1.1.0'
45-
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
46-
implementation 'androidx.localbroadcastmanager:localbroadcastmanager:1.0.0'
67+
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4"
68+
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4"
69+
implementation 'androidx.appcompat:appcompat:1.7.0'
70+
implementation 'androidx.core:core-ktx:1.15.0'
71+
implementation 'androidx.constraintlayout:constraintlayout:2.2.0'
72+
implementation 'androidx.localbroadcastmanager:localbroadcastmanager:1.1.0'
4773
implementation 'me.dm7.barcodescanner:zxing:1.9.8'
4874
implementation 'com.beust:klaxon:5.5'
4975
implementation 'com.squareup.okhttp3:okhttp:4.3.0'
50-
implementation 'com.google.android.material:material:1.4.0'
76+
implementation 'com.google.android.material:material:1.12.0'
5177
implementation 'net.swiftzer.semver:semver:1.1.1'
52-
implementation 'io.sentry:sentry-android:1.7.27'
78+
implementation 'io.sentry:sentry-android:7.18.0'
5379
implementation 'org.slf4j:slf4j-nop:1.7.25'
54-
implementation 'com.google.android.gms:play-services-base:10.2.4'
55-
implementation 'com.android.installreferrer:installreferrer:1.1'
80+
implementation 'com.google.android.gms:play-services-base:18.5.0'
81+
implementation 'com.android.installreferrer:installreferrer:2.2'
5682
testImplementation 'junit:junit:4.12'
57-
androidTestImplementation 'androidx.test:runner:1.2.0'
58-
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
83+
androidTestImplementation 'androidx.test:runner:1.6.2'
84+
androidTestImplementation 'androidx.test.espresso:espresso-core:3.6.1'
5985
}

‎app/src/main/AndroidManifest.xml

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
<?xml version="1.0" encoding="utf-8"?>
22
<manifest
33
xmlns:android="http://schemas.android.com/apk/res/android"
4-
xmlns:tools="http://schemas.android.com/tools"
5-
package="tech.httptoolkit.android">
4+
xmlns:tools="http://schemas.android.com/tools">
65

76
<uses-permission android:name="android.permission.INTERNET" />
87
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
98
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
10-
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
9+
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
10+
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC" />
1111
<uses-permission android:name="android.permission.CAMERA" />
1212
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"
1313
tools:ignore="QueryAllPackagesPermission" />
@@ -19,9 +19,14 @@
1919
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
2020
tools:node="remove" />
2121

22-
<uses-feature android:name="android.software.leanback"
22+
<uses-feature
23+
android:name="android.software.leanback"
2324
android:required="false" />
24-
<uses-feature android:name="android.hardware.touchscreen"
25+
<uses-feature
26+
android:name="android.hardware.touchscreen"
27+
android:required="false" />
28+
<uses-feature
29+
android:name="android.hardware.camera"
2530
android:required="false" />
2631

2732
<application
@@ -37,6 +42,7 @@
3742
android:banner="@drawable/ic_tv_banner">
3843
<service
3944
android:name=".ProxyVpnService"
45+
android:foregroundServiceType="dataSync"
4046
android:permission="android.permission.BIND_VPN_SERVICE"
4147
android:exported="true">
4248
<intent-filter>
@@ -104,5 +110,8 @@
104110
<activity android:name=".PortListActivity" />
105111

106112
<meta-data android:name="search-engine" android:resource="@xml/noindex" />
113+
114+
<meta-data android:name="io.sentry.enabled" android:value="${sentryEnabled}" />
115+
<meta-data android:name="io.sentry.dsn" android:value="${sentryDsn}" />
107116
</application>
108117
</manifest>

‎app/src/main/java/tech/httptoolkit/android/ApplicationListActivity.kt

Lines changed: 33 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,13 @@ import android.os.Bundle
88
import android.view.MenuItem
99
import android.view.View
1010
import android.widget.PopupMenu
11+
import androidx.activity.OnBackPressedCallback
1112
import androidx.appcompat.app.AppCompatActivity
1213
import androidx.appcompat.view.ContextThemeWrapper
1314
import androidx.core.widget.doAfterTextChanged
1415
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
15-
import kotlinx.android.synthetic.main.apps_list.*
1616
import kotlinx.coroutines.*
17+
import tech.httptoolkit.android.databinding.AppsListBinding
1718
import java.util.*
1819
import kotlin.collections.ArrayList
1920

@@ -23,6 +24,8 @@ const val UNSELECTED_APPS_EXTRA = "tech.httptoolkit.android.UNSELECTED_APPS_EXTR
2324
class ApplicationListActivity : AppCompatActivity(), SwipeRefreshLayout.OnRefreshListener,
2425
CoroutineScope by MainScope(), PopupMenu.OnMenuItemClickListener, View.OnClickListener {
2526

27+
private lateinit var binding: AppsListBinding
28+
2629
private val allApps = ArrayList<PackageInfo>()
2730
private val filteredApps = ArrayList<PackageInfo>()
2831

@@ -34,50 +37,62 @@ class ApplicationListActivity : AppCompatActivity(), SwipeRefreshLayout.OnRefres
3437

3538
override fun onCreate(savedInstanceState: Bundle?) {
3639
super.onCreate(savedInstanceState)
37-
setContentView(R.layout.apps_list)
3840

3941
blockedPackages = intent.getStringArrayExtra(UNSELECTED_APPS_EXTRA)!!.toHashSet()
4042

41-
apps_list_recyclerView.adapter =
43+
binding = AppsListBinding.inflate(layoutInflater)
44+
setContentView(binding.root)
45+
46+
binding.appsListRecyclerView.adapter =
4247
ApplicationListAdapter(
4348
filteredApps,
4449
::isAppEnabled,
4550
::setAppEnabled
4651
)
47-
apps_list_swipeRefreshLayout.setOnRefreshListener(this)
48-
apps_list_more_menu.setOnClickListener(this)
52+
binding.appsListSwipeRefreshLayout.setOnRefreshListener(this)
53+
binding.appsListMoreMenu.setOnClickListener(this)
4954

50-
apps_list_filterEditText.doAfterTextChanged {
55+
binding.appsListFilterEditText.doAfterTextChanged {
5156
textFilter = it.toString()
5257
applyFilters()
5358
}
5459

60+
onBackPressedDispatcher.addCallback(this, object : OnBackPressedCallback(true) {
61+
override fun handleOnBackPressed() {
62+
setResult(RESULT_OK, Intent().putExtra(
63+
UNSELECTED_APPS_EXTRA,
64+
blockedPackages.toTypedArray()
65+
))
66+
finish()
67+
}
68+
})
69+
5570
onRefresh()
5671
}
5772

5873
override fun onRefresh() {
5974
launch(Dispatchers.Main) {
60-
if (apps_list_swipeRefreshLayout.isRefreshing.not()) {
61-
apps_list_swipeRefreshLayout.isRefreshing = true
75+
if (binding.appsListSwipeRefreshLayout.isRefreshing.not()) {
76+
binding.appsListSwipeRefreshLayout.isRefreshing = true
6277
}
6378

6479
val apps = loadAllApps()
6580
allApps.clear()
6681
allApps.addAll(apps)
6782
applyFilters()
6883

69-
apps_list_swipeRefreshLayout.isRefreshing = false
84+
binding.appsListSwipeRefreshLayout.isRefreshing = false
7085
}
7186
}
7287

7388
private fun applyFilters() {
7489
filteredApps.clear()
7590
filteredApps.addAll(allApps.filter(::matchesFilters))
76-
apps_list_recyclerView.adapter?.notifyDataSetChanged()
91+
binding.appsListRecyclerView.adapter?.notifyDataSetChanged()
7792
}
7893

7994
private fun matchesFilters(app: PackageInfo): Boolean {
80-
val appInfo = app.applicationInfo
95+
val appInfo = app.applicationInfo ?: return false
8196
val appLabel = AppLabelCache.getAppLabel(packageManager, appInfo)
8297
val isSystemApp = appInfo.flags and ApplicationInfo.FLAG_SYSTEM == 1
8398

@@ -103,13 +118,14 @@ class ApplicationListActivity : AppCompatActivity(), SwipeRefreshLayout.OnRefres
103118

104119
private suspend fun loadAllApps(): List<PackageInfo> =
105120
withContext(Dispatchers.IO) {
106-
return@withContext packageManager.getInstalledPackages(PackageManager.GET_META_DATA).apply {
107-
sortBy { pkg ->
108-
AppLabelCache.getAppLabel(packageManager, pkg.applicationInfo).toUpperCase(
121+
return@withContext packageManager.getInstalledPackages(PackageManager.GET_META_DATA)
122+
.filter { pkg ->
123+
pkg.applicationInfo != null
124+
}.sortedBy { pkg ->
125+
AppLabelCache.getAppLabel(packageManager, pkg.applicationInfo!!).toUpperCase(
109126
Locale.getDefault()
110127
)
111128
}
112-
}
113129
}
114130

115131
override fun onMenuItemClick(item: MenuItem?): Boolean {
@@ -136,7 +152,7 @@ class ApplicationListActivity : AppCompatActivity(), SwipeRefreshLayout.OnRefres
136152
if (showEnabledOnly) {
137153
applyFilters()
138154
} else {
139-
apps_list_recyclerView.adapter?.notifyDataSetChanged()
155+
binding.appsListRecyclerView.adapter?.notifyDataSetChanged()
140156
}
141157
true
142158
}
@@ -147,7 +163,7 @@ class ApplicationListActivity : AppCompatActivity(), SwipeRefreshLayout.OnRefres
147163
override fun onClick(v: View?) {
148164
when (v?.id) {
149165
R.id.apps_list_more_menu -> {
150-
PopupMenu(ContextThemeWrapper(this, R.style.PopupMenu), apps_list_more_menu).apply {
166+
PopupMenu(ContextThemeWrapper(this, R.style.PopupMenu), binding.appsListMoreMenu).apply {
151167
this.inflate(R.menu.menu_app_list)
152168
this.menu.findItem(R.id.action_show_system).isChecked = showSystem
153169
this.menu.findItem(R.id.action_show_enabled).isChecked = showEnabledOnly
@@ -162,12 +178,4 @@ class ApplicationListActivity : AppCompatActivity(), SwipeRefreshLayout.OnRefres
162178
}
163179
}
164180
}
165-
166-
override fun onBackPressed() {
167-
setResult(RESULT_OK, Intent().putExtra(
168-
UNSELECTED_APPS_EXTRA,
169-
blockedPackages.toTypedArray()
170-
))
171-
finish()
172-
}
173181
}

‎app/src/main/java/tech/httptoolkit/android/ApplicationListAdapter.kt

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,23 @@ package tech.httptoolkit.android
22

33
import android.content.pm.PackageInfo
44
import android.view.LayoutInflater
5-
import android.view.View
65
import android.view.ViewGroup
76
import androidx.recyclerview.widget.RecyclerView
8-
import kotlinx.android.synthetic.main.item_app_row.view.*
7+
import tech.httptoolkit.android.databinding.ItemAppRowBinding
98

109
class ApplicationListAdapter(
1110
private val data: MutableList<PackageInfo>,
1211
private val isAppWhitelisted: (PackageInfo) -> Boolean,
1312
private val onCheckChanged: (PackageInfo, Boolean) -> Unit
14-
) :
15-
RecyclerView.Adapter<ApplicationListAdapter.AppsViewHolder>() {
13+
) : RecyclerView.Adapter<ApplicationListAdapter.AppsViewHolder>() {
1614

1715
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): AppsViewHolder {
18-
return AppsViewHolder(
19-
LayoutInflater.from(parent.context).inflate(R.layout.item_app_row, parent, false)
16+
val binding = ItemAppRowBinding.inflate(
17+
LayoutInflater.from(parent.context),
18+
parent,
19+
false
2020
)
21+
return AppsViewHolder(binding)
2122
}
2223

2324
override fun getItemCount() = data.size
@@ -26,23 +27,25 @@ class ApplicationListAdapter(
2627
holder.bind(data[position])
2728
}
2829

29-
inner class AppsViewHolder(v: View) : RecyclerView.ViewHolder(v) {
30+
inner class AppsViewHolder(
31+
private val binding: ItemAppRowBinding
32+
) : RecyclerView.ViewHolder(binding.root) {
3033
private val packageManager by lazy {
3134
itemView.context.packageManager
3235
}
3336

3437
init {
35-
itemView.row_app_switch.setOnCheckedChangeListener { _, isChecked ->
38+
binding.rowAppSwitch.setOnCheckedChangeListener { _, isChecked ->
3639
onCheckChanged(data[layoutPosition], isChecked)
3740
}
3841
}
3942

4043
fun bind(packageInfo: PackageInfo) {
41-
val appInfo = packageInfo.applicationInfo
42-
itemView.row_app_icon_image.setImageDrawable(appInfo.loadIcon(packageManager))
43-
itemView.row_app_name.text = AppLabelCache.getAppLabel(packageManager, appInfo)
44-
itemView.row_app_package_name.text = packageInfo.packageName
45-
itemView.row_app_switch.isChecked = isAppWhitelisted(packageInfo)
44+
val appInfo = packageInfo.applicationInfo!!
45+
binding.rowAppIconImage.setImageDrawable(appInfo.loadIcon(packageManager))
46+
binding.rowAppName.text = AppLabelCache.getAppLabel(packageManager, appInfo)
47+
binding.rowAppPackageName.text = packageInfo.packageName
48+
binding.rowAppSwitch.isChecked = isAppWhitelisted(packageInfo)
4649
}
4750
}
4851
}

‎app/src/main/java/tech/httptoolkit/android/HttpToolkitApplication.kt

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import com.android.installreferrer.api.InstallReferrerClient.InstallReferrerResp
1010
import com.android.installreferrer.api.InstallReferrerStateListener
1111
import com.beust.klaxon.Klaxon
1212
import io.sentry.Sentry
13-
import io.sentry.android.AndroidSentryClientFactory
1413
import kotlinx.coroutines.Dispatchers
1514
import kotlinx.coroutines.withContext
1615
import net.swiftzer.semver.SemVer
@@ -67,17 +66,13 @@ class HttpToolkitApplication : Application() {
6766
prefs.edit().putBoolean(APP_CRASHED_PREF, true).apply()
6867
}
6968

70-
if (BuildConfig.SENTRY_DSN != null) {
71-
Sentry.init(BuildConfig.SENTRY_DSN, AndroidSentryClientFactory(this))
72-
}
73-
7469
// Check if we've been recreated unexpectedly, with no crashes in the meantime:
7570
val appCrashed = prefs.getBoolean(APP_CRASHED_PREF, false)
7671
prefs.edit().putBoolean(APP_CRASHED_PREF, false).apply()
7772

7873
vpnWasKilled = vpnShouldBeRunning && !isVpnActive() && !appCrashed && !isProbablyEmulator
7974
if (vpnWasKilled) {
80-
Sentry.capture("VPN killed in the background")
75+
Sentry.captureMessage("VPN killed in the background")
8176
// The UI will show an alert next time the MainActivity is created.
8277
}
8378

@@ -293,7 +288,7 @@ private fun tryParseSemver(version: String?): SemVer? = try {
293288

294289
private fun getInstalledVersion(context: Context): SemVer {
295290
return SemVer.parse(
296-
context.packageManager.getPackageInfo(context.packageName, 0).versionName
291+
context.packageManager.getPackageInfo(context.packageName, 0).versionName!!
297292
)
298293
}
299294

‎app/src/main/java/tech/httptoolkit/android/MainActivity.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -392,7 +392,7 @@ class MainActivity : AppCompatActivity(), CoroutineScope by MainScope() {
392392

393393
// We report errors only that aren't simple connection failures
394394
if (e !is SocketTimeoutException && e !is ConnectException) {
395-
Sentry.capture(e)
395+
Sentry.captureException(e)
396396
}
397397
}
398398
}
@@ -544,7 +544,7 @@ class MainActivity : AppCompatActivity(), CoroutineScope by MainScope() {
544544
// ignored us) then try try again.
545545
requestNotificationPermission(true)
546546
} else {
547-
Sentry.capture("Non-OK result $resultCode for requestCode $requestCode")
547+
Sentry.captureMessage("Non-OK result $resultCode for requestCode $requestCode")
548548
mainState = MainState.FAILED
549549
updateUi()
550550
}
@@ -599,7 +599,7 @@ class MainActivity : AppCompatActivity(), CoroutineScope by MainScope() {
599599

600600
// We report errors only that aren't simple connection failures
601601
if (e !is SocketTimeoutException && e !is ConnectException) {
602-
Sentry.capture(e)
602+
Sentry.captureException(e)
603603
}
604604
}
605605
}

‎app/src/main/java/tech/httptoolkit/android/PortListActivity.kt

Lines changed: 30 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,12 @@ package tech.httptoolkit.android
33
import android.content.Intent
44
import android.os.Bundle
55
import android.widget.PopupMenu
6+
import androidx.activity.OnBackPressedCallback
67
import androidx.appcompat.app.AppCompatActivity
78
import androidx.appcompat.view.ContextThemeWrapper
89
import androidx.core.widget.doAfterTextChanged
9-
import kotlinx.android.synthetic.main.ports_list.*
1010
import kotlinx.coroutines.*
11+
import tech.httptoolkit.android.databinding.PortsListBinding
1112
import java.util.*
1213

1314
val DEFAULT_PORTS = setOf(
@@ -26,37 +27,41 @@ class PortListActivity : AppCompatActivity(), CoroutineScope by MainScope() {
2627

2728
private lateinit var ports: TreeSet<Int> // TreeSet = Mutable + Sorted
2829

30+
private lateinit var binding: PortsListBinding
31+
2932
override fun onCreate(savedInstanceState: Bundle?) {
3033
super.onCreate(savedInstanceState)
31-
setContentView(R.layout.ports_list)
34+
35+
binding = PortsListBinding.inflate(layoutInflater)
36+
setContentView(binding.root)
3237

3338
ports = intent.getIntArrayExtra(SELECTED_PORTS_EXTRA)!!
3439
.toCollection(TreeSet())
3540

36-
ports_list_recyclerView.adapter =
41+
binding.portsListRecyclerView.adapter =
3742
PortListAdapter(
3843
ports,
3944
::deletePort
4045
)
4146

42-
ports_list_input.filters = arrayOf(MinMaxInputFilter(MIN_PORT, MAX_PORT))
47+
binding.portsListInput.filters = arrayOf(MinMaxInputFilter(MIN_PORT, MAX_PORT))
4348

4449
// Match the UI enabled state to the input field contents:
45-
ports_list_add_button.isEnabled = false
46-
ports_list_input.doAfterTextChanged {
47-
ports_list_add_button.isEnabled = isValidInput(it.toString())
50+
binding.portsListAddButton.isEnabled = false
51+
binding.portsListInput.doAfterTextChanged {
52+
binding.portsListAddButton.isEnabled = isValidInput(it.toString())
4853
}
4954

5055
// Add ports when enter/+ is pressed/clicked:
51-
ports_list_add_button.setOnClickListener { addEnteredPort() }
52-
ports_list_input.setOnEditorActionListener { _, _, _ ->
56+
binding.portsListAddButton.setOnClickListener { addEnteredPort() }
57+
binding.portsListInput.setOnEditorActionListener { _, _, _ ->
5358
addEnteredPort()
5459
return@setOnEditorActionListener true
5560
}
5661

5762
// Show the menu, and listen for clicks:
58-
ports_list_more_menu.setOnClickListener {
59-
PopupMenu(ContextThemeWrapper(this, R.style.PopupMenu), ports_list_more_menu).apply {
63+
binding.portsListMoreMenu.setOnClickListener {
64+
PopupMenu(ContextThemeWrapper(this, R.style.PopupMenu), binding.portsListMoreMenu).apply {
6065
this.inflate(R.menu.menu_ports_list)
6166

6267
this.menu.findItem(R.id.action_reset_ports).isEnabled =
@@ -75,17 +80,27 @@ class PortListActivity : AppCompatActivity(), CoroutineScope by MainScope() {
7580
}
7681
}.show()
7782
}
83+
84+
onBackPressedDispatcher.addCallback(this, object : OnBackPressedCallback(true) {
85+
override fun handleOnBackPressed() {
86+
setResult(RESULT_OK, Intent().putExtra(
87+
SELECTED_PORTS_EXTRA,
88+
ports.toIntArray()
89+
))
90+
finish()
91+
}
92+
})
7893
}
7994

8095
private fun isValidInput(input: String): Boolean =
8196
input.toIntOrNull() != null &&
8297
!ports.contains(input.toInt())
8398

8499
private fun addEnteredPort() {
85-
if (!isValidInput(ports_list_input.text.toString())) return
100+
if (!isValidInput(binding.portsListInput.text.toString())) return
86101

87-
ports.add(ports_list_input.text.toString().toInt())
88-
ports_list_input.text.clear()
102+
ports.add(binding.portsListInput.text.toString().toInt())
103+
binding.portsListInput.text.clear()
89104
updateList()
90105
}
91106

@@ -95,14 +110,6 @@ class PortListActivity : AppCompatActivity(), CoroutineScope by MainScope() {
95110
}
96111

97112
private fun updateList() {
98-
ports_list_recyclerView.adapter?.notifyDataSetChanged()
99-
}
100-
101-
override fun onBackPressed() {
102-
setResult(RESULT_OK, Intent().putExtra(
103-
SELECTED_PORTS_EXTRA,
104-
ports.toIntArray()
105-
))
106-
finish()
113+
binding.portsListRecyclerView.adapter?.notifyDataSetChanged()
107114
}
108115
}

‎app/src/main/java/tech/httptoolkit/android/PortListAdapter.kt

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
package tech.httptoolkit.android
22

33
import android.view.LayoutInflater
4-
import android.view.View
54
import android.view.ViewGroup
65
import androidx.recyclerview.widget.RecyclerView
7-
import kotlinx.android.synthetic.main.item_port_row.view.*
6+
import tech.httptoolkit.android.databinding.ItemPortRowBinding
87

98
val PORT_DESCRIPTIONS = mapOf(
109
80 to "Standard HTTP port",
@@ -26,9 +25,12 @@ class PortListAdapter(
2625
) : RecyclerView.Adapter<PortListAdapter.PortViewHolder>() {
2726

2827
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PortViewHolder {
29-
return PortViewHolder(
30-
LayoutInflater.from(parent.context).inflate(R.layout.item_port_row, parent, false)
28+
val binding = ItemPortRowBinding.inflate(
29+
LayoutInflater.from(parent.context),
30+
parent,
31+
false
3132
)
33+
return PortViewHolder(binding)
3234
}
3335

3436
override fun getItemCount() = ports.size
@@ -37,18 +39,20 @@ class PortListAdapter(
3739
holder.bind(ports.elementAt(position))
3840
}
3941

40-
inner class PortViewHolder(v: View) : RecyclerView.ViewHolder(v) {
42+
inner class PortViewHolder(
43+
private val binding: ItemPortRowBinding
44+
) : RecyclerView.ViewHolder(binding.root) {
4145

4246
init {
43-
itemView.row_port_delete.setOnClickListener { _ ->
47+
binding.rowPortDelete.setOnClickListener {
4448
onPortDeleted(ports.elementAt(layoutPosition))
4549
}
4650
}
4751

4852
fun bind(port: Int) {
49-
itemView.row_port.text = port.toString()
50-
itemView.row_port_description.text = PORT_DESCRIPTIONS[port]
51-
?: "Unknown port";
53+
binding.rowPort.text = port.toString()
54+
binding.rowPortDescription.text = PORT_DESCRIPTIONS[port]
55+
?: "Unknown port"
5256
}
5357
}
5458
}

‎app/src/main/java/tech/httptoolkit/android/ProxyDetails.kt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,10 @@ package tech.httptoolkit.android
22

33
import android.os.Parcelable
44
import android.util.Base64
5-
import android.util.Log
65
import com.beust.klaxon.Converter
76
import com.beust.klaxon.Json
87
import com.beust.klaxon.JsonValue
9-
import kotlinx.android.parcel.Parcelize
8+
import kotlinx.parcelize.Parcelize
109
import java.io.ByteArrayInputStream
1110
import java.security.cert.Certificate
1211
import java.security.cert.CertificateFactory

‎app/src/main/java/tech/httptoolkit/android/ProxySetup.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ fun whereIsCertTrusted(proxyConfig: ProxyConfig): String? {
191191
proxyCertAliases.any { alias -> alias.startsWith("system:") } -> "system"
192192
proxyCertAliases.any { alias -> alias.startsWith("user:") } -> "user"
193193
else -> {
194-
Sentry.capture("Cert has no recognizable aliases")
194+
Sentry.captureMessage("Cert has no recognizable aliases")
195195
return "unknown-store"
196196
}
197197
}

‎app/src/main/java/tech/httptoolkit/android/ProxyVpnRunnable.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ class ProxyVpnRunnable(
9595
(e is PacketHeaderException && errorMessage.contains("IP version should be 4 but was 6"))
9696

9797
if (!isIgnorable) {
98-
Sentry.capture(e)
98+
Sentry.captureException(e)
9999
}
100100
}
101101

‎app/src/main/java/tech/httptoolkit/android/ProxyVpnService.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -277,7 +277,7 @@ class ProxyVpnService : VpnService(), IProtectSocket {
277277
vpnInterface?.close()
278278
vpnInterface = null
279279
} catch (e: IOException) {
280-
Sentry.capture(e)
280+
Sentry.captureException(e)
281281
}
282282

283283
stopForeground(true)
@@ -296,7 +296,7 @@ class ProxyVpnService : VpnService(), IProtectSocket {
296296
vpnInterface?.close()
297297
vpnInterface = null
298298
} catch (e: IOException) {
299-
Sentry.capture(e)
299+
Sentry.captureException(e)
300300
}
301301

302302
stopForeground(true)

‎build.gradle

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
// Top-level build file where you can add configuration options common to all sub-projects/modules.
22

33
buildscript {
4-
ext.kotlin_version = '1.3.60'
4+
ext.kotlin_version = '1.9.25'
55
repositories {
66
google()
77
jcenter()
88
}
99
dependencies {
10-
classpath 'com.android.tools.build:gradle:4.2.2'
10+
classpath 'com.android.tools.build:gradle:8.7.2'
1111
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
12-
classpath 'com.google.gms:google-services:4.0.1'
12+
classpath 'com.google.gms:google-services:4.4.2'
1313
// NOTE: Do not place your application dependencies here; they belong
1414
// in the individual module build.gradle files
1515
}
@@ -22,6 +22,6 @@ allprojects {
2222
}
2323
}
2424

25-
task clean(type: Delete) {
25+
tasks.register('clean', Delete) {
2626
delete rootProject.buildDir
2727
}
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
#Fri Dec 04 13:54:32 CET 2020
1+
#Wed Nov 20 12:08:44 CET 2024
22
distributionBase=GRADLE_USER_HOME
3+
distributionUrl=https\://services.gradle.org/distributions/gradle-8.11-bin.zip
34
distributionPath=wrapper/dists
4-
zipStoreBase=GRADLE_USER_HOME
55
zipStorePath=wrapper/dists
6-
distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-bin.zip
6+
zipStoreBase=GRADLE_USER_HOME

0 commit comments

Comments
 (0)
Please sign in to comment.