mirror of
https://github.com/spotiflacapp/SpotiFLAC-Mobile.git
synced 2026-06-01 03:15:17 +07:00
perf: reduce APK size - switch to audio-only FFmpeg, enable ProGuard, split APK by ABI
This commit is contained in:
parent
d4d3a48167
commit
c033c73a95
7 changed files with 77 additions and 16 deletions
15
.github/workflows/release.yml
vendored
15
.github/workflows/release.yml
vendored
|
|
@ -71,12 +71,18 @@ jobs:
|
||||||
run: dart run flutter_launcher_icons
|
run: dart run flutter_launcher_icons
|
||||||
|
|
||||||
- name: Build APK (Release)
|
- name: Build APK (Release)
|
||||||
run: flutter build apk --release
|
run: flutter build apk --release --split-per-abi
|
||||||
|
|
||||||
- name: Rename APK
|
- name: Rename APKs
|
||||||
run: |
|
run: |
|
||||||
VERSION=${{ steps.get_version.outputs.version }}
|
VERSION=${{ steps.get_version.outputs.version }}
|
||||||
mv build/app/outputs/flutter-apk/app-release.apk build/app/outputs/flutter-apk/SpotiFLAC-${VERSION}-android.apk
|
cd build/app/outputs/flutter-apk
|
||||||
|
# Rename split APKs
|
||||||
|
mv app-arm64-v8a-release.apk SpotiFLAC-${VERSION}-arm64.apk || true
|
||||||
|
mv app-armeabi-v7a-release.apk SpotiFLAC-${VERSION}-arm32.apk || true
|
||||||
|
# Also rename universal if exists
|
||||||
|
mv app-release.apk SpotiFLAC-${VERSION}-universal.apk || true
|
||||||
|
ls -la
|
||||||
|
|
||||||
- name: Upload APK artifact
|
- name: Upload APK artifact
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
|
|
@ -185,7 +191,8 @@ jobs:
|
||||||
Download Spotify tracks in FLAC quality from Tidal, Qobuz & Amazon Music.
|
Download Spotify tracks in FLAC quality from Tidal, Qobuz & Amazon Music.
|
||||||
|
|
||||||
### Downloads
|
### Downloads
|
||||||
- **Android**: `SpotiFLAC-${{ needs.build-android.outputs.version }}-android.apk`
|
- **Android (arm64)**: `SpotiFLAC-${{ needs.build-android.outputs.version }}-arm64.apk` (recommended for most devices)
|
||||||
|
- **Android (arm32)**: `SpotiFLAC-${{ needs.build-android.outputs.version }}-arm32.apk` (for older devices)
|
||||||
- **iOS**: `SpotiFLAC-${{ needs.build-android.outputs.version }}-ios-unsigned.ipa` (requires sideloading)
|
- **iOS**: `SpotiFLAC-${{ needs.build-android.outputs.version }}-ios-unsigned.ipa` (requires sideloading)
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
|
|
|
||||||
|
|
@ -29,13 +29,34 @@ android {
|
||||||
versionCode = flutter.versionCode
|
versionCode = flutter.versionCode
|
||||||
versionName = flutter.versionName
|
versionName = flutter.versionName
|
||||||
multiDexEnabled = true
|
multiDexEnabled = true
|
||||||
|
|
||||||
|
// Only include arm64-v8a for smaller APK (most modern devices)
|
||||||
|
// Remove this line if you need to support older 32-bit devices
|
||||||
|
ndk {
|
||||||
|
abiFilters += listOf("arm64-v8a", "armeabi-v7a")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
buildTypes {
|
buildTypes {
|
||||||
release {
|
release {
|
||||||
signingConfig = signingConfigs.getByName("debug")
|
signingConfig = signingConfigs.getByName("debug")
|
||||||
isMinifyEnabled = false
|
// Enable code shrinking and resource shrinking
|
||||||
isShrinkResources = false
|
isMinifyEnabled = true
|
||||||
|
isShrinkResources = true
|
||||||
|
proguardFiles(
|
||||||
|
getDefaultProguardFile("proguard-android-optimize.txt"),
|
||||||
|
"proguard-rules.pro"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Split APKs by ABI for smaller individual downloads
|
||||||
|
splits {
|
||||||
|
abi {
|
||||||
|
isEnable = true
|
||||||
|
reset()
|
||||||
|
include("arm64-v8a", "armeabi-v7a")
|
||||||
|
isUniversalApk = true // Also generate universal APK
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
33
android/app/proguard-rules.pro
vendored
Normal file
33
android/app/proguard-rules.pro
vendored
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
# Flutter specific rules
|
||||||
|
-keep class io.flutter.app.** { *; }
|
||||||
|
-keep class io.flutter.plugin.** { *; }
|
||||||
|
-keep class io.flutter.util.** { *; }
|
||||||
|
-keep class io.flutter.view.** { *; }
|
||||||
|
-keep class io.flutter.** { *; }
|
||||||
|
-keep class io.flutter.plugins.** { *; }
|
||||||
|
|
||||||
|
# Go backend (gobackend.aar)
|
||||||
|
-keep class gobackend.** { *; }
|
||||||
|
-keep class go.** { *; }
|
||||||
|
|
||||||
|
# FFmpeg Kit
|
||||||
|
-keep class com.arthenica.ffmpegkit.** { *; }
|
||||||
|
-keep class com.arthenica.smartexception.** { *; }
|
||||||
|
|
||||||
|
# Keep native methods
|
||||||
|
-keepclasseswithmembernames class * {
|
||||||
|
native <methods>;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Kotlin coroutines
|
||||||
|
-keepnames class kotlinx.coroutines.internal.MainDispatcherFactory {}
|
||||||
|
-keepnames class kotlinx.coroutines.CoroutineExceptionHandler {}
|
||||||
|
-keepclassmembers class kotlinx.coroutines.** {
|
||||||
|
volatile <fields>;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Prevent R8 from removing metadata
|
||||||
|
-keepattributes *Annotation*
|
||||||
|
-keepattributes SourceFile,LineNumberTable
|
||||||
|
-keepattributes Signature
|
||||||
|
-keepattributes Exceptions
|
||||||
|
|
@ -2,8 +2,8 @@ import 'dart:async';
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:path_provider/path_provider.dart';
|
import 'package:path_provider/path_provider.dart';
|
||||||
import 'package:ffmpeg_kit_flutter_new/ffmpeg_kit.dart';
|
import 'package:ffmpeg_kit_flutter_new_audio/ffmpeg_kit.dart';
|
||||||
import 'package:ffmpeg_kit_flutter_new/return_code.dart';
|
import 'package:ffmpeg_kit_flutter_new_audio/return_code.dart';
|
||||||
import 'package:spotiflac_android/models/download_item.dart';
|
import 'package:spotiflac_android/models/download_item.dart';
|
||||||
import 'package:spotiflac_android/models/settings.dart';
|
import 'package:spotiflac_android/models/settings.dart';
|
||||||
import 'package:spotiflac_android/models/track.dart';
|
import 'package:spotiflac_android/models/track.dart';
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
import 'package:ffmpeg_kit_flutter_new/ffmpeg_kit.dart';
|
import 'package:ffmpeg_kit_flutter_new_audio/ffmpeg_kit.dart';
|
||||||
import 'package:ffmpeg_kit_flutter_new/return_code.dart';
|
import 'package:ffmpeg_kit_flutter_new_audio/return_code.dart';
|
||||||
|
|
||||||
/// FFmpeg service for audio conversion and remuxing
|
/// FFmpeg service for audio conversion and remuxing
|
||||||
class FFmpegService {
|
class FFmpegService {
|
||||||
|
|
|
||||||
|
|
@ -313,14 +313,14 @@ packages:
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.4"
|
version: "2.1.4"
|
||||||
ffmpeg_kit_flutter_new:
|
ffmpeg_kit_flutter_new_audio:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: ffmpeg_kit_flutter_new
|
name: ffmpeg_kit_flutter_new_audio
|
||||||
sha256: d127635f27e93a7f21f0a14ce0a1a148e80919c402dac4a2118d73bfb17ce841
|
sha256: "0a698b46cd163c8e9917af75325c84d27871a2a8b2c37de3b40486cd0ab662ae"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "4.1.0"
|
version: "2.0.0"
|
||||||
ffmpeg_kit_flutter_platform_interface:
|
ffmpeg_kit_flutter_platform_interface:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|
|
||||||
|
|
@ -48,8 +48,8 @@ dependencies:
|
||||||
device_info_plus: ^12.3.0
|
device_info_plus: ^12.3.0
|
||||||
share_plus: ^10.1.4
|
share_plus: ^10.1.4
|
||||||
|
|
||||||
# FFmpeg for audio conversion
|
# FFmpeg for audio conversion (audio-only version - much smaller)
|
||||||
ffmpeg_kit_flutter_new: ^4.1.0
|
ffmpeg_kit_flutter_new_audio: ^2.0.0
|
||||||
open_filex: ^4.7.0
|
open_filex: ^4.7.0
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue