GPS-трекер, мониторинг местоположения сотрудника.

Проектирование Android – приложения

1. Запустите Eclipse и выполните импорт сгенерированного в 1С шаблона-проекта.
2. Откройте макет res/layout/activity_main.xml  и добавьте в него 2 кнопки и TextView для отображения статуса:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<Button
    android:id="@+id/btnStop"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/btnStart"
        android:layout_alignRight="@+id/btnStart"
        android:layout_below="@+id/btnStart"
        android:text="@string/switch_off" />
 
    <TextView
        android:id="@+id/status"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_above="@+id/btnStart"
        android:layout_centerHorizontal="true"
        android:padding="10dp"
        android:textAppearance="?android:attr/textAppearanceMedium" />
 
    <Button
        android:id="@+id/btnStart"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"
        android:minWidth="160dp"
        android:text="@string/switch_on" />
<Button
   	android:id="@+id/btnStop"
    	android:layout_width="wrap_content"
    	android:layout_height="wrap_content"
    	android:layout_alignLeft="@+id/btnStart"
    	android:layout_alignRight="@+id/btnStart"
    	android:layout_below="@+id/btnStart"
    	android:text="@string/switch_off" />

	<TextView
    	android:id="@+id/status"
    	android:layout_width="wrap_content"
    	android:layout_height="wrap_content"
    	android:layout_above="@+id/btnStart"
    	android:layout_centerHorizontal="true"
    	android:padding="10dp"
    	android:textAppearance="?android:attr/textAppearanceMedium" />

	<Button
    	android:id="@+id/btnStart"
    	android:layout_width="wrap_content"
    	android:layout_height="wrap_content"
    	android:layout_centerHorizontal="true"
    	android:layout_centerVertical="true"
    	android:minWidth="160dp"
    	android:text="@string/switch_on" />

3. Откройте MainActivity.java и добавьте следующий метод: 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
private void init() {
    TextView tvStatus = (TextView) findViewById(R.id.status);
    tvStatus.setText("Текущий статус: "
        + (LocationService.isRunning() ? "Включен" : "Выключен"));
 
    Button bnt = (Button) findViewById(R.id.btnStart);
    bnt.setOnClickListener(new OnClickListener() {
 
        @Override
        public void onClick(View v) {
            LocationService.start(MainActivity.this,
                Const.LOCATION_MIN_TIME, Const.LOCATION_MIN_DISTANCE);
        }
    });
 
    bnt = (Button) findViewById(R.id.btnStop);
    bnt.setOnClickListener(new OnClickListener() {
 
        @Override
        public void onClick(View v) {
            LocationService.stop(MainActivity.this);
        }
    });
}
private void init() {
    TextView tvStatus = (TextView) findViewById(R.id.status);
    tvStatus.setText("Текущий статус: "
        + (LocationService.isRunning() ? "Включен" : "Выключен"));

    Button bnt = (Button) findViewById(R.id.btnStart);
    bnt.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {
            LocationService.start(MainActivity.this,
                Const.LOCATION_MIN_TIME, Const.LOCATION_MIN_DISTANCE);
        }
    });

    bnt = (Button) findViewById(R.id.btnStop);
    bnt.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {
            LocationService.stop(MainActivity.this);
        }
    });
}

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

Критерии  получения местоположения пользователя вынесены в файл настроек Const.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public final class Const {
 
    /*
     * На сколько должна изменится текущая позиция (в метрах) прежде чем будет
     * получено новое значение координат
     */
    public static int LOCATION_MIN_DISTANCE = 100;
 
    /*
     * Максимальное время, которое должно пройти, прежде чем пользователь
     * получает обновление местоположения.
     */
    public static long LOCATION_MIN_TIME = 1000 * 60;
}
public final class Const {

    /*
     * На сколько должна изменится текущая позиция (в метрах) прежде чем будет
     * получено новое значение координат
     */
    public static int LOCATION_MIN_DISTANCE = 100;

    /*
     * Максимальное время, которое должно пройти, прежде чем пользователь
     * получает обновление местоположения.
     */
    public static long LOCATION_MIN_TIME = 1000 * 60;
}

Условно вся работа сервиса сводится к одному:  передаче новых координат на сервер 1С в момент их  обновления.

Для работы с методами веб-сервиса используется класс ExchageManager, который выполнит вызов в отдельном потоке. Авторизация (метод Login)  будет произведена автоматически, если разработчик забыл это сделать самостоятельно.

1
2
3
4
5
6
7
8
9
10
11
// Инициализация менеджера обмена с web-сервером
App app = (App) getApplication();
ExchangeManager mExchangeManager = new ExchangeManager(app.getExchangeSettings());
 
// cериализатор JSON, десериализатор в 1С понимает этот формат даты (см.
// в 1С функцию XMLЗначение)
Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd'T'HH:mm:ss")
           .create();
 
// отправить данные веб-сервису
mExchangeManager.writeShortData(“Идентификатор”, “Строка в json”, null);
// Инициализация менеджера обмена с web-сервером
App app = (App) getApplication();
ExchangeManager mExchangeManager = new ExchangeManager(app.getExchangeSettings());

// cериализатор JSON, десериализатор в 1С понимает этот формат даты (см.
// в 1С функцию XMLЗначение)
Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd'T'HH:mm:ss")
           .create();

// отправить данные веб-сервису
mExchangeManager.writeShortData(“Идентификатор”, “Строка в json”, null);

4. Скачайте полный код примера по адресу
https://xp-dev.com/svn/fba_toolkit_public/samples/fbaSample2Tracker
Добавьте  из него в ваш проект классы:
LocationService.java
Const.java
BootCompleteReceiver.java

5. Откройте манифест вашего приложения AndroidManifest.xml  и добавьте строки:

1
2
3
4
5
6
7
<service android:name="LocationService" />
<receiver android:name="BootCompleteReceiver" >
    <intent-filter>
        <action android:name="android.intent.action.BOOT_COMPLETED" />
        <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
    </intent-filter>
</receiver>
<service android:name="LocationService" />
<receiver android:name="BootCompleteReceiver" >
    <intent-filter>
        <action android:name="android.intent.action.BOOT_COMPLETED" />
        <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
    </intent-filter>
</receiver>

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

Второе – это регистрация нашего подписчика на событие перезагрузки устройства и смены статуса соединения. Дело в том, что если приложение установлено на внешнюю карту, оно не получит уведомление android.intent.action.BOOT_COMPLETED и один из вариантов в этом случае,  это воспользоваться уведомлением android.net.conn.CONNECTIVITY_CHANGE.

Дополнительные изменения, сделанные в примере (не обязательно)

Убран интерактивный запуск процедуры обмена по предопределенным правилам, для этого:
1. Откройте res/menu/activity_main.xml и удалите из него пункт меню запуска обмена, должен остаться один пункт меню:

1
2
3
4
5
6
7
8
9
10
11
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
 
    <item
        android:id="@id/fba_menu_settings"
        android:icon="@android:drawable/ic_menu_preferences"
        android:orderInCategory="100"
        android:showAsAction="ifRoom|withText"
        android:title="@string/fba_settings"/>
 
</menu>
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" >

	<item
    	android:id="@id/fba_menu_settings"
    	android:icon="@android:drawable/ic_menu_preferences"
    	android:orderInCategory="100"
    	android:showAsAction="ifRoom|withText"
    	android:title="@string/fba_settings"/>

</menu>

2. И так как теперь незачем наследоваться от FbaDBExchangeActivity, измените наследование вашей MainActivity  на: 

1
2
3
public class MainActivity extends FbaActivity {
...
...
public class MainActivity extends FbaActivity {
...
...

3. Удалите из процедуры onOptionsItemSelected класса MainActivity.java неиспользуемый код

1
2
3
4
5
else if (id == R.id.fba_menu_exchange) {
 
          startExchange(ExchangeVariant.FULL, true);
          return true;
    }
else if (id == R.id.fba_menu_exchange) {

          startExchange(ExchangeVariant.FULL, true);
          return true;
    }

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

Мобильное приложение готово!

Похожие записи: