diff --git a/app/build.gradle b/app/build.gradle
index 3c647b58d76e74d92c31f17f8d8d3d8a8e9b6a54..108622ac77631851a5e4dd18fda725e1bcc54760 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -110,7 +110,10 @@ allOpen {
dependencies {
- api "com.gitlab.AuroraOSS:gplayapi:0e224071f3"
+ // TODO: Add splitinstall-lib to a repo https://gitlab.e.foundation/e/os/backlog/-/issues/628
+ api files('libs/splitinstall-lib.jar')
+
+ implementation 'foundation.e:gplayapi:3.0.1'
implementation 'androidx.core:core-ktx:1.7.0'
implementation 'androidx.appcompat:appcompat:1.4.1'
implementation 'com.google.android.material:material:1.5.0'
@@ -181,6 +184,7 @@ dependencies {
def lifecycle_version = "2.4.0"
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version"
implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version"
+ implementation "android.arch.lifecycle:extensions:1.1.1"
// Coroutines
def coroutines_version = "1.6.0"
diff --git a/app/libs/splitinstall-lib.jar b/app/libs/splitinstall-lib.jar
new file mode 100644
index 0000000000000000000000000000000000000000..a18b464e1ce836e121e24e1be57a9fbdbd5a9c43
Binary files /dev/null and b/app/libs/splitinstall-lib.jar differ
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 05e9d66c5812295a2a363721d41f667e5a8e12af..c6155ab22b06ab8bdabe8a83d0e2a94e6491f6b9 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -5,6 +5,7 @@
+
@@ -26,7 +27,6 @@
tools:ignore="ProtectedPermissions" />
-
+
+
\ No newline at end of file
diff --git a/app/src/main/aidl/foundation/e/apps/ISplitInstallService.aidl b/app/src/main/aidl/foundation/e/apps/ISplitInstallService.aidl
new file mode 100644
index 0000000000000000000000000000000000000000..bf327d45daffb03ea6941486f1b453c5c3ca5722
--- /dev/null
+++ b/app/src/main/aidl/foundation/e/apps/ISplitInstallService.aidl
@@ -0,0 +1,6 @@
+package foundation.e.apps;
+
+interface ISplitInstallService {
+
+ void installSplitModule(String packageName, String moduleName);
+}
\ No newline at end of file
diff --git a/app/src/main/java/foundation/e/apps/api/DownloadManager.kt b/app/src/main/java/foundation/e/apps/api/DownloadManager.kt
index 85b1ba5525f8e08f7740220e916803e080b44820..c9a29d489ea5b88d531c82d95e90cc19dc8a46b4 100644
--- a/app/src/main/java/foundation/e/apps/api/DownloadManager.kt
+++ b/app/src/main/java/foundation/e/apps/api/DownloadManager.kt
@@ -39,7 +39,11 @@ class DownloadManager @Inject constructor(
@Named("cacheDir") private val cacheDir: String,
private val downloadManagerQuery: DownloadManager.Query,
) {
- private var isDownloading = false
+ private val downloadsMaps = HashMap()
+
+ companion object {
+ const val EXTERNAL_STORAGE_TEMP_CACHE_DIR = "/sdcard/Download/AppLounge/SplitInstallApks"
+ }
fun downloadFileInCache(
url: String,
@@ -47,17 +51,44 @@ class DownloadManager @Inject constructor(
fileName: String,
downloadCompleted: ((Boolean, String) -> Unit)?
): Long {
- val directoryFile = File(cacheDir + subDirectoryPath)
+ val directoryFile = File("$cacheDir/$subDirectoryPath")
+ if (!directoryFile.exists()) {
+ directoryFile.mkdirs()
+ }
+
val downloadFile = File("$cacheDir/$fileName")
+
+ return downloadFile(url, downloadFile, downloadCompleted)
+ }
+
+ fun downloadFileInExternalStorage(
+ url: String,
+ subDirectoryPath: String,
+ fileName: String,
+ downloadCompleted: ((Boolean, String) -> Unit)?
+ ): Long {
+
+ val directoryFile = File("$EXTERNAL_STORAGE_TEMP_CACHE_DIR/$subDirectoryPath")
if (!directoryFile.exists()) {
directoryFile.mkdirs()
}
+
+ val downloadFile = File("$directoryFile/$fileName")
+
+ return downloadFile(url, downloadFile, downloadCompleted)
+ }
+
+ private fun downloadFile(
+ url: String,
+ downloadFile: File,
+ downloadCompleted: ((Boolean, String) -> Unit)?
+ ): Long {
val request = DownloadManager.Request(Uri.parse(url))
.setTitle("Downloading...")
.setDestinationUri(Uri.fromFile(downloadFile))
val downloadId = downloadManager.enqueue(request)
- isDownloading = true
- tickerFlow(.5.seconds).onEach {
+ downloadsMaps[downloadId] = true
+ tickerFlow(downloadId, .5.seconds).onEach {
checkDownloadProgress(downloadId, downloadFile.absolutePath, downloadCompleted)
}.launchIn(CoroutineScope(Dispatchers.IO))
return downloadId
@@ -82,11 +113,11 @@ class DownloadManager @Inject constructor(
cursor.getLong(cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR))
if (status == DownloadManager.STATUS_FAILED) {
Timber.d("Download Failed: $filePath=> $bytesDownloadedSoFar/$totalSizeBytes $status")
- isDownloading = false
+ downloadsMaps[downloadId] = false
downloadCompleted?.invoke(false, filePath)
} else if (status == DownloadManager.STATUS_SUCCESSFUL) {
Timber.d("Download Successful: $filePath=> $bytesDownloadedSoFar/$totalSizeBytes $status")
- isDownloading = false
+ downloadsMaps[downloadId] = false
downloadCompleted?.invoke(true, filePath)
}
}
@@ -94,11 +125,12 @@ class DownloadManager @Inject constructor(
} catch (e: Exception) {
Timber.e(e)
}
+
}
- private fun tickerFlow(period: Duration, initialDelay: Duration = Duration.ZERO) = flow {
+ private fun tickerFlow(downloadId: Long, period: Duration, initialDelay: Duration = Duration.ZERO) = flow {
delay(initialDelay)
- while (isDownloading) {
+ while (downloadsMaps[downloadId]!!) {
emit(Unit)
delay(period)
}
diff --git a/app/src/main/java/foundation/e/apps/api/fused/FusedAPIImpl.kt b/app/src/main/java/foundation/e/apps/api/fused/FusedAPIImpl.kt
index 226c26de80d7952d2cd7a72775306a9421a13951..13cd0111013e21680316f38a77c3e07b407f2073 100644
--- a/app/src/main/java/foundation/e/apps/api/fused/FusedAPIImpl.kt
+++ b/app/src/main/java/foundation/e/apps/api/fused/FusedAPIImpl.kt
@@ -391,6 +391,23 @@ class FusedAPIImpl @Inject constructor(
return gPlayAPIRepository.validateAuthData(authData)
}
+ suspend fun getOnDemandModule(
+ authData: AuthData,
+ packageName: String,
+ moduleName: String,
+ versionCode: Int,
+ offerType: Int
+ ) : String? {
+ val list = gPlayAPIRepository.getOnDemandModule(packageName, moduleName, versionCode, offerType, authData)
+ for (element in list) {
+ if (element.name == "$moduleName.apk") {
+ return element.url
+ }
+ }
+ return null
+ }
+
+
suspend fun updateFusedDownloadWithDownloadingInfo(
authData: AuthData,
origin: Origin,
diff --git a/app/src/main/java/foundation/e/apps/api/fused/FusedAPIRepository.kt b/app/src/main/java/foundation/e/apps/api/fused/FusedAPIRepository.kt
index 6502866f94e414ec3b295fc4fb8e6632f8e20dc7..232af31fa0b2f174b7a5afc8d8f4e17b6d13d929 100644
--- a/app/src/main/java/foundation/e/apps/api/fused/FusedAPIRepository.kt
+++ b/app/src/main/java/foundation/e/apps/api/fused/FusedAPIRepository.kt
@@ -105,6 +105,16 @@ class FusedAPIRepository @Inject constructor(
)
}
+ suspend fun getOnDemandModule(
+ authData: AuthData,
+ packageName: String,
+ moduleName: String,
+ versionCode: Int,
+ offerType: Int
+ ) : String? {
+ return fusedAPIImpl.getOnDemandModule(authData, packageName, moduleName, versionCode, offerType)
+ }
+
suspend fun getCategoriesList(
type: Category.Type,
authData: AuthData
diff --git a/app/src/main/java/foundation/e/apps/api/gplay/GPlayAPIImpl.kt b/app/src/main/java/foundation/e/apps/api/gplay/GPlayAPIImpl.kt
index 54a8341fc67da0d9c0f8833b4f7da0ebdab4e116..6b40827c13ed7261f4e83d94dbe5051058a7dfa5 100644
--- a/app/src/main/java/foundation/e/apps/api/gplay/GPlayAPIImpl.kt
+++ b/app/src/main/java/foundation/e/apps/api/gplay/GPlayAPIImpl.kt
@@ -158,6 +158,21 @@ class GPlayAPIImpl @Inject constructor(
return downloadData
}
+ suspend fun getOnDemandModule(
+ packageName: String,
+ moduleName: String,
+ versionCode: Int,
+ offerType: Int,
+ authData: AuthData
+ ) : List {
+ val downloadData = mutableListOf()
+ withContext(Dispatchers.IO) {
+ val purchaseHelper = PurchaseHelper(authData).using(gPlayHttpClient)
+ downloadData.addAll(purchaseHelper.getOnDemandModule(packageName, moduleName, versionCode, offerType))
+ }
+ return downloadData
+ }
+
suspend fun getAppDetails(packageName: String, authData: AuthData): App? {
var appDetails: App?
withContext(Dispatchers.IO) {
diff --git a/app/src/main/java/foundation/e/apps/api/gplay/GPlayAPIRepository.kt b/app/src/main/java/foundation/e/apps/api/gplay/GPlayAPIRepository.kt
index bfb08b876772180dbe9a911d56afdbfd7995f56f..ca31e917000e3c50382e752eacff2393c20a816e 100644
--- a/app/src/main/java/foundation/e/apps/api/gplay/GPlayAPIRepository.kt
+++ b/app/src/main/java/foundation/e/apps/api/gplay/GPlayAPIRepository.kt
@@ -54,6 +54,16 @@ class GPlayAPIRepository @Inject constructor(
return gPlayAPIImpl.getSearchResults(query, authData)
}
+ suspend fun getOnDemandModule(
+ packageName: String,
+ moduleName: String,
+ versionCode: Int,
+ offerType: Int,
+ authData: AuthData
+ ) : List {
+ return gPlayAPIImpl.getOnDemandModule(packageName, moduleName, versionCode, offerType, authData)
+ }
+
suspend fun getDownloadInfo(
packageName: String,
versionCode: Int,
diff --git a/app/src/main/java/foundation/e/apps/manager/fused/FusedManagerImpl.kt b/app/src/main/java/foundation/e/apps/manager/fused/FusedManagerImpl.kt
index cc4780ba8ad8d6aebcd2bbd0899b64b378fa63b1..5df157e8c80f5ed66da394af1dd9ea31b0a8f975 100644
--- a/app/src/main/java/foundation/e/apps/manager/fused/FusedManagerImpl.kt
+++ b/app/src/main/java/foundation/e/apps/manager/fused/FusedManagerImpl.kt
@@ -120,6 +120,7 @@ class FusedManagerImpl @Inject constructor(
val parentPathFile = File("$cacheDir/${fusedDownload.packageName}")
parentPathFile.listFiles()?.let { list.addAll(it) }
list.sort()
+
if (list.size != 0) {
try {
Timber.d("installApp: STARTED ${fusedDownload.name} ${list.size}")
diff --git a/app/src/main/java/foundation/e/apps/manager/pkg/PkgManagerModule.kt b/app/src/main/java/foundation/e/apps/manager/pkg/PkgManagerModule.kt
index a743d7496c2f17bf15659c8bb194e336e1a49874..ad411ac0a4e79d1e065d45f3b5f3957df2db5e85 100644
--- a/app/src/main/java/foundation/e/apps/manager/pkg/PkgManagerModule.kt
+++ b/app/src/main/java/foundation/e/apps/manager/pkg/PkgManagerModule.kt
@@ -24,7 +24,8 @@ import android.content.Intent
import android.content.IntentFilter
import android.content.pm.ApplicationInfo
import android.content.pm.PackageInfo
-import android.content.pm.PackageInstaller
+import android.content.pm.PackageInstaller.Session
+import android.content.pm.PackageInstaller.SessionParams
import android.content.pm.PackageManager
import android.os.Build
import androidx.core.content.pm.PackageInfoCompat
@@ -134,29 +135,13 @@ class PkgManagerModule @Inject constructor(
@OptIn(DelicateCoroutinesApi::class)
fun installApplication(list: List, packageName: String) {
- val packageInstaller = packageManager.packageInstaller
- val params = PackageInstaller
- .SessionParams(PackageInstaller.SessionParams.MODE_FULL_INSTALL)
- .apply {
- setAppPackageName(packageName)
- setOriginatingUid(android.os.Process.myUid())
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
- setRequireUserAction(PackageInstaller.SessionParams.USER_ACTION_NOT_REQUIRED)
- }
- }
+ val sessionId = createInstallSession(packageName, SessionParams.MODE_FULL_INSTALL)
+ val session = packageManager.packageInstaller.openSession(sessionId)
- // Open a new specific session
- val sessionId = packageInstaller.createSession(params)
- val session = packageInstaller.openSession(sessionId)
try {
// Install the package using the provided stream
list.forEach {
- val inputStream = it.inputStream()
- val outputStream = session.openWrite(it.nameWithoutExtension, 0, -1)
- inputStream.copyTo(outputStream)
- session.fsync(outputStream)
- inputStream.close()
- outputStream.close()
+ syncFile(session, it)
}
val callBackIntent = Intent(context, InstallerService::class.java)
@@ -188,14 +173,37 @@ class PkgManagerModule @Inject constructor(
}
}
+ private fun createInstallSession(packageName: String, mode: Int): Int {
+
+ val packageInstaller = packageManager.packageInstaller
+ val params = SessionParams(mode).apply {
+ setAppPackageName(packageName)
+ setOriginatingUid(android.os.Process.myUid())
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
+ setRequireUserAction(SessionParams.USER_ACTION_NOT_REQUIRED)
+ }
+ }
+
+ return packageInstaller.createSession(params)
+ }
+
+ private fun syncFile(session: Session, file: File) {
+
+ val inputStream = file.inputStream()
+ val outputStream = session.openWrite(file.nameWithoutExtension, 0, -1)
+ inputStream.copyTo(outputStream)
+ session.fsync(outputStream)
+ inputStream.close()
+ outputStream.close()
+ }
+
/**
* Un-install the given package
* @param packageName Name of the package
*/
fun uninstallApplication(packageName: String) {
val packageInstaller = packageManager.packageInstaller
- val params =
- PackageInstaller.SessionParams(PackageInstaller.SessionParams.MODE_FULL_INSTALL)
+ val params = SessionParams(SessionParams.MODE_FULL_INSTALL)
val sessionId = packageInstaller.createSession(params)
val pendingIntent = PendingIntent.getBroadcast(
diff --git a/app/src/main/java/foundation/e/apps/splitinstall/SplitInstallBinder.kt b/app/src/main/java/foundation/e/apps/splitinstall/SplitInstallBinder.kt
new file mode 100644
index 0000000000000000000000000000000000000000..e024dbf9854a841405ac6a83710edffc679caf73
--- /dev/null
+++ b/app/src/main/java/foundation/e/apps/splitinstall/SplitInstallBinder.kt
@@ -0,0 +1,97 @@
+/*
+ * Apps Quickly and easily install Android apps onto your device!
+ * Copyright (C) 2021-2022 E FOUNDATION
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package foundation.e.apps.splitinstall
+
+import android.content.Context
+import com.aurora.gplayapi.data.models.AuthData
+import foundation.e.apps.ISplitInstallService
+import foundation.e.apps.api.DownloadManager
+import foundation.e.apps.api.fused.FusedAPIRepository
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.withContext
+import timber.log.Timber
+
+class SplitInstallBinder(
+ val context: Context,
+ private val coroutineScope: CoroutineScope,
+ val fusedAPIRepository: FusedAPIRepository,
+ val downloadManager: DownloadManager,
+ val authData: AuthData?,
+ private var splitInstallSystemService: foundation.e.splitinstall.ISplitInstallService?
+) : ISplitInstallService.Stub() {
+
+ private val modulesToInstall = HashMap()
+
+ companion object {
+ const val TAG = "SplitInstallerBinder"
+ }
+
+ override fun installSplitModule(packageName: String, moduleName: String) {
+ if (authData == null) {
+ Timber.i("No authentication data. Could not install on demand module")
+ return
+ }
+
+ coroutineScope.launch {
+ downloadModule(packageName, moduleName)
+ }
+ }
+
+ fun setService(service: foundation.e.splitinstall.ISplitInstallService) {
+ splitInstallSystemService = service
+ installPendingModules()
+ }
+
+ private suspend fun downloadModule(packageName: String, moduleName: String) {
+ withContext(Dispatchers.IO) {
+ val versionCode = getPackageVersionCode(packageName)
+ val url = fusedAPIRepository.getOnDemandModule(
+ authData!!, packageName, moduleName,
+ versionCode, 1
+ ) ?: return@withContext
+
+ downloadManager.downloadFileInExternalStorage(
+ url, packageName, "$packageName.split.$moduleName.apk"
+ ) { success, path ->
+ if (success) {
+ Timber.i("Split module has been downloaded: $path")
+ if (splitInstallSystemService == null) {
+ Timber.i("Not connected to system service now. Adding $path to the list.")
+ modulesToInstall[path] = packageName
+ }
+ splitInstallSystemService?.installSplitModule(packageName, path)
+ }
+ }
+ }
+ }
+
+ private fun getPackageVersionCode(packageName: String): Int {
+ val applicationInfo = context.packageManager.getPackageInfo(packageName, 0)
+ return applicationInfo.versionCode
+ }
+
+ private fun installPendingModules() {
+ for (module in modulesToInstall.keys) {
+ val packageName = modulesToInstall[module]
+ splitInstallSystemService?.installSplitModule(packageName, module)
+ }
+ }
+}
diff --git a/app/src/main/java/foundation/e/apps/splitinstall/SplitInstallService.kt b/app/src/main/java/foundation/e/apps/splitinstall/SplitInstallService.kt
new file mode 100644
index 0000000000000000000000000000000000000000..d85534533b3f008e7ac4ad4e398cfcf53ec80658
--- /dev/null
+++ b/app/src/main/java/foundation/e/apps/splitinstall/SplitInstallService.kt
@@ -0,0 +1,101 @@
+/*
+ * Apps Quickly and easily install Android apps onto your device!
+ * Copyright (C) 2021-2022 E FOUNDATION
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package foundation.e.apps.splitinstall
+
+import android.content.ComponentName
+import android.content.Intent
+import android.content.ServiceConnection
+import android.os.IBinder
+import androidx.lifecycle.LifecycleService
+import androidx.lifecycle.lifecycleScope
+import com.aurora.gplayapi.data.models.AuthData
+import com.google.gson.Gson
+import dagger.hilt.android.AndroidEntryPoint
+import foundation.e.apps.api.DownloadManager
+import foundation.e.apps.api.fused.FusedAPIRepository
+import foundation.e.apps.utils.modules.DataStoreModule
+import foundation.e.splitinstall.ISplitInstallService
+import foundation.e.splitinstall.SplitInstall
+import kotlinx.coroutines.launch
+import javax.inject.Inject
+
+@AndroidEntryPoint
+class SplitInstallService : LifecycleService() {
+
+ companion object {
+ const val TAG = "SplitInstallService"
+ }
+
+ @Inject lateinit var dataStoreModule: DataStoreModule
+ @Inject lateinit var fusedAPIRepository: FusedAPIRepository
+ @Inject lateinit var downloadManager: DownloadManager
+ @Inject lateinit var gson: Gson
+ private lateinit var binder: SplitInstallBinder
+ private var authData: AuthData? = null
+ private var splitInstallSystemService: ISplitInstallService? = null
+
+ private val serviceConnection = object : ServiceConnection {
+ override fun onServiceConnected(name: ComponentName, service: IBinder) {
+ splitInstallSystemService = ISplitInstallService.Stub.asInterface(service)
+ binder.setService(splitInstallSystemService!!)
+ }
+
+ override fun onServiceDisconnected(name: ComponentName?) {
+ splitInstallSystemService = null
+ }
+ }
+
+ override fun onCreate() {
+ super.onCreate()
+
+ val intent = Intent().apply {
+ component = SplitInstall.SPLIT_INSTALL_SYSTEM_SERVICE
+ }
+ bindService(intent, serviceConnection, BIND_AUTO_CREATE)
+
+ lifecycleScope.launch {
+ fetchAuthData()
+ }
+ }
+
+ override fun onDestroy() {
+ splitInstallSystemService?.let {
+ unbindService(serviceConnection)
+ }
+ super.onDestroy()
+ }
+
+ private suspend fun fetchAuthData() {
+ dataStoreModule.authData.collect {
+ authData = gson.fromJson(it, AuthData::class.java)
+ }
+ }
+
+ override fun onBind(intent: Intent): IBinder {
+ binder = SplitInstallBinder(
+ applicationContext,
+ lifecycleScope,
+ fusedAPIRepository,
+ downloadManager,
+ authData,
+ splitInstallSystemService
+ )
+ return binder
+ }
+}
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 7531c17019e96d6d4f89627aaf9568dcb3418582..ae79a32265e8ba44fd1cf8e368a65c425a12af7a 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -192,5 +192,4 @@
This app may not work properly!
Forcing installation will allow you to download and install it, but it won\'t guarantee that it will work.<br /><br />Attempting to install unsupported apps may cause crashes or slow down the system.<br /><br />We\'re working on improving compatiblity with this application in a near future.
-
diff --git a/gradle.properties b/gradle.properties
index 98bed167dc90ffee72b7affb37a659966b1bd114..1462a5544209e2d5ac79d3c2450af02b82fcdfbc 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -6,7 +6,7 @@
# http://www.gradle.org/docs/current/userguide/build_environment.html
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
-org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
+org.gradle.jvmargs=-Xmx4096m -Dfile.encoding=UTF-8
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
diff --git a/settings.gradle b/settings.gradle
index f50810cc5de859b98efb6cbd2d1faaa5d58bebb4..9ccfa34b954be1499ef6a267caa746d505c86f5a 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -4,6 +4,52 @@ dependencyResolutionManagement {
google()
mavenCentral()
maven { url 'https://jitpack.io' }
+
+ // Gitlab repository configuration for gplayapi dependency
+ def ciJobToken = System.getenv("CI_JOB_TOKEN")
+ def ciApiV4Url = System.getenv("CI_API_V4_URL")
+
+ if (ciJobToken != null) {
+ // Build on CI
+ maven {
+ url "https://gitlab.e.foundation/api/v4/projects/1269/packages/maven"
+ name "GitLab"
+ credentials(HttpHeaderCredentials) {
+ name = 'Job-Token'
+ value = ciJobToken
+ }
+ authentication {
+ header(HttpHeaderAuthentication)
+ }
+ }
+ } else {
+ // Build locally
+ // To build locally, you should set the gitLabPrivateToken variable with
+ // your Gitlab Private Token in your ./local.properties file:
+ //
+ // gitLabPrivateToken=YOUR_TOKEN
+ //
+ // To create a Private Token, go to:
+ // https://gitlab.e.foundation/e/os/gplayapi/-/settings/access_tokens
+ // and tick "api" as scope.
+
+ def localProperties = new Properties()
+ localProperties.load(new FileInputStream(rootProject.projectDir.path + "/local.properties"))
+
+ maven {
+ url "https://gitlab.e.foundation/api/v4/projects/1269/packages/maven"
+ name "GitLab"
+
+ credentials(HttpHeaderCredentials) {
+ name = 'Private-Token'
+ value = localProperties['gitLabPrivateToken']
+ }
+ authentication {
+ header(HttpHeaderAuthentication)
+ }
+ }
+ }
+
}
}
rootProject.name = "App Lounge"