Dynamic APL using one Flow ->Intermediate

Dynamic APL using one Flow, and only one Display Block? This tutorial should allow ANYONE to add images to their skills, and it does it in such a way that they are totally dynamic. Whenever you include an Interaction Block, you can change the image and text being displayed. It is IMPORTANT TO NOTE, you can NOT change the APL BETWEEN Speak Blocks. They are only allowed to change when a user has to say something!

The tutorial ‘assumes’ that the project you are creating is a question with 4 possible answers type of skill. It also ‘assumes’ that you have an image that you want displayed (otherwise why use APL?) with each question. For the purpose of the tutorial, I used a group of images I had, and substituted ‘more-or-less‘ meaningless text for the questions and answers.

Here’s what this sample project looks like. Just 11 blocks, with 4 blocks in the main part, the flow that does all of the ‘heavy-lifting‘!

It uses a few variables in the JSON files to allow the images and text to change with each ‘question‘. In this simplified version, it also uses 3 arrays (in a Code Block). This can easily be replaced with data acquired in another way (e.g. Google Sheets)

There are FOUR main variables used in this tutorial.

  • {website} this is the basic URL for where your files are stored.
    (e.g. ‘mysite/folder’)
  • {image} this is the name of a PNG file that is at least 300 pixels by 400 pixels in size. If you use JPG files, change the extension in the JSON files. Try to keep the shape of your images to a square, or a size that is slightly taller than it is wide, because if a user views the APL image with an Echo Spot, the centre circle will be displayed, and ALL corner sections will NOT be visible!
  • {QQ} this is a text file representing a question
  • {AA} this is a text file that is set up as HTML code to allow the data to be displayed as 4 possible answers (A, B, C, or D)

The project has one more VERY IMPORTANT variable! I named it {imgSetNum}. I like my variable names to be self-explanatory. It represents a Number that is reSet (actually incremented) at specific times, and it relates specifically to my images. It’s essentially a counter that I use to determine which question (along with its image and answers) that I want displayed as the APL.


Shown above are two images (from Voiceflow’s image tester) to show you what happens with your images with an Echo Spot! The first shows what a Spot will display, while the second is for an Echo Show (2nd generation). NOTE, the spot ONLY shows the image we change {image} with each question, while the Show also displays the background image that was ‘hard-coded‘ into the JSON file.  You can also see that a circle will be cut out of the centre of your image file. If, for example, it is a portrait shaped picture of a person, you would probably lose the eyes and the forehead! Not exactly an optimal case!

Here is the VERY SIMPLE Flow, that will do ALL of the MAGIC! The 2 Speak Blocks were just added for continuity sake. Neither are really needed. Only the Code block and the Display Block are really essential.

The bottom one just tells me there was an ERROR in the Code Block (if there was one). The RETURN block is there also mainly because I want it there. It’s a short <Break> statement of 0.1 second. It would also have the name of the flow, and the value of any variables changed in the flow, in text in the block, until after it works perfectly. Just another way for me to check for errors while I am testing the project.

//increment counter//
imgSetNum+=1;
APLarr1= [0,’img00001′,’img00002′,’img00003′,’img00004′];
APLarr2= [0,’question 1 goes here’,’second question here’,’here is the 3rd question’,’4th and last question here’];
APLarr3= [0,’Q1- A-an1<br>B-an2<br>C-an3<br>D-an4′, ‘Q2- A-an1<br>B-an2<br>C-an3<br>D-an4’, ‘Q3- A-an1<br>B-an2<br>C-an3<br>D-an4’, ‘Q4- A-an1<br>B-an2<br>C-an3<br>D-an4’];
image=APLarr1[imgSetNum];
QQ=APLarr2[imgSetNum];
AA=APLarr3[imgSetNum];

The REAL MAGIC, is performed by the Code Block! Displayed above is the complete code for this simplified demo version of a quiz, that will show a question, 4 answers and an image, for each section of the quiz.  Remember, it’s a DEMO skill! All data could be done much better using Google Sheets, with a smaller more specific block of code.

I used 3 arrays in the code.

  • APlarr1 is an array of image names
  • APLarr2 is an array of pseudo questions
  • APLarr3 is an array representing 4 possible answers for each question, with an HTML line break separating each

The first thing that happens is the counter, {imgSetNum} is increased by 1 (it had a value of zero when it was created). Each of my 3 arrays has 5 elements in it. The first element of each is NOT being used, so for simplicity sake, all were set to zero. The last 3 lines assign the corresponding values (1st, 2nd, etc.) from each array to the correct variable. That’s all there is. Each time this flow is called, the counter is incremented and the next value is assigned to each of the 3 variables, and the APL data is updated.

Remember to have ‘Update on Variable Changes’ ticked of on your Display block and you will have no problems. Contact me through Facebook Messenger if you need help.

Have fun!

———– APL Document —————

{
“type”: “APL”,
“version”: “1.0”,
“theme”: “dark”,
“import”: [
{
“name”: “alexa-layouts”,
“version”: “1.0.0”
}
],
“resources”: [
{
“description”: “Stock color for the light theme”,
“colors”: {
“colorTextPrimary”: “#151920”
}
},
{
“description”: “Stock color for the dark theme”,
“when”: “${viewport.theme == ‘dark’}”,
“colors”: {
“colorTextPrimary”: “#f0f1ef”
}
},
{
“description”: “Standard font sizes”,
“dimensions”: {
“textSizeBody”: 24,
“textSizePrimary”: 24,
“textSizeSecondary”: 24,
“textSizeSecondaryHint”: 25
}
},
{
“description”: “Common spacing values”,
“dimensions”: {
“spacingThin”: 6,
“spacingSmall”: 12,
“spacingMedium”: 24,
“spacingLarge”: 48,
“spacingExtraLarge”: 72
}
},
{
“description”: “Common margins and padding”,
“dimensions”: {
“marginTop”: 40,
“marginLeft”: 60,
“marginRight”: 60,
“marginBottom”: 40
}
}
],
“styles”: {
“textStyleBase”: {
“description”: “Base font description; set color”,
“values”: [
{
“color”: “@colorTextPrimary”
}
]
},
“textStyleBase0”: {
“description”: “Thin version of basic font”,
“extend”: “textStyleBase”,
“values”: {
“fontWeight”: “100”
}
},
“textStyleBase1”: {
“description”: “Light version of basic font”,
“extend”: “textStyleBase”,
“values”: {
“fontWeight”: “300”
}
},
“mixinBody”: {
“values”: {
“fontSize”: “@textSizeBody”
}
},
“mixinPrimary”: {
“values”: {
“fontSize”: “@textSizePrimary”
}
},
“mixinSecondary”: {
“values”: {
“fontSize”: “@textSizeSecondary”
}
},
“textStylePrimary”: {
“extend”: [
“textStyleBase1”,
“mixinPrimary”
]
},
“textStyleSecondary”: {
“extend”: [
“textStyleBase0”,
“mixinSecondary”
]
},
“textStyleBody”: {
“extend”: [
“textStyleBase1”,
“mixinBody”
]
},
“textStyleSecondaryHint”: {
“values”: {
“fontFamily”: “Bookerly”,
“fontStyle”: “italic”,
“fontSize”: “@textSizeSecondaryHint”,
“color”: “@colorTextPrimary”
}
}
},
“layouts”: {},
“mainTemplate”: {
“parameters”: [
“payload”
],
“items”: [
{
“when”: “${viewport.shape == ’round’}”,
“type”: “Container”,
“direction”: “column”,
“width”: “100vw”,
“height”: “100vh”,
“items”: [
{
“type”: “Image”,
“source”: “${payload.bodyTemplate2Data.image.sources[0].url}”,
“scale”: “best-fill”,
“width”: “100vw”,
“height”: “100vh”,
“position”: “absolute”,
“overlayColor”: “rgba(0, 0, 0, 0.6)”
},
{
“type”: “ScrollView”,
“width”: “100vw”,
“height”: “100vh”,
“item”: [
{
“type”: “Container”,
“direction”: “column”,
“alignItems”: “center”,
“paddingLeft”: “70dp”,
“paddingRight”: “70dp”,
“items”: [
{
“type”: “AlexaHeader”,
“headerAttributionImage”: “${payload.bodyTemplate2Data.logoUrl}”,
“headerTitle”: “${payload.bodyTemplate2Data.title}”
},
{
“type”: “Text”,
“text”: “<b>${payload.bodyTemplate2Data.textContent.title.text}</b>”,
“style”: “textStyleBody”,
“width”: “70vw”,
“textAlign”: “center”
},
{
“type”: “Text”,
“text”: “${payload.bodyTemplate2Data.textContent.subtitle.text}”,
“style”: “textStylePrimary”,
“width”: “70vw”,
“textAlign”: “center”
},
{
“type”: “Text”,
“text”: “${payload.bodyTemplate2Data.textContent.primaryText.text}”,
“paddingTop”: 20,
“style”: “textStylePrimary”,
“width”: “70vw”,
“textAlign”: “center”
}
]
}
]
}
]
},
{
“type”: “Container”,
“width”: “100vw”,
“height”: “100vh”,
“items”: [
{
“type”: “Image”,
“source”: “${payload.bodyTemplate2Data.backgroundImage.sources[0].url}”,
“scale”: “best-fill”,
“width”: “100vw”,
“height”: “100vh”,
“position”: “absolute”
},
{
“type”: “AlexaHeader”,
“headerTitle”: “${payload.bodyTemplate2Data.title}”,
“headerAttributionImage”: “${payload.bodyTemplate2Data.logoUrl}”
},
{
“type”: “Container”,
“direction”: “row”,
“paddingLeft”: “60dp”,
“paddingRight”: “72dp”,
“grow”: 1,
“shrink”: 1,
“height”: “100vh”,
“items”: [
{
“type”: “ScrollView”,
“height”: “100%”,
“grow”: 1,
“shrink”: 1,
“item”: [
{
“type”: “Container”,
“items”: [
{
“type”: “Text”,
“text”: “”,
“style”: “textStylePrimary”,
“color”: “#4dd2ff”
},
{
“type”: “Text”,
“text”: “<b>${payload.bodyTemplate2Data.textContent.title.text}</b>”,
“style”: “textStyleBody”
},
{
“type”: “Text”,
“text”: “${payload.bodyTemplate2Data.textContent.subtitle.text}”,
“style”: “textStylePrimary”
},
{
“type”: “Text”,
“text”: “${payload.bodyTemplate2Data.textContent.primaryText.text}”,
“spacing”: “@spacingSmall”,
“paddingTop”: “40dp”,
“paddingRight”: “70dp”,
“style”: “textStylePrimary”
}
]
}
]
},
{
“type”: “Image”,
“source”: “${payload.bodyTemplate2Data.image.sources[0].url}”,
“width”: 340,
“height”: 384,
“scale”: “best-fit”,
“align”: “center”
}
]
},
{
“type”: “AlexaFooter”,
“footerHint”: “${payload.bodyTemplate2Data.hintText}”
}
]
}
]
}
}

—————— Default Database ———————-

{
“bodyTemplate2Data”: {
“type”: “object”,
“objectId”: “bt2Sample”,
“backgroundImage”: {
“contentDescription”: null,
“smallSourceUrl”: null,
“largeSourceUrl”: null,
“sources”: [
{
“url”: “https://{website}/canada_flag.png”,
“size”: “small”,
“widthPixels”: 0,
“heightPixels”: 0
},
{
“url”: “https://{website}/canada_flag.png”,
“size”: “large”,
“widthPixels”: 0,
“heightPixels”: 0
}
]
},
“title”: “”,
“image”: {
“contentDescription”: null,
“smallSourceUrl”: null,
“largeSourceUrl”: null,
“sources”: [
{
“url”: “https://{website}/{image}.png”,
“size”: “small”,
“widthPixels”: 0,
“heightPixels”: 0
},
{
“url”: “https://{website}/{image}.png”,
“size”: “large”,
“widthPixels”: 0,
“heightPixels”: 0
}
]
},
“textContent”: {
“title”: {
“type”: “PlainText”,
“text”: “{QQ}”
},
“subtitle”: {
“type”: “PlainText”,
“text”: “”
},
“primaryText”: {
“type”: “PlainText”,
“text”: “{allAnswers}”
}
},
“logoUrl”: “https://{website}/mapleLeaf.png”,
“hintText”: “”
}
}

————— end of files —————–

Search

About This Site

This site was created as a place for users of our Alexa skill to find more information about creating their own skills, without programming.