Если вам приходилось работать над сравнительно большим приложением в тесном контакте с заказчиком, то вы знаете, какой процент требований заказчик выставляет "вдогонку", после утверждения ТЗ. Можно долго обсуждать, насколько это неприятно и неправильно, но с этим, как правило, приходиться жить. Большинство таких "дополнительных" требований касается того, что заказчик видит, т.е. интерфейса: "Тут сделайте жирным, а вот это подвиньте...". Здорово было бы, чтобы эту малоприятную работу делали не суровые java(objective-C)-программисты, а обычные html-css верстальщики, которых, кстати, нанять легче и дешевле. Таким образом приложение с помощью PhoneGap можно сделать не только кроссплатформенным, но и "двухслойным". Интерфейс и навигацию делаем на HTML5, а "тяжёлую" логику, если она есть, делаем нативной. При этом основной разработчик освобождается от вёрстки xml layout-ов, что само по себе уже даёт существенный прирост его производительности.
На выходе получаем вполне здоровый производственный процесс: html-css-javacsript-программисты пишут приложение на PhoneGap, а за всякой нетривиальной задачей обращаются к плагинам, которые пишут "настоящие" Android-разработчики. Вот давайте и посмотрим, насколько легко можно писать и использовать плагины для PhoneGap.
Что бы нам этакого сделать?
Сделаем приложение, которое будет фотографировать, получать данные о текущем местоположении и времени и всё это отправлять куда-нибудь как письмо с вложением, используя стандартное почтовое приложение, установленное на нашем Android-устройстве. Всё, кроме отправки почты мы сделаем стандартными средствами PhoneGap, а для вызова почтового клиента реализуем и используем свой плагин. Создание проекта и привязывание к нему PhoneGap я описал ранее, поэтому сейчас остановимся на собственно программировании.
Главная и единственная страница
Вот код нашей HTML+JavaScript страницы, в которой всё и происходит:
<!DOCTYPE html> <html> <head> <title>Event Wave</title> <script type="text/javascript" src="cordova-2.0.0.js" /> <script type="text/javascript" src="mailsender.js" /> <script type="text/javascript"> var imgPath = new Array(); var coordsLat = ""; var coordsLon = ""; var coordsTime = ""; var startPhoto = function() { navigator.device.capture.captureImage(captureSuccess, captureError, {limit:1}); } var captureSuccess = function(mediaFiles) { var i, len; for (i = 0, len = mediaFiles.length; i < len; i += 1) { imgPath[i] = mediaFiles[i].fullPath; } navigator.geolocation.getCurrentPosition(onGpsSuccess, onGpsError); }; var onGpsSuccess = function(position) { coordsLat = position.coords.latitude; coordsLon = position.coords.longitude; coordsTime = position.timestamp; MailSender.sendMail("your@email.com", "test subject", "Geo:"+coordsLat+","+coordsLon+" time:"+coordsTime, imgPath[0], function() { navigator.notification.alert('Sended successfully', null, 'MailSender'); }, function() { navigator.notification.alert('Failed to send email', null, 'MailSender'); }); }; var onGpsError = function(error) { navigator.notification.alert('Error: ' + error.code + ' message: ' + error.message, null, 'GPS Error'); } var captureError = function(error) { navigator.notification.alert('Error: ' + error.code, null, 'Capture Error'); }; </script> </head> <body style="width: 100%; height: 100%; margin: 0 0 0 0;"> <div style="margin: 25% 25% 25% 25%; width: 50%; height: 50%; text-align: center;"> <button onclick="startPhoto()">Send photo</button> </div> </body> </html>
Тут мы последовательно вызываем:
1. Окно фотографирования
При вызове метода captureImage мы указываем callback-функции на случай успеха и ошибки, а также параметры (в данном случае говорим, что ждём только одну фотографию).
2. Метод поучения геокоординат
Вызываем в onSuccess фотографирования. Получаем координаты и отметку времени. Как и путь к фотографии укладываем полученные данные в глобальные переменные.
3. Метод нашего плагина
В этот метод передаём всё что собрали, а он уже делает то, что нам нужно.
Плагин
Как видно из схемы в начале поста, плагин устроен так же как и сам PhoneGap, т.е. состоит из js и java-части. При чём обе части реализуются на удивление просто.
mailsender.js:
var MailSender = new Array(); MailSender.sendMail = function(mail, subject, text, attachment, success, fail) { var params = {mail:mail, subject:subject, text:text, attachment:attachment}; return cordova.exec(function(args) { success(args); }, function(args) { fail(args); }, 'MailSender', 'send', [params]); }
Тут просто собираем все данные в объект и отдаём методу exec, который используется в PhoneGap для передачи управления нативному коду плагина. Параметрами в этот метод передаём также callback-функции, имя плагина в реестре и action - имя идентификатора действия.
Реестр плагинов - это просто файл res/xml/config.xml, куда нужно добавить строку вида:
<plugin name="MailSender" value="your.plugin.package.name.MailSender"/>
И, наконец, MailSender.java:
import android.content.Intent; import android.net.Uri; import com.phonegap.api.Plugin; import com.phonegap.api.PluginResult; import org.json.JSONArray; import org.json.JSONObject; public class MailSender extends Plugin { public static final String SEND = "send"; @Override public PluginResult execute(String action, JSONArray args, String callbackId) { PluginResult rez = new PluginResult(com.phonegap.api.PluginResult.Status.INVALID_ACTION); try { if (SEND.equals(action) && args.length()==1) { JSONObject jo = args.getJSONObject(0); Intent it = new Intent(Intent.ACTION_SEND); it.putExtra(Intent.EXTRA_EMAIL, jo.optString("email")); it.putExtra(Intent.EXTRA_TEXT, jo.optString("text")); it.putExtra(Intent.EXTRA_SUBJECT, jo.optString("subject")); it.putExtra(Intent.EXTRA_STREAM, Uri.parse(jo.optString("attachment"))); it.setType("plain/text"); this.cordova.getActivity().startActivity(Intent.createChooser(it, "Choose Email Client")); rez = new PluginResult(PluginResult.Status.OK); } } catch (Exception e) { rez = new PluginResult(PluginResult.Status.ERROR); e.printStackTrace(); } return rez; } }
Тут становится понятно, зачем нужен action: один метод exec можно использовать для создания нескольких "фасадных" javascript-методов, представляющих разные нативные действия.
Комментариев нет:
Отправить комментарий