Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4f72e485 authored by Jonathan Klee's avatar Jonathan Klee
Browse files

Merge branch '5266-implement-split-install-service' into 'main'

Implement SplitInstallService

See merge request !170
parents 04a5c70a e93af01c
Loading
Loading
Loading
Loading
Loading
+5 −1
Original line number Diff line number Diff line
@@ -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"
+4.58 KiB

File added.

Preview suppressed by a .gitattributes entry or the file's encoding is unsupported.

+5 −1
Original line number Diff line number Diff line
@@ -5,6 +5,7 @@

    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.GET_TASKS" />
    <uses-permission android:name="foundation.e.pwaplayer.provider.READ_WRITE" />

    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
@@ -26,7 +27,6 @@
        tools:ignore="ProtectedPermissions" />
    <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
    <uses-permission android:name="android.permission.REQUEST_DELETE_PACKAGES" />
    <uses-permission android:name="android.permission.UPDATE_PACKAGES_WITHOUT_USER_ACTION" />

    <application
        android:name=".AppLoungeApplication"
@@ -95,6 +95,10 @@
            tools:node="remove" />

        <service android:name=".manager.pkg.PackageInstallerService" />

        <service
            android:name=".splitinstall.SplitInstallService"
            android:exported="true" />
    </application>

</manifest>
 No newline at end of file
+6 −0
Original line number Diff line number Diff line
package foundation.e.apps;

interface ISplitInstallService {

    void installSplitModule(String packageName, String moduleName);
}
 No newline at end of file
+40 −8
Original line number Diff line number Diff line
@@ -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<Long, Boolean>()

    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)
        }
Loading