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

Commit 549a5650 authored by Guillaume Jacquart's avatar Guillaume Jacquart
Browse files

4025:test: add demo app and maestro tests

parent 62732cd4
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -141,6 +141,8 @@ telemetry = { module = "foundation.e.lib:telemetry", version.ref = "telemetry" }
timber = { module = "com.jakewharton.timber:timber", version.ref = "timber" }
truth = { module = "com.google.truth:truth", version.ref = "truth" }
viewpager2 = { module = "androidx.viewpager2:viewpager2", version.ref = "viewpager2" }
ui = { group = "androidx.compose.ui", name = "ui" }
ui-graphics = { group = "androidx.compose.ui", name = "ui-graphics" }
work-runtime-ktx = { module = "androidx.work:work-runtime-ktx", version.ref = "workRuntimeKtx" }
work-testing = { group = "androidx.work", name = "work-testing", version.ref = "workTesting" }

+1 −0
Original line number Diff line number Diff line
/build
 No newline at end of file
+68 −0
Original line number Diff line number Diff line
plugins {
    alias(libs.plugins.android.application)
    alias(libs.plugins.kotlin.android)
    alias(libs.plugins.compose.compiler)
}

android {
    namespace = "foundation.e.apps.installapp.demo"
    compileSdk = libs.versions.compileSdk.get().toInt()

    defaultConfig {
        applicationId = "foundation.e.apps.installapp.demo"
        minSdk = libs.versions.minSdk.get().toInt()
        targetSdk = libs.versions.targetSdk.get().toInt()
        versionCode = 1
        versionName = "1.0"
    }

    signingConfigs {
        create("platformConfig") {
            storeFile = file("../../app/keystore/platform.jks")
            storePassword = "platform"
            keyAlias = "platform"
            keyPassword = "platform"
        }
    }

    buildTypes {
        debug {
            signingConfig = signingConfigs.get("platformConfig")
        }

        release {
            isMinifyEnabled = false
        }
    }
    compileOptions {
        sourceCompatibility = JavaVersion.toVersion(libs.versions.jvmTarget.get())
        targetCompatibility = JavaVersion.toVersion(libs.versions.jvmTarget.get())
    }
    kotlinOptions {
        jvmTarget = libs.versions.jvmTarget.get()
    }
    buildFeatures {
        compose = true
    }
}

dependencies {
    implementation(project(":install-app-lib"))
//    implementation("foundation.e.apps:install-app-lib:1.0.0")

    implementation(libs.core.ktx)
    implementation(libs.lifecycle.runtime.ktx)
    implementation(libs.activity.compose)
    implementation(platform(libs.compose.bom))
    implementation(libs.ui)
    implementation(libs.ui.graphics)
    implementation(libs.compose.ui.tooling.preview)
    implementation(libs.compose.material3)
    testImplementation(libs.junit)
    androidTestImplementation(libs.ext.junit)
    androidTestImplementation(libs.espresso.core)
    androidTestImplementation(platform(libs.compose.bom))
    androidTestImplementation(libs.compose.ui.test.junit4)
    debugImplementation(libs.compose.ui.tooling)
    debugImplementation(libs.compose.ui.test.manifest)
}
+18 −0
Original line number Diff line number Diff line
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
    <uses-permission android:name="foundation.e.apps.permission.BIND_INSTALL_SERVICE"/>
    <application
        android:allowBackup="true"
        android:label="InstallAppDemo"
        android:supportsRtl="true">
        <activity
            android:name=".MainActivity"
            android:exported="true"
            >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>
+143 −0
Original line number Diff line number Diff line
package foundation.e.apps.installapp.demo

import android.os.Bundle
import android.util.Log
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Button
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.TextField
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.lifecycle.lifecycleScope
import foundation.e.apps.installapp.AppInstaller
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.launch

class MainActivity : ComponentActivity() {
    private val status = MutableStateFlow<String>("Not-connected")
    private val installStatus = MutableStateFlow<String?>(null)
    private var installJob: Job? = null


    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        enableEdgeToEdge()
        setContent {
            //AppLoungeTheme {
                Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
                    InstallAppScreen(
                        modifier = Modifier.padding(innerPadding),
                        status,
                        installStatus,
                        ::installApp,
                        ::stopInstallApp
                    )
                }
            //}
        }
    }


    private fun installApp(packageName: String) {
        installStatus.value = null
        val appInstaller = AppInstaller(this)

//        installJob = appInstaller.installByPackageName(packageName, installSource)
//            .map { status.value = it.name }
//            .launchIn(lifecycleScope)

        installJob = lifecycleScope.launch {
            appInstaller.status.map {
                Log.d("DebugGJ", "install ${packageName} status: $it ")
                //lastStatus = it
                status.value = it.name
            }.launchIn(lifecycleScope)

            installStatus.value = appInstaller.installByPackageName(packageName).name
        }
    }


    private fun stopInstallApp() {
        installJob?.cancel()
    }
}

@Composable()
private fun InstallAppScreen(
    modifier: Modifier,
    statusFlow: Flow<String>,
    installStatusFlow: Flow<String?>,
    installApp: (String)-> Unit,
    stopInstallApp: () -> Unit) {

    var packageName by remember { mutableStateOf("") }
    val status by statusFlow.collectAsState("not connected")
    val installStatus by installStatusFlow.collectAsState(null)

    Column(
        modifier = modifier
            .fillMaxWidth()
            .padding(16.dp)
    ) {
        TextField(
            value = packageName,
            onValueChange = { packageName = it },
            label = { Text(text = "Package name") },
            modifier = Modifier.fillMaxWidth()
        )

        Button(onClick = {
            installApp(packageName)
        },
            modifier = Modifier
                .fillMaxWidth()
                .padding(top = 12.dp)) {
            Text("Install")
        }

        Button(onClick = {
            stopInstallApp()
        },
            modifier = Modifier
                .fillMaxWidth()
                .padding(top = 12.dp)) {
            Text("STOP")
        }

        Row(modifier = Modifier
            .fillMaxWidth()
            .padding(top = 12.dp)) {
            Text("Status: ")
            Text(status)
        }
        installStatus?.let {
            Row(
                modifier = Modifier
                    .fillMaxWidth()
                    .padding(top = 12.dp)
            ) {
                Text("Install status: ")
                Text(it)
            }
        }
    }
}
Loading