Pull to refresh

Эпопея начинающего web разработчика в мире мобильных приложений

Исходные условия


Начну с того, что я «начинающий web разработчик». Изучил html, css около полу года назад и как-то не слишком стремился изучать JS. Работаю в компании где моих скудных знаний хватает. Но как-то пришел момент, когда мне позвонил мой научный руководитель с предложением сделать мобильное приложение, в котором будет его книга и несколько видео к ней. Я согласился, еще не зная, что мне предстоит пройти.


Проблема использование онлайн сервисов


Начал я с поиска быстрых способов сделать приложение. Наткнулся на сервис AppsGeyser, в нём есть графический интерфейс, в котором я быстро набросал приложение. Сервис далёк од идеала, много чего реализовать не удалось, но зато я быстро получил apk файл и был готов к публикации его в play макете. Но меня постигла неудача – тонны ошибок посыпались при попытке загрузить apk. Исправить их я не мог, так что откинул эту затею и начал искать иные варианты реализации моей задачи.


Одностраничное приложение на JavaScript в apk


Я решил сверстать сайт и собрать каким то образом apk. Нашел на просторах YouTube небольшую инструкцию о создании одностраничного приложения на чистом JS.


  <div class="page active" id="book">
    <a href="#" class="nav-links" data-target="about"></a>
    <a href="#" class="nav-links" data-target="info"></a>
  </div>
  <div class="page" id="about">
    <a href="#" class="nav-links" data-target="book"></a>
    <a href="#" class="nav-links" data-target="info"></a>
  </div>
  <div class="page" id="info">
    <a href="#" class="nav-links" data-target="about"></a>
    <a href="#" class="nav-links" data-target="book"></a>
  </div>

.page {
  display: none;
  width: 100%;
}

.active {
  display: block;
}

const app = {
  pages: [],
  show: new Event('show'),
  init: function(){
    app.pages = document.querySelectorAll('.page');
    app.pages.forEach(pg => {
      pg.addEventListener('show', app.pageShown)
    })

    document.querySelectorAll('.nav-links').forEach(link => {
      link.addEventListener('click', app.nav);
    })

    history.replaceState({}, 'Home', '#home');
    window.addEventListener('popstate', app.poppin)
  },
  nav: function(ev){
    ev.preventDefault();
    let curentPage = ev.target.getAttribute('data-target');
    document.querySelector('.active').classList.remove('active');
    document.getElementById(curentPage).classList.add('active');
    history.pushState({}, curentPage, `#${curentPage}`);
    document.getElementById(curentPage).dispatchEvent(app.show);
  },
  pageShown: function(ev){
    console.log('Page', ev.target.id)
  },
  poppin: function(ev){
    console.log(location.hash, 'popstate event');
    let hash = location.hash.replace('#', '');
    document.querySelector('.active').classList.remove('active');
    document.getElementById(hash).classList.add('active');
    document.getElementById(hash).dispatchEvent(app.show);
  }
}

document.addEventListener('DOMContentLoaded', app.init);

Благополучно всё повторив у меня вышло одностраничное приложение (SPA) и я начал искать способы компиляции его в apk.


Быстрая сборка apk из html, css, js


С ходу наткнулся на Apache Cordova, но сразу понял, что это мне не по зубам, да и сроки поджимали. Я решил использовать Adobe PhoneGap.
Прочитав документацию:


  1. Создал файл config.xml с настройками
    <?xml version='1.0' encoding='utf-8'?>
    <widget id="howitzer_2s3m" version="1.0.0" xmlns="http://www.w3.org/ns/widgets" xmlns:gap="http://phonegap.com/ns/1.0">
    <name>2С3М</name>
    <description>
        У навчальному посібнику розглянуто будову та дію складових частин 152-мм гаубиці 2А33,
        штатних боєприпасів до неї (осколково-фугасних, кумулятивних снарядів, снарядів із готовими
        уражувальними елементами, бойових зарядів та підривників).
    </description>
    <author email="vvdehtiarov@gmail.com" href="https://www.facebook.com/profile.php?id=100022376462010">
        Vladyslav Dehtiarov
    </author>
    <content src="index.html" />
    <preference name="DisallowOverscroll" value="true" />
    <preference name="android-minSdkVersion" value="14" />
    <plugin name="cordova-plugin-whitelist" source="npm" spec="*"/>
    <plugin name="cordova-plugin-splashscreen" source="npm" />  
    <preference name="SplashScreenDelay" value="3000" />  
    <preference name="AutoHideSplashScreen" value="true" />
    <preference name="SplashMaintainAspectRatio" value="true" /> 
    <allow-navigation href="https://*youtube.com/*"/>
    <icon src="icon.png" />
    <splash src="splash.png" />
    <access origin="*" />
    <allow-intent href="http://*/*" />
    <allow-intent href="https://*/*" />
    <allow-intent href="tel:*" />
    <allow-intent href="sms:*" />
    <allow-intent href="mailto:*" />
    <allow-intent href="geo:*" />
    <platform name="android">
        <allow-intent href="market:*" />
    </platform>
    <platform name="ios">
        <allow-intent href="itms:*" />
        <allow-intent href="itms-apps:*" />
    </platform>
    </widget>
  2. Создал необходимую структуру:


В папке www находиться сам сайт



icon.png — иконка приложения размером 512х512px


  1. Заархивировал в zip и загрузил архив PhoneGap Build

В бесплатном тарифе можно загрузить только одно приложение



После не долгого ожидания приложение было собрано под ios и android



  1. Проследовав инструкции создал ключ и добавил его к приложению


Настало время публиковать приложение, но снова получил ошибку, сообщавшую мне о том, что целевой уровень моего приложения API – 14, а должен быть не меньше 28


Android Studio который решил все проблемы


Снова столкнувшись с ошибками, я понял, что по идя простым путём я потратил слишком много времени и мой взор пал на Android Studio.


Я создал пустой проект, добавил widget WebView и растянул его на весь экран



Затем создал папку assets, а внутри неё папку, в которую поместил сайт



После чего я добавил свою иконку приложения (ПКМ по папке res -> New -> Image Asset)




После чего дописал пару строчек в MainActivity.java



package com.howitzer.a2c3m;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;

import  android.webkit.WebView;

public class MainActivity extends AppCompatActivity {
    protected WebView howitzer;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //init
        howitzer = (WebView) findViewById(R.id.howitzer);

        //setting
        howitzer.setInitialScale(1);
        howitzer.getSettings().setUseWideViewPort(true);
        howitzer.getSettings().setJavaScriptEnabled(true);
        howitzer.getSettings().setLoadWithOverviewMode(true);
        howitzer.getSettings().setAllowContentAccess(true);
        howitzer.getSettings().setDomStorageEnabled(true);
        howitzer.getSettings().setAllowUniversalAccessFromFileURLs(true);
        howitzer.getSettings().setAllowFileAccessFromFileURLs(true);

        //load
        howitzer.loadUrl("file:///android_asset/howitzer/index.html");
    }
}

В итоге приложение заработало в эмуляторе, и я его собрал в apk использовав ключ созданный ранее




Итог


Если вам нужно быстро собрать apk из сайта – используйте Adobe PhoneGap, это быстрый и кроссплатформенный способ.
Если же вы хотите опубликовать приложение в Google Play – Android Studio лучший выбор

Tags:
Hubs:
You can’t comment this publication because its author is not yet a full member of the community. You will be able to contact the author only after he or she has been invited by someone in the community. Until then, author’s username will be hidden by an alias.