Программист мобильных приложений
0,3
рейтинг
30 января 2014 в 22:39

Разработка → Пишем приложения для Sony SmartWatch и SmartWatch 2 tutorial

Sony SmartWatch – достаточно интересный девайс своего времени, разработку под который почему-то обошли стороной на хабре. Ну раз так – давайте исправлять! В качестве примера мы разработаем простое приложение для управлением любым аудио-плеером.

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



Установка необходимых библиотек


Запускаем Android SDK Manager и идём в меню Tools -> Manage Add-on Sites



На вкладке User Defined Sites добавляем адрес с SDK под часы:
dl-developer.sonymobile.com/sdk_manager/Sony-Add-on-SDK.xml

На самом деле, данный SDK поддерживает не только часы, но и некоторые другие хитрые устройства от Sony, такие как например Smart Headset… Но нам пока интересны только часы.



И теперь выбираем новые, появившиеся в списке пакеты и устанавливаем их:



Кроме собственно необходимых библиотек, после установки обязательно загляните в папку [директория Android SDK]/sdk/add-ons/addon-sony_add-on_sdk_2_1-sony-16/samples. Там есть примеры использованию абсолютно всех возможностей часиков, мы поговорим только об избранных.

Эмулятор часов


В принципе, разрабатывать под реальные часы гораздо проще и удобнее, но тем не менее, вместе с SDK идёт и эмулятор. Для его использования пойдём в AVD Manager и создадим одно из появившихся в списке новых устройство от Sony, например, Xperia T. Главное, что бы в качестве параметра Target был выбран Sony Add-on SDK.



Теперь, если запустить такое устройство на эмуляцию, то в списке приложений на эмулируемом устройстве можно найти Accessory emulator



Который эмулирует необходимые нам часики (и не только, как уже упоминалось выше).



План проекта


Ну а теперь, что именно мы будем разрабатывать? Как мне кажется, делать всякие hello word скучно, так что напишем приложение для управления плеером! Любым плеером на телефоне. Вот это подходящий масштаб действий. ;)

  • Приложение будет управляться жестами и кликами. Жест справа-налево и обратно – это следующий/предыдущий трек, вверх/вниз – громче/тише. Клик в центре – поставить на паузу/продолжить воспроизведение.
  • Кроме самого экрана приложения реализуем виджет (для часов), который по клику будет вызывать основное окно программы.
  • Сделаем заготовку для экрана настроек приложения – ну просто про запас.
  • Поддерживать оно должно обе версии SmartWatch (первую и вторую, как подсказываем Кэп).


Подключаем библиотеки к проекту в IntelliJ IDEA


Поскольку я использую IntelliJ IDEA, то и пример приводить на ней. Для начала – создадим проект, в качестве версии SDK выбираем вариант от Sony.



Кроме того, для работы мы подключим к проекту пару модулей из той самой папки samples– в частности SmartExtensions/SmartExtensionAPI и SmartExtensions/SmartExtensionUtils. Вторую, теоретически, можно не подключать, и написать всё её содержимое с нуля, но мы, адепты тёмной стороны силы, ценим эффективность и удобство, а желание писать с нуля то, что уже существует нам чуждо. Инструкции по самому подключению я убрал под спойлер, благо там всё просто.

Подключаем библиотеки.
Идём в File -> Project Structure, там – на закладку Modules, кликаем по “плюсику” и выбираем Import Module



Находим папку SmartExtensionAPI:



Дальше ОК и Next->Next->Next до победного конца, как в старые добрые времена.
После чего подключаем к основному проекту добавленный модуль.





Аналогичным образом подключаем и SmartExtensionUtils.


Настраиваем базовые классы и параметры


Начнём с манифеста.

AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="com.smartwatch_habra_demo">
    <uses-sdk android:minSdkVersion="9"
              android:targetSdkVersion="16"/>
    <uses-permission android:name="com.sonyericsson.extras.liveware.aef.EXTENSION_PERMISSION" />

    <application android:label="Демо-приложения для часов для хабра" android:icon="@drawable/icon">

        <activity
                android:name="DemoConfigActivity"
                android:label="Экран с настройками" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
            </intent-filter>
        </activity>

        <service android:name="DemoReceiverService" />

        <receiver
                android:name="DemoExtensionReceiver"
                android:permission="com.sonyericsson.extras.liveware.aef.HOSTAPP_PERMISSION" >
            <intent-filter>

                <!-- Generic extension intents. -->
                <action android:name="com.sonyericsson.extras.liveware.aef.registration.EXTENSION_REGISTER_REQUEST" />
                <action android:name="com.sonyericsson.extras.liveware.aef.registration.ACCESSORY_CONNECTION" />
                <action android:name="android.intent.action.LOCALE_CHANGED" />

                <!-- Notification intents -->
                <action android:name="com.sonyericsson.extras.liveware.aef.notification.VIEW_EVENT_DETAIL" />
                <action android:name="com.sonyericsson.extras.liveware.aef.notification.REFRESH_REQUEST" />

                <!-- Widget intents -->
                <action android:name="com.sonyericsson.extras.aef.widget.START_REFRESH_IMAGE_REQUEST" />
                <action android:name="com.sonyericsson.extras.aef.widget.STOP_REFRESH_IMAGE_REQUEST" />
                <action android:name="com.sonyericsson.extras.aef.widget.ONTOUCH" />
                <action android:name="com.sonyericsson.extras.liveware.extension.util.widget.scheduled.refresh" />

                <!-- Control intents -->
                <action android:name="com.sonyericsson.extras.aef.control.START" />
                <action android:name="com.sonyericsson.extras.aef.control.STOP" />
                <action android:name="com.sonyericsson.extras.aef.control.PAUSE" />
                <action android:name="com.sonyericsson.extras.aef.control.RESUME" />
                <action android:name="com.sonyericsson.extras.aef.control.ERROR" />
                <action android:name="com.sonyericsson.extras.aef.control.KEY_EVENT" />
                <action android:name="com.sonyericsson.extras.aef.control.TOUCH_EVENT" />
                <action android:name="com.sonyericsson.extras.aef.control.SWIPE_EVENT" />
                <action android:name="com.sonyericsson.extras.aef.control.OBJECT_CLICK_EVENT" />
                <action android:name="com.sonyericsson.extras.aef.control.MENU_ITEM_SELECTED" />
            </intent-filter>
        </receiver>
    </application>
</manifest>


Суть происходящего такова: мы создаём в приложении класс, который будет принимать события от часов, передавать их в сервис обработки, который и будет производить некие осмысленные действия. Единственная activity нам нужна для окна настроек, если же таковое нам не нужно – можно было бы выкинуть её совсем.

Класс-receiver совсем простой:
DemoExtensionReceiver.java
public class DemoExtensionReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(final Context context, final Intent intent) {
        intent.setClass(context, DemoReceiverService.class);
        context.startService(intent);
    }
}


Ну а теперь перейдём к самому сервису:
DemoReceiverService.java
public class DemoReceiverService extends ExtensionService {

    public static final String EXTENSION_KEY = "com.smartwatch_habra_demo"; //todo не смог найти в документации подробностей о применимости, так что просто копипастим из примеров по шаблону "пакет.приложения"

    public DemoReceiverService() {
        super(EXTENSION_KEY);
    }

    @Override
    protected RegistrationInformation getRegistrationInformation() {
        return new DemoRegistrationInformation(this);
    }

    @Override
    protected boolean keepRunningWhenConnected() {//нам не нужно постоянно держать сервис работающим
        return false;
    }

    @Override
    public WidgetExtension createWidgetExtension(String hostAppPackageName) { //возвращаем объект виджета
        return new DemoWidget(this,hostAppPackageName);
    }

    @Override
    public ControlExtension createControlExtension(String hostAppPackageName) {//возвращаем объект основной программы
        boolean IsSmartWatch2= DeviceInfoHelper.isSmartWatch2ApiAndScreenDetected(
                this, hostAppPackageName);
        if (IsSmartWatch2){
            return new DemoControl2(this,hostAppPackageName);
        }else{
            return new DemoControl(this,hostAppPackageName);
        }
    }
}


Достаточно лаконично, правда? Ключевые моменты поясняются комментариями, вопросов вроде не должно возникнуть. ControlExtension нам нужен для обработки и рисования основного приложения на часах, WidgetExtension – для тех же целей, но уже для виджета.

А вот RegistrationInformation – это информация для регистрации нашего расширения в программе управления часами так сказать.
DemoRegistrationInformation.java
public class DemoRegistrationInformation extends RegistrationInformation {
    public static final int WIDGET_WIDTH_SMARTWATCH = 128;
    public static final int WIDGET_HEIGHT_SMARTWATCH = 110;

    public static final int CONTROL_WIDTH_SMARTWATCH = 128;
    public static final int CONTROL_HEIGHT_SMARTWATCH = 128;
    public static final int CONTROL_WIDTH_SMARTWATCH_2 = 220;
    public static final int CONTROL_HEIGHT_SMARTWATCH_2 = 176;

    Context mContext;

    protected DemoRegistrationInformation(Context context) {
        if (context == null) {
            throw new IllegalArgumentException("context == null");
        }
        mContext = context;
    }

    @Override
    public ContentValues getExtensionRegistrationConfiguration() {
        String iconHostapp = ExtensionUtils.getUriString(mContext, R.drawable.icon);

        ContentValues values = new ContentValues();
        values.put(Registration.ExtensionColumns.CONFIGURATION_ACTIVITY,DemoConfigActivity.class.getName()); //активити, которое будет отображаться в меню "настройки расширения". Если оно нам не нужно - убираем параметр совсем.
        values.put(Registration.ExtensionColumns.CONFIGURATION_TEXT,"Настройки демо-расширения");//а это текст, отображащийся в качестве пункта меню программы управления часами. Если оно нам не нужно - убираем параметр совсем.

        values.put(Registration.ExtensionColumns.NAME, "Хабра-демо-расширение");//имя, отображаемое в списке приложений внутри программы управления часами
        values.put(Registration.ExtensionColumns.EXTENSION_KEY,DemoReceiverService.EXTENSION_KEY); //уникальный ключ расширения

        values.put(Registration.ExtensionColumns.HOST_APP_ICON_URI, iconHostapp); //иконка в списке приложений в телефоне
        values.put(Registration.ExtensionColumns.EXTENSION_ICON_URI, iconHostapp); //иконка в списке приложений на самих часах, в идеале 48x48
        values.put(Registration.ExtensionColumns.NOTIFICATION_API_VERSION,getRequiredNotificationApiVersion());//нужная версия механизма уведомлений
        values.put(Registration.ExtensionColumns.PACKAGE_NAME, mContext.getPackageName());

        return values;
    }

    @Override
    public int getRequiredNotificationApiVersion() { //нам не нужно управление нотификациями
        return 0;
    }

    @Override
    public int getRequiredSensorApiVersion() { //нам не нужна инфа с сенсоров вроде акселерометра
        return 0;
    }

    //---------------------------------------------
    //всё что нужно для поддержки виджета
    //---------------------------------------------

    @Override
    public boolean isWidgetSizeSupported(final int width, final int height) {
        return (width == WIDGET_WIDTH_SMARTWATCH && height == WIDGET_HEIGHT_SMARTWATCH);
    }

    @Override
    public int getRequiredWidgetApiVersion() { //для поддержки первых часов
        return 1;
    }

    //---------------------------------------------
    //всё что нужно для поддержки контроллера
    //---------------------------------------------

    @Override
    public int getRequiredControlApiVersion() { //для поддержки первых часов
        return 1;
    }

    @Override
    public int getTargetControlApiVersion() { //для поддержки второй версии часов
        return 2;
    }

    @Override
    public boolean isDisplaySizeSupported(int width, int height) {
        return (width == CONTROL_WIDTH_SMARTWATCH_2 && height == CONTROL_HEIGHT_SMARTWATCH_2)
                || (width == CONTROL_WIDTH_SMARTWATCH && height == CONTROL_HEIGHT_SMARTWATCH);
    }
}


Здесь стоит остановиться поподробнее. Дело в том, что скачанное нами API от Sony – универсальное для целой пачки устройств от Sony, и никто не мешает нам написать приложение (расширение), которое может запуститься на всех этих устройствах разом. Или только на избранных из них.

Раз такое дело, нам надо сообщить, какие размеры экранов и версии API для сенсоров, виджетов и т.п. нам нужно поддержать. Нам нужно указать:
  • Поддержка разных сенсоров (акселерометров и т.п.) – getRequiredSensorApiVersion. Нам оно не надо совсем, так что версия API = 0.
  • Нотификации (Notification) — всплывающие сообщения-уведомления; нам они тоже не нужны. Так что в getRequiredNotificationApiVersion снова 0.
  • “Контроллер” – это то самое “обычное окно программы на часах”. Для него нам нужно определить версию. Кроме того, нам придётся указать поддерживаемые размеры экранов первых и вторых часов, и только их, никакие иные устройства нам не нужны. Поэтому передаём:
    • getRequiredControlApiVersion – версию 1 (для поддержки первой версии часов). Если бы передали 2 – поддерживались бы только Smartwatch 2, на первых бы не запустилось.
    • getTargetControlApiVersion – целевая версия API, здесь 2 для опять же поддержки Smartwatch 2
    • isDisplaySizeSupported – получаем размеры экрана устройства и определяем, хотим ли мы запускаться на нём или нет.

  • “Виджет” (Widget) – это изображение в списке виджетов. Аналогично, нужно указать требуемую версию и размеры экрана. Важный момент: вторая версия часов виджеты не поддерживает. Увы.

Плюс пачка параметров в getExtensionRegistrationConfiguration, но там всё понятно из комментариев.

Основное окно программы


Здесь важно осознать следующим момент. На часы в первой версии часов мы можем отправлять только изображения. Картинки. Всё. Ничего больше. Иным способом рисовать мы не можем. Во второй версии появились расширенные контроллеры, но мы-то изначально пишем для поддержки обоих версий, так что только изображения.

Если же вы хотите использовать для рендера возможности Layout, например, отрендерить компоненты – без проблем, но координаты кликов и прочее взаимодействие придётся обрабатывать вручную. Безрадостная перспектива… Но тем не менее. Вот так будет выглядеть наша картинка:



А вот так — код, который за всё ответит:
DemoControl.java
public class DemoControl extends ControlExtension {

    static final Rect buttonStopPlaySmartWatch = new Rect(43, 42, 85, 88);

    public DemoControl(Context context, String hostAppPackageName) {
        super(context, hostAppPackageName);
    }

    @Override
    public void onTouch(final ControlTouchEvent event) {//реакция на клики
        if (event.getAction() == Control.Intents.CLICK_TYPE_SHORT) {
            if (buttonStopPlaySmartWatch.contains(event.getX(), event.getY())){
                MusicBackgroundControlWrapper.TogglePausePlay(mContext);
            }
        }
    }

    @Override
    public void onSwipe(int direction) {//реакция на жесты
        if (direction== Control.Intents.SWIPE_DIRECTION_UP){
            MusicBackgroundControlWrapper.VolumeUp(mContext);
        }
        if (direction==Control.Intents.SWIPE_DIRECTION_DOWN){
            MusicBackgroundControlWrapper.VolumeDown(mContext);
        }
        if (direction==Control.Intents.SWIPE_DIRECTION_LEFT){
            MusicBackgroundControlWrapper.Next(mContext);
        }
        if (direction==Control.Intents.SWIPE_DIRECTION_RIGHT){
            MusicBackgroundControlWrapper.Prev(mContext);
        }
    }

    @Override
    public void onResume() {//рисуем изображение
        Bitmap mPicture = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.control_picture);
        showBitmap(mPicture);
    }
}


Назначение событий onSwipe и onTouch говорят сами за себя, onResume вызывается каждый раз, как оно программы будет видно, например, часы вышли из спячки или была выбрана иконка приложения. В принципе, этого достаточно для большинства взаимодействий с приложением.

MusicBackgroundControlWrapper – это небольшой самописный класс, предназначенный для управления плеером с использованием эмуляции нажатий мультимедийных клавиш. Нормально работает не со всеми плеерами и телефонами, но там где работает – работает на ура. Если знаете лучший способ (с поддержкой Android 2.3 и выше!) – поделитесь пожалуйста в комментариях.

MusicBackgroundControlWrapper.java
public class MusicBackgroundControlWrapper {
    public static void KeyPressDownAndUp(int key,Context context){
        long eventtime = SystemClock.uptimeMillis() - 1;

        Intent downIntent = new Intent(Intent.ACTION_MEDIA_BUTTON, null);
        KeyEvent downEvent = new KeyEvent(eventtime, eventtime,
                KeyEvent.ACTION_DOWN, key, 0);
        downIntent.putExtra(Intent.EXTRA_KEY_EVENT, downEvent);
        context.sendOrderedBroadcast(downIntent, null);

        eventtime++;
        Intent upIntent = new Intent(Intent.ACTION_MEDIA_BUTTON, null);
        KeyEvent upEvent = new KeyEvent(eventtime, eventtime,
                KeyEvent.ACTION_UP, key, 0);
        upIntent.putExtra(Intent.EXTRA_KEY_EVENT, upEvent);
        context.sendOrderedBroadcast(upIntent, null);
    }

    public static void VolumeUp(Context context){
        AudioManager audioManager =(AudioManager)context.getSystemService(Context.AUDIO_SERVICE);

        int max=audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
        int current=audioManager.getStreamVolume(AudioManager.STREAM_MUSIC);

        if (current<max){
            current++;
        }

        audioManager.setStreamVolume(AudioManager.STREAM_MUSIC,
                current,0);
    }

    public static void VolumeDown(Context context){
        AudioManager audioManager =(AudioManager)context.getSystemService(Context.AUDIO_SERVICE);

        int current=audioManager.getStreamVolume(AudioManager.STREAM_MUSIC);

        if (current>0){
            current--;
        }

        audioManager.setStreamVolume(AudioManager.STREAM_MUSIC,
                current,0);
    }

    public static void TogglePausePlay(Context context){
        KeyPressDownAndUp(KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE,context);
    }

    public static void Next(Context context){
        KeyPressDownAndUp(KeyEvent.KEYCODE_MEDIA_NEXT, context);
    }

    public static void Prev(Context context){
        KeyPressDownAndUp(KeyEvent.KEYCODE_MEDIA_PREVIOUS, context);
    }
}


Для поддержки второй версии часов мы унаследуем DemoControl2 от DemoControl, с парой изменений – в onResume() будем передавать другое изображение, а в onTouch – проверять иные координаты.

DemoControl2.java
public class DemoControl2 extends DemoControl {
    static final Rect buttonStopPlaySmartWatch2 = new Rect(59, 52, 167, 122);

    public DemoControl2(Context context, String hostAppPackageName) {
        super(context, hostAppPackageName);
    }

    @Override
    public void onTouch(final ControlTouchEvent event) {//реакция на клики
        if (event.getAction() == Control.Intents.CLICK_TYPE_SHORT) {
            if (buttonStopPlaySmartWatch2.contains(event.getX(), event.getY())){
                MusicBackgroundControlWrapper.TogglePausePlay(mContext);
            }
        }
    }

    @Override
    public void onResume() {//рисуем изображение
        Bitmap mPicture = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.control_picture2);
        showBitmap(mPicture);
    }
}


Виджет


Итак, виджет. Каноничный виджет имеет разрешение 92x92 пикселя для первой версии часов и не поддерживаются в принципе для второй. Можно растянуть его и на бОльшие разрешения (вплоть до 128x110), но он тогда будет выбиваться из стилистики и закрывать стандартные элементы управления и индикации.

Нам от него понадобится только одно действие – по клику запускать наше основное приложение на часах. Класс, отвечающий за это тоже очень простой, все подробности в комментариях.

DemoWidget.java
public class DemoWidget extends WidgetExtension {

    public DemoWidget(Context context, String hostAppPackageName) {
        super(context, hostAppPackageName);
    }

    @Override
    public void onStartRefresh() { //Когда виджет становится видимым и/или обновляется.
        showBitmap(new DemoWidgetImage(mContext).getBitmap());
    }

    @Override
    public void onStopRefresh() { //Когда виджет перестаёт быть видимым. Нам ничего не нужно делать, мы и так не обновляем его и не анимируем.
    }

    @Override
    public void onTouch(final int type, final int x, final int y) {
        if (!SmartWatchConst.ACTIVE_WIDGET_TOUCH_AREA.contains(x, y)) { //если кликнули вне иконки приложения - ничего не делаем
            return;
        }

        //по клику (быстрому или долгому) запускаем основное окно программы
        if (type == Widget.Intents.EVENT_TYPE_SHORT_TAP || type==Widget.Intents.EVENT_TYPE_LONG_TAP) {
            Intent intent = new Intent(Control.Intents.CONTROL_START_REQUEST_INTENT);
            intent.putExtra(Control.Intents.EXTRA_AEA_PACKAGE_NAME, mContext.getPackageName());
            intent.setPackage(mHostAppPackageName);
            mContext.sendBroadcast(intent, Registration.HOSTAPP_PERMISSION);
        }
    }
}


Хотя есть там и интересный момент. В комплекте с API, среди утилит есть класс специально для виджетов, самостоятельно рендерящий Layout в картинку. Грех такой возможностью не воспользоваться, хотя бы и в целях обучения. Рендерить будем через класс DemoWidgetImage.

DemoWidgetImage.java
public class DemoWidgetImage extends SmartWatchWidgetImage {

    public DemoWidgetImage(Context context) {
        super(context);
        setInnerLayoutResourceId(R.layout.music_widget_image);
    }

    @Override
    protected void applyInnerLayout(LinearLayout innerLayout) {
        //даже если ничего не делаем с содержимым - переопределить обязаны. Угу.
    }
}


Окно настроек


Ну тут нужно совсем минимум. Поскольку в классе DemoRegistrationInformation мы уже прописали имя активити, то тут нам сейчас остаётся только заполнить её ну хоть чем-то. Даже комментировать не буду. Просто код.

DemoConfigActivity.java
public class DemoConfigActivity extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.config);
    }
}

config.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical"
              android:layout_width="match_parent"
              android:layout_height="match_parent">

    <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textAppearance="?android:attr/textAppearanceMedium"
            android:text="Демонстрационный текст"
            android:id="@+id/textView" android:layout_gravity="center_horizontal"/>
</LinearLayout>


Как опубликовать приложение в Google Play


Что бы ваше приложение находилось утилитой управления часами в магазине приложений – нужно добавить в текст описания программы на Google Play:
  • Для поддержки SmartWatch — “LiveWare extension for SmartWatch”
  • Для поддержки SmartWatch 2 – “Smart Connect extension for SmartWatch 2”
  • Если нужны оба – добавляем соответственно обе строки.

Что характерно, установить приложение сможет и человек, у которого самих часов нет. Установить, не запустить и влепить минимальную оценку, да. Привыкайте, это мир Google Play! Но нам ведь не важна оценка, нам важно, что мир становится чуточку лучше, верно…?

Что ещё можно доделать в приложении-примере


  • Окно настроек (сделать, например инвертирование жестов).
  • Более корректный и универсальный способ управления плеерами. В Android 4.4 уже реализован нужный API (Remote controllers кажется называется), а вот для более старых – проблема.
  • Сделать (придумать, найти) автоматический расчет координат для объектов, находящихся на вьюшке. Что бы руками не считать каждый раз, вдруг Sony создаст третьи часы с третьим разрешением.


Результат нашей работы






Исходный код примера из статьи


github.com/Newbilius/smartwatch_habra_demo

Источник в лице сайта Sony


developer.sonymobile.com/knowledge-base/sony-add-on-sdk

И повторюсь, если возникли вопросы по другим фичам часов – смотрите папку examples (полный путь был приведён выше), там есть примеры использования абсолютно всех датчиков и возможностей. Цель этой статьи – дать вам возможность совершить “быстрый старт” и заинтересовать, надеюсь, у меня это получилось сделать.

P.S. Если вам нужно готовое приложение, описанное в этой статье, но нет желание заниматься разработкой – в Google Play уже есть такое, и даже более функциональные — но или платные, или не совсем такие или с подобными же недостатками.

P.P.S. У меня нет на руках второй версии часов, так что всё что о них написано — это информация из примеров или документации, плюс проверка на эмуляторе, на реальных часах второй версии не проверял. Первая же версия часов есть, там всё точно и проверено.
Дмитрий @Newbilius
карма
90,2
рейтинг 0,3
Программист мобильных приложений
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Спецпроект

Самое читаемое Разработка

Комментарии (13)

  • +1
    >DemoControl.cs
    O_o здесь нужно использовать C#?
    А по теме: все больше начинают интересовать часы на андроиде. Вот только понимаю, что они мне не нужны. Вот через годик-второй, когда эти штуки созреют, они будут интересными девайсами
    • +1
      Судя по коду, это Java, .cs — наверное опечатка
      • 0
        Я в курсе ;)
    • 0
      Аааа блин! Конечно Java. Просто у нас в компании основной язык серверной части разработки — C#, вот видимо и глюкнуло что-то в мозге. Поправлено.
  • +2
    Насколько большая аудитория у этого девайса?
    Стоит ли заниматься коммерческой разработкой под такие часы?
    P.S. Я бы обобщил вопрос: на какие виды умных устройств вообще стоит обратить внимание? SmartTV, часы…
    • +1
      Не знаю на сколько большая, но лично я с десяток утилит под них просто купил (типа умного будильника, и всяких там звонилок, диктофонов..).
      Вот сейчас прочитав данную статью думаю сесть написать виджет для запуска видеорегистратора через них на S3 (экран у телефона сдох), а вот как видеорегистратор работать бы мог).
      Был бы готовый плугин — просто купил.
      P.S. У меня первая версия часов. До второй еще не дотянулся, да и эти тогда будет логично привязать к телефону S3, и можно удаленно использовать.
  • +1
    Спасибо за статью! Подумываю о приобретении подобного девайса, но смущают жалобы владельцев… Решена ли проблема с постоянной потерей bluetooth-соединения и появилась ли возможность работы как обычных часов без наличия хоста?
    • 0
      Владелец SmartWatch 2 (4 месяца). Проблемы с постоянной потерей bluetooth-соединения не было замечено. Естественные отключения при превышении радиуса стабильного соединения начинаются приблизительно с 30 метров (без преград). Если находиться за радиусом не сильно долго (чаю на кухне налить), то соединение автоматически восстанавливается по возвращении. Возможность работы как обычных часов естественно имеется. Более того экран устроен таким образом, что в обычном режиме «просто часов» совершенно не используется подсветка и изображение прекрасно читается при любом типе освещения. Поясню цитатой с хобота:
      ЖК-матрица гибридная, в ней есть ячейки, работающие на просвет (ярко светятся на фотографии выше) и на отражение (они побольше и затемнены). Действительно, при смене режима, когда выключается подсветка, видно, что меняется и само изображение, то есть оно начинает формироваться другим типом ячеек.

      Источник и тесты.
    • 0
      Потер соединения бывают, но во-первых, восстанавливаются оно за считанные секунды в такой ситуации (обычно не более 5, а то и быстрее). Причем происходит это далеко не каждый день.
      Без хоста не работает. Тем не менее, если подключиться к телефону, а потом выйти за границу доступности связи (метров 3-5 с парой-тройкой стен между) — они потеряют связь, но продолжат работать как часы. Воспользоваться софтинками будет нельзя (т.к. весь софт фактически в телефоне), но как часы работать будут. Но, думаю, это не самый оптимальный вариант использования этого устройства, учитывая цену. ;)
  • +1
    Имею SmartWatch 2, как раз думал что-нибудь написать для них, и тут эта статья. Спасибо! На досуге попробую.
    Так же поделюсь мнением об устройстве, вторые явно лучше первых, но еще не идеальны. Многие недостатки которые были уже подправили в обновлении, но многие приложения всё еще неудобные в управлении. В остальном девайсом очень доволен. При подключении гарнитуры, можно мобилу не доставать с кармана. Лично у меня соединение не теряет с Sony ZR, работает на 10 метров даже через стену.
    NFS — здесь лишнее, лучше бы сделали беспроводную зарядку.
  • –1
    Что характерно, установить приложение сможет и человек, у которого самих часов нет. Установить, не запустить и влепить минимальную оценку, да. Привыкайте, это мир Google Play!


    А это на что?
    image
    • 0
      Я могу ошибаться, но… там ведь можно исключить из списка только конкретные устройства или по параметрам вроде версии ОС или разрешения экрана. Параметра «телефон, к которому не подключены SmartWatch» там нет.
    • 0
      Divers, не могли бы вы развить свою мысль?

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.