📜 ⬆️ ⬇️

Hybrid Android apps for kids



Today is an article about hybrid Android applications for kids. In every sense of these words. We will talk about writing the simplest hybrid (Java + HTML + Javascript) Android application for interviewing primary school students about their backpacks. A minimal knowledge of the basics of Java, HTML and JavaScript is assumed. If you are an Android developer, even with minimal experience, you are unlikely to be interested in this article, you can not open it. All others who are just starting or thinking about starting development for Android, and who are interested in the fundamentals of development for Android, I ask for cat.

Introductory. A daughter (grade 2) was commissioned to do research work on the theme “Influence of the weight of a backpack on a child’s health”. Naturally, by virtue of age, the main work fell to the parents. We decided to conduct a class survey in order to determine how much a backpack weighs, who weighs how much (to calculate the weight norm of a backpack, which should not exceed 10% of the child’s weight), who carries the backpack to school and so on. In order to diversify the school routine, I decided to make an application for an Android phone, which my daughter has, a survey application. It was originally planned to include in the questionnaire the weight of the backpack and the cub, but did not have time, and as a result, these parameters were written on a leaf, in the old fashioned way. There were only those questions that the young could answer on their own.

The essence of the task: to develop an application for interviewing young schoolchildren to create a presentation to the daughter about how harmful it is to carry heavy backpacks. In the picture above you can see what we have on the result.
Immediately make a reservation, I usually develop native Android applications, HTML is purely for Web applications, but this time it was decided to develop a hybrid application because, firstly, it was faster for this task, and the deadlines were extremely short, secondly, it was it is more convenient from the point of view of application functionality; thirdly, it was the first project developed in Android Studio, I wanted to minimize possible problems when using a new tool in order to finish on time.
')
So let's get started. To begin with, of course, Java-code (explained in the comments), of course, do not forget to add WebView to our Activity, we assign it the id webView:



package com.probosoft.survey; import android.os.Build; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.Window; import android.webkit.WebSettings; import android.webkit.WebView; public class MainActivity extends AppCompatActivity { //   onCreate,      WebView      @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //   ,    WebView wv = (WebView) findViewById(R.id.webView); //  WebView – -   WebSettings settings = wv.getSettings(); //     - settings.setDisplayZoomControls(true); //      - wv.loadUrl("file://android_asset/html/index.html"); //      - } } 

Place the test index.html in the assets / html folder. We try to run. Nothing happens. We find out the important point that when accessing internal resources, slashes after the protocol should be not two, but three. Change:

  wv.loadUrl("file://android_asset/html/index.html"); 

on:

  wv.loadUrl("file:///android_asset/html/index.html"); 

Hooray! Everything is loaded. We start writing HTML and JS code.

 <!DOCTYPE html> <html> <head> <title>Survey</title> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <!-- Bootstrap --> <link href="vendor/bootstrap/css/bootstrap.min.css" rel="stylesheet" media="screen"> <link href="vendor/bootstrap/css/bootstrap-theme.css" rel="stylesheet" media="screen"> <link href="vendor/jquery/jquery-ui.min.css" rel="stylesheet" media="screen"> <link href="vendor/jquery/jquery-ui.theme.css" rel="stylesheet" media="screen"> <link href="css/main.css" rel="stylesheet" media="screen"> <style> #menu { width: 100%; } </style> </head> <body> <!—  jQuery  Bootstrap --> <script src="vendor/jquery/external/jquery/jquery.js"></script> <script src="vendor/jquery/jquery-ui.min.js"></script> <script src="vendor/bootstrap/js/bootstrap.min.js"></script> <!—    --> <script src="js/consts.js"></script> <script src="js/respondents.js"></script> <script src="js/survey.js"></script> <script src="js/questions.js"></script> <script src="js/admin.js"></script> <script src="data/respondents.js"></script> <script src="data/questions.js"></script> <div id="menuDiv"> <div class="page-header" onclick="javascript: showResults ();"> <center><h3 id="title"></h3></center> </div> <div style="display: none;" id="clearButton"> <input type="button" value="Clear all" onclick="javascript: clearAll ();"/><br/><br/> </div> <!—-      ,        --> <div style="display: none;" id="showResults"> <input type="button" value="Show results" onclick="javascript: showResults (true);"/><br/><br/> </div> <!—-      http://www.w3schools.com/bootstrap/bootstrap_list_groups.asp --> <div id="mainPane"> <ul class="list-group" id="menu"> </ul> </div> <!—    --> <div id="resultsPane" style="display: none;"> <form method="post" action="http://serj.by/survey/api/storeSurveyData.php" id="storeForm"> <textarea name="surveyData" id="surveyData" style="width: 100%; height: 100%;" rows=25> </textarea> <input type="submit" value="Store on server"/> <input type="hidden" name="redirectURL" value="."/> </form> </div> </div> <div id="thanks">  !<br/><br/><input type="button" title="Ok" value="!" id="ok"/></div> <script> var respondents; var adminMode = true; // function clearAll () { try { if(typeof(Storage) !== "undefined") { this.storage = localStorage; } } catch (e) { alert ("Local storage error: "+e); } this.storage.clear (); } function init () { $("#mainPane").show (); $("#resultsPane").hide (); if (adminMode) $("#showResults").show (); $("#title").html (" "); var res = dataRespondents; res.forEach (function (element, i, arr) { element.id = i+1; }); respondents = new Respondents (res); respondents.renderRespondents ($("#menu")); $("#storeForm redirectURL").val (document.location.href); } init (); </script> </body> </html> 

At first I tried to use AJAX to load data, but I quickly became convinced that it simply did not work on the inside of WebView, and on local resources. Therefore, it was necessary to use a rather controversial method for downloading content - to save all the data about respondents in the global array.
We try to run. Again does not work. What is the matter? For our webview we did not allow javascript execution. Fix it. Add to Java code:
  settings.setJavaScriptEnabled(true); 

It works now. Hooray! We needed to enable the execution of JavaScript in our WebView. We write functional classes. I will not give the code. You can get to know him on the GitHub project (at the end of the article). Here I also describe the main problems that a novice developer of hybrid applications may face.

Next, we connect LocalStorage to save the data of our profiles. For this, we use the Survey class in survey.js. Traditionally, comments on the code in it.

 /** * Represents survey for particular respondent * @param integer id Id of respondent */ var Survey = function (in_respondentId, in_respondent) { var respondentId; // Id   var respondent = null; // ,    var questions = null; //   var parent = this; //  ,        var storage = null; //   LocalStorage        this.answers = []; //      /** * Begins survey for chosen respondent */ this.start = function () { var res = dataQuestions; //     parent.questions = new Questions (res, parent.respondent); //    parent.questions.start (); //    } /** * Stores all answers in storage */ this.collectAnswersAndStore = function () { this.storage.setItem (window.UNIQUE_STORAGE_ID+this.respondentId, JSON.stringify (this.answers)); //    window.init (); //     } this.surveyOption = function (val) { this.answers.push (val); //    //alert (this.answers); if (!this.questions.advanceQuestion ()) // ,     { this.collectAnswersAndStore (); //    ,   } } //   this.respondentId = in_respondentId; this.respondent = in_respondent; //      try { if(typeof(Storage) !== "undefined") { this.storage = localStorage; } } catch (e) { alert ("Local storage error: "+e); } } 

Everything seems to work, but nothing is saved. Along the way, we find out the funny detail - in the latest versions of the Android alert in the WebView does ... nothing. Nothing at all. No errors, no message in the console. Just as if it is not. We find out that in order to use LocalStorage in WebView, we need to set additional flags for WebView. Let's do it:

 settings.setDomStorageEnabled(true); settings.setDatabaseEnabled(true); 

Hooray! LocalStorage earned. How long is it short, over the weekend something useful to use was written. The child was sent to the gymnasium with the telephone on which this division was installed. The guys (already with the help of a teacher, or on their own - this was left behind the scenes) went through a questionnaire in good faith, and there were no data for only four students who, for one reason or another, were absent from classes.

Now I had a problem: I had to somehow extract the data (yes, I had to think about it initially, but do not forget that the application was developed in a terrible time pressure, and it was assumed that this task was not complicated or urgent. it is quite possible to decide later).

The main problem turned out to be that the daughter had a rather old and weak phone (it was chosen taking into account the factor “so that it would not be a pity that”). I tried to pull the data through Bluetooth, sending an AJAX request to the server, creating a form for sending, etc. - no options. The text in the DIV is not selected, as a result of the DIV has been converted to TextArea (which can be seen in the final code on GitHub). From there, we managed to select and copy the text with the survey results and send it to my E-mail. As a result, it turned out to be the only working option.

We write the script to the data were in the Excel spreadsheet. At this stage, another problem of the original architecture emerged - those students who did not pass the questionnaire were marked with a simple line “The form was not filled out”. Naturally, regexps that were designed for normal data on these lines “stumbled”. The benefit of such lines was only four. Manually, they were removed from the final results and we received a completely adequate sample (real names were replaced with placeholders):

  1, :  ,,      2.  2, :  , ,  4.  3, : , , ,     5.  5, : ,,      6.  6, : , ,      7.  7, : , ,      8.  8, : ,,      9.  9, : , ,      10.  10, : , ,      11.  11, : , ,      12.  12, : , ,      14.  14, :  ,,      16.  16, : , - ,      17.  17, : , ,      18.  18, : , - ,      19.  19, : , , ,     21.  21, :  , - ,      22.  22, : ,,  23.  23, : , ,      24.  24, : , ,  

It was possible, of course, to convert all this on the phone, but it seemed so simpler. This is easily understood by a simple regular expression. We write a PHP script:

 <pre> <?php function normLastOption ($s) { switch ($s) { case "": return "     "; case "": return " "; case "": return " ,    "; } } $results = []; $data = "”; preg_match_all ("/(((\d+)\. (.+), (.+): (.+),(.+),(.+)))+ /U", $data, $results); print_r ($results); $csv = ""; foreach ($results [3] as $key => $value) { $csv .= " ".($key+1).",".$results [6] [$key].",".$results [7] [$key].",".normLastOption($results [8] [$key])."\n"; } print $csv; $f = fopen ("survey.csv", "w"); fwrite ($f, $csv); fclose ($f); ?> 

As can be seen from the code, the last parameter due to the presence of spaces was initially parsed incorrectly. How can I write the correct regular expression, I did not bother again, due to the lack of time. If someone tells in the comments - thank you very much!

So, the application, in spite of all its simplicity, completely fulfilled its function - we collected data on how children use their backpacks. The data was included in the report and presentation and successfully approved by the teacher.

Thus, we developed a simple hybrid application for Android and even pulled data from it.
The complete application code on Github is the MIT License. If anyone needs this “on the knee”, use it for health!

Source: https://habr.com/ru/post/312876/


All Articles