How install and run Android app on device by gradle task? - android

Gradle 2.14
android {
dev {
}
}
task runAppDev(type: Exec, dependsOn: 'installDev') {
description "Install and run app (dev env)"
android.applicationVariants.all { variant ->
if ("installDev".toUpperCase().endsWith(variant.getName().toUpperCase())) {
commandLine getRunAppCommandLine(variant)
}
}
}
def getRunAppCommandLine(variant) {
List<String> commandLine = ["adb", "shell", "am", "start", "-n", variant.getApplicationId() + "/.activity.SplashActivity"]
return commandLine
}
Run my task by: gradlew runAppDev
Result:
Installing APK 'app-dev.apk' on 'Nexus 5 - 6.0.1' for app:dev
Installed on 1 device.
:app:runAppDev
BUILD SUCCESSFUL
So, my application success installed on device, but NOT run on device.

I found bug. I send incorrect adb arg. Here fix:
def getRunAppCommandLine(variant) {
List<String> commandLine = ["adb", "shell", "monkey", "-p", variant.getApplicationId() + " 1"]
return commandLine
}

Related

'--target=armv7-linux-androideabi' which wasn't expected, or isn't valid in this context

I'm trying to add a rust-implemented Android native library to my Flutter package (plugin), this Android module has only one build.gradle file which is in the projectRoot directory.
Add the rust-android-gradle to the build.gradle file
buildscript {
repositories {
...
maven {
url "https://plugins.gradle.org/m2/"
}
}
dependencies {
...
classpath "org.mozilla.rust-android-gradle:plugin:0.9.3"
}
}
Add the Rust part to the build.gradle file
android {
...
}
cargo {
module = "src/main/rust/shadowsocks-rust"
libname = "sslocal"
targets = ["arm", "arm64"]
profile = findProperty("CARGO_PROFILE")?.toString() ?: getCurrentFlavor()
extraCargoBuildArguments = ["--bin", libname]
featureSpec.noDefaultBut(
"stream-cipher",
"aead-cipher-extra",
"logging",
"local-flow-stat",
"local-dns",
"armv8",
"neon",
"aead-cipher-2022",
)
exec = { spec, toolchain ->
{
try {
Runtime.getRuntime().exec("python3 -V >/dev/null 2>&1")
spec.environment("RUST_ANDROID_GRADLE_PYTHON_COMMAND", "python3")
project.logger.lifecycle("Python 3 detected.")
} catch (java.io.IOException e1) {
project.logger.lifecycle("No python 3 detected.")
try {
Runtime.getRuntime().exec("python -V >/dev/null 2>&1")
spec.environment("RUST_ANDROID_GRADLE_PYTHON_COMMAND", "python")
project.logger.lifecycle("Python detected.")
} catch (java.io.IOException e2) {
throw GradleException("No any python version detected. You should install the python first to compile project.")
}
}
spec.environment("RUST_ANDROID_GRADLE_LINKER_WRAPPER_PY", "$projectDir/$module/../linker-wrapper.py")
spec.environment("RUST_ANDROID_GRADLE_TARGET", "target/${toolchain.target}/$profile/lib${libname}.so")
}
}
}
tasks.whenTaskAdded { task ->
if (task.name == "mergeDebugJniLibFolders" || task.name == "mergeReleaseJniLibFolders") {
task.dependsOn("cargoBuild")
}
}
tasks.register("cargoClean", Exec) {
executable("cargo") // cargo.cargoCommand
args("clean")
workingDir("${projectDir}/${cargo.module}")
}
tasks.clean.dependsOn("cargoClean")
dependencies {
...
}
def getCurrentFlavor() {
...
}
Add Rust Android targets
rustup target add armv7-linux-androideabi aarch64-linux-android i686-linux-android x86_64-linux-android
info: component 'rust-std' for target 'armv7-linux-androideabi' is up to date
info: component 'rust-std' for target 'aarch64-linux-android' is up to date
info: component 'rust-std' for target 'i686-linux-android' is up to date
info: component 'rust-std' for target 'x86_64-linux-android' is up to date
But it reports the following ERROR when I build the project, Where is wrong?
Found argument '--target=armv7-linux-androideabi' which wasn't expected, or isn't valid in this context
I have installed all required tools and I'm sure my Windows PC can compile other Rust Android native libraries fine.
I have tried Rust stable and nightly version
rustup default stable
info: using existing install for 'stable-x86_64-pc-windows-msvc'
info: default toolchain set to 'stable-x86_64-pc-windows-msvc'
stable-x86_64-pc-windows-msvc unchanged - rustc 1.64.0 (a55dd71d5 2022-09-19)
rustup default nightly
info: using existing install for 'nightly-x86_64-pc-windows-msvc'
info: default toolchain set to 'nightly-x86_64-pc-windows-msvc'
nightly-x86_64-pc-windows-msvc unchanged - rustc 1.66.0-nightly (a24a020e6 2022-10-18)

Could not get unknown property 'apkNames' in android gradle plugin 4.1.0

I am using this code in build.gradle:
android {
applicationVariants.all { variant ->
variant.packageApplicationProvider.configure { packageApplicationTask ->
doLast {
packageApplicationTask.apkNames.each { apkName ->
def apkDir = "./build/outputs/apk/${flavorName}/${buildType.name}"
def apkDestName = apkName.replace("app-", "stickerly-android-" + variant.versionName + "-").replace(".apk", "-" + getDate() + ".apk")
println "#####Rename ${variant.name} Apk File"
copy {
from("$apkDir/$apkName").into(apkDir).rename { String fileName -> apkDestName }
}
println "#####Copy mapping File"
def mappingDir = "./build/outputs/mapping/${flavorName}${buildType.name.capitalize()}"
copy {
from("$mappingDir/mapping.txt").into(mappingDir).rename {
"mapping-stickerly-${variant.versionName}.txt"
}
}
}
}
}
}
}
With this code I rename apk file and copy mapping file. I worked in android gradle plugin 4.0, but it does not work in 4.1 with this message
Where:
Script '/Users/snow/workspace/stickerly-android/app/build-android-extra.gradle' line: 5
What went wrong:
Execution failed for task ':app:packageExternalArm8Debug'.
Could not get unknown property 'apkNames' for task ':app:packageExternalArm8Debug' of type com.android.build.gradle.tasks.PackageApplication.
I think API has changed but I can not find any documents. Someone can help me?
Thanks.
property apkNames is removed in AGP 4.1
you can try this
gradle.taskGraph.afterTask { Task task, TaskState state ->
if (!state.failure
&& task.project.name == project.name
&& task.name.startsWith("package")
&& !task.name.endsWith("UnitTest")) {
def outputDir = task.outputDirectory.getAsFile().get()
task.variantOutputs.getOrNull()?.each { variant ->
println "" + outputDir + "/" + variant.outputFileName.get()
}
}
}
add this at the end of your build.gradle file.
change println to whatever logic you want.
by the way, if you want to check the properties you may use, just add gradle plugin as a dependency of your project, click Sync in Android Stuido, then you can find it in External Librarys (key map: Command + 1, and switch to project view).
like this
dependencies {
implementation 'com.android.tools.build:gradle:4.1.0'
}
and these properties and tasks are intentionally invisible in lib com.android.tools.build:gradle-api, modifications in future releases are expected.

Gradle Crittercism on-build mapping upload not working

I'm trying to upload to Crittercism on build, and I put this at the bottom of my gradle file. However, it doesn't seem to be working when I build debug. What am I doing wrong?
task uploadMappingToProd() << {
def critterAppId = "abcde"
def appVersionName = "1.0.1"
def appVersionCode = "DEBUG"
def critterKey = "12345"
commandLine 'curl',
"https://app.crittercism.com/api_beta/proguard/$critterAppId",
'-F', 'proguard=#build/outputs/mapping/production/release/mapping.txt',
'-F', "app_version=$appVersionName-$appVersionCode",
'-F', "key=$critterKey"
type Exec
dependsOn 'assembleDebug'
}
The way you've done it, the task that you have defined, uploadMappingToProd, will if invoked by some reason also invoke assembleDebug. Because you have asked uploadMappingToProd to depend on assembleDebug - not the reverse. Therefore assembleDebug will happily finish without getting anywhere close to uploadMappingToProd.
If you want the reverse dependency i.e. assembleDebug to depend on uploadMappingToProd then you need to add this line after defining your task.
afterEvaluate {
tasks.assembleDebug.dependsOn uploadMappingToProd
}
This will guarantee uploadMappingToProd is invoked everytime and before assembleDebug is invoked.
My solution is working fine.(local build and jenkins build)
for me, only working when build is from jenkins
make sure your APPID, APPKEY, and path(release_jenkins.... normally release)
build.gradle (app) (add at the end)
task uploadPro << {
logger.error("Uploading mapping.txt file to crittercism")
String temp = projectDir;
temp = temp.replace("\\", "/");
String[] cmd = ["curl", "-k", "https://app.crittercism.com/api_beta/proguard/AppIDSting",
"-F", "proguard=#" + temp + "/build/outputs/mapping/release_jenkins/mapping.txt",
"-F", "app_version=" + VERSION_NAME + '-' + VERSION_CODE,
"-F", "key=API_KEY"]
logger.error("CMD : " + cmd)
ProcessBuilder builder = new ProcessBuilder(cmd);
Process process = builder.start();
process.waitFor()
println process.err.text
println process.text
}
gradle.buildFinished {
//check your build type. I am not sure it's the best way to do it.
logger.error("JSC : 이름 ! - " + gradle.startParameter.taskNames);
if (gradle.startParameter.taskNames.contains("assembleRelease_jenkins")) {
logger.error("JSC : 올리기 시작 ! - " + gradle.startParameter.taskNames);
tasks.uploadPro.execute()
} else {
logger.error("JSC : PASS")
}
}
sample project -> https://github.com/SinsangMarket/CrittercismMappingTXT

gradle Exec block should not fail for non zero output in

I am writing a gradle task. The task it invokes returns 3 for successful run instead of 3. How do I go about doing this ?
task copyToBuildShare(){
def robocopySourceDir = "build\\outputs\\apk"
def cmd = "robocopy "+ robocopySourceDir + " C:\\TEST *.* /MIR /R:5 2>&1"
exec {
ignoreExitValue = true
workingDir '.'
commandLine "cmd", "/c", cmd
if (execResult.exitValue == 3) {
println("It probably succeeded")
}
}
}
It gives the error:
Could not find property 'execResult' on task
I don't want to create a separate task. I want it to be in the exec block. What am I doing wrong?
project.exec() has a return value typed ExecResult.
def result = exec {
ignoreExitValue true
executable "cmd"
args = ["/c", "exit", "1"]
}
println "exit value:"+result.getExitValue()
Reference here:
https://docs.gradle.org/current/dsl/org.gradle.api.Project.html#org.gradle.api.Project:exec(groovy.lang.Closure)
You're going to need to specify that this task is of type Exec. This is done by specifying the task type like so
task testExec(type: Exec) {
}
In your specific case, You'll also want to make sure you don't try to get the execResult until the exec has finished this can be done by wrapping the check in a doLast.
task testExec(type: Exec) {
doLast {
if (execResult.exitValue == 3) {
println("It probably succeeded")
}
}
}
Here's an example of executing ls and checking its return value
task printDirectoryContents(type: Exec) {
workingDir '.'
commandLine "sh", "-c", "ls"
doLast{
if (execResult.exitValue == 0) {
println("It probably succeeded")
}
}
}

Iterative exec task

In the code provided below I can print each of the file names in the directory, but when it reaches the Exec command it only performs an Exec on the last file.
task frmf2xml(type:Exec) {
new File('src/orca/').eachFile {file ->
if(file.name.endsWith(".fmb")){
println file
commandLine 'cmd', '/c', 'frmf2xml.bat', file, 'OVERWRITE=YES'
}
}
}
I would like it to run the tool on every file
Actually i found a Solution, using execute().
task frmf2xml() {
new File('src/orca/').eachFile {file ->
if(file.name.endsWith(".fmb")){
def cmd = "cmd /c frmf2xml.bat ${file} OVERWRITE=YES"
def result = cmd.execute();
result.waitFor();
}
}
}

Categories

Resources