Эпопея начинающего 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.
Прочитав документацию:
- Создал файл 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>
- Создал необходимую структуру:
В папке www находиться сам сайт
icon.png — иконка приложения размером 512х512px
- Заархивировал в zip и загрузил архив PhoneGap Build
В бесплатном тарифе можно загрузить только одно приложение
После не долгого ожидания приложение было собрано под ios и android
- Проследовав инструкции создал ключ и добавил его к приложению
Настало время публиковать приложение, но снова получил ошибку, сообщавшую мне о том, что целевой уровень моего приложения 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 лучший выбор