- Undocumented Matlab - https://undocumentedmatlab.com -

AppDesigner's mlapp file format

Posted By Yair Altman On August 17, 2016 | 13 Comments

Six years ago, I exposed the fact that *.fig files are simply MAT files in disguise [1]. This information, in addition to the data format that I explained in that article, can help us to introspect and modify FIG files without having to actually display the figure onscreen.
Matlab has changed significantly since 2010, and one of the exciting new additions is the AppDesigner [2], Matlab’s new GUI layout designer/editor. Unfortunately, AppDesigner still has quite a few limitations in functionality and behavior. I expect that this will improve in upcoming releases since AppDesigner is undergoing active development. But in the meantime, it makes sense to see whether we could directly introspect and potentially manipulate AppDesigner’s output (*.mlapp files), as we could with GUIDE’s output (*.fig files).
A situation for checking this was recently raised by a reader on the Answers forum: apparently AppDesigner becomes increasingly sluggish [3] when the figure’s code has more than a few hundred lines of code (i.e., a very simplistic GUI). In today’s post I intend to show how we can explore the resulting *.mlapp file, and possibly manipulate it in a text editor outside AppDesigner.

Matlab's new AppDesigner (a somewhat outdated screenshot)
Matlab's new AppDesigner (a somewhat outdated screenshot)

The MLAPP file format

Apparently, *.mlapp files are simply ZIP files in disguise (note: not MAT files as for *.fig files). A typical MLAPP’s zipped contents contains the following files (note that this might be a bit different on different Matlab releases):

  • [Content_Types].xml – this seems to be application-independent:
    
    
       
       
       
       
       
       
    
    
  • _rels/.rels – also application-independent:
    
    
       
       
       
       
       
    
    
  • metadata/coreProperties.xml – contains the timestamp of figure creation and last update:
    
    
       2016-08-01T18:20:26Z
       2016-08-01T18:20:27Z
    
    
  • metadata/mwcoreProperties.xml – contains information on the generating Matlab release:
    
    
       application/vnd.mathworks.matlab.app
       MATLAB App
       R2016a
    
    
  • metadata/mwcorePropertiesExtension.xml – more information about the generating Matlab release. Note that the version number is not exactly the same as the main Matlab version number: here we have 9.0.0.328027 whereas the main Matlab version number is 9.0.0.341360. I do not know whether this is checked anywhere.
    
    
       9.0.0.328027
    
    
  • appdesigner/appModel.mat – This is a simple MAT file that holds a single Matlab object called “appData” (of type appdesigner.internal.serialization.app.AppData) the information about the uifigure, similar in concept to the *.fig files generated by the old GUIDE:
    >> d = load('C:\Yair\App3\appdesigner\appModel.mat')
    Warning: Functionality not supported with figures created with the uifigure function. For more information,
    see Graphics Support in App Designer.
    (Type "warning off MATLAB:ui:uifigure:UnsupportedAppDesignerFunctionality" to suppress this warning.)
    d =
        appData: [1x1 appdesigner.internal.serialization.app.AppData]
    >> d.appData
    ans =
      AppData with properties:
          UIFigure: [1x1 Figure]
          CodeData: [1x1 appdesigner.internal.codegeneration.model.CodeData]
          Metadata: [1x1 appdesigner.internal.serialization.app.AppMetadata]
        ToolboxVer: '2016a'
    >> d.appData.CodeData
    ans =
      CodeData with properties:
        GeneratedClassName: 'App3'
                 Callbacks: [0x0 appdesigner.internal.codegeneration.model.AppCallback]
                StartupFcn: [1x1 appdesigner.internal.codegeneration.model.AppCallback]
           EditableSection: [1x1 appdesigner.internal.codegeneration.model.CodeSection]
                ToolboxVer: '2016a'
    >> d.appData.Metadata
    ans =
      AppMetadata with properties:
        GroupHierarchy: {}
            ToolboxVer: '2016a'
    
  • matlab/document.xml – this file contains a copy of the figure’s classdef code in plain-text XML:
    
    
       
          
             
                
             
             
                
                   
             
          
       
    
    

I do not know why the code is duplicated, both in document.xml and (twice!) in appModel.mat. On the face of it, this does not seem to be a wise design decision.

Editing MLAPP files outside AppDesigner

We can presumably edit the app in an external editor as follow:

  1. Open the *.mlapp file in your favorite zip viewer (e.g., winzip or winrar). You may need to rename/copy the file as *.zip.
  2. Edit the contents of the contained matlab/document.xml file in your favorite text editor (Matlab’s editor for example)
  3. Load appdesigner/appModel.mat into Matlab workspace.
  4. Go to appData.CodeData.EditableSection.Code and update the cell array with the lines of your updated code (one cell element per user-code line).
  5. Do the same with appData.CodeData.GeneratedCode (if existing), which holds the same data as appData.CodeData.EditableSection.Code but also including the AppDesigner-generated [non-editable] code.
  6. Save the modified appData struct back into appdesigner/appModel.mat
  7. Update the zip file (*.mlapp) with the updated appModel.mat and document.xml

In theory, it is enough to extract the classdef code and same it in a simple *.m file, but then you would not be able to continue using AppDesigner to make layout modifications, and you would need to make all the changes manually in the m-file. If you wish to continue using AppDesigner after you modified the code, then you need to save it back into the *.mlapp file as explained above.
If you think this is not worth all the effort, then you’re probably right. But you must admit that it’s a bit fun to poke around…
One day maybe I’ll create wrapper utilities (mlapp2m and m2mlapp) that do all this automatically, in both directions. Or maybe one of my readers here will pick up the glove and do it sooner – are you up for the challenge?

Caveat Emptor

Note that the MLAPP file format is deeply undocumented and subject to change without prior notice in upcoming Matlab releases. In fact, MathWorker Chris Portal warns us [4] that:

A word of caution for anyone that tries this undocumented/unsupported poking into their MLAPP file. Taking this approach will almost certainly guarantee your app to not load in one of the subsequent releases. Just something to consider in your off-roading expedition!

Then again, the same could have been said about the FIG and other binary file formats used by Matlab, which remained essentially the same for the past decade: Some internal field values may have changed but not the general format, and in any case the newer releases still accept files created with previous releases. For this reason, I speculate that future AppDesigners will accept MLAPP files created by older releases, possibly even hand-modified MLAPP files. Perhaps a CRC hash code of some sort will be expected, but I believe that any MLAPP that we modify today will still work in future releases. However, I could well be mistaken, so please be very careful with this knowledge. I trust that you can make up your own mind about whether it is worth the risk (and fun) or not.
AppDesigner is destined to gradually replace the aging GUIDE over the upcoming years. They currently coexist since AppDesigner (and its web-based uifigures) still does not contain all the functionality that GUIDE (and JFrame-based figures) provides (a few examples [5]). I already posted a few short posts about AppDesigner (use the AppDesigner tag [6] to list them), and today’s article is another in that series. Over the next few years I intend to publish more on AppDesigner and its associated new GUI framework (uifigures [7]).

Zurich visit, 21-31 Aug 2016

I will be traveling to Zürich for a business trip between August 21-31. If you are in the Zürich area and wish to meet me to discuss how I could bring value to your work, then please email me (altmany at gmail).

Categories: GUI, High risk of breaking in future versions, Undocumented feature


13 Comments (Open | Close)

13 Comments To "AppDesigner's mlapp file format"

#1 Comment By Sam On August 17, 2016 @ 20:19

Though not quite the same as what you’re envisioning, there’s a proof of concept implementation of *.mlapp -> *.m classdef on FEX ( [14]).

It’s a pretty basic thing thrown together so I could use AppDesigner’s layout tools and get a programmatic GUI out of it, which is my preferred GUI medium. It also attempts to strip the new UI elements out in favor of the “traditional” ones so I could work with older versions of MATLAB.

#2 Comment By Sam On August 17, 2016 @ 20:23

Forgot the GH link: [15]

#3 Comment By Dev-iL On August 17, 2016 @ 21:34

I’d like to point out one of the things we found while making the tool that Sam had mentioned: .mlapp -> .m conversion can very easily be done using the built-in function type ( [16]). The earliest MATLAB version where it worked (out of those we collectively had access to) was 2014b.
Regarding the customization of .mlapp figures – the fact they’re webpages might actually be beneficial for customization, as UI elements can now be customized using CSS. I have explored this a bit and [17] after reading your “ [18]” post. (Thanks!)

#4 Comment By Yair Altman On August 17, 2016 @ 21:40

Thanks for this – I believe that a guest post about your experience with customizing uifigures using CSS would be highly appreciated by readers. Care to give it a shot? Send me an email to discuss the technical details

#5 Comment By Terry Brennan On October 7, 2016 @ 18:15

Why not use class inheritance to achieve your goals? As for working programmatically, one of the things I like about the app designer is that the resulting mlapp file defines a class so I can derive other classes from the gui-created class and work programmatically without the visual interface on the derived class. One can add components, modify properties etc. One can even declare methods and/or properties in the mlapp to be Abstract within the appdesigner. This allows the creation of a base class from which customizations can be derived.

For example if I have a working appGUI.mlapp I can create

classdef myAppGUI < appGUI
   properties
      NewButton matlab.ui.control.Button
   end
   methods
      function A = myAppGUI
         % A = A@appGUI; <-- usually not necessary
         A.NewButton = uibutton(A.UIFigure);
         A.NewButton.Position = [20 20 100 22];
      end
   end
end

To assist you in recalling component names, etc, while programming the derived class you can have an instance of the base class (if it is not Abstract) in the workspace

>> Base = appGUI;

to interrogate its methods and properties. This is almost as good as having the appGUI code.

Of course, this approach should not become obsolete, unless the MathWorks does something dumb like making mlapp classes Sealed.

#6 Comment By Oleg On March 21, 2017 @ 17:01

The following methods load the data:

lf      = appdesigner.internal.serialization.AppLoadingFactory.instance();

appData = lf.getAppData('C:\Users\ok1011\Documents\github\carv-realtime-matlab\src\utilities\+carv\+plot\turn.mlapp')

  AppData with properties:

                   UIFigure: [1×1 Figure]
                   CodeData: [1×1 appdesigner.internal.codegeneration.model.CodeData]
                   Metadata: [1×1 appdesigner.internal.serialization.app.AppMetadata]
                 ToolboxVer: '2016b'
                FullVersion: '9.1.0.441655 (R2016b)'
    MinimumSupportedVersion: 'R2016b'

Or using the file reader, which allows to read Matlab code directly:

fid     = appdesigner.internal.serialization.FileReader('C:\Users\ok1011\Documents\github\carv-realtime-matlab\src\utilities\+carv\+plot\turn.mlapp');
appData = fid.readAppDesignerData();
mcode   = fid.readMATLABCodeText();

The appdesigner.internal.serialization.FileWriter() class allows to write code to the .mlapp file.

#7 Comment By Tom On April 17, 2018 @ 16:43

Thanks for this tutorial. You saved me a ton of work. After Matlab crashed and corrupted my .mlapp file, I was able to unzip the .mlapp file and get to my GUI code and recreate my GUI. Without this, I would be months behind recreating the GUI and rewriting all the code. This website was a lifesaver. Thank you very much.

#8 Comment By Antonio Martinez On July 30, 2019 @ 18:06

So, I don’t know if anyone is still reading this comment section but I tried digging a bit more into how MLAPP files are generated, following up Oleg’s contribution.

My conclusion is that, as far as I have been able to reach without basically fully reverse engineering AppDesigner’s inner workings, there is no way to use the methods available in appdesigner.internal such as FileWriter() to generate MLAPP files from the class definition in text format in an M file.

Here’s what I found.

• In newer versions of MATLAB the MLAPP file is organized in pretty much the same way but the appdesigner/appModel.mat file has a different organization. Now the AppData field is deprecated but kept for compatibility, and the data it contained is replace by two new fields ‘code’ and ‘components’. The ‘code’ struct stores the code from the app in separated sections (EditableSectionCode which is the part that contains the methods and properties, Callbacks, StartupCallback, etc), and components stores the UIFigure and the group hierarchy (I have no idea what this is, is generated by the AppModel method getGroupHierarchy() and is way to deep for me too understand already). The groups hierarchy was previusly stored inside appData.metadata.

AppModel: probably the parent for all apps created in AppDesigner is the class appdesigner.internal.model.AppModel . The AppModel contains the save() method, and has the properties Metadata and CodeModel among others. CodeModel is generated from the class appdesigner.internal.codegeneration.model.CodeModel, and contains the different sections of the code.

FileWriter(): as Oleg’s pointed correctly, appdesigner.internal.serialization.FileWriter() is a class that can generate and write to MLAPP files. It has 4 methods (writeMATLABCodeText, writeAppDesignerData, writeAppMetadata, writeAppScreenshot) that have to be called to succesfully contruct an MLAPP file, and can be called from the command line, which would allow using them to generate MLAPP files from its components. The problem is, this components can only be accessed by AppDesigner itself, which renders this methods useless.

Hypothesis for MLAPP file saving: my hypothesis is that when an app is saved, the save() method in the AppModel class is called, which in turn calls the AppModel method writeAppToFile(), which creates an appdesigner.internal.serialization.MLAPPSerializer instance. The AppModel’s method setDataOnSerializer() copies all the required information to MLAPPSerializer, including the code sections, the metadata, group hierarchy, etc. Then, MLAPPSerializer creates a fileWriter instance, divides the different objects received from AppModel and passes them to the relevant fileWriter methods to generate the MLAPP file.

I’m afraid there is literally no way to correctly generate the data scructures that are necessary to reconstruct an MLAPP file from the plain code without putting a ton of hours into untangling all the logic behind AppDesigner. Maybe someone can use this information to take on that task in the future.

#9 Comment By Antonio Martinez On July 30, 2019 @ 18:07

By the way, these are the relevant MATLAB files if someone wants so keep reverse engineering this thing

• C:\Program Files\MATLAB\R2018b\toolbox\matlab\appdesigner\appdesigner\+appdesigner\+internal\+model\AppModel.m
• C:\Program Files\MATLAB\R2018b\toolbox\matlab\appdesigner\appdesigner\+appdesigner\+internal\+codegeneration\+model\CodeModel.m
• C:\Program Files\MATLAB\R2018b\toolbox\matlab\appdesigner\appdesigner\+appdesigner\+internal\+serialization\MLAPPSerializer.m
• C:\Program Files\MATLAB\R2018b\toolbox\matlab\appdesigner\appdesigner\+appdesigner\+internal\+serialization\FileWriter.m

#10 Comment By Bradley Stiritz On November 5, 2019 @ 01:13

It’s great to see that Yair and others are digging into the internals of AppDesigner. It seems to have a lot of promise. At the same time, AppDesigner is still often unstable and unusable, as of R2019b. I just posted on the running Mathworks Answers thread about this–

[3]

Question for anyone who has studied the internals– have you also experienced problems in AppDesigner, and then gained any insights whatsoever via your sleuthing? Do you have any clues or hypotheses about what could be going wrong for so many users?

Surely, after all these years of hard work, the AppDesigner team should have worked out most of the minor bugs..?

#11 Comment By Adil On November 15, 2020 @ 05:02

Thank you for the blog, it was useful for me. I have a file named App_project.mlapp.zip and when I extract it through Winzip it gives all the files exactly as you described above. I don’t know how to load these all files in App designer in matlab. Please guide. I have also all functions .m files that were used in this app as well.

#12 Comment By Stéphane Issartel On July 27, 2021 @ 13:08

Both .mlx and .mlapp file format seem to be “Open Packaging Conventions” formatted files. See [19] and [20]

#13 Comment By Eric Delgado On June 19, 2023 @ 15:18

Hey guys, first of all, thanks to @Yair, your site saved me a lot of times! 🙂
That’s why I am sharing that I wrote m2mlapp (*.m => *.mlapp) file conversion, that works from R2021b. I hope it helps!
[21]


Article printed from Undocumented Matlab: https://undocumentedmatlab.com

URL to article: https://undocumentedmatlab.com/articles/appdesigner-mlapp-file-format

URLs in this post:

[1] *.fig files are simply MAT files in disguise: http://undocumentedmatlab.com/blog/fig-files-format

[2] AppDesigner: http://undocumentedmatlab.com/blog/sliders-in-matlab-gui#AppDesigner

[3] AppDesigner becomes increasingly sluggish: https://www.mathworks.com/matlabcentral/answers/279042-app-designer-s-editor-is-slow-and-gets-stuck-alot

[4] warns us: https://www.mathworks.com/matlabcentral/answers/279042#comment_383621

[5] a few examples: http://undocumentedmatlab.com/blog/customizing-uifigures-part-1#comment-384672

[6] AppDesigner tag: http://undocumentedmatlab.com/blog/tag/appdesigner

[7] uifigures: http://undocumentedmatlab.com/blog/tag/uifigure

[8] FIG files format : https://undocumentedmatlab.com/articles/fig-files-format

[9] MLintFailureFiles or: Why can't I save my m-file?! : https://undocumentedmatlab.com/articles/mlintfailurefiles

[10] Setting axes tick labels format : https://undocumentedmatlab.com/articles/setting-axes-tick-labels-format

[11] File deletion memory leaks, performance : https://undocumentedmatlab.com/articles/file-deletion-memory-leaks-performance

[12] Customizing uifigures part 1 : https://undocumentedmatlab.com/articles/customizing-uifigures-part-1

[13] Customizing uifigures part 3 : https://undocumentedmatlab.com/articles/customizing-uifigures-part-3

[14] : http://www.mathworks.com/matlabcentral/fileexchange/56237-mlapp2classdef

[15] : https://github.com/StackOverflowMATLABchat/mlapp2classdef

[16] : http://www.mathworks.com/help/matlab/ref/type.html

[17] : http://stackoverflow.com/q/38933254/3372061

[18] : https://undocumentedmatlab.com/blog/customizing-uifigures-part-1

[19] : https://en.wikipedia.org/wiki/Open_Packaging_Conventions#Package,_parts,_and_relationships

[20] : https://docs.microsoft.com/en-us/previous-versions/windows/desktop/opc/packaging

[21] : https://www.mathworks.com/matlabcentral/fileexchange/130069-m2mlapp

Copyright © Yair Altman - Undocumented Matlab. All rights reserved.