Skip to content

Commit c41ebf3

Browse files
committed
APL-VH-Android: November 2023 Release of APL 2023.3 compliant Viewhost Code
1 parent 179863e commit c41ebf3

File tree

124 files changed

+4999
-1425
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

124 files changed

+4999
-1425
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Alexa Presentation Language (APL) ViewHost Android version 2023.2
1+
# Alexa Presentation Language (APL) ViewHost Android version 2023.3
22

33
APLViewHostAndroid is a view host implementation for the Android Platform. It consists of
44
a thin JNI layer that interacts with APL Core Engine for component inflation and command

apl/build.gradle

Lines changed: 238 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,255 @@
11
/*
2-
* Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
* SPDX-License-Identifier: Apache-2.0
34
*/
45

5-
// Top-level build file where you can add configuration options common to all sub-projects/modules.
6+
import org.apache.tools.ant.taskdefs.condition.Os
67

7-
def version = "1.10.0";
8+
apply plugin: 'com.android.library'
9+
apply plugin: 'jacoco'
10+
apply plugin: 'maven-publish'
811

9-
project.buildDir = "build"
12+
jacoco {
13+
toolVersion = '0.8.2'
14+
}
15+
16+
tasks.withType(Test) {
17+
jacoco.includeNoLocationClasses = true
18+
jacoco.excludes = ['jdk.internal.*']
19+
}
1020

11-
buildscript {
21+
tasks.withType(Test) {
22+
testLogging {
23+
events "standardOut", "started", "passed", "skipped", "failed"
24+
}
1225

13-
repositories {
14-
google()
15-
jcenter()
26+
filter {
27+
/**
28+
* This filter can be used when you want to debug some failed unit test in local test run
29+
* if you wish to run locally, you should use ./gradlew :apl:testDebugUnitTest in command line
30+
* For example, uncomment the line below for running tests in a specific class
31+
*/
32+
//includeTestsMatching "com.amazon.apl.android.font.TypefaceResolverTest"
1633
}
17-
dependencies {
18-
classpath 'com.android.tools.build:gradle:4.1.2'
19-
classpath 'org.jacoco:org.jacoco.core:0.8.2'
34+
}
35+
36+
task jacocoTestReport(type: JacocoReport, dependsOn: ['test']) {
37+
def mainSrc = "$project.projectDir/src/main/java"
38+
39+
def fileFilter = ['**/R.class', '**/R$*.class', '**/BuildConfig.*', '**/Manifest*.*', '**/*Test*.*', '**/AutoValue_*.*']
40+
def debugTree = fileTree(dir: "$project.buildDir/intermediates/javac/release/", excludes: fileFilter)
41+
42+
sourceDirectories.from(files([mainSrc]))
43+
classDirectories.from(files(debugTree))
44+
45+
executionData.from(fileTree(dir: "$buildDir", includes: [
46+
"jacoco/*.exec",
47+
"outputs/code_coverage/debugAndroidTest/connected/*coverage.ec"
48+
]))
49+
reports {
50+
xml.enabled = true
51+
html.enabled = true
52+
}
53+
}
2054

21-
// NOTE: Do not place your application dependencies here; they belong
22-
// in the individual module build.gradle files
55+
ext {
56+
cmakeProjectPath = projectDir.absolutePath
57+
if (Os.isFamily(Os.FAMILY_WINDOWS)) {
58+
cmakeProjectPath = cmakeProjectPath.replace('\\', '/')
59+
}
60+
aplAndroidCmakeArgs = "-DCMAKE_VERBOSE_MAKEFILE=ON"
61+
aplCoreDirCmakeArg = "-DAPL_CORE_DIR=${cmakeProjectPath}/../../apl-core-library"
62+
if (project.hasProperty('aplCoreDir')) {
63+
aplCoreDirCmakeArg = "-DAPL_CORE_DIR=" + aplCoreDir
2364
}
2465
}
2566

26-
allprojects {
27-
if (System.getenv("MAINLINE_BUILD")) {
28-
project.version = "${version}-SNAPSHOT"
29-
} else {
30-
project.version = "${version}." + (System.getenv("CODEBUILD_BUILD_NUMBER") ?: "0")
67+
android {
68+
compileSdkVersion 31
69+
ndkVersion "23.0.7599858"
70+
buildToolsVersion "30.0.2"
71+
defaultConfig {
72+
minSdkVersion 22
73+
targetSdkVersion 31
74+
versionCode 1
75+
versionName "1.0"
76+
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
77+
testInstrumentationRunnerArguments clearPackageData: 'true'
78+
renderscriptTargetApi 22
79+
externalNativeBuild {
80+
cmake {
81+
// Sets optional flags for the C++ compiler.
82+
cppFlags "-std=c++11", "-fno-rtti", "-fno-exceptions"
83+
// Build the APL Core JNI library (excludes all other targets)
84+
targets "apl", "apl-jni"
85+
// Enable APL Core JNI build, and be verbose.
86+
arguments aplCoreDirCmakeArg, aplAndroidCmakeArgs
87+
}
88+
}
89+
}
90+
compileOptions {
91+
sourceCompatibility JavaVersion.VERSION_1_8
92+
targetCompatibility JavaVersion.VERSION_1_8
93+
}
94+
buildTypes {
95+
release {
96+
// minifyEnabled true
97+
// proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
98+
buildConfigField("long", "VERSION_CODE", "${defaultConfig.versionCode}")
99+
buildConfigField("String", "VERSION_NAME", "\"${defaultConfig.versionName}-core\"")
100+
buildConfigField 'boolean', 'DEBUG_LOGGING', 'false'
101+
}
102+
debug {
103+
testCoverageEnabled true
104+
debuggable true
105+
aplAndroidCmakeArgs += " -DDEBUG_MEMORY_USE=ON"
106+
buildConfigField("long", "VERSION_CODE", "${defaultConfig.versionCode}")
107+
buildConfigField("String", "VERSION_NAME", "\"${defaultConfig.versionName}-core\"")
108+
buildConfigField 'boolean', 'DEBUG_LOGGING', 'true'
109+
}
31110
}
32-
project.group = "APLViewhostAndroid"
111+
// Temporary fix until alpha10 - "More than one file was found with OS independent path 'META-INF/proguard/androidx-annotations.pro"
112+
packagingOptions {
113+
exclude 'META-INF/proguard/androidx-annotations.pro'
114+
}
115+
116+
externalNativeBuild {
117+
cmake {
118+
version "3.18.1"
33119

34-
repositories {
35-
google()
36-
jcenter()
120+
// Tells Gradle to find the root CMake APL build script. path is relative to
121+
// the directory containing the module's build.gradle file. Gradle requires this
122+
// build script to designate a CMake project as a build dependency and
123+
// pull native sources into the Android project.
124+
path "CMakeLists.txt"
125+
}
126+
}
127+
lintOptions {
128+
// If set to true, turns off analysis progress reporting by lint.
129+
quiet false
130+
// if set to true (default), stops the build if errors are found.
131+
abortOnError true
132+
// if true, only report errors.
133+
ignoreWarnings false
134+
// flag code marked for unreleasable
135+
fatal 'StopShip'
136+
disable 'LongLogTag'
137+
}
138+
testOptions {
139+
animationsDisabled true
140+
141+
unitTests {
142+
includeAndroidResources = true
143+
}
37144
}
38145
}
39146

40-
task clean(type: Delete) {
41-
delete rootProject.buildDir
42-
}
147+
dependencies {
148+
compileOnly 'org.projectlombok:lombok:1.18.28'
149+
implementation fileTree(include: ['*.jar'], dir: 'libs')
150+
implementation 'androidx.annotation:annotation:1.4.0'
151+
implementation 'androidx.core:core:1.0.0'
152+
implementation 'androidx.appcompat:appcompat:1.2.0'
153+
implementation 'com.github.bumptech.glide:glide:4.11.0'
154+
implementation project(':common')
155+
implementation(project(':discovery')) { transitive = false }
156+
testImplementation 'junit:junit:4.13.2'
157+
testImplementation 'org.robolectric:robolectric:4.8.1'
158+
testImplementation 'org.robolectric:shadows-httpclient:4.2'
159+
testImplementation 'androidx.test:core:1.1.0'
160+
testImplementation 'androidx.test.ext:junit:1.1.0'
161+
testImplementation 'org.mockito:mockito-core:4.7.0'
162+
testImplementation 'androidx.test:rules:1.4.0'
163+
androidTestImplementation 'org.mockito:mockito-core:3.12.4'
164+
androidTestImplementation 'androidx.test.ext:junit:1.1.0'
165+
androidTestImplementation 'androidx.test:core:1.1.0'
166+
androidTestImplementation 'androidx.annotation:annotation:1.4.0'
167+
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
168+
androidTestImplementation 'androidx.test:runner:1.4.0'
169+
androidTestImplementation 'androidx.test:rules:1.4.0'
170+
androidTestImplementation 'androidx.test.uiautomator:uiautomator:2.2.0'
171+
androidTestImplementation 'com.linkedin.dexmaker:dexmaker:2.25.0'
172+
androidTestImplementation 'com.linkedin.dexmaker:dexmaker-mockito:2.25.0'
173+
androidTestImplementation project(":commonTest")
174+
androidTestImplementation 'com.squareup.leakcanary:leakcanary-android-instrumentation:2.9.1'
175+
androidTestImplementation 'com.squareup.leakcanary:leakcanary-object-watcher-android:2.9.1'
176+
androidTestUtil 'androidx.test:orchestrator:1.1.1'
177+
api "com.google.auto.value:auto-value-annotations:1.7"
178+
api 'com.google.guava:guava:27.0.1-jre'
179+
annotationProcessor "com.google.auto.value:auto-value:1.7"
180+
annotationProcessor 'org.projectlombok:lombok:1.18.28'
181+
}
182+
183+
184+
tasks.whenTaskAdded { theTask ->
185+
if (theTask.name.startsWith("test")) {
186+
theTask.outputs.upToDateWhen { false }
187+
}
188+
}
189+
190+
project.afterEvaluate {
191+
// Dump configuration settings
192+
println "APL CMake Args: " + aplAndroidCmakeArgs
193+
println "APL Core Directory: " + aplCoreDirCmakeArg
194+
println "Android SDK Directory: " + android.sdkDirectory.path
195+
println "Android NDK Directory: " + android.ndkDirectory.path
196+
197+
// enforce native tools build runs first for enum dependencies
198+
compileDebugJavaWithJavac.dependsOn externalNativeBuildDebug
199+
compileReleaseJavaWithJavac.dependsOn externalNativeBuildRelease
200+
201+
javaPreCompileDebug.dependsOn externalNativeBuildDebug
202+
203+
tasks.test.finalizedBy(jacocoTestReport)
204+
}
205+
206+
afterEvaluate {
207+
publishing {
208+
publications {
209+
release(MavenPublication) {
210+
from components.release
211+
pom {
212+
description = 'Commits: APLViewhostAndroid=' + System.env.CODEBUILD_RESOLVED_SOURCE_VERSION +
213+
',APLCoreEngine=' + System.env.CORE_SOURCE_VERSION
214+
}
215+
}
216+
}
217+
}
218+
}
219+
220+
tasks.build.dependsOn(assembleAndroidTest)
221+
222+
apply plugin: 'checkstyle'
223+
224+
checkstyle {
225+
configDirectory = file("$project.projectDir/checkstyle")
226+
ignoreFailures = false
227+
}
228+
229+
task checkstyle(type: Checkstyle, group: 'verification') {
230+
source 'src'
231+
include '**/*.java'
232+
exclude '**/gen/**'
233+
exclude '**/R.java'
234+
classpath = files()
235+
}
236+
237+
task release(dependsOn: ['build', 'publish']) {
238+
doLast {
239+
copy {
240+
from 'build/outputs/aar'
241+
into '../build/apl'
242+
}
243+
244+
copy {
245+
from 'build/reports'
246+
into '../build/apl/reports/'
247+
rename 'jacocoTestReport.xml', 'coverage.xml'
248+
}
249+
250+
copy {
251+
from 'build/outputs/apk/androidTest/debug'
252+
into '../build/apl/androidTest'
253+
}
254+
}
255+
}
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
/*
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package com.amazon.apl.android.component;
7+
8+
import androidx.test.espresso.Espresso;
9+
10+
import com.amazon.apl.android.APLOptions;
11+
import com.amazon.apl.android.RootConfig;
12+
import com.amazon.apl.android.dependencies.ISendEventCallbackV2;
13+
import com.amazon.apl.android.document.AbstractDocViewTest;
14+
import com.amazon.apl.enums.RootProperty;
15+
16+
import org.junit.AfterClass;
17+
import org.junit.Test;
18+
19+
import static androidx.test.espresso.Espresso.onView;
20+
import static androidx.test.espresso.action.ViewActions.click;
21+
import static androidx.test.espresso.matcher.ViewMatchers.withId;
22+
import static com.amazon.apl.android.espresso.APLViewActions.finish;
23+
import static com.amazon.apl.android.espresso.APLViewAssertions.isFinished;
24+
import static com.amazon.apl.android.utils.KeyboardHelper.isKeyboardOpen;
25+
import static org.junit.Assert.assertEquals;
26+
import static org.junit.Assert.assertFalse;
27+
import static org.junit.Assert.assertTrue;
28+
import static org.mockito.Mockito.mock;
29+
30+
public class EditTextViewTest extends AbstractDocViewTest {
31+
private static final String DOC =
32+
" \"type\": \"Frame\",\n" +
33+
" \"width\": \"100vw\",\n" +
34+
" \"height\": \"100vh\",\n" +
35+
" \"backgroundColor\": \"black\",\n" +
36+
" \"items\": {\n" +
37+
" \"type\": \"Container\",\n" +
38+
" \"width\": \"100vw\",\n" +
39+
" \"height\": \"100vh\",\n" +
40+
" \"items\": [\n" +
41+
" {\n" +
42+
" \"type\": \"EditText\",\n" +
43+
" \"id\": \"myEditText\",\n" +
44+
" \"text\": \"My favourite edit text box\"\n" +
45+
" },\n" +
46+
" {\n" +
47+
" \"type\": \"Text\",\n" +
48+
" \"id\": \"myPlainText\",\n" +
49+
" \"text\": \"Some other text that is plain\"\n" +
50+
" }\n" +
51+
" ]\n" +
52+
" }\n" +
53+
" }";
54+
private final ISendEventCallbackV2 mSendEventCallback = mock(ISendEventCallbackV2.class);
55+
56+
@AfterClass
57+
public static void closeKeyboard() {
58+
// Try to close the keyboard if open.
59+
try {
60+
Espresso.closeSoftKeyboard();
61+
} catch (RuntimeException ex) {
62+
// Do nothing.
63+
}
64+
}
65+
66+
@Test
67+
public void testView_click_on_EditText_opens_keyboard() {
68+
RootConfig rootConfig = RootConfig.create("EditText Test", "1.0");
69+
70+
onView(withId(com.amazon.apl.android.test.R.id.apl))
71+
.perform(inflate(DOC, "", "", "{}", APLOptions.builder().build(), rootConfig))
72+
.check(hasRootContext());
73+
onView(withComponent(mTestContext.getRootContext().findComponentById("myEditText")))
74+
.perform(click());
75+
76+
assertTrue(isKeyboardOpen());
77+
}
78+
}

0 commit comments

Comments
 (0)