Skip to content

Commit

Permalink
GitHub Source: Added support for libretorrent, FairEmail, k-9, tutano…
Browse files Browse the repository at this point in the history
…ta, SpotiFlyer, koreader

GitHub Source: Filter releases without APKs
GitHub Source: Clean tag name before comparison
GitHub Source: Try to select apk with correct arch
Fix PNG icons
Fix TV Banner
Portuguese Translation
#409: Fix displaying installation failed message when the install was actually succeeding
Only show notification when there are updates
  • Loading branch information
rumboalla committed Aug 20, 2023
1 parent 8b92df0 commit 7ce5c64
Show file tree
Hide file tree
Showing 18 changed files with 141 additions and 19 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ The 3.x branch is a full rewrite using modern technologies like **Jetpack Compos
* Supports **installs without user interaction** on Android 12+.
* **Root install** of updates.
* No ads. No tracking.
* **Languages**: English, Spanish, Dutch, German, Traditional Chinese, Simplified Chinese, Romanian, Italian.
* **Languages**: English, Spanish, Dutch, German, Traditional Chinese, Simplified Chinese, Romanian, Italian, Portuguese.

# Download
* [Beta Release (3.0.0-beta-04)](https://github.com/rumboalla/apkupdater/releases/download/3.0.0-beta-04/com.apkupdater.release.47.apk)
Expand All @@ -31,6 +31,7 @@ If you want to help with translations, open a [Pull Request](https://github.com/
* Simplified Chinese by [Nriver](https://github.com/Nriver)
* Romanian by [StormProductionsMusic](https://github.com/StormProductionsMusic)
* Italian by [NicKoehler](https://github.com/NicKoehler)
* Portuguese by [zekabra](https://github.com/zekabra)

# Feedback
- To give feedback and request new features go to [Discussions](https://github.com/rumboalla/apkupdater/discussions).
Expand Down
2 changes: 1 addition & 1 deletion app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ android {

applicationVariants.configureEach {
outputs.configureEach {
outputFileName = defaultConfig.applicationId + "." + buildType.name + "." + defaultConfig.versionCode + ".apk"
outputFileName = defaultConfig.applicationId + "-" + buildType.name + ".apk"
}
}

Expand Down
2 changes: 1 addition & 1 deletion app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@android:style/Theme.DeviceDefault.NoActionBar"
android:banner="@mipmap/ic_launcher"
android:banner="@drawable/banner"
tools:targetApi="34"
>
<activity
Expand Down
8 changes: 7 additions & 1 deletion app/src/main/java/com/apkupdater/data/github/GitHubApp.kt
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,11 @@ val GitHubApps = listOf(
GitHubApp("com.duckduckgo.mobile.android", "duckduckgo", "Android"),
GitHubApp("com.foobnix.pro.pdf.reader", "foobnix", "LibreraReader"),
GitHubApp("com.kunzisoft.keepass.free", "Kunzisoft", "KeePassDX"),
GitHubApp("dev.imranr.obtainium", "ImranR98", "Obtainium")
GitHubApp("dev.imranr.obtainium", "ImranR98", "Obtainium"),
GitHubApp("org.proninyaroslav.libretorrent", "proninyaroslav", "libretorrent"),
GitHubApp("eu.faircode.email", "M66B", "FairEmail"),
GitHubApp("com.fsck.k9", "thundernest", "k-9"),
GitHubApp("de.tutao.tutanota", "tutao", "tutanota"),
GitHubApp("com.shabinder.spotiflyer", "Shabinder", "SpotiFlyer"),
GitHubApp("org.koreader.launcher", "koreader", "koreader")
)
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
package com.apkupdater.data.ui

data class AppInstallStatus(val success: Boolean, val id: Int)
data class AppInstallStatus(val success: Boolean, val id: Int, val snack: Boolean = true)
51 changes: 48 additions & 3 deletions app/src/main/java/com/apkupdater/repository/GitHubRepository.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.apkupdater.repository

import android.net.Uri
import android.os.Build
import android.util.Log
import com.apkupdater.BuildConfig
import com.apkupdater.data.github.GitHubApps
Expand Down Expand Up @@ -99,8 +100,11 @@ class GitHubRepository(
packageName: String,
currentVersion: String
) = flow {
val releases = service.getReleases(user, repo).filter { filterPreRelease(it) }
if (releases.isNotEmpty() && Version(releases[0].tag_name.trimStart('v')) > Version(currentVersion)) {
val releases = service.getReleases(user, repo)
.filter { filterPreRelease(it) }
.filter { findApkAsset(it.assets).isNotEmpty() }

if (releases.isNotEmpty() && Version(filterVersion(releases[0].tag_name)) > Version(currentVersion)) {
val app = apps?.getApp(packageName)
emit(listOf(AppUpdate(
name = repo,
Expand All @@ -110,7 +114,7 @@ class GitHubRepository(
versionCode = 0L,
oldVersionCode = app?.versionCode ?: 0L,
source = GitHubSource,
link = findApkAsset(releases[0].assets),
link = findApkAssetArch(releases[0].assets),
whatsNew = releases[0].body,
iconUri = if (apps == null) Uri.parse(releases[0].author.avatar_url) else Uri.EMPTY
)))
Expand All @@ -134,10 +138,51 @@ class GitHubRepository(
else -> true
}

private fun filterVersion(version: String) = version
.replace(Regex("^\\D*"), "")
//.replace(Regex("\\D+\$"), "") // In case we want to remove non-numeric at end too

private fun findApkAsset(assets: List<GitHubReleaseAsset>) = assets
.filter { it.browser_download_url.endsWith(".apk", true) }
.maxByOrNull { it.size }
?.browser_download_url
.orEmpty()

private fun findApkAssetArch(assets: List<GitHubReleaseAsset>): String {
val apks = assets.filter { it.browser_download_url.endsWith(".apk", true) }
when {
apks.isEmpty() -> return ""
apks.size == 1 -> return apks.first().browser_download_url
else -> {
// Try to match exact arch
Build.SUPPORTED_ABIS.forEach { arch ->
apks.forEach { apk ->
if (apk.browser_download_url.contains(arch, true)) {
return apk.browser_download_url
}
}
}
// Try to match arm64
if (Build.SUPPORTED_ABIS.contains("arm64-v8a")) {
apks.forEach { apk ->
if (apk.browser_download_url.contains("arm64", true)) {
return apk.browser_download_url
}
}
}
// Try to match arm
if (Build.SUPPORTED_ABIS.contains("armeabi-v7a")) {
apks.forEach { apk ->
if (apk.browser_download_url.contains("arm", true)) {
return apk.browser_download_url
}
}
}
// If no match, return biggest apk in the hope it's universal
return apks.maxByOrNull { it.size }?.browser_download_url.orEmpty()
}
}

}

}
13 changes: 8 additions & 5 deletions app/src/main/java/com/apkupdater/viewmodel/InstallViewModel.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.apkupdater.data.snack.InstallSnack
import com.apkupdater.data.ui.ApkMirrorSource
import com.apkupdater.data.ui.AppInstallStatus
import com.apkupdater.data.ui.AppUpdate
import com.apkupdater.prefs.Prefs
import com.apkupdater.util.Downloader
Expand Down Expand Up @@ -35,10 +36,10 @@ abstract class InstallViewModel(
}

protected fun subscribeToInstallLog(
block: (Boolean, Int) -> Unit
block: (AppInstallStatus) -> Unit
) = viewModelScope.launch(Dispatchers.IO) {
mainViewModel.appInstallLog.collect {
block(it.success, it.id)
block(it)
if (it.success) {
finishInstall(it.id).join()
} else {
Expand Down Expand Up @@ -66,9 +67,11 @@ abstract class InstallViewModel(
}
}

protected fun sendInstallSnack(updates: List<AppUpdate>, success: Boolean, id: Int) {
updates.find { id == it.id && it.isInstalling }?.let { app ->
mainViewModel.sendSnack(InstallSnack(success, app.name))
protected fun sendInstallSnack(updates: List<AppUpdate>, log: AppInstallStatus) {
if (log.snack) {
updates.find { log.id == it.id }?.let { app ->
mainViewModel.sendSnack(InstallSnack(log.success, app.name))
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ class MainViewModel(private val prefs: Prefs) : ViewModel() {
fun changeUpdatesBadge(number: String) = changeBadge(Screen.Updates.route, number)

fun cancelCurrentInstall() = viewModelScope.launch(Dispatchers.IO) {
appInstallLog.emit(AppInstallStatus(false, currentInstallId))
appInstallLog.emit(AppInstallStatus(false, currentInstallId, false))
}

fun processIntent(
Expand Down
4 changes: 2 additions & 2 deletions app/src/main/java/com/apkupdater/viewmodel/SearchViewModel.kt
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ class SearchViewModel(
private var job: Job? = null

init {
subscribeToInstallLog { success, id ->
sendInstallSnack(state.value.updates(), success, id)
subscribeToInstallLog { log ->
sendInstallSnack(state.value.updates(), log)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ class UpdatesViewModel(
private val state = MutableStateFlow<UpdatesUiState>(UpdatesUiState.Loading)

init {
subscribeToInstallLog { success, id ->
sendInstallSnack(state.value.updates(), success, id)
subscribeToInstallLog { log ->
sendInstallSnack(state.value.updates(), log)
}
}

Expand Down
4 changes: 3 additions & 1 deletion app/src/main/java/com/apkupdater/worker/UpdatesWorker.kt
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,9 @@ class UpdatesWorker(

override suspend fun doWork(): Result {
updatesRepository.updates().collect {
notification.showUpdateNotification(it.size)
if (it.isNotEmpty()) {
notification.showUpdateNotification(it.size)
}
}
return Result.success()
}
Expand Down
Binary file added app/src/main/res/drawable/banner.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified app/src/main/res/mipmap-hdpi/ic_launcher.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified app/src/main/res/mipmap-mdpi/ic_launcher.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified app/src/main/res/mipmap-xhdpi/ic_launcher.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified app/src/main/res/mipmap-xxhdpi/ic_launcher.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
65 changes: 65 additions & 0 deletions app/src/main/res/values-pt/strings.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<resources>

<string name="app_name" translatable="false">APKAtualizador</string>
<string name="tab_apps">"Apps"</string>
<string name="tab_search">"Procurar"</string>
<string name="tab_updates">"Atualizações"</string>
<string name="tab_settings">"Configurações"</string>
<string name="something_went_wrong">"Aconteceu algo de errado\n\uD83E\uDD26"</string>
<string name="ignore_cd">"Ignorar app"</string>
<string name="unignore_cd">"Não ignorar app"</string>
<string name="refresh_updates">"Procurar atualizações"</string>
<string name="exclude_system_apps">"Excluir apps do sistema"</string>
<string name="include_system_apps">"Incluir apps do sistema"</string>
<string name="exclude_app_store">"Excluir App Store"</string>
<string name="include_app_store">"Incluir App Store"</string>
<string name="exclude_disabled_apps">"Excluir apps desativadas"</string>
<string name="include_disabled_apps">"Incluir apps desativadas"</string>
<string name="install_cd">"Instalar app"</string>
<string name="app_cd">"App ícone"</string>
<string name="install_success">"%1$s instalada."</string>
<string name="install_failure">"%1$s falhou a instalação."</string>

// Settings
<string name="settings_portrait_columns">"Colunas em modo retrato"</string>
<string name="settings_landscape_columns">"Colunas em modo paisagem"</string>
<string name="settings_sources">"Código fonte"</string>
<string name="settings_ui">"UI"</string>
<string name="settings_alarm">"Alarme"</string>
<string name="settings_options">"Opções"</string>
<string name="settings_hour">"Hora do alarme"</string>
<string name="settings_alarm_daily">"Diário"</string>
<string name="settings_alarm_3day">"3-Dias"</string>
<string name="settings_alarm_weekly">"Semanalmente"</string>
<string name="settings_android_tv_ui" translatable="false">Android TV UI</string>
<string name="ignore_alpha">"Ignorar alpha"</string>
<string name="ignore_beta">"Ignorar beta"</string>
<string name="ignore_preRelease">"Ignorar pré-lançamento"</string>
<string name="use_safe_stores">"Utilizar lojas seguras (Aptoide)"</string>
<string name="root_install">"Instalação root"</string>
<string name="source_apkmirror" translatable="false">ApkMirror</string>
<string name="source_fdroid" translatable="false">F-Droid (Principal)</string>
<string name="source_izzy" translatable="false">F-Droid (Izzy)</string>
<string name="source_aptoide" translatable="false">Aptoide</string>
<string name="source_github" translatable="false">GitHub</string>
<string name="about">"Sobre"</string>
<string name="frequency">"Frequência"</string>
<string name="theme">"Tema"</string>
<string name="theme_system">"Sistema"</string>
<string name="theme_dark">"Escuro"</string>
<string name="theme_light">"Claro"</string>
<string name="about_github">"Obter código fonte, reportar bugs, requisitar novas funcionalidades e traduções."</string>
<string name="about_donate">"Se gostas da app, considera fazer um donativo para uma causa justa."</string>

// Notifications
<string name="notification_channel_name">Atualizações</string>
<string name="notification_channel_description">Canal para notificações de atualizações.</string>
<string name="notification_channel_id" translatable="false">updateChannel</string>
<string name="notification_update_title">Atualizações</string>
<plurals name="notification_update_description">
<item quantity="zero">Nenhuma atualização encontrada.</item>
<item quantity="one">Encontrada %1$d atualização.</item>
<item quantity="other">Encontradas %1$d atualizações.</item>
</plurals>

</resources>

0 comments on commit 7ce5c64

Please sign in to comment.