Presenter (предъявитель)

Presenter является посредником между графическим представлением и моделью. Он извлекает данные из модели и возвращает их в удобной форме представлению. В отличии от типичного MVC он так же решает, что произойдет, при взаимодействии с представлением.

View (представление)

Как правило это Activity, Fragment или View, в зависимости от структуры приложения, содержащее ссылку на presenter. В идеале, добавлениеpresenter-а осуществляется с помощью механизма внедрения зависимостей, таких как Dagger, в противном случаи в view должен быть создан объект presenter-а. Единственное, что view будет делать это вызывать методыpresenter-а, каждый раз когда происходит взаимодействие с графическим интерфейсом (нажатие кнопок, свайпы и т.д).

Model (модель)

В приложении с хорошей многоуровневой архитектурой, model является точкой доступа к данным или бизнес логики. В "стерильной" архитектуре, model вероятно будет Interactor, который реализует какое-то действие.

Рисунок 5: наглядная разница двух паттерновMVC иMVP

 

3.4. Средства разработки мобильных приложений

Приложения для Android пишутся на языке программирования Java. Инструменты Android SDK (SoftwareDevelopmentKit – комплект разработки программного обеспечения) компилируют написанный вами код — и все требуемые файлы данных и ресурсов — в файл APK – программный пакет Android, который представляет собой файл архива с расширением.apk. В файле APK находится все, что требуется для работы Android-приложения, и он позволяет установить приложение на любом устройстве под управлением системы Android.

Каждое приложение Android, установленное на устройстве, работает в собственной "песочнице" (изолированной программной среде):

- операционная система Android представляет собой многопользовательскую систему Linux, в которой каждое приложение является отдельным пользователем;

- по умолчанию система назначает каждому приложению уникальный идентификатор пользователя Linux (этот идентификатор используется только системой и неизвестен приложению); система устанавливает полномочия для всех файлов в приложении, с тем чтобы доступ к ним был разрешен только пользователю с идентификатором, назначенным этому приложению;

- у каждого процесса имеется собственная виртуальная машина (ВМ), так что код приложения выполняется изолированно от других приложений;

- по умолчанию каждое приложение выполняется в собственном процессе Linux. Android запускает процесс, когда требуется выполнить какой-либо компонент приложения, а затем завершает процесс, когда он больше не нужен либо когда системе требуется освободить память для других приложений.

Таким образом система Android реализует принцип предоставления минимальных прав. То есть каждое приложение по умолчанию имеет доступ только к тем компонентам, которые ему необходимы для работы, и ни к каким другим. Благодаря этому формируется исключительно безопасная среда, в которой приложение не имеет доступа к недозволенным областям системы.

Однако у приложения есть варианты предоставления своих данных другим приложениям и доступа к системным службам:

- двум приложениям можно назначить один идентификатор пользователя Linux. В этом случае каждый из них сможет обращаться к файлам другого приложения. Для экономии ресурсов системы также можно сделать так, чтобы приложения с одинаковым идентификатором пользователя выполнялись в одном процессе Linux и использовали одну ВМ (приложения также должны быть подписаны одним сертификатом);

- приложение может запросить разрешение на доступ к данным устройства, например к контактам пользователя, SMS-сообщениям, подключаемой карте памяти (SD-карте), камере, Bluetooth и др. Все разрешения должны предоставляться приложению при его установке.

       Официальной средой разработки под операционную систему Android является AndroidStudio.

AndroidStudio — это интегрированная среда разработки (IDE) для работы с платформой Android, анонсированная 16 мая 2013 года на конференции Google I/O.

IDE находилась в свободном доступе начиная с версии 0.1, опубликованной в мае 2013, а затем перешла в стадию бета-тестирования, начиная с версии 0.8, которая была выпущена в июне 2014 года. Первая стабильная версия 1.0 была выпущена в декабре 2014 года, тогда же прекратилась поддержка плагина AndroidDevelopmentTools (ADT) для Eclipse.

AndroidStudio, основанная на программном обеспечении IntelliJ IDEA от компании JetBrains, официальное средство разработки Android приложений.

Основные функции AndroidStudio:

- способность работать с UI компонентами при помощи Drag-and-Drop, функция предпросмотра макета на нескольких конфигурациях экрана;

- сборка приложений, основанная на Gradle;

- различные виды сборок и генерация нескольких.apk файлов;

- рефакторинг кода;

- статический анализатор кода (Lint), позволяющий находить проблемы производительности, несовместимости версий и другое;

- встроенный ProGuard и утилита для подписывания приложений;

- шаблоны основных макетов и компонентов Android;

- поддержка разработки приложений для AndroidWear и Android TV;

- встроенная поддержка GoogleCloudPlatform, которая включает в себя интеграцию с сервисами GoogleCloudMessaging и AppEngine;

- способность работать с обновленным компилятором Jack, а также получила улучшенную поддержку Java 8 и усовершенствованную функцию InstantRun;

- В AndroidStudio 3.0 будут по стандарту включены инструменты языка Kotlin основанные на JetBrains IDE.

 


Глава 4. Программная реализация серверной части системы и мобильных приложений

4.1. Разработка структуры базы данных

В процессе разработки системы была спроектирована база данных, представленная на рисунке 6. Структура позволяет гибко управлять как пользователями системы, так и курьерскими заказами, и их оплатой, а также устройствами пользователей с учетом того, что у пользователя может быть несколько устройств.

 


Рисунок 6: структуры разработанной базы данных

Ниже, представлены основные таблицы, составляющие костяк системы. Все таблицы базы данных можно разделить на три категории:

4.1.1 Категория “Посылка”

Таблица t_order

Таблица содержит информацию о типе отправляемой посылки.

Таблица содержит следующие поля:

- idt_order. Первичный ключ;

- size_x, size_y, size_z. Габариты груза, указывается если груз не является документами (указан параметр idc_packet_type);

- dc_packet_type. Тип документов (А3, А4, А5 и т.д.).

 

t_packet

idt_packet int
idc_packet_type int
size_x int
size_y int
size_z int
weight int

 

Таблица t_order

Таблица содержит информацию о текущем заказе.

Таблица содержит следующие поля:

- idt_order. Первичный ключ;

- order_state. Статус заказа (курьер едет в точку “А”, курьер находится в точке “А”, получил посылку и т.д.);

- phone. Телефон отправителя;

- order_number. Уникальный номер заказа, необходим для идентификации заказов курьерами и клиентами;

- sender_name. Имя отправителя или название компании отправителя;

- rec_phone. Телефон получателя;

- rec_name. Имя получателя или название компании получателя;

- cost. Стоимость заказа;

- pickup_time. Время в которое необходимо забрать посылку. Храниться в виде таймштампа. По умолчанию, текущее время.

- delivery_time. Время доставки посылки, по умолчанию также текущее время. При сохранении значений происходит проверка pickup_time<= delivery_time;

- size_x, size_y, size_z. Габариты груза, указывается если груз не является документами (указан параметр idc_packet_type);

- idc_packet_type. Тип документов (А3, А4, А5 и т.д.);

- weight. Вес посылки;

- addr_a. Адрес точки А;

- lat_a, long_a. Координаты точки Б;

- addr_b. Адрес точки Б;

- lat_b, long_b. Координаты точки Б;

- cost_earn. Сумма выплаты курьеру за вычетом комиссии (20%);

- order_photo. Фотография груза. Храниться строка в виде Url фотографии на сервере;

- is_already_payed. Булевыйфлаг. Истина если заказ уже оплачен по безналичному расчету, ложь если оплата наличными.

t_order

idt_order int
order_state int
phone String
order_number int
sender_name String
rec_phone String
rec_name String
cost int
description String
pickup_time long
delivery_time long
size_x int
size_y int
size_z int
idc_packet_type int
weight int
addr_a String
lat_a double
long_a double
addr_b String
lat_b double
long_b double
cost_earn int
order_photo String
is_already_payed booblean

4.1.2 Категория “Клиент”

Таблица t_client

Таблица содержит информацию о клиенте сделавщем курьерский заказ.

Таблица содержит следующие поля:

- idt_client. Первичный ключ;

- a_time. Дата регистрации пользователя;

- email. Электронный адрес;

- idt_city. Город проживания;

- first_name, last_name, middle_name. Фамилия имя и отчество пользователя;

- rate. Рейтиг пользователя в баллах от 1 до 5;

- statistic. Статистические данные. Собираются с помощью сервиса FabricCrashlytics (модель телефона, ip, браузер, источник трафика).

t_client

idt_client int
phone String
a_time long
email String
idt_city String
first_name String
last_name String
middle_name String
rate double
statistic String
avatar String

 

Таблица t_pay_method

Таблица содержит информацию о платежной системе клиента.

Таблица содержит следующие поля:

- idt_pay_method. Первичныйключ;

- idt_client. id клиента;

- idc_pay_method_type. id типаметодаоплаты;

- is_default. Булевое значение метода по умолчанию. Истина, если наличными курьеру.

 

t_pay_method

idt_pay_method int
idt_client int
idc_pay_method_type int
is_default boolean

 

4.1.3 Категория “Курьер”

Таблица t_courier

Таблица содержит информацию о курьере.

Таблица содержит следующие поля:

- idt_courier. Первичный ключ;

- first_name, last_name, middle_name. Фамилия имя и отчество курьера;

- phone. Номер телефона;

- idc_courier_status. Статус курьера (работает/отдыхает);

- birthday. Дата рождения;

- passport. Пароль который генерируется автоматически после регистрации. Может свободно изменяться курьером;

- email. Электронный адрес;

- rate. Рейтинг курьера на основании оценок клиентами;

- achieve. Флаг для присвоения курьера мотивационных статусов (типа “Самый быстрый”, “Самый пунктуальный” и т.д.)

- avatar. Фотография курьера.

 

t_courier

idt_courier int
first_name String
last_name String
middle_name String
phone String
idc_courier_status int
birthday String
passport String
email String
rate double
achieve int
avatar String

 

4.2. API для работы с мобильными приложениями

Рисунок 7: иерархия классов API

API доступно по адресу: «https://api.a3technology.ru/ version / section / methodAlias» и имеет следующие методы:

 

Секция common.

В секции commonпредставлены универсальные методы,которые можно применить как в клиентском, так и в курьерском приложениях. Например, смена аватара.

- calcCost () - Расчет цены из точки А в точку Б;

- rate ($token= '') - Оценить заказ и оставить отзыв;

- setAvatar ($token= '') - Загрузить аватар;

- addOrderPhoto ($token= '') - Загрузка фото заказа;

- addUpdateDevice () - Добавить либо обновить devicetoken.

 

Секция client

Секция clientсодержит Apiметоды для работы с клиентским приложением.

- sendSmsCode () - Получить пин клиента для авторизации;

- confirmAccountByCode () - Получить токен авторизации;

- getProfile ($token="") - Клиент получает данные профиля;

- addOrder ($token="") - Добавить заказ пользователя;

- confirmOrder () - Подтвердить заказ;

- getOrderStatus ($token="") - Получить статус заказа;

- getCourierProfile($token="") - Получить данные профиля курьера;

- setProfileData ($token="") - Изменить данные профиля;

- geoLog ($token="") - Записать лог местоположения клиента;

- getOrderHistory ($token="") - Получить count заказов клиента из истории, со сдвигом offset;

- getAddresses ($token="") - Получить список адресов клиента;

- setFaveAddress ($token="") - Добавить или удалить адрес в список избранного;

- trackCourier ($token="") - последняя координата курьера;

- signup () - Зарегистрировать клиента с указанием личной информации;

- getDeliveryOptions () - получить список активных доп. опций заказа;

- bindCard ($token="") - Привязать карту пользователя;

- getBindedCards ($token="") - Получить список привязанных пластиковых карт;

- unbindCard ($token="") - Удалить привязанную карту;

- setCardAlias ($token="") - Изменить пользовательское название карты;

- payWithCard ($token="") - оплатить с помощью карты;

- rejectOrder ($token="") - отменить заказ;

- logout ($token="") - выйти из текущего аккаунта;

- getOrderData ($token="") - Получить данные заказа.

Секция courier

Методы для работы с курьерским приложением.

- signUpRequest () - Запрос курьера на регистрацию Номер телефона должен быть уникальным;

- authorize () - Получить токен, данные профиля и состояния курьера по логину и паролю;

- getProfile ($token="") - Курьер получает данные профиля;

- setActive ($token="") - Управление статусом занятости курьера;

- checkOffer ($token="") - Проверить предложения работы для курьера;

- choiceOrder ($token="") - Выбрать текущий доступный заказ;

- rejectOrder ($token="") - Отклонить текущий доступный заказ;

- getOrderData ($token="") - Подробные данные о заказе;

- setOrderState ($token="") - Управление статусом заказа;

- geoLog ($token="") - Записать лог местоположения курьера;

- getStatus ($token="") - Получить статус курьера;

- getOrderHistory ($token="") - Получить count заказов курьера из истории, со сдвигом offset;

- logout ($token="") - выйти из текущего аккаунта;

- restorePassword () - Получить смс с пин-кодом восстановления пароля;

- changePass () - Сменить пароль курьера;

- addOrderSign () - Загрузить файл с росписью клиента на экране устройства курьера;

- setProfileData ($token="") - Записать лог местоположения курьера;

- bindCard ($token="") - Привязать карту курьера;

- getBindedCards ($token="") - Получить список привязанных пластиковых карт;

- unbindCard ($token="") - Удалить привязанную карту;

- setCardAlias ($token="") - Изменить пользовательское название карты;

- getEarning ($token="") - получить заработок курьера;

- getOrders ($token="") - получить список активных заказов курьера.

Для обращения ко всем методам необходимо использовать HTTP POST-запрос с как минимум одним параметром (токен пользователя). Все методы написаны на языке PHP.

Ниже, для наглядного примера реализации методов, приведен листинг метода получения данных о клиенте:

Рисунок 8 метод получения данных о клиенте PHP

Как видно из рисунка 8, для того чтобы получить данные о пользователе, необходимо в параметрах POST запроса указать токен пользователя.

Пример этого же метода, на языке Java, со стороны клиентского мобильного Android приложения приведен на рисунке 9:

Рисунок 9: метод получения данных о клиенте Java

 


4.3. Структура Android приложения

Для разработки мобильных приложений использован паттерн MVP.

4.3.1 Model

Рисунок 10: классы компонента паттерна MVP – Model

Классы компонента Model, в двух приложениях, представляют из себя «сущности», содержащие только их свойства (члены классов) и set/get методы.

НижеприведенлистингклассаPlace, используемый в клиентском приложении для реализации модели для «Избранных» мест пользователя.


public class Place extends RealmObject {

@PrimaryKey
private intid;
private String mPrimaryAddress, mSecondaryAddress;

public void setIncId(int id){
this. id = id;
}
public int getId(){
return this. id;
}

//sets/gets
public void setPrimaryAddress(CharSequencepr_addrass){
this. mPrimaryAddress = pr_addrass.toString();
}
public String getPrimaryAddress(){
return this. mPrimaryAddress;
}

public void setSecondaryAddress(CharSequencesec_address){
this. mSecondaryAddress = sec_address.toString();
}
public String getSecondaryAddress(){
return this. mSecondaryAddress;
}
}

 

Можно заметить, что класс Placeнаследуется от RealmObject. Дело в том что в проект интегрирована база данных Realmдля локального хранения информации о сущностях.

Данная база данных позволяет, в прямом смысле, в одну строку реализовывать основные транзакции необходимые для работы и имеющиеся в SQLite.

 


4.3.2 View

Рисунок 11: классы компонента паттерна MVP –View

Весь графический интерфейс приложений реализован в Activityилив Fragment. Активности и фрагменты взаимодействуют с моделями через Presenter-ы. Для этого, в последних определяются интерфейсы для управления активностями, а в самих активностях реализуются методы этих интерфейсов.

На приведенном ниже листинге представлен пример реализации Активности для подтверждения пользователем заказа.

public class ConfirmOrderActivity extends AppCompatActivity implements
SmsReceiver.OnSmsCodeReceiverListener,
View.OnClickListener,
ConfirmOrderPresenter.OnConfirmOrderDirection{

private Context mContext;
private ConfirmOrderPresenter mConfirmOrderPresenter;

private FieldPresenter mFieldPresenter;
private SmsReceiver mSmsReceiver;


private TextView tv_title;
private ImageView iv_btn_close;
private TextView tv_info;
private TextInputLayout til_cvc_code, til_sms_code;
private EditText et_cvc_code, et_sms_code;
private TextInputLayout[] fieldParents;
private EditText[] fields;
private Button btn_confirm;

@Override
protected void onCreate(@NullableBundle savedInstanceState) {
super. onCreate(savedInstanceState);
setContentView(R.layout. activity_confirm_order);
try {
initTools();
initViews();
setParams();
   } catch (Exception mE) {
mE.printStackTrace();
   }
}


private void initTools() throws Exception{
mContext = ConfirmOrderActivity. this;
mConfirmOrderPresenter = new ConfirmOrderPresenter(mContext);
mFieldPresenter = new FieldPresenter(mContext);
mSmsReceiver = new SmsReceiver(ConfirmOrderActivity. this);
}

private void initViews() throws Exception{
tv_title = (TextView)findViewById(R.id. tv_title);
iv_btn_close = (ImageView)findViewById(R.id. iv_btn_close);
tv_info = (TextView)findViewById(R.id. tv_info);
til_cvc_code = (TextInputLayout)findViewById(R.id. til_cvc_code);
til_sms_code = (TextInputLayout)findViewById(R.id. til_sms_code);
et_cvc_code = (EditText)findViewById(R.id. et_cvc_code);
et_sms_code = (EditText)findViewById(R.id. et_sms_code);
btn_confirm = (Button)findViewById(R.id. btn_confirm);

fieldParents = new TextInputLayout[]{ til_cvc_code, til_sms_code };
fields = new EditText[]{ et_cvc_code, et_sms_code };
}

private void setParams() throws Exception{
mFieldPresenter. setParamsFieldCvc(et_cvc_code);
mFieldPresenter. setParamsFieldSms(et_sms_code);

iv_btn_close. setOnClickListener(this);
btn_confirm. setOnClickListener(this);

mConfirmOrderPresenter. setOnConfirmOrderDirection(this);
mConfirmOrderPresenter. getTitle();
mConfirmOrderPresenter. getScreenParamByPayMethod();

mSmsReceiver. setOnSmsCodeReceiverListener(this);
mSmsReceiver. startReceiveSms();
}

@Override
public void onReceivedTitle(String title) {
tv_title. setText(title);
}

@Override
public void onReceivedScreenParamByPayMethod(int payMethodId, String phone, String payDescription) {
switch (payMethodId){
case CASH:
til_sms_code. setVisibility(View. VISIBLE);
tv_info. setText(getString(R.string. text_sms_confirm)
                  .concat(phone));
break;
case BANK_CARD:
til_cvc_code. setVisibility(View. VISIBLE);
tv_info. setText(getString(R.string. text_card_confirm)
                  .concat(payDescription));
break;
   }
}

@Override
public void onReceivedRequestParamByPayMethod(Map<String, String>http_params, int pay_method) {
new ConfirmOrderTask(mContext, http_params, pay_method).execute();
}

@Override
public void onClick(View v) {
int id = v.getId();
switch (id){
case R.id. iv_btn_close:
           finish();
break;

case R.id. btn_confirm:
try {
boolean isFieldValid = mConfirmOrderPresenter. checkFieldValid(fieldParents, fields);

if (isFieldValid){
                   String pin = et_sms_code. getText().toString();
                   String cvc = et_cvc_code. getText().toString();
mConfirmOrderPresenter. getRequestParamByPayMethod(pin, cvc);
               }
           } catch (Exception mE) {
mE.printStackTrace();
           }
break;
   }
}

@Override
public void onSmsCodeReceived(String sms) {
et_sms_code. setText(sms);
et_sms_code. setSelection(et_sms_code. length());
}

@Override
protected void onPause() {
super. onPause();
try {
if (mSmsReceiver!= null)
mSmsReceiver. stopReceiveSms();
   } catch (Exception mE) {
mE.printStackTrace();
   }
}

@Override
protected void onResume() {
super. onResume();
}

}

 

 

Как видно из листинга, класс реализует сразу три интерфейса: для прослушивания входящих СМС, для обработчика нажатий и для интерфейса из, Presenter-а для этой активности.

 

4.3.3 Presenter

Рисунок 12: классы компонента паттерна MVP–Presenter

На следующем листинге представлен Presenterдля активности, описанной в предыдущем блоке (View):

public class ConfirmOrderPresenter {

private final static String TAG = ConfirmOrderPresenter. class. getSimpleName();
private Context mContext;
private OrderTempRepository mOrderTempRepository;
private SettingRepository mSettingRepository;
private FieldsValidation mValidation;
private StringProcessing mStringProcessing;
private OrderHistoryItem mOrderCurrent;

private OnConfirmOrderDirection mOnConfirmOrderDirection;
private final static String TITLE = "Поддержка";

public ConfirmOrderPresenter(Context context){
this. mContext = context;
try {
init();
   } catch (Exception mE) {
mE.printStackTrace();
   }
}

public void setOnConfirmOrderDirection(OnConfirmOrderDirection direction){
mOnConfirmOrderDirection = direction;
}

private void init() throws Exception{
mOrderCurrent = getCurrentOrder();
mOrderTempRepository = new OrderTempRepository(mContext);
mSettingRepository = new SettingRepository();
mValidation = new FieldsValidation(mContext);
mStringProcessing = new StringProcessing();
}

public void getTitle(){
if (mOnConfirmOrderDirection!= null) mOnConfirmOrderDirection. onReceivedTitle(TITLE);
}

public void getScreenParamByPayMethod(){
int payMethod = getPayMethod();
   String phone = mOrderTempRepository. getOrderDataByKey(KEY_PHONE);
   String pay_id = mOrderTempRepository. getOrderDataByKey(KEY_PAY_METHOD);
   String pay_description = mSettingRepository. getData(pay_id);

Log. e (TAG, phone);

if (mOnConfirmOrderDirection!= null) mOnConfirmOrderDirection. onReceivedScreenParamByPayMethod(payMethod, phone, pay_description);
}

public void getRequestParamByPayMethod(String pin, String cvc) throws Exception{
/*set pay method*/
int payMethod = getPayMethod();
/*set request parameters by pay method*/
String token = mSettingRepository. getData(USER_TOKEN);
   String idtOrder = mOrderCurrent. getIdtOrder();

   Map<String, String>confirmParam = new HashMap<String, String>();
switch (payMethod){
case CASH:
           String phone = mStringProcessing. convertPhoneToString(mOrderTempRepository. getOrderDataByKey(KEY_PHONE));

confirmParam.put("phone", phone);
confirmParam.put("idt_order", idtOrder);
confirmParam.put("pin", pin);
confirmParam.put("token", token);
break;
case BANK_CARD:
           String idtPayMethod = mOrderTempRepository. getOrderDataByKey(KEY_PAY_METHOD);

confirmParam.put("token", token);
confirmParam.put("idt_order", idtOrder);
confirmParam.put("idt_pay_method", idtPayMethod);
confirmParam.put("cvc", cvc);
break;
default:
break;
   }
if (mOnConfirmOrderDirection!= null) mOnConfirmOrderDirection. onReceivedRequestParamByPayMethod(confirmParam, payMethod);
}

public boolean checkFieldValid(TextInputLayout[] fieldParents, EditText[] fields){
int pay_method = getPayMethod();

TextInputLayouttil_cvc_code = fieldParents[0];
TextInputLayouttil_sms_code = fieldParents[1];
EditTextet_cvc_code = fields[0];
EditTextet_sms_code = fields[1];

switch (pay_method){
case CASH:
return mValidation. isFieldEmpty(til_sms_code, et_sms_code);
case BANK_CARD:
return mValidation. isFieldEmpty(til_cvc_code, et_cvc_code) && mValidation. isValidCvc(til_cvc_code, et_cvc_code);
default:
return false;
   }
}

private OrderHistoryItemgetCurrentOrder() throws Exception{
int idt_order = new SettingRepository().getId(CURRENT_ORDER_ID);
return new RealmHelper<>(OrderHistoryItem. class).getById(idt_order);
}
private int getPayMethod(){
int payMethod = CASH;
if (mOrderTempRepository. isDataExist(KEY_PAY_METHOD)){
payMethod = BANK_CARD;
   }
return payMethod;
}

public interface OnConfirmOrderDirection{
void onReceivedTitle(String title);
void onReceivedScreenParamByPayMethod(int payMethodId, String phone, String payDescription);
void onReceivedRequestParamByPayMethod(Map<String, String>http_params, int pay_method);
}
}

 

4.3.4Общая структура

«Страницы» в Android приложении называются активити (Activity). Активити, если она должна что-то показывать пользователю, состоит из разметки графического интерфейса, написанной в формате XML, и кода на языке Java, отвечающего за работу интерфейса. Активити могут содержать фрагменты – сущности, тоже имеющие свой жизненный цикл схожий с активити, однако фрагмент не может существовать вне активити.

 

Рисунок 13: жизненный цикл активности (экрана в android приложении)

 

Можно использовать для одного и того же активити разные фрагменты, что придает гибкость и вариативность в процессе разработки.

На рисунке 14 показан простой пример в виде XML кода для WebActivity используемый в приложениях проекта, а также код Java для этого XML файла.

 

Рисунок 14: XML разметка классаWebActivity

Рисунок 15: java код для XML разметки WebActivity

Этот примитивный пример показывает структуру Android приложения в целом. В XML файле мы определили заголовок активности Toolbar и WebView для отображения веб страниц внутри приложения. Далее, в java файле мы описываем логику для этих View. По такому принципу строится весь графический интерфейс приложения.


 

Глава 5. Проверка выполнения разработанных сценариев для реализованной системы

 

Разработанная система предназначена для удобного взаимодействия клиентов службы курьерской доставки с курьерами.

Таким образом, разработанная система предоставляет следующие возможности:

Для клиента:

- возможность редактировать профиль (ФИО, номер телефона, адрес электронной почты, способ оплаты по умолчанию), все данные используются для автоматической подстановки при заполнении формы заказа;

- управление заказами. В приложении предусмотрена возможность управлять несколькими заказами одновременно;

- добавлять избранные (любимые адреса);

- обратная связь с технической поддержкой.

Для курьера:

- просматривать данные профиля (изменять данные профиля можно, но изменения вступают в силу только после модерации;

- управление своим статусом для поиска заказов (работаю/отдыхаю);

- просматривать историю выполненных заказов с подробной детализацией;

- управление заработком (курьер может привязать банковскую карту, на которую будут выведены денежные средства);

- обратная связь с технической поддержкой.

 

Рисунок 16: меню с функциями управления для клиентского и курьерского приложения

 

Рисунок 17: управление аккаунтами для клиентского и курьерского приложения

Далее следует сценарий выполнения заказа. Все начинается со стороны клиентского приложения, заполнения данных об отправителе и получателе. Если пользователь пожелает заполнить профиль пользователя, то эти данные будут автоматически подставляться в поля с информацией об отправителе. Есть возможность выбора номера телефона и имени из записной книжки. Адрес отправления, по умолчанию, текущие координаты пользователя.

Рисунок 18: экраны для заполнения информации об отправителе и получателе

 

Предусмотрен экран для заполнения подробной информации о предстоящем заказе. Какой груз, его вес и габариты, описание, фотография и т.д. Однако, все поля на этом экране являются не обязательными и заполняются по желанию.

 

 

Рисунок 19: экраны для заполнения более подробной информации о заказе

 

Далее по сценарию клиент подтверждает сформированный заказ. Либо по смс, в случае если выбрана оплата курьеру наличными, либо по CVC привязанной банковской карты, в случае безналичной оплаты.

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

Курьерское приложение свободного курьера в этот момент находится в режиме поиска заказа.

 

Рисунок 20: экраны ожидания заказа в клиентском и курьерском приложениях

Следующий этап сценария - “Курьер выехал в точку А”, начинается после того как курьер принял заказ. Клиенту приходит соответствующее Push уведомление.

По прибытию на место, курьер должен взять у отправителя электронную подпись, а также сфотографировать груз. До того, как курьер не выполнит эти действия, он не сможет изменить статус выполнения заказа.

Рисунок 21: курьер едет в точку “А” в клиентском и курьерском приложениях

 

Рисунок 22: встроенный в приложение планшет для получения подписи отправителя (получателя)

На этапе сценария - “Курьер получил посылку и выехал в точку Б”, на экране у курьера акцентируется внимание на кнопках “Перейти в навигатор” и “Позвонить получателю”. На всех этапах выполнения заказа курьер может связаться с отправителем и получателем, перейти в навигатор, а также написать в поддержку и посмотреть подробную информацию о заказе. На экране клиентского приложения статус поменяется на “Курьер получил посылку”, а также он сможет увидеть его текущее местоположение.

Рисунок 23: курьерское приложение в развернутом режиме во время выполнения заказа

 

На этапе “Курьер едет в точку Б” алгоритм работы приложений тот же что и при работе с получением посылки у отправителя. Курьер должен взять подпись отправителя и сфотографировать груз. После чего он сможет сменить статус на “Отправление доставлено”.

На экранах приложений появиться экран с просьбой оценить друг друга. Это действие не является обязательным как для клиента,так и для курьера.

 

Рисунок 24: мобильные приложения в режиме выставления взаимных оценок клиентом и курьером


Заключение. Анализ результатов работы

Основной целью настоящего дипломного проекта было создание современной и высокотехнологичной службы курьерской доставки, интегрированной в мобильное приложение.

Для достижения указанной цели был произведен анализ существующих систем, выявлены их недостатки в контексте предъявленных требований. Было принято решение о необходимости разработки новой системы, решающей весь спектр поставленных задач.

В специальной части был произведен анализ использования системы: выделены основные роли пользователей, описаны сценарии их взаимодействия с системой. Были обозначены основные функции системы, намечены стратегии архитектурного решения и выбраны технологии, позволяющие реализовать требуемую функциональность. Для описания организации данных была разработана информационная модель, представляющая структуру организации данных на различных уровнях: концептуальном, логическом и физическом. Также была разработана архитектура системы, которая послужила основой для реализации алгоритмов, описывающих функциональность системы. С целью реализации взаимодействия с пользователя с системой был реализован удобный, понятный и дружественный интерфейс пользователя. Для проверки работоспособности отдельных составляющих системы проведено модульное тестирование.

Исходя из вышесказанного, можно сделать вывод о том, что поставленная цель достигнута. Программный комплекс является завершенным и работоспособным, однако в дальнейшей перспективе возможно внедрить мобильное приложение для iOS с использованием iOS SDK.

 

 


 

Список литературы:

1. Харди, Б., Филлипс, Б. Программирование под Android. Для профессионалов. – СПБ.: Питер, 2014. – 592 с.

2. ISO/IEC/IEEE 42010:2011(E) Systems and software engineering – Architecture description. – NY, 2011. – 46 p.

3. Википедия. MVP архитектура. – https://ru.wikipedia.org/wiki/Model-View-Presenter.

4. Википедия. MVC архитектура. – https://ru.wikipedia.org/wiki/Model-View-Controller.

5. Назначение и особенности этапов проектирования базы данных (БД). – http://e-educ.ru/bd10.html.

6. Fowler, M. Inversion of Control Containers and the Dependency Injection pattern / M. Fowler. – http://martinfowler.com/articles/injection.html.

7. SQLitevsMySQLvsPostgreSQL: сравнение систем управления базами данных – http://devacademy.ru/posts/sqlite-vs-mysql-vs-postgresql/

8. Случайный курьер: как заработать на краудсорсинговой– доставке http://www.rbc.ru/own_business/22/04/2015/5534d7029a7947fb9982491c

9. Android Architecture Components – https://developer.android.com/develop/index.html?hl=ru.

10. MVP для Android. Перевод – https://tttzof351.blogspot.ru/2014/04/mvp-android.html















































































































































































































Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: