Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Root installation, update dependencies & more default repositories #101

Open
wants to merge 24 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
176cb85
Update: Gradle wrapper
machiav3lli Sep 15, 2021
ab12b80
Update: Dependencies
machiav3lli Sep 15, 2021
b9ed252
Update: AGP
machiav3lli Sep 15, 2021
43d4587
Update: Tweak gradle build
machiav3lli Sep 15, 2021
97286f7
Update: Kotlin
machiav3lli Sep 15, 2021
6ebf500
Update: Migrate from Jcenter to MavenCentral
machiav3lli Sep 15, 2021
6461c31
Update: Compile- and targetSDK to 31
machiav3lli Sep 15, 2021
a8438c9
Fix: Removed/deprecated Kotlin functions
machiav3lli Sep 15, 2021
94f5b66
Add: Root installation preference
machiav3lli Sep 15, 2021
d1d3ebe
Add: Root installation
machiav3lli Sep 16, 2021
acdfdd8
Update: True/amoled black dark mode
machiav3lli Sep 16, 2021
c7aaa3a
Add: Query all apps permission (needed for SDK30+)
machiav3lli Sep 16, 2021
2ada120
Fix: Root installation key name
machiav3lli Sep 16, 2021
9b1c567
Update: Grey out root installation option when not available
machiav3lli Sep 16, 2021
15242ea
Update: Allow root installation in background even when in other Acti…
machiav3lli Sep 16, 2021
6057637
Update: Make startPackageInstaller an extension of Activity. Add: Cle…
machiav3lli Sep 16, 2021
032e999
Add: 23 repositories to default
machiav3lli Sep 16, 2021
695646e
Update: Sort default repositories by name
machiav3lli Sep 16, 2021
c5f3f18
Update: Don't open app's page after installing/updating
machiav3lli Sep 27, 2021
4253c5d
Update: Move toInstalledItem and abstract install/update action to Utils
machiav3lli Sep 27, 2021
6bfb437
Update: Update icon
machiav3lli Sep 27, 2021
8b68032
Add: Update all (skeleton)
machiav3lli Sep 27, 2021
2690205
Update: Hide update all button else where as updates page
machiav3lli Oct 9, 2021
6e9d2eb
Fix: Installing new app through install button
machiav3lli Oct 9, 2021
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
28 changes: 15 additions & 13 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
buildscript {
ext.versions = [
android: '3.4.1',
kotlin: '1.3.72'
android: '7.0.2',
kotlin: '1.5.30'
]

repositories {
mavenCentral()
google()
jcenter()
}

dependencies {
Expand All @@ -19,14 +19,13 @@ apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'

android {
compileSdkVersion 29
buildToolsVersion '29.0.3'
compileSdkVersion 31

defaultConfig {
archivesBaseName = 'foxy-droid'
applicationId 'nya.kitsunyan.foxydroid'
minSdkVersion 21
targetSdkVersion 29
targetSdkVersion 31
versionCode 4
versionName '1.3'

Expand Down Expand Up @@ -111,18 +110,21 @@ android {
}

repositories {
mavenCentral()
google()
jcenter()
maven { url 'https://jitpack.io' }
}

dependencies {
implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk7:' + versions.kotlin
implementation 'androidx.fragment:fragment:1.2.5'
implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk8:' + versions.kotlin
implementation 'androidx.fragment:fragment-ktx:1.3.6'
implementation 'androidx.viewpager2:viewpager2:1.0.0'
implementation 'androidx.vectordrawable:vectordrawable:1.1.0'
implementation 'com.squareup.okhttp3:okhttp:4.7.2'
implementation 'io.reactivex.rxjava3:rxjava:3.0.4'
implementation 'com.squareup.okhttp3:okhttp:5.0.0-alpha.2'
implementation 'io.reactivex.rxjava3:rxjava:3.1.1'
implementation 'io.reactivex.rxjava3:rxandroid:3.0.0'
implementation 'com.fasterxml.jackson.core:jackson-core:2.11.0'
implementation 'com.squareup.picasso:picasso:2.71828'
implementation 'io.reactivex.rxjava3:rxkotlin:3.0.1'
implementation 'com.fasterxml.jackson.core:jackson-core:2.12.5'
implementation 'com.squareup.picasso:picasso:2.8'
implementation 'com.github.topjohnwu.libsu:core:3.1.2'
}
3 changes: 3 additions & 0 deletions gradle.properties
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
android.useAndroidX=true
android.enableJetifier=true
org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
org.gradle.parallel=true
5 changes: 3 additions & 2 deletions gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#Wed Sep 15 23:07:46 CEST 2021
distributionBase=GRADLE_USER_HOME
distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
9 changes: 7 additions & 2 deletions src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
<uses-permission android:name="android.permission.REQUEST_DELETE_PACKAGES" />
<uses-permission
android:name="android.permission.QUERY_ALL_PACKAGES"
tools:ignore="QueryAllPackagesPermission" />

<application
android:name=".MainApplication"
Expand All @@ -20,7 +23,8 @@
tools:ignore="GoogleAppIndexingWarning">

<receiver
android:name=".MainApplication$BootReceiver">
android:name=".MainApplication$BootReceiver"
android:exported="false">

<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
Expand All @@ -31,7 +35,8 @@
<activity
android:name=".MainActivity"
android:launchMode="singleTask"
android:windowSoftInputMode="adjustResize">
android:windowSoftInputMode="adjustResize"
android:exported="true">

<intent-filter>
<action android:name="android.intent.action.MAIN" />
Expand Down
8 changes: 1 addition & 7 deletions src/main/kotlin/nya/kitsunyan/foxydroid/MainApplication.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,31 +9,25 @@ import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.content.pm.PackageInfo
import com.squareup.picasso.OkHttp3Downloader
import com.squareup.picasso.Picasso
import nya.kitsunyan.foxydroid.content.Cache
import nya.kitsunyan.foxydroid.content.Preferences
import nya.kitsunyan.foxydroid.content.ProductPreferences
import nya.kitsunyan.foxydroid.database.Database
import nya.kitsunyan.foxydroid.entity.InstalledItem
import nya.kitsunyan.foxydroid.index.RepositoryUpdater
import nya.kitsunyan.foxydroid.network.Downloader
import nya.kitsunyan.foxydroid.network.PicassoDownloader
import nya.kitsunyan.foxydroid.service.Connection
import nya.kitsunyan.foxydroid.service.SyncService
import nya.kitsunyan.foxydroid.utility.Utils
import nya.kitsunyan.foxydroid.utility.Utils.toInstalledItem
import nya.kitsunyan.foxydroid.utility.extension.android.*
import java.net.InetSocketAddress
import java.net.Proxy

@Suppress("unused")
class MainApplication: Application() {
private fun PackageInfo.toInstalledItem(): InstalledItem {
val signatureString = singleSignature?.let(Utils::calculateHash).orEmpty()
return InstalledItem(packageName, versionName.orEmpty(), versionCodeCompat, signatureString)
}

override fun attachBaseContext(base: Context) {
super.attachBaseContext(Utils.configureLocale(base))
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ object Preferences {

private val subject = PublishSubject.create<Key<*>>()

private val keys = sequenceOf(Key.AutoSync, Key.IncompatibleVersions, Key.ProxyHost, Key.ProxyPort, Key.ProxyType,
private val keys = sequenceOf(Key.AutoSync, Key.IncompatibleVersions, Key.RootInstallation, Key.ProxyHost, Key.ProxyPort, Key.ProxyType,
Key.SortOrder, Key.Theme, Key.UpdateNotify, Key.UpdateUnstable).map { Pair(it.name, it) }.toMap()

fun init(context: Context) {
Expand Down Expand Up @@ -82,6 +82,7 @@ object Preferences {
sealed class Key<T>(val name: String, val default: Value<T>) {
object AutoSync: Key<Preferences.AutoSync>("auto_sync", Value.EnumerationValue(Preferences.AutoSync.Wifi))
object IncompatibleVersions: Key<Boolean>("incompatible_versions", Value.BooleanValue(false))
object RootInstallation : Key<Boolean>("root_installation",Value.BooleanValue(false))
object ProxyHost: Key<String>("proxy_host", Value.StringValue("localhost"))
object ProxyPort: Key<Int>("proxy_port", Value.IntValue(9050))
object ProxyType: Key<Preferences.ProxyType>("proxy_type", Value.EnumerationValue(Preferences.ProxyType.Direct))
Expand Down
3 changes: 2 additions & 1 deletion src/main/kotlin/nya/kitsunyan/foxydroid/database/Database.kt
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,13 @@ import nya.kitsunyan.foxydroid.utility.extension.android.*
import nya.kitsunyan.foxydroid.utility.extension.json.*
import java.io.ByteArrayOutputStream

// TODO migrate to Room
object Database {
fun init(context: Context): Boolean {
val helper = Helper(context)
db = helper.writableDatabase
if (helper.created) {
for (repository in Repository.defaultRepositories) {
for (repository in Repository.defaultRepositories.sortedBy { it.name }) {
RepositoryAdapter.put(repository)
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/main/kotlin/nya/kitsunyan/foxydroid/entity/Product.kt
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ data class Product(val repositoryId: Long, val packageName: String, val name: St

companion object {
fun <T> findSuggested(products: List<T>, installedItem: InstalledItem?, extract: (T) -> Product): T? {
return products.maxWith(compareBy({ extract(it).compatible &&
return products.maxWithOrNull(compareBy({ extract(it).compatible &&
(installedItem == null || installedItem.signature in extract(it).signatures) }, { extract(it).versionCode }))
}

Expand Down
94 changes: 93 additions & 1 deletion src/main/kotlin/nya/kitsunyan/foxydroid/entity/Repository.kt
Original file line number Diff line number Diff line change
Expand Up @@ -107,12 +107,104 @@ data class Repository(val id: Long, val address: String, val mirrors: List<Strin
"official repository of The Guardian Project apps for use with the F-Droid client. Applications in this " +
"repository are official binaries built by the original application developers and signed by the same key as " +
"the APKs that are released in the Google Play Store.",
21, false, "B7C2EEFD8DAC7806AF67DFCD92EB18126BC08312A7F2D6F3862E46013C7A6135", "")
21, true, "B7C2EEFD8DAC7806AF67DFCD92EB18126BC08312A7F2D6F3862E46013C7A6135", "")
}, run {
defaultRepository("https://guardianproject.info/fdroid/archive", "Guardian Project Archive", "The official " +
"repository of The Guardian Project apps for use with the F-Droid client. This contains older versions of " +
"applications from the main repository.", 21, false,
"B7C2EEFD8DAC7806AF67DFCD92EB18126BC08312A7F2D6F3862E46013C7A6135", "")
}, run {
defaultRepository("https://apt.izzysoft.de/fdroid/repo", "IzzyOnDroid",
"IzzyOnDoird is a hub for official binaries of huge collection of open-source applications.",
21, true, "3BF0D6ABFEAE2F401707B6D966BE743BF0EEE49C2561B9BA39073711F628937A", "")
}, run {
defaultRepository("https://microg.org/fdroid/repo", "MicroG Project",
"Official repository of the open-source implementation of Google Play Services.",
21, true, "9BD06727E62796C0130EB6DAB39B73157451582CBD138E86C468ACC395D14165", "")
}, run {
defaultRepository("https://repo.netsyms.com/fdroid/repo", "Netsyms Technologies",
"Open-source apps created by Netsyms Technologies.",
21, true, "2581BA7B32D3AB443180C4087CAB6A7E8FB258D3A6E98870ECB3C675E4D64489", "")
}, run {
defaultRepository("https://fdroid.bromite.org/fdroid/repo", "Bromite",
"Bromite is a Chromium plus ad blocking and enhanced privacy; take back your browser.",
21, true, "E1EE5CD076D7B0DC84CB2B45FB78B86DF2EB39A3B6C56BA3DC292A5E0C3B9504", "")
}, run {
defaultRepository("https://molly.im/fdroid/foss/fdroid/repo", "Molly",
"Molly is a fork of Signal focused on security.",
21, false, "5198DAEF37FC23C14D5EE32305B2AF45787BD7DF2034DE33AD302BDB3446DF74", "")
}, run {
defaultRepository("https://archive.newpipe.net/fdroid/repo", "NewPipe",
"NewPipe's official independent repository.",
21, false, "E2402C78F9B97C6C89E97DB914A2751FDA1D02FE2039CC0897A462BDB57E7501", "")
}, run {
defaultRepository("https://www.collaboraoffice.com/downloads/fdroid/repo", "Collabora Office",
"Collabora Office is an office suite based on LibreOffice.",
21, false, "573258C84E149B5F4D9299E7434B2B69A8410372921D4AE586BA91EC767892CC", "")
}, run {
defaultRepository("https://www.droidware.info/fdroid/repo", "Ungoogled Chromium",
"Chromium sans dependency on Google web services. It also features some enhancments to privacy, control & transparency",
21, false, "2144449AB1DD270EC31B6087409B5D0EA39A75A9F290DA62AC1B238A0EAAF851", "")
}, run {
defaultRepository("https://fdroid.libretro.com/repo", "LibRetro",
"The official canary repository for this great retro emulators hub.",
21, false, "3F05B24D497515F31FEAB421297C79B19552C5C81186B3750B7C131EF41D733D", "")
}, run {
defaultRepository("https://cdn.kde.org/android/fdroid/repo", "KDE Android",
"The official nightly repository for KDE Android apps.",
21, false, "B3EBE10AFA6C5C400379B34473E843D686C61AE6AD33F423C98AF903F056523F", "")
}, run {
defaultRepository("https://rfc2822.gitlab.io/fdroid-firefox/fdroid/repo", "Unofficial Firefox",
"An unofficial repository with some of the most well known FOSS apps not on F-Droid.",
21, false, "8F992BBBA0340EFE6299C7A410B36D9C8889114CA6C58013C3587CDA411B4AED", "")
}, run {
defaultRepository("https://calyxos.gitlab.io/calyx-fdroid-repo/fdroid/repo", "Calyx OS Repo",
"The official Calyx Labs F-Droid repository.",
21, false, "C44D58B4547DE5096138CB0B34A1CC99DAB3B4274412ED753FCCBFC11DC1B7B6", "")
}, run {
defaultRepository("https://divestos.org/fdroid/official", "Divest OS Repo",
"The official Divest OS F-Droid repository.",
21, false, "E4BE8D6ABFA4D9D4FEEF03CDDA7FF62A73FD64B75566F6DD4E5E577550BE8467", "")
}, run {
defaultRepository("https://fdroid.fedilab.app/repo", "Fedilab",
"Fedilab's official F-Droid repository.",
21, false, "11F0A69910A4280E2CD3CCC3146337D006BE539B18E1A9FEACE15FF757A94FEB", "")
}, run {
defaultRepository("https://store.nethunter.com/repo", "Kali Nethunter",
"Kali Nethunter's official selection of original binaries.",
21, false, "7E418D34C3AD4F3C37D7E6B0FACE13332364459C862134EB099A3BDA2CCF4494", "")
}, run {
defaultRepository("https://secfirst.org/fdroid/repo", "Umbrella",
"Security advices, tutorials, tools etc..",
21, false, "39EB57052F8D684514176819D1645F6A0A7BD943DBC31AB101949006AC0BC228", "")
}, run {
defaultRepository("https://thecapslock.gitlab.io/fdroid-patched-apps/fdroid/repo", "Patched Apps",
"A collection of patched applications to provide better compatibility, privacy etc..",
21, false, "313D9E6E789FF4E8E2D687AAE31EEF576050003ED67963301821AC6D3763E3AC", "")
}, run {
defaultRepository("https://mobileapp.bitwarden.com/fdroid/repo", "Bitwarden",
"The official repository for Bitwarden.",
21, false, "BC54EA6FD1CD5175BCCCC47C561C5726E1C3ED7E686B6DB4B18BAC843A3EFE6C", "")
}, run {
defaultRepository("https://briarproject.org/fdroid/repo", "Briar",
"An serverless/offline messenger that hides your metadata.",
21, false, "1FB874BEE7276D28ECB2C9B06E8A122EC4BCB4008161436CE474C257CBF49BD6", "")
}, run {
defaultRepository("https://guardianproject-wind.s3.amazonaws.com/fdroid/repo", "Wind Project",
"A collection of interesting offline/serverless apps.",
21, false, "182CF464D219D340DA443C62155198E399FEC1BC4379309B775DD9FC97ED97E1", "")
}, run {
defaultRepository("https://repo.alefvanoon.xyz/fdroid/repo", "Alefvanoon",
"A collection of open-source apps that for one reason or another not on F-Droid.",
21, false, "04DF198F553069C7BE60F057AE12000E99F7700DA895CC1CE2EB11DC871581F1", "")
}, run {
defaultRepository("https://repo.unifiedpush.org/", "UnifiedPush",
"A repository of apps for unifiedPush.",
21, false, "DF11176406C63A7876103CE6CC1A8FCA239DF76AA5F6DE5CDBAFE73ECDBF1875", "")
}, run {
defaultRepository("https://nanolx.org/fdroid/repo", "NanoDroid",
"A companion repository to microG's installer.",
21, false, "862ED9F13A3981432BF86FE93D14596B381D75BE83A1D616E2D44A12654AD015", "")
})
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import android.widget.TextView
import android.widget.Toolbar
import androidx.fragment.app.DialogFragment
import androidx.fragment.app.Fragment
import com.topjohnwu.superuser.Shell
import io.reactivex.rxjava3.disposables.Disposable
import nya.kitsunyan.foxydroid.R
import nya.kitsunyan.foxydroid.content.Preferences
Expand Down Expand Up @@ -82,6 +83,8 @@ class PreferencesFragment: ScreenFragment() {
is Preferences.Theme.Dark -> getString(R.string.dark)
}
}
addSwitch(Preferences.Key.RootInstallation, getString(R.string.root_installation),
getString(R.string.root_installation_summary))
addSwitch(Preferences.Key.IncompatibleVersions, getString(R.string.incompatible_versions),
getString(R.string.incompatible_versions_summary))
}
Expand Down Expand Up @@ -110,6 +113,7 @@ class PreferencesFragment: ScreenFragment() {
preferences[Preferences.Key.ProxyHost]?.setEnabled(enabled)
preferences[Preferences.Key.ProxyPort]?.setEnabled(enabled)
}
preferences[Preferences.Key.RootInstallation]?.setEnabled(Shell.getShell().isRoot)
if (key == Preferences.Key.Theme) {
requireActivity().recreate()
}
Expand Down
21 changes: 3 additions & 18 deletions src/main/kotlin/nya/kitsunyan/foxydroid/screen/ProductFragment.kt
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import nya.kitsunyan.foxydroid.service.Connection
import nya.kitsunyan.foxydroid.service.DownloadService
import nya.kitsunyan.foxydroid.utility.RxUtils
import nya.kitsunyan.foxydroid.utility.Utils
import nya.kitsunyan.foxydroid.utility.Utils.startPackageInstaller
import nya.kitsunyan.foxydroid.utility.extension.android.*
import nya.kitsunyan.foxydroid.widget.DividerItemDecoration

Expand All @@ -55,7 +56,7 @@ class ProductFragment(): ScreenFragment(), ProductAdapter.Callbacks {

private enum class Action(val id: Int, val adapterAction: ProductAdapter.Action, val iconResId: Int) {
INSTALL(1, ProductAdapter.Action.INSTALL, R.drawable.ic_archive),
UPDATE(2, ProductAdapter.Action.UPDATE, R.drawable.ic_archive),
UPDATE(2, ProductAdapter.Action.UPDATE, R.drawable.ic_update),
LAUNCH(3, ProductAdapter.Action.LAUNCH, R.drawable.ic_launch),
DETAILS(4, ProductAdapter.Action.DETAILS, R.drawable.ic_tune),
UNINSTALL(5, ProductAdapter.Action.UNINSTALL, R.drawable.ic_delete)
Expand Down Expand Up @@ -332,23 +333,7 @@ class ProductFragment(): ScreenFragment(), ProductAdapter.Callbacks {
ProductAdapter.Action.INSTALL,
ProductAdapter.Action.UPDATE -> {
val installedItem = installed?.installedItem
val productRepository = Product.findSuggested(products, installedItem) { it.first }
val compatibleReleases = productRepository?.first?.selectedReleases.orEmpty()
.filter { installedItem == null || installedItem.signature == it.signature }
val release = if (compatibleReleases.size >= 2) {
compatibleReleases
.filter { it.platforms.contains(Android.primaryPlatform) }
.minBy { it.platforms.size }
?: compatibleReleases.minBy { it.platforms.size }
?: compatibleReleases.firstOrNull()
} else {
compatibleReleases.firstOrNull()
}
val binder = downloadConnection.binder
if (productRepository != null && release != null && binder != null) {
binder.enqueue(packageName, productRepository.first.name, productRepository.second, release)
}
Unit
Utils.startInstallUpdateAction(packageName, installedItem, products, downloadConnection)
}
ProductAdapter.Action.LAUNCH -> {
val launcherActivities = installed?.launcherActivities.orEmpty()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,10 @@ class ProductsFragment(): ScreenFragment(), CursorOwner.Callback {
private const val STATE_LAYOUT_MANAGER = "layoutManager"
}

enum class Source(val titleResId: Int, val sections: Boolean, val order: Boolean) {
AVAILABLE(R.string.available, true, true),
INSTALLED(R.string.installed, false, false),
UPDATES(R.string.updates, false, false)
enum class Source(val titleResId: Int, val sections: Boolean, val order: Boolean, val updates: Boolean) {
AVAILABLE(R.string.available, true, true, false),
INSTALLED(R.string.installed, false, false, false),
UPDATES(R.string.updates, false, false, true)
}

constructor(source: Source): this() {
Expand Down
Loading