This post was initially published for AppInventor classic. Currently sources are available also for AI2 but unless explicitly noted comments and images correspond still to classic version since the app is roughly the same.
This post completes the tutorial for creating a login template. In part 1 we designed the user interface. Now we’re going to add the code necessary for it to work!
The following image depicts the blocks for all the functionalities:
The blocks editor layout intends to be organized in a way that facilitates its comprehension:
- Constants: Variables with an initial value that does not change. According to the standard programming convention their name is fully written with capital letters and the character “_” is used to separate words.
- Variables: Variables that change over time. They are typically initialized in the initializations functions (see below). By convention they have a prefix indicating their type (s: text, i: number, lst: list, b: boolean)
- Auxiliary functions: General purpose procedures shared by different functionalities
General events: Events captured during the screen execution
- One column for each of the functionalities: Login dialog, Register dialog, Send password dialog, Goggle login interface, Menu
- C_BLUE, C_CYAN, C_ORANGE, C_GREEN, C_RED: Some customized colors for the menu. For example:
- C_BLUE_SEL, C_CYAN_SEL, C_ORANGE_SEL, C_GREEN_SEL, C_RED_SEL: Some more colors, slightly lighter than the previous ones. They’re used to change the menu option color when pressed.
- CLIENT_ID, CLIENT_SECRET, RESPONSE_OK, RESPONSE_DENIED: Constant values for the Google Login functionality explained in the tutorial How to redirect to the Google login.
- SCR_LOGIN, SCR_REG, SCR_SEND, SCR_HELP, SCR_GOOGLE, SCR_MAIN: We associate a numeric value to each window. This is used in the screen management tutorial to make code more readable (e.g. the sentence “CurrentScreen = SCR_MAIN” is much easier to understand than “CurrentScreen = 1”
- DATA_PWD, DATA_MAIL, DATA_SENDMAIL: We associate a numeric value to the fields stored in the database. This is used to make the code more readable (e.g. when this information is stored in a list we can obtain “SELECT LIST ITEM list DATA_MAIL” which is easier to understand than “SELECT LIST ITEM list 2”). This way, to add a new field to the database we simply need to create a new constant with a significant name and assign to it the first available number.
- ALPHANUMERIC_CHARS: This string contains all the valid characters for both username and password. It’s used for validating the entered values and also in the encryption algorithm explained in the post A simple way to encrypt texts with App Inventor.
- APPENGINE_ADDRESS, AUTH_KEY: The authenticator key and address for the mail sending service. They MUST be informed with the right value as explained in the post How to send direct mails
- CRYPTO_KEY: A key used to encrypt passwords. You should change it to a value that only you know
- lstStack, lstScreens, iStackPointer: Variables used to control the back navigation (see the post An “optimal” way to manage multiple screens)
- lstUserInfo: A list containing all the information from a user: password, email, sendmail
- iScreenHeight, iScreenWidth, iHeight, iWidth: Variables that store the screen size. They are used to calculate dynamically the dimension of some components (for example when changing the screen orientation as explained in tutorial How to adapt controls appearance depending on the screen orientation)
- sCode, sResponse, sToken, lstResponse: Used in the Google Login window
- sEncrypterKey: A string used by the encrypter algorithm. It’s calculated at initialization time by merging the constants ALPHANUMERIC_CHARS and CRYPTO_KEY
- sUser: Stores the user that’s currently logged in
- bLogged: Indicator of whether the user is already logged. It’s used to decide the behaviour in some places (e.g. make visible the User label at the header screen)
- iIndex, iVal, sVal: Auxiliary variables used in several places
- sRet_checkPassword, sRet_isAlphanumeric, sRet_xor: Return values for functions
- initMenuSize: Used to set the height and width of menu options depending in the screen size. It’s called when initializing the screen and also when changing the screen orientation. The code is explained in the post How to adapt controls appearance depending on the screen orientation
- popScreen, pushScreen, getCurrentScreen, showScreen, showMain: Functions used to manage the screens. They are explained in the tutorial An ‘optimal’ way to manage multiple screens
- initCrypto, encrypt, decrypt, pseudoXOR: Functions used to encrypt/decrypt passwords. They are explained in the tutorial A simple way to encrypt texts with App Inventor
- initColors: Used to apply the customized colors to the components. It simply sets the right Backgroundcolor attribute to each component
- initScreens: Initializes the variable lstScreens with the list of existing windows
- initHelpLabels: This function is called every time the help button is pressed. It sets the text labels of the screen buttons according to the currently selected window (which is received as an input parameter)
- checkUsername, checkPassword: Validation functions that enforce some rules regarding the username and password format. The code is self-explanatory
- isAlphanumeric: Auxiliary function that returns true if all the characters of the string received are alphanumeric (i.e. exist in the ALPHANUMERIC_CHARS constant)
In this case let’s see the checkUsername function both in AI classic and AI2, since it’s a simple example that demonstrates how to make our code cleaner and safer thanks to local variables:
- BackPressed: Manages the behaviour of the “back” button in order to simulate the window closing, as explained in the post An ‘optimal’ way to manage multiple screens
- ScreenOrientationChanged: Resizes controls according to the current screen height and width, as explained in the post How to adapt to screen orientation
- OtherScreenClosed: Restores the components’ colors since they may have changed to improve user feedback.
- Initialize: Calls the initialization functions, shows the login window, obtains default values for some fields (username and password) and redirects to Google Login if this is the default option
- ButtonLogin.Click: Queries TinyWebDB to verify that the username/password exist in the database.
- TinyWebDB_LOGIN.GotValue: Obtains the information about the user by means of the getUserInformation function (explained below). If password is correct shows the menu window calling the ShowMain function explained in the tutorial An ‘optimal’ way to manage multiple screens. Additionally, if “Remember” is checked, stores the values entered in the TinyDB so that they become the default options for the device.
- ButtonGuest.Click: shows the menu window calling the ShowMain function explained in the tutorial An ‘optimal’ way to manage multiple screens. This function receives the user as a parameter, which in this case is informed with the special value “_guest”. In further places a comparison with this value is used to limit the available options (e.g. disable the option to modify the profile)
This window is used both for the initial register and to modify the profile. In the second case the username textbox is disabled. The code uses this condition to skip some controls in case we’re just modifying information.
- ButtonRegister.Click: Shows the Register window using the PushScreen function explained in the post An ‘optimal’ way to manage multiple screens.
- ButtonOk_REG.Click: Validates that username and password format and queries TinyWebDB to verify the username does not already exist in the database
- TinyWebDB_REG.GotValue: After some validations stores the information in the database and closes the window using the popscreen function explained in the post An ‘optimal’ way to manage multiple screens.
- GetUserInformation: Auxiliary function that receives as input parameter a string of data separated by the characters “|||” (i.e. the way it’s stored in the database) and returns a list with an element for each piece encountered (e.g. the input string “myPwd|||myMail|||1” would return a list of 3 elements: [myPwd] [myMail]  ). Additionally, this function decrypts the password
- SetUserInformation: As opposite to the previous function, this one receives the information fields as parameters and returns a string in the format required to store the information in the database. It also encrypts the password
Forgot password window
- ButtonForgetPWD.Click: Shows the Forgot Password window using the PushScreen function explained in the post An ‘optimal’ way to manage multiple screens
- ButtonOk_SEND.Click: Queries TinyWebDB to obtain the information about the username from the database
- TinyWebDB_SEND.GotValue: Stores the information read into some hidden fields and calls the sendMail function. Finally closes the window using the PopScreen function
- sendMail: This is the function that performs the actual job. It’s explained in the post How to send direct mails
- Button_1.Click, Button_2.Click, Button_3.Click, Button_4.Click: Open the second window passing as a parameter the logged user. It also changes the button to a somewhat lighter color
- ButtonProfile.Click: Opens the Register window initializing previously the username textbox and disabling it. It also queries TinyWebDB to obtain the information about the username
- TinyWebDB_Profile.GotValue: Calls the GetUserInformation function in order to convert the information read into a list, and then initializes the fields with this information.