Skip to content

Mobile 3.5 Support

Marcus Green edited this page Nov 8, 2022 · 81 revisions

Most of this page is being moved to https://docs.moodle.org/dev/Creating_mobile_question_types

I work for Moodle Partner Titus Learning. Contact us if you require Moodle support hosting or consultancy. http://www.tituslearning.com

Announcement of the new way of doing things. https://docs.moodle.org/dev/Mobile_support_for_plugins

Support for the Moodle Mobile App v3.5 was added to Gapfill 1.973. This was done with huge amounts of help from Dani Palou from Moodle HQ who repeatedly responded to my questions in great detail. Mobile support means that if your site is enabled for the App and you have the plugin installed it will work seamlessly in the same way that question type plugins work in the core app. These notes describe how to update an existing question type. Most of the code with question types for mobile is in Javascript so you need to comfortable with that language and its tools such as the browser based debugger. I have yet to configure an IDE to launch a javascript debugger but would be interested to hear from anyone who has.

If you are creating a new question type 'from scratch' see this template

https://github.com/marcusgreen/moodle-qtype_TEMPLATE

The files that need to be modified/added are

  • db/mobile.php
  • classes/output/mobile.php
  • mobile/mobile.js
  • mobile/addon-qtype-YOURQTYPENAME.html
  • mobile/styles_app.css

Testing link

It is possible to test your plugin through this link https://mobileapp.moodledemo.net/ Provided your Moodle installation is on a publicly visible URL.

That will effectively load up a complete implementation of the mobile App within your browser. However if you use standard Chrome it can throw security errors, e.g. when attempting to load your .css file. The error in the console will say something about ..bla bla blocked by CORS policy... To get around this you can load Chromium (the open source version of chrome) with a special command line that disables the standard browser security features.

Read more here https://moodledev.io/general/app/development/setup/app-in-browser

On Mac OSX this takes the form

'/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary' --allow-file-access-from-files --disable-web-security --user-data-dir=/tmp -allow-running-insecure-content master.apps.moodledemo.net

For other operating systems experiment with to find the equivalent command line. The last item in that command is the URL of the website that will run the Moodle App within the browser. It is not a substitute for testing on native target hardware but it has a significant advantage of allowing you to debug through the javascript code as it runs.

Common errors

It is common when first developing to get the error This quiz can't be attempted in the app because it contains questions not supported' YOURQTYPENAME. (where YOURQTYPENAME, is the name of your question type).

You should check the javascript console on start to see if you find "YOURQTYPENAME" in the log. You should be able to see if the qtype is being registered or not

if it doesn't appear, then you should check this code:

https://github.com/moodlehq/moodlemobile2/blob/v3.5.0/src/core/siteplugins/providers/helper.ts#L101

you should debug both fetchSitePlugins and loadSitePlugins to check why is it failing

Presentation

I gave a presentation on modifying question types for the Mobile App at the Novermber 2018 developers meeting. You can find a recording of this here

https://moodle.zoom.us/recording/play/mtX7qcu_G9HnEIxfEuxjMVCX7PmZqAG7128XnAWUkLfvVLusBS07tIyJ5U-pv1Sm?continueMode=true

The associated slide show is here. https://docs.google.com/presentation/d/1jUyfULul_g6hh_3s-wISXIVphv_RKqgpHuxMHZ0F800/edit#slide=id.p

There is pdf of a really good presentation given by Sam Marsshall of the Open University about mobile development here

https://assets.moodlemoot.org/sites/91/20190423200836/5.-Moodle-Mobile-how-to-build-_-test-support-for-your-custom-module-Sam-Marshall-The-Open-University.pdf

What students want from mobile

https://assets.moodlemoot.org/sites/91/20190423201732/1.-Moodle-Mobile-at-the-OU-what-do-students-really-want-Davina-Beegoo-Price-The-Open-University.pdf

Steps

The steps to do it are

Create a new file db/mobile.php

defined('MOODLE_INTERNAL') || die();

$addons = [
    "qtype_YOURQTYPENAME" => [
        "handlers" => [ // Different places where the add-on will display content.
            'YOURQTYPENAME' => [ // Handler unique name (can be anything).
                'displaydata' => [
                    'title' => 'YOURQTYPENAME question',
                    'icon' => '/question/type/YOURQTYPENAME/pix/icon.gif',
                    'class' => '',
                ],
                'delegate' => 'CoreQuestionDelegate', // Delegate (where to display the link to the add-on).
                'method' => 'mobile_get_YOURQTYPENAME',
                'offlinefunctions' => [
                    'mobile_get_YOURQTYPENAME' => [],// function in classes/output/mobile.php
                ], // Function needs caching for offline.
                'styles' => [
                    'url' => '/question/type/YOURQTYPENAME/mobile/styles_app.css',
                    'version' => '1.00'
                ]
            ]
        ],
        'lang' => [
                    ['pluginname', 'qtype_YOURQTYPENAME'], // matching value in  lang/en/qtype_YOURQTYPENAME
        ],
    ]
];

Your question type will need an html template file that controls how it is displayed at runtime. This is the template from the core shortanswer question type and gives an idea of some of the options.

Create a file named mobile/addon-qtype-YOURQTYPENAME.html

<section ion-list *ngIf="question.text || question.text === ''">
    <ion-item text-wrap>
        <p><core-format-text [component]="component" [componentId]="componentId" [text]="question.text"></core-format-text></p>
    </ion-item>
    <ion-input padding-left type="text" placeholder="{{ 'core.question.answer' | translate }}" 
    [attr.name]="question.input.name" [value]="question.input.value" autocorrect="off" 
    [disabled]="question.input.readOnly" [ngClass]="[question.input.correctClass]">
    </ion-input>
</section>

Create a new file classes/output/mobile.php

namespace qtype_YOURQTYPENAME\output;

defined('MOODLE_INTERNAL') || die();

class mobile {

    /**
     * Returns the YOURQTYPENAME quetion type for the quiz the mobile app.
     *
     * @return void
     */
    public static function mobile_get_YOURQTYPENAME() {
        global $CFG;
        $templatepath = $CFG->wwwroot . '/question/type/YOURQTYPENAME/mobile/addon-qtype-YOURQTYPENAME.html';
        $template = file_get_contents($templatepath);
        $jsfilepath = $CFG->wwwroot . '/question/type/YOURQTYPENAME/mobile/mobile.js';
        $jscontent = file_get_contents($jsfilepath);
        return [
            'templates' => [
                [
                    'id' => 'main',
                    'html' => $template
                ]
            ],
            'javascript' => $jscontent
        ];
    }
}

javascript/mobile.js

var that = this;
var result = {

    componentInit: function() {
        /**
         * If the question is in a readonly state, e.g. after being
         * answered or in the review page then stop any further
         * selections.
         *
         * @param {NodeList} draggables
         * @param {MouseEvent} event
         * @return {string} value of target
         **/
        if (!this.question) {
            console.warn('Aborting because of no question received.');
            return that.CoreQuestionHelperProvider.showComponentError(that.onAbort);
        }
        const div = document.createElement('div');
        div.innerHTML = this.question.html;
         // Get question questiontext.
        const questiontext = div.querySelector('.qtext');

        // Replace Moodle's correct/incorrect and feedback classes with our own.
        this.CoreQuestionHelperProvider.replaceCorrectnessClasses(div);
        this.CoreQuestionHelperProvider.replaceFeedbackClasses(div);

         // Treat the correct/incorrect icons.
        this.CoreQuestionHelperProvider.treatCorrectnessIcons(div);

 
        if (div.querySelector('.readonly') !== null) {
            this.question.readonly = true;
        }
        if (div.querySelector('.feedback') !== null) {
            this.question.feedback = div.querySelector('.feedback');
            this.question.feedbackHTML = true;
        }

        if (typeof this.question.text == 'undefined') {
            this.logger.warn('Aborting because of an error parsing question.', this.question.name);
            return this.CoreQuestionHelperProvider.showComponentError(this.onAbort);
        }

        // Wait for the DOM to be rendered.
        setTimeout(() => {
 
        });
        return true;
    }
};
result;

Supported plugins in the plugins Moodle.org database

https://moodle.org/plugins/browse.php?list=award&id=6

All supported plugins plus some not in the Moodle.org database

Some other links for mobile dev

This is the source of the Mobile app and can be useful for looking up how core plugins are implemented. https://github.com/moodlehq/moodlemobile2/tree/v3.5.0

https://docs.moodle.org/dev/Mobile_support_for_plugins

How to set up your dev environment https://docs.moodle.org/dev/Setting_up_your_development_environment_for_Moodle_Mobile_2

https://docs.moodle.org/dev/index.php?title=Mobile_support_for_plugins&oldid=54590

Another plugin with mobile support being developed. https://github.com/tigusigalpa/moodle-mod_questionnaire/tree/moodlemobile35 https://github.com/PoetOS/moodle-mod_questionnaire/tree/MOODLE-MOBILE_35_BETA