PhoneGap a właściwie PhoneGap Build to narzędzie do tworzenia aplikacji mobilnych z wykorzystaniem technologii webowych. W tym artykule pokażę prosty sposób na konwersję aplikacji webowej w pełnoprawną aplikację mobilną, która można zainstalować na telefonie lub tablecie a nawet umieścić w sklepie Google Play.
Co to jest PhoneGap Build?
Fachowo rzecz ujmując PhoneGap Build to chmurowe narzędzie do tworzenia „z automatu” aplikacji w technologii PhoneGap. PhoneGap to dystrybucja frameworka o nazwie Cordova.

Cordova potrafi opakować aplikację HTML5 / JavaScript (plus biblioteki) do kontenera, który ma dostęp do natywnych funkcji urządzenia. Funkcje te są udostępniane za pośrednictwem zunifikowanego interfejsu JavaScript API, dzięki czemu można łatwo napisać jedną aplikację która będzie działać niemal z każdym telefonem i tabletem. Motywacją do wykonania aplikacji w ten sposób może być możliwość opublikowania jej na wiele platform – stworzone w ten sposób aplikacje można śmiało publikować w sklepach z aplikacjami – Google Play, Microsoft Store, AppStore.
Jakie są zalety tworzenia aplikacji mobilnej?
Jak już pisałem w zaletach i wadach aplikacji mobilnych, ponad połowa ruchu w polskim Internecie odbywa się za pomocą urządzeń mobilnych. Tworząc aplikację mobilną, możemy dostarczyć użytkownikom dużo lepszych wrażeń niż na standardowych stronach responsywnych lub stronach mobilnych.
Głównymi zaletami aplikacji mobilnych (także tych wykonanych w PhoneGap) jest możliwość skorzystania z zaawansowanych funkcji telefonu, oraz możliwość działania aplikacji bez połączenia z internetem. Aplikację mobilną można łatwo monetyzować oraz dać użytkownikom możliwość jej personalizacji.
Krok 1: Tworzenie aplikacji HTML/JavaScript
W pierwszym kroku musimy stworzyć jakaś aplikację. Ja np. szybciutko zrobiłem aplikację typu TODO list. Ściągnę Bootstrapa aby nie marnować czasu na tworzenie interfejsu od podstaw:
<!doctype html>
<html lang="pl">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link rel="stylesheet" href="css/bootstrap.min.css">
<title>Nazwa apliakcji</title>
</head>
<body>
<!-- Ciało aplikacji -->
</body>
<script src="js/jquery-3.2.1.min.js"></script>
<script src="js/popper.min.js"></script>
<script src="js/bootstrap.min.js"></script>
</body>
</html>
Następnie dodamy odpowiednie formularze:
<form id="todoForm">
<div class="row">
<div class="col-md-6 mb-3">
<label for="firstName">Tytuł</label>
<input type="text" class="form-control" id="todo_title" placeholder="" value="" required>
</div>
<div class="col-md-6 mb-3">
<label for="lastName">Termin</label>
<input type="datetime-local" class="form-control" id="todo_date" placeholder="" value="" required>
</div>
<div class="col-md-12">
<label for="lastName">Uwagi</label>
<textarea class="form-control" id="todo_content" placeholder="" required></textarea>
</div>
</div>
<hr class="mb-4">
<button class="btn btn-primary btn-lg btn-block" type="submit">Zapisz zadanie</button>
</form>
Całość powinna wyglądać mniej więcej tak (plik todo.html):

Przyda nam się jeszcze widok do odczytywania zadań todolist.html:
<div class="container" id="container">
<table class="table table-striped table-sm">
<thead>
<tr>
<th>Termin</th>
<th>Tytuł</th>
<th>Uwagi</th>
<th>Akcje</th>
</tr>
</thead>
<tbody id="datacontainer">
</tbody>
</table>
<a href="todo.html" class="btn btn-secondary fullwidth">Dodaj nowe zadanie</a>
</div>

Następnie dodamy logikę odpowiedzialną za dodawanie kolejnych zadań TODO. Zapis i odczyt wszystkich danych odbywa się za pomocą Web SQL Database, jest to API, które umożliwia przechowywanie bezpośrednio na urządzeniu lokalnym baz danych, które możemy odpytywać za pomocą języka SQL
Tak wygląda zapis:
<script>
$(document).ready(function(){
var db;
db = openDatabase('persona', '1.0', 'persona', 65536);
db.transaction(
function(transaction){
transaction.executeSql(
'CREATE TABLE IF NOT EXISTS todos' + '(todo_id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
todo_date DATETIME NOT NULL, todo_title TEXT NOT NULL, todo_content TEXT NOT NULL);'
);
}
);
$('#todoForm').submit(function(e){
e.preventDefault();
db.transaction(
function(transaction){
transaction.executeSql(
'INSERT INTO todos' + '(todo_date, todo_title, todo_content) VALUES (?,?,?);',
[$('#todo_date').val(), $('#todo_title').val(), $('#todo_content').val()],
function(){
location.href="todolist.html";
}
);
}
);
});
});
</script>
A to będzie odczyt wraz z usuwanie pozycji:
<script>
var db;
db = openDatabase('persona', '1.0', 'persona', 65536);
function getResults(){
db.transaction(
function(transaction){
transaction.executeSql(
'SELECT todo_id, todo_date, todo_title, todo_content FROM todos ORDER BY todo_date ASC;', [],
function(transaction, result){
$('#datacontainer').html("");
for (var i=0; i<result.rows.length; i++){
var row = result.rows.item(i);
$('#datacontainer').append('<tr><td>'+row.todo_date+'</td><td>'+row.todo_title+'</td><td>'+row.todo_content+'</td><td><a href="#" class="delete" data-id="'+row.todo_id+'">Zrobione</a></td></tr>');
}
}
);
}
);
}
$(document).ready(function(){
getResults();
});
$(document).on("click",".delete", function(e) {
e.preventDefault();
var id = $(this).data("id");
db.transaction(
function(transaction){
transaction.executeSql(
'DELETE FROM todos WHERE todo_id = ?;', [id],
getResults()
);
}
);
});
</script>
Tak stworzona aplikacja pewnie nie zdobędzie większej popularności ale dla potrzeb dydaktycznych – w sam raz.
Pozostaje nam jeszcze zrobić plik index.html z jakimś menu powitalnym i z linkami do todo.html i todolist.html. Można też oprzeć naszą aplikację na mechanizmie SPA (Single Page Application), czyli zrobić plik index.html który ładowałby asynchronicznie sam kontent zawarty w dodatkowych plikach ale to zrobimy kiedyś w osobnym wpisie o SPA.
Jeżeli aplikacja działa 100% sprawnie w przeglądarce możemy przejść do następnego etapu.
Krok 2: Tworzymy plik config.xml
PhoneGap wymaga od nas stworzenia specjalnego pliku XML. Musimy w nim zawrzeć platformy, na których chcemy aby nasza aplikacja działała i parę innych informacji:
<?xml version="1.0" encoding="UTF-8" ?>
<widget xmlns = "http://www.w3.org/ns/widgets"
xmlns:gap = "http://phonegap.com/ns/1.0"
id = "pl.mansfeld.persona"
versionCode = "12"
version = "1.2" >
<platform name="android">
<allow-intent href="market:*" />
<preference name="android-minSdkVersion" value="12" />
<preference name="android-targetSdkVersion" value="26" />
</platform>
<name>Persona</name>
<description>
Persona = Projekt demo.
</description>
<author href="https://mansfeld.pl" email="pawel@mansfeld.pl">
Paweł Mansfeld
</author>
</widget>
W powyższym przykładzie definiujemy id, wersję, platformę z minimalnym i maksymalnym SDK oraz nazwę i autora aplikacji.
Plik ten może zawierać także ścieżki do niestandardowych ikon oraz tzw. splashscreena, który pojawia się przy uruchomieniu aplikacji. Jeżeli aplikacja wymaga dostępu do aparatu lub innych API np. powiadomień „Toast”, należy je także wypisać w pliku config.xml. W pliku config.xml musimy także umieścić w „whitelist” wszelkie domeny z którymi aplikacja będzie się chciała połączyć.
Krok 3: Pakujemy aplikację do pliku ZIP:
Wszystkie stworzone pliki wraz z zasobami i plikiem konfiguracyjnym kompresujemy w jeden plik w formacie zip:

Krok 4: Kompilujemy projekt w Adobe PhoneGap Build
Po zalogowaniu na https://build.phonegap.com/apps należy przesłać aplikację za pomocą specjalnego formularza:

Krok 5: Testowanie aplikacji
Skompilowaną aplikację pobieramy w wersji „debug” i aplikację możemy testować na wirtualnych wersjach Androida np. za pomocą AVD managera z Android Studio lub na fizycznym urządzeniu z włączonymi opcjami dla deweloperów (Tryb debugowania i akceptuj nieznane aplikacje).
Krok 6: Tworzenie podpisu cyfrowego i wersji produkcyjnej (release)
Ze względów bezpieczeństwa system Android wymaga takiego podpisania aplikacji w celu jej zainstalowania i umieszczenia w Google Play. Podpisanie aplikacji wymaga najpierw utworzenia magazynów kluczy za pomocą Java JDK. Wygenerowany w ten sposób plik keystore, wysyłamy w kolejnym formularzu PhoneGap i po wpisaniu dwóch haseł można przez następną godzinę zbudować „release” czyli wersję produkcyjną aplikacji.
Podpisanie pliku APK w ten sposób pozwala Google upewnić się, że przyszłe aktualizacje pliku APK tej samej aplikacji pochodzą od konkretnego dewelopera.
Ściągamy Java JDK uruchamiamy keytoola wpisując komendę:
keytool -genkey -v -keystore my-release-key.keystore -alias nazwa_aliasu -keyalg RSA -keysize 2048 -validity 10000
Keytool prosi o podanie haseł do magazynu kluczy, podanie pól nazwy wyróżniającej, a następnie hasła do klucza. Następnie generuje magazyn kluczy jako plik o nazwie my-release-key.keystore w katalogu, w którym się znajdujemy. Magazyn kluczy i klucz są chronione wprowadzonymi hasłami. Magazyn kluczy zawiera pojedynczy klucz, ważny przez 10000 dni. Alias to nazwa, której będziesz używał później, aby odnosić się do tego magazynu kluczy podczas podpisywania aplikacji.
Więcej o keytoolu:
https://docs.oracle.com/javase/6/docs/technotes/tools/windows/keytool.html
Teraz dosyłamy wygenerowany klucz w dodatkowym formularzu na dole po prawej stronie i wpisujemy wcześniej ustalone hasła.
Stworzoną aplikację można śmiało opublikować np. na swojej stronie internetowej lub zainstalować na urządzeniach naszych klientów.
Dodatkowy krok 7: Publikacja aplikacji w Google Play
Po założeniu konta dewelopera w Google Play Console, podaniu linku do polityki prywatności, przesłana zrzutów i wypełnieniu formularzy związanych z brandingiem, opisem aplikacji i kategoriami wiekowymi mamy możliwość przesłania pliku APK. Po kilkunastu minutach aplikacja pojawia się w katalogu.

Odpowiedz lub skomentuj