The sample module requires a complement of data that will be delivered in production via a Google Play APK Expansion File. To create and transfer this data to your device during development use the bundled content.py
script:
python content.py clone
python content.py generate_json
python content.py zip_content
python content.py adb_push_files
As work progresses on the liger data repository you can update your repository and re-bundle the APK Expansion File:
python content.py pull
python content.py generate_json
python content.py zip_content
python content.py adb_push_files
To run the test suite, you simply need add the correct instrumentation runner to the Run config. In Android Studio, open the 'Run' -> 'Edit Configurations' -> 'General tab.' Expand 'Android Tests' on the left and click 'LearningGuideTest' or 'DefaultLibraryTest'. Under 'Specific instrumentation runner (optional)', paste the following: com.google.android.apps.common.testing.testrunner.GoogleInstrumentationTestRunner. Prior to testing, a current obb file (renamed to main..scal.io.liger.test.obb) must be placed in the scal.io.liger.test files folder. Also, the files SAMPLE.jpg, SAMPLE.mp3, SAMPLE.mp4, SAMPLE.png must be placed in the same folder (copied/renamed from the example files in learning guide 1)
id - string value, an identifier for the story path which is unique within the file system
title - string value, a title for the story path
dependencies - array of dependency structures, see format below
no dependency is required if the cards in a story path only reference other cards in the same story path
cards - array of card structures, see format below
dependencyId - string value, the identifier of another story path which is referenced by cards within this story path
dependencyFile - string value, the path of the json file of another story path which is referenced by cards within this story path
the path must be relative to either the root of the sd card or the asset directory of the app
id - string value, an identifier for the card which is unique within the story path
title - string value, a title for the card
references - array of string values, references to values in other cards/story paths
required format: <story path id>::<card id>::<key>::<value>
values - array of string values, values to be serialized with the card/story path and referenced by other cards/story paths
required format: <key>::<value>
references - string value, must equal scal.io.liger.model.IntroCardModel
headline - string value, a headline to display on the card, most likely the lesson title
level - string value, the difficulty of the lesson, most likely a numeric value
time - string value, the approximate time that the lesson will take to complete
references - string value, must equal scal.io.liger.model.ClipInstructionListCardModel
media_path - string value, the path of an image file to display on the card
header - string value, a header to display on the card
bullet_list - array of string values, a list of instructions for capturing media
references - string value, must equal scal.io.liger.model.ClipInstructionTypeCardModel
media_path - string value, the path of an image file to display on the card
header - string value, a header to display on the card
clip_types - array of string values, a list of media capture types
references - string value, must equal scal.io.liger.model.SelfEvalCardModel
header - string value, a header to display on the card
checklist - array of string values, a list of self evaluation options
references - string value, must equal scal.io.liger.CongratsCardModel
headline - string value, a headline to display on the card, most likely a congratulatory message
text - string value, text to display on the card
story_paths - array of string values, a list of optional follow-up story paths
---
id: story_path
title: STORY PATH
dependencies:
-
dependencyId: completed_quiz
dependencyFile: completed_quiz.json
cards:
-
type: scal.io.liger.model.IntroCardModel
id: intro_card
title: INTRO CARD
headline: Headline that creates interest for what's coming
level: Basic 1
time: 20 minutes
-
type: scal.io.liger.model.ClipInstructionListCardModel
id: instruction_list_card
title: INSTRUCTION LIST CARD
media_path: /path/to/media.file
header: Character
bullet_list:
- Bullet point structure of qualities & tips
- Another quality
- Another quality
-
type: scal.io.liger.model.ClipInstructionTypeCardModel
id: instruction_type_card
title: INSTRUCTION TYPE CARD
media_path: /path/to/media.file
header: This card tells the maker which clip to capture.
clip_types:
- Photo
- Video
- Import
-
type: scal.io.liger.model.SelfEvalCardModel
id: eval_card
title: EVAL CARD
header: What's next?
checklist:
- Option 1
- Option 2
- Option 3
values:
- option_1::true
-
type: scal.io.liger.model.IntroCardModel
id: eval_check_1
title: EVAL CHECK 1
headline: YOU CHECKED THE FIRST BOX
references:
- story_path::eval_card::option_1::true
-
type: scal.io.liger.model.IntroCardModel
id: eval_check_2
title: EVAL CHECK 2
headline: YOU CHECKED THE SECOND BOX
references:
- story_path::eval_card::option_2::true
-
type: scal.io.liger.model.IntroCardModel
id: eval_check_3
title: EVAL CHECK 3
headline: YOU CHECKED THE THIRD BOX
references:
- story_path::eval_card::option_3::true
-
type: scal.io.liger.CongratsCardModel
id: congrats_card
title: CONGRATS CARD
headline: Congratulations!
text: NEXT UP Create a Compelling Narrative
story_paths:
- Recording stable shots
- Photo Stories
- Replay this path with a new story
This is a combination of several files, the syntax should be correct, but it is not necessarily logical.
{
"id": "story_path",
"title": "STORY PATH",
"dependencies": [
{
"dependencyId": "completed_quiz",
"dependencyFile": "completed_quiz.json"
}
],
"cards": [
{
"type": "scal.io.liger.model.IntroCardModel",
"id": "intro_card",
"title": "INTRO CARD",
"headline": "Headline that creates interest for what's coming",
"level": "Basic 1",
"time": "20 minutes"
},
{
"type": "scal.io.liger.model.ClipInstructionListCardModel",
"id": "instruction_list_card",
"title": "INSTRUCTION LIST CARD",
"media_path": "/path/to/media.file",
"header": "Character",
"bullet_list": [
"Bullet point structure of qualities & tips",
"Another quality",
"Another quality"
]
},
{
"type": "scal.io.liger.model.ClipInstructionTypeCardModel",
"id": "instruction_type_card",
"title": "INSTRUCTION TYPE CARD",
"media_path": "/path/to/media.file",
"header": "This card tells the maker which clip to capture.",
"clip_types": [
"Photo",
"Video",
"Import"
]
},
{
"type": "scal.io.liger.model.SelfEvalCardModel",
"id": "eval_card",
"title": "EVAL CARD",
"header": "What's next?",
"checklist": [
"Option 1",
"Option 2",
"Option 3"
],
"values": [
"option_1::true"
]
},
{
"type": "scal.io.liger.model.IntroCardModel",
"id": "eval_check_1",
"title": "EVAL CHECK 1",
"headline": "YOU CHECKED THE FIRST BOX",
"references": [
"story_path::eval_card::option_1::true"
]
},
{
"type": "scal.io.liger.model.IntroCardModel",
"id": "eval_check_2",
"title": "EVAL CHECK 2",
"headline": "YOU CHECKED THE SECOND BOX",
"references": [
"story_path::eval_card::option_2::true"
]
},
{
"type": "scal.io.liger.model.IntroCardModel",
"id": "eval_check_3",
"title": "EVAL CHECK 3",
"headline": "YOU CHECKED THE THIRD BOX",
"references": [
"story_path::eval_card::option_3::true"
]
},
{
"type": "scal.io.liger.CongratsCardModel",
"id": "congrats_card",
"title": "CONGRATS CARD",
"headline": "Congratulations!",
"text": "NEXT UP Create a Compelling Narrative",
"story_paths": [
"Recording stable shots",
"Photo Stories",
"Replay this path with a new story"
]
}
]
}
These were created to support aspects of the prototype, and don't necessarily correspond to any of the card types described in the design documents.
references - string value, must equal scal.io.liger.ClipTypeCardModel
clip_types - array of string values, a list of supported media types
references - string value, must equal scal.io.liger.model.QuizCardModel
description - string value, text to display on the card, most likely a question
options - array of string values, a list of possible answers to a question
references - string value, must equal scal.io.liger.model.QuizReportCardModel
description - string value, text to display on the card, most likely feedback on the quiz results
results - array of string values, references to options selected in previous quiz cards
this field is obsolete now that the "references" field has been added to the base class
references - string value, must equal scal.io.liger.model.VideoCaptureTypeCardModel
body - array of widget structures, see possible formats below
these widgets will be objects with functionality such as media capture or image display
references - string value, must equal scal.io.liger.widget.VideoCaptureWidget
camera_references - string value, the camera type to use for the capture, most likely front/back
references - string value, must equal scal.io.liger.widget.MarkdownWidget
text - string value, markdown text to display on the card
Android flips bold and italic from the markdown standard in the textview for some reason. Also, here is the subset of HTML and hence Markdown that is supported: HTML Tags Supported By TextView
references - string value, must equal scal.io.liger.widget.ImageWidget
path - string value, the path of an image file to display on the card
---
id: story_path
title: Story Path
cards:
-
type: scal.io.liger.model.VideoCaptureTypeCardModel
id: video_capture
title: Video Capture
body:
-
type: scal.io.liger.widget.MarkdownWidget
text: Some markdown text here
-
type: scal.io.liger.widget.ImageWidget
path: file:///sdcard/foo.jpg
-
type: scal.io.liger.widget.MarkdownWidget
text: Some more markdown
-
type: scal.io.liger.widget.VideoCaptureWidget
camera_type: front
-
type: scal.io.liger.widget.MarkdownWidget
text: Final markdown
this covers the video capture type card only, the other card types are generally similar to those covered in the previous example.
{
"id": "story_path",
"title": "Story Path",
"cards": [
{
"type": "scal.io.liger.model.VideoCaptureTypeCardModel",
"id": "video_capture",
"title": "Video Capture",
"body": [
{
"type": "scal.io.liger.widget.MarkdownWidget",
"text": "Some markdown text here"
},
{
"type": "scal.io.liger.widget.ImageWidget",
"path": "file:///sdcard/foo.jpg"
},
{
"type": "scal.io.liger.widget.MarkdownWidget",
"text": "Some more markdown"
},
{
"type": "scal.io.liger.widget.VideoCaptureWidget",
"camera_type": "front"
},
{
"type": "scal.io.liger.widget.MarkdownWidget",
"text": "Final markdown"
}
]
}
]
}
To convert YAML to JSON before you push to your phone to test, you can run a command like this:
python -c 'import sys, yaml, json; json.dump(yaml.load(sys.stdin), sys.stdout, indent=4)' < my.yaml > my.json
Then you can push this to your phone for testing:
adb push my.json /sdcard/Liger/
Create a credentials file for the Google Play API:
vim ./lib/src/main/res/values/google_play.xml
The file must include the public key belonging to your publisher account. You can find the key in the Developer Console under your profile information. You must also provide a string containing an array of random bytes that will be used for obfuscation.
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="base64_public_key">REPLACE WITH YOUR PUBLIC KEY</string>
<string name="liger_salt">REPLACE WITH A STRING OF BYTES</string>
</resources>
Liger utilizes icon webfonts instead of the traditional path of generating multiple drawables per screen resolution. Here are the steps to creating/editing icons:
- Generate your desired icons in SVG format
- Convert your SVG files to a .TTF file
- There are several ways to do this online. We use the command line tool Font Custom
- After generating your .TFF file, you need to make 3 changes:
-
Add your .TFF file to the android-iconify folder "src/main/assets/"
-
In "Iconify.java", change the 'TFF_FILE' variable to reflect your new file
private static final String TTF_FILE = "YOUR_FILE_NAME.ttf";
-
Still in "Iconify.java", change 'IconValue' variable to include your font names and unicode values
public static enum IconValue { fa_clip_ex_action('\uf145'), fa_clip_ex_character('\uf146'); }
Here is a small script to help quicken the process of converting the generated "fontcustom.css" to a usable Enum list in "Iconify.java"
Note: Your enum keys must begin with "fa"
-
You are now ready to use your new icons
<IconTextView android:text="{fa-clip_ex_action}" android:shadowColor="#22000000" android:shadowDx="3" android:shadowDy="3" android:shadowRadius="1" android:textSize="90dp" android:textColor="#FF33B5E5" ... />