Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 28 additions & 3 deletions .github/workflows/android.yml
Original file line number Diff line number Diff line change
Expand Up @@ -68,11 +68,36 @@ jobs:
path: app/src/main/libs/**/*.so
if-no-files-found: warn

# AGP drives ndk-build, so the native inputs must be staged before ./gradlew (keeping
# that here rather than in a preBuild hook leaves Gradle offline-clean for local builds).
assemble:
name: assemble (AGP 8)
runs-on: ubuntu-24.04
container: ghcr.io/xroche/httrack-android-build:latest
steps:
- uses: actions/checkout@v6
with:
submodules: recursive # MUST be recursive: coucal is nested in httrack
- name: Vendor libiconv
run: tools/ci/vendor-libiconv.sh
- name: Stage OpenSSL statics into prebuild/
run: tools/ci/fetch-openssl-statics.sh # picks up $OPENSSL_ANDROID_ROOT from the image
- name: Gradle assemble + lint
run: ./gradlew --no-daemon assembleDebug assembleRelease lint
- uses: actions/upload-artifact@v4
with:
name: apk
path: app/build/outputs/apk/**/*.apk
if-no-files-found: error
- uses: actions/upload-artifact@v4
if: always() # the report is most useful when lint is unhappy
with:
name: lint-report
path: app/build/reports/lint-results-*.*
if-no-files-found: warn

# --- Phases below land with the app modernization (see the plan) ---
#
# assemble: ./gradlew assembleDebug assembleRelease lint — needs the AGP 8 /
# AndroidX migration (Phase 3), and can use the GHCR toolchain image.
#
# emulator-smoke: reactivecircus/android-emulator-runner (x86_64, api 21/29/34),
# installs the APK and runs an instrumented crawl against a local fixture
# server. Needs Phase 4 (storage) + the coffeecatch x86_64 fix.
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ workspace.xml
/.gradle
/local.properties
/build
/gradle
/.idea/libraries
/app/.externalNativeBuild
/app/build
Expand Down
100 changes: 61 additions & 39 deletions app/build.gradle
Original file line number Diff line number Diff line change
@@ -1,39 +1,61 @@
apply plugin: 'com.android.application'
android {
compileSdkVersion 11
buildToolsVersion "25.0.2"

defaultConfig {
applicationId "com.httrack.android"
minSdkVersion 9
targetSdkVersion 25

ndk {
moduleName "libhtsjni"
abiFilters = [ "arm64-v8a", "x86_64" ]
}
}

buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
}
}

dependencies {
// ContextCompat.checkSelfPermission needs version 23
compile 'com.android.support:support-v4:23.0.0'
}

productFlavors {
}
externalNativeBuild {
ndkBuild {
path 'src/main/jni/Android.mk'
}
}
}

dependencies {
}
plugins {
id 'com.android.application'
}

android {
namespace 'com.httrack.android'
compileSdk 35
// Pinned to what the toolchain image installs, so no build-tools are fetched at build time.
buildToolsVersion "35.0.0"
ndkVersion "26.3.11579264"

defaultConfig {
applicationId "com.httrack.android"
minSdk 24
// Left at master's value: 26 would silently drop the channel-less notifications,
// and 29 would take legacy storage away from the still File-based crawl.
targetSdk 25
versionCode 63
versionName "3.49.02.63"

ndk {
abiFilters "arm64-v8a", "x86_64"
}
}

buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}

buildFeatures {
// HTTrackActivity reads BuildConfig.APPLICATION_ID for the FileProvider authority.
buildConfig true
}

compileOptions {
sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_17
}

// This 2017-era code trips many modern checks; keep the build green and tighten later.
lint {
abortOnError false
}

externalNativeBuild {
ndkBuild {
path 'src/main/jni/Android.mk'
}
}
}

dependencies {
// Without this, coroutines' stale jdk7/jdk8 shims collide with the stdlib that absorbed them.
implementation platform('org.jetbrains.kotlin:kotlin-bom:1.8.22')

implementation 'androidx.core:core:1.13.1'
implementation 'androidx.fragment:fragment:1.8.2'
}
2 changes: 2 additions & 0 deletions app/proguard-rules.pro
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Native code resolves these reflectively, leaving R8 no Java caller to trace.
-keep class com.httrack.android.jni.** { *; }
18 changes: 4 additions & 14 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,13 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.httrack.android"
android:installLocation="auto"
android:versionCode="63"
android:versionName="3.49.02.63" >

<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="25" />
android:installLocation="auto" >

<!-- We need to read/write copied Websites to the SD card. -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Expand All @@ -27,7 +20,8 @@
android:theme="@style/AppTheme" >
<activity
android:name="com.httrack.android.HTTrackActivity"
android:label="@string/title_activity_startup" >
android:label="@string/title_activity_startup"
android:exported="true" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />

Expand All @@ -42,10 +36,6 @@
android:name="com.httrack.android.OptionsActivity"
android:label="@string/title_activity_options" >
</activity>
<activity
android:name="com.httrack.android.HelpActivity"
android:label="@string/title_activity_options" >
</activity>
<activity
android:name="com.httrack.android.OptionsActivity$ScanRulesTab"
android:label="@string/title_activity_options" >
Expand Down Expand Up @@ -91,7 +81,7 @@
android:label="@string/title_activity_file_chooser" >
</activity>
<provider
android:name="android.support.v4.content.FileProvider"
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
Expand Down
15 changes: 8 additions & 7 deletions app/src/main/java/com/httrack/android/HTTrackActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -68,13 +68,6 @@
import android.os.Handler;
import android.os.Parcelable;
import android.os.StrictMode;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.NotificationCompat;
import android.support.v4.content.ContextCompat;
import android.support.v4.content.FileProvider;
import android.text.Editable;
import android.text.Html;
import android.text.TextUtils;
Expand All @@ -96,6 +89,14 @@
import android.widget.TextView;
import android.widget.Toast;

import androidx.core.app.ActivityCompat;
import androidx.core.app.NotificationCompat;
import androidx.core.content.ContextCompat;
import androidx.core.content.FileProvider;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import androidx.fragment.app.FragmentManager;

import com.httrack.android.jni.HTTrackCallbacks;
import com.httrack.android.jni.HTTrackLib;
import com.httrack.android.jni.HTTrackStats;
Expand Down
8 changes: 6 additions & 2 deletions app/src/main/java/com/httrack/android/OptionsActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.os.Parcelable;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Gravity;
Expand Down Expand Up @@ -349,8 +350,11 @@ protected void onCreate(final Bundle savedInstanceState) {
mapper.resetMap();

// Load map
mapper.unserialize(getIntent()
.getParcelableExtra("com.httrack.android.map"));
// Pinned to Parcelable: inlined, T infers as File & Parcelable and unserialize(File)
// matches just as well, which javac rejects as ambiguous.
final Parcelable savedMap =
getIntent().getParcelableExtra("com.httrack.android.map");
mapper.unserialize(savedMap);
Log.d(getClass().getSimpleName(), "map size: " + mapper.size());

// Create tabs
Expand Down
3 changes: 2 additions & 1 deletion app/src/main/res/values-v11/styles.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
<style name="AppBaseTheme" parent="@android:style/Theme.Holo.Light" />

<!-- Custom styles -->
<style name="ButtonStyle" parent="@android:attr/buttonStyle">
<!-- No parent: buttons already pick the theme's buttonStyle up as their default style. -->
<style name="ButtonStyle">
<item name="android:background">?android:attr/selectableItemBackground</item>
</style>

Expand Down
3 changes: 2 additions & 1 deletion app/src/main/res/values/styles.xml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@
</style>

<!-- Custom styles -->
<style name="ButtonStyle" parent="@android:attr/buttonStyle" />
<!-- No parent: buttons already pick the theme's buttonStyle up as their default style. -->
<style name="ButtonStyle" />

<style name="DividerLineVertical">
<item name="android:layout_width">0dip</item>
Expand Down
20 changes: 5 additions & 15 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,15 +1,5 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.3.2'
}
}

allprojects {
repositories {
jcenter()
}
}
// Top-level build file where you can add configuration options common to all sub-projects/modules.
// Repositories live in settings.gradle (pluginManagement + dependencyResolutionManagement).
plugins {
id 'com.android.application' version '8.6.0' apply false
}
6 changes: 6 additions & 0 deletions gradle.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
android.useAndroidX=true
# OptionsActivity drives its tabs off annotations like @Fields({R.id.editRules}), which
# only compile while R fields are constants. AGP 8 makes them non-final by default.
android.nonFinalResIds=false
org.gradle.jvmargs=-Xmx2048m
org.gradle.parallel=true
Binary file added gradle/wrapper/gradle-wrapper.jar
Binary file not shown.
6 changes: 4 additions & 2 deletions gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#Sat Mar 18 16:47:53 CET 2017
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
distributionSha256Sum=544c35d6bd849ae8a5ed0bcea39ba677dc40f49df7d1835561582da2009b961d
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip
Loading
Loading