もう、ruputerは卒業だぁ! smartwatchアプリを作ろう/すまべん関西#20

72
もう、Ruputerは卒業だぁ! SmartWatchアプリを作ろう たろサ(@momoonga)

Upload: -

Post on 28-May-2015

6.071 views

Category:

Technology


0 download

TRANSCRIPT

Page 1: もう、Ruputerは卒業だぁ! SmartWatchアプリを作ろう/すまべん関西#20

もう、Ruputerは卒業だぁ!

SmartWatchアプリを作ろう

たろサ(@momoonga)

Page 2: もう、Ruputerは卒業だぁ! SmartWatchアプリを作ろう/すまべん関西#20

2

自己紹介

和歌山県有田市

太刀重太刀重

ご当地名産

最近作ったスマホアプリ

最太刀重一丁!

Page 3: もう、Ruputerは卒業だぁ! SmartWatchアプリを作ろう/すまべん関西#20

内 容

(1)SmartWatchについて

(2)SmartWatchの開発環境

(3)SmartWatch用アプリの作成

(4)何、作ろうか?

Page 4: もう、Ruputerは卒業だぁ! SmartWatchアプリを作ろう/すまべん関西#20

SmartWatch MN2について

余計な話が、いっぱい出てくると思います。すいません。

Page 5: もう、Ruputerは卒業だぁ! SmartWatchアプリを作ろう/すまべん関西#20

5

SmartWatch MN2発売

Bluetooth

Android SmartWatch

LiveViewの後継機

Page 6: もう、Ruputerは卒業だぁ! SmartWatchアプリを作ろう/すまべん関西#20

6

SmartWatch MN2発売

4月10日発売約3時間で売り

切れ!

Page 7: もう、Ruputerは卒業だぁ! SmartWatchアプリを作ろう/すまべん関西#20

7

SmartWatch MN2発売

4月10日発売約3時間で売り

切れ!

Page 8: もう、Ruputerは卒業だぁ! SmartWatchアプリを作ろう/すまべん関西#20

8

SmartWatch MN2発売

Wristomo(リストモ)NTTドコモのPHS

2003年5月7日午前10時より発売、約15分で売り切れる

Page 9: もう、Ruputerは卒業だぁ! SmartWatchアプリを作ろう/すまべん関西#20

9

SmartWatch MN2発売

Wristomo(リストモ)NTTドコモのPHS

2003年5月7日午前10時より発売、約15分で売り切れる

ちなみに、BTウォッチは結構出ています。

Page 10: もう、Ruputerは卒業だぁ! SmartWatchアプリを作ろう/すまべん関西#20

10

SmartWatch MN2発売

Testanova(発表のみ発売せず)

・BT通信・EL液晶・着信を振動や音で知らせる・発信者名の表示する・腕時計の操作で保留応答や着信拒否・置き忘れ防止(携帯電話と腕時計がある程度の距離で離れ、双方のリンクが途絶えた場合、腕時計がアラートする)・着信音のミュート及び解除・時刻情報の同期

プログラムできないのが残念

Page 11: もう、Ruputerは卒業だぁ! SmartWatchアプリを作ろう/すまべん関西#20

11

SmartWatch MN2発売

Testanova(発表のみ発売せず)

・BT通信・EL液晶・着信を振動や音で知らせる・発信者名の表示する・腕時計の操作で保留応答や着信拒否・置き忘れ防止(携帯電話と腕時計がある程度の距離で離れ、双方のリンクが途絶えた場合、腕時計がアラートする)・着信音のミュート及び解除・時刻情報の同期

プログラムできないのが残念

プログラムできる腕時計といえば

Page 12: もう、Ruputerは卒業だぁ! SmartWatchアプリを作ろう/すまべん関西#20

12

SmartWatch MN2発売

Ruputer

・赤外線通信・シリアル通信・モノクロ液晶・WPS-DOS搭載・プログラムできる[非公開仕様]・ソフト的にvsync割り込み取得可・M/B上にA/D変換端子の有り

元宇宙飛行士の毛利さんも使っていた

Page 13: もう、Ruputerは卒業だぁ! SmartWatchアプリを作ろう/すまべん関西#20

13

SmartWatchのスペック

SmartWatch

・Android OS 2.3以降のXperia™シリーズ専用

Page 14: もう、Ruputerは卒業だぁ! SmartWatchアプリを作ろう/すまべん関西#20

14

SmartWatchのスペック

SmartWatch

・Android OS 2.3以降のXperia™シリーズ専用

そうでもなさそうです・・・

Page 15: もう、Ruputerは卒業だぁ! SmartWatchアプリを作ろう/すまべん関西#20

15

SmartWatchのスペック

SmartWatch

・Android OS 2.3以降のXperia™シリーズ専用(そうでもなさそうです・・・)・大きさ:36mm×36mm×8mm

Page 16: もう、Ruputerは卒業だぁ! SmartWatchアプリを作ろう/すまべん関西#20

16

SmartWatchのスペック

SmartWatch

・Android OS 2.3以降のXperia™シリーズ専用(そうでもなさそうです・・・)・大きさ:36mm×36mm×8mm

確かに小さいです。

Page 17: もう、Ruputerは卒業だぁ! SmartWatchアプリを作ろう/すまべん関西#20

17

SmartWatchのスペック

SmartWatch

・Android OS 2.3以降のXperia™シリーズ専用(そうでもなさそうです・・・)・大きさ:36mm×36mm×8mm・質量:15.5g (リストバンド除く)

Page 18: もう、Ruputerは卒業だぁ! SmartWatchアプリを作ろう/すまべん関西#20

18

SmartWatchのスペック

SmartWatch

・Android OS 2.3以降のXperia™シリーズ専用(そうでもなさそうです・・・)・大きさ:36mm×36mm×8mm・質量:15.5g (リストバンド除く)・ディスプレイ:1.3インチカラー有機ELディスプレイ(128×128ドット)

Page 19: もう、Ruputerは卒業だぁ! SmartWatchアプリを作ろう/すまべん関西#20

19

SmartWatchのスペック

SmartWatch

・Android OS 2.3以降のXperia™シリーズ専用(そうでもなさそうです・・・)・大きさ:36mm×36mm×8mm・質量:15.5g (リストバンド除く)・ディスプレイ:1.3インチカラー有機ELディスプレイ(128×128ドット)

SmartWatch

Ruputer

128ドット

102ドット

128ド

ット64

ドッ

トカラー有機ELディスプレイは屋外でたいへん見にくいです。

Page 20: もう、Ruputerは卒業だぁ! SmartWatchアプリを作ろう/すまべん関西#20

20

SmartWatchのスペック

SmartWatch

・Android OS 2.3以降のXperia™シリーズ専用(そうでもなさそうです・・・)・大きさ:36mm×36mm×8mm・質量:15.5g (リストバンド除く)・ディスプレイ:1.3インチカラー有機ELディスプレイ(128×128ドット)・内蔵電池:リチウムイオン電池(専用充電端子)

Page 21: もう、Ruputerは卒業だぁ! SmartWatchアプリを作ろう/すまべん関西#20

21

SmartWatchのスペック

SmartWatch

・Android OS 2.3以降のXperia™シリーズ専用(そうでもなさそうです・・・)・大きさ:36mm×36mm×8mm・質量:15.5g (リストバンド除く)・ディスプレイ:1.3インチカラー有機ELディスプレイ(128×128ドット)・内蔵電池:リチウムイオン電池(専用充電端子)

CR2025×2

Page 22: もう、Ruputerは卒業だぁ! SmartWatchアプリを作ろう/すまべん関西#20

22

SmartWatchのスペック

SmartWatch

・Android OS 2.3以降のXperia™シリーズ専用(そうでもなさそうです・・・)・大きさ:36mm×36mm×8mm・質量:15.5g (リストバンド除く)・ディスプレイ:1.3インチカラー有機ELディスプレイ(128×128ドット)・内蔵電池:リチウムイオン電池(専用充電端子)・全面マルチタッチディスプレイ・加速度センサ3軸・振動アラーム

Page 23: もう、Ruputerは卒業だぁ! SmartWatchアプリを作ろう/すまべん関西#20

23

SmartWatchのスペック

SmartWatch

・Android OS 2.3以降のXperia™シリーズ専用(そうでもなさそうです・・・)・大きさ:36mm×36mm×8mm・質量:15.5g (リストバンド除く)・ディスプレイ:1.3インチカラー有機ELディスプレイ(128×128ドット)・内蔵電池:リチウムイオン電池(専用充電端子)・全面マルチタッチディスプレイ・加速度センサ3軸・振動アラーム

リストモの方がブルブル

Page 24: もう、Ruputerは卒業だぁ! SmartWatchアプリを作ろう/すまべん関西#20

SmartWatchの開発環境

Page 25: もう、Ruputerは卒業だぁ! SmartWatchアプリを作ろう/すまべん関西#20

25

EDK 2.0のインストール

Android SDK Managerを使って、EDK 2.0をインストール

Page 26: もう、Ruputerは卒業だぁ! SmartWatchアプリを作ろう/すまべん関西#20

26

AVDの作成

ウィンドウ>設定の「Android」のところに、ターゲット名 EDK 2.0ができている

Page 27: もう、Ruputerは卒業だぁ! SmartWatchアプリを作ろう/すまべん関西#20

27

AVDの作成

EDK 2.0(Sony Mobile Communications AB)用AVDが作成できる

SD CardはEDK 2.0にあるsdcard.imgを使う

フォルダ/android-sdk/add-ons/addon-edk_2_0-sony_ericsson_mobile_communications_ab-10/images/sdcard.img

Page 28: もう、Ruputerは卒業だぁ! SmartWatchアプリを作ろう/すまべん関西#20

28

AVDの作成

作成したAVDには、LiveWare マネージャと、Smart Extendion Emulatorがある

Page 29: もう、Ruputerは卒業だぁ! SmartWatchアプリを作ろう/すまべん関西#20

29

ASmart Extension Emuの設定

SmartWatchを選ぶ

Page 30: もう、Ruputerは卒業だぁ! SmartWatchアプリを作ろう/すまべん関西#20

30

Smart Extension SDKのダウンロード

Smart Extension SDKを選ぶ

http://developer.sonymobile.com/cws/devworld/search-downloads/docstools/sdk

Page 31: もう、Ruputerは卒業だぁ! SmartWatchアプリを作ろう/すまべん関西#20

31

Smart Extension SDKのダウンロード

SmartExtensionAPISmartExtensionUtils

SampleControlExtensionSampleNotificationExtensionSampleSensorExtensionSampleWidgetExtension

ライブラリがソースで入っている

サンプルプログラムソース

Eclipseにインポートします

・ライブラリとして使うのはUtilsのみです。APIは、Utilsが使っています。

Page 32: もう、Ruputerは卒業だぁ! SmartWatchアプリを作ろう/すまべん関西#20

SmartWatch用

アプリの作成

Page 33: もう、Ruputerは卒業だぁ! SmartWatchアプリを作ろう/すまべん関西#20

33

SmartWatchアプリの仕組み

LiveWareマネージャ

SmartWatch

Bluetooth

SmartWatchアプリ(1)

サービスとして常駐

SmartWatchアプリ(2)

SmartWatchアプリ(3)

SmartWatchアプリを管理

SmartWatchとのやり取りは、すべてLiveWareマネージャが行っている

イベント

画面データ

タッチデータ

Page 34: もう、Ruputerは卒業だぁ! SmartWatchアプリを作ろう/すまべん関西#20

34

SmartWatchアプリの仕組み

LiveWareマネージャ

SmartWatch

Bluetooth

SmartWatchアプリ(1)

サービスとして常駐

SmartWatchアプリ(2)

SmartWatchアプリ(3)

SmartWatchアプリを管理

SmartWatchとのやり取りは、すべてLiveWareマネージャが行っている

イベント

画面データ

タッチデータ

なんと、SmartWatchは画像しかもらえない

Page 35: もう、Ruputerは卒業だぁ! SmartWatchアプリを作ろう/すまべん関西#20

35

SmartWatchアプリの仕組み

LiveWareマネージャ

SmartWatch

Bluetooth

SmartWatchアプリ(1)

サービスとして常駐

SmartWatchアプリ(2)

SmartWatchアプリ(3)

SmartWatchアプリを管理

SmartWatchとのやり取りは、すべてLiveWareマネージャが行っている

イベント

画面データ

タッチデータ

画像のみの送信

Page 36: もう、Ruputerは卒業だぁ! SmartWatchアプリを作ろう/すまべん関西#20

36

Manifest

<uses-permission android:name="com.sonyericsson.extras.liveware.aef.EXTENSION_PERMISSION" />

<intent-filter> <action android:name="android.intent.action.MAIN" /></intent-filter>

<service android:name="SampleExtensionService" />

Page 37: もう、Ruputerは卒業だぁ! SmartWatchアプリを作ろう/すまべん関西#20

37

Manifest

<receiver android:name=".ExtensionReceiver"> <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"/> </intent-filter>

Page 38: もう、Ruputerは卒業だぁ! SmartWatchアプリを作ろう/すまべん関西#20

38

プログラムの概要

Page 39: もう、Ruputerは卒業だぁ! SmartWatchアプリを作ろう/すまべん関西#20

39

プログラムに必要なクラス

・PreferenceActivityクラス 

  Android本体側での設定等を行うために用いるクラス

・ExtensionServiceクラス

  常駐するためのサービスクラス

・BroadcastReceiverクラス

  Manifestに設定されたインテントを受けてサービスを開始させる

  ためのクラス

・メイン処理クラス

  実処理が書かれているクラス。ExtensionServiceクラスから呼ばれる。

・RegistrationInformationクラス

  LiveWareマネージャに登録するためクラス

プログラムには6つのクラスが必要です。

Page 40: もう、Ruputerは卒業だぁ! SmartWatchアプリを作ろう/すまべん関西#20

40

プログラムに必要なクラス

・PreferenceActivityクラス 

  Android本体側での設定等を行うためのクラス

・ExtensionServiceクラス

  常駐するためのサービスクラス

・BroadcastReceiverクラス

  Manifestに設定されたインテントを受けてサービスを開始させる

  ためのクラス

・メイン処理クラス

  実処理が書かれているクラス。ExtensionServiceクラスから呼ばれる。

・RegistrationInformationクラス

  LiveWareマネージャに登録するためクラス

プログラムには6つのクラスが必要です。

メイン処理のクラスは、2つです。

Page 41: もう、Ruputerは卒業だぁ! SmartWatchアプリを作ろう/すまべん関西#20

41

プログラムに必要なクラス

・ControlExtensionクラス 

  SmartWatch本体側プログラムとして振舞うクラス

・WidgetExtensionクラス

  SmartWatch本体でWidgetプログラムとして振舞うクラス

メイン処理のクラス

Page 42: もう、Ruputerは卒業だぁ! SmartWatchアプリを作ろう/すまべん関西#20

42

プログラムに必要なクラス

・ControlExtensionクラス 

  SmartWatch本体側プログラムとして振舞うクラス

・WidgetExtensionクラス

  SmartWatch本体でWidgetプログラムとして振舞うクラス

メイン処理のクラス

振舞うクラス?

Page 43: もう、Ruputerは卒業だぁ! SmartWatchアプリを作ろう/すまべん関西#20

43

プログラムに必要なクラス

・ControlExtensionクラス 

  SmartWatch本体側プログラムとして振舞うクラス

・WidgetExtensionクラス

  SmartWatch本体でWidgetプログラムとして振舞うクラス

メイン処理のクラス

SmartWatch本体ではプログラムは動いていないからです。

プログラムは全て、Android側で動いている

Page 44: もう、Ruputerは卒業だぁ! SmartWatchアプリを作ろう/すまべん関西#20

44

プログラムの概要

PreferenceActivityクラスを継承

RegistrationInformationクラスを継承

BroadcastReceiverクラスを継承

ExtensionServiceクラスを継承

メイン処理のクラス

ControlExtensionクラスを継承している

Page 45: もう、Ruputerは卒業だぁ! SmartWatchアプリを作ろう/すまべん関西#20

45

PreferenceActivityクラス

/** * The sample control preference activity handles the preferences for * the sample control extension. */public class SamplePreferenceActivity extends PreferenceActivity {

private static final int DIALOG_READ_ME = 1;

@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);

// Load the preferences from an XML resource addPreferencesFromResource(R.xml.preference);

// Handle read me Preference preference = findPreference(getText(R.string.preference_key_read_me)); preference.setOnPreferenceClickListener(new OnPreferenceClickListener() {

public boolean onPreferenceClick(Preference preference) { showDialog(DIALOG_READ_ME); return true; } });

}

Page 46: もう、Ruputerは卒業だぁ! SmartWatchアプリを作ろう/すまべん関西#20

46

PreferenceActivityクラス

@Override protected Dialog onCreateDialog(int id) { Dialog dialog = null;

switch (id) { case DIALOG_READ_ME: dialog = createReadMeDialog(); break; default: Log.w(SampleExtensionService.LOG_TAG, "Not a valid dialog id: " + id); break; }

return dialog; } /** * Create the Read me dialog * * @return the Dialog */ private Dialog createReadMeDialog() { AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setMessage(R.string.preference_option_read_me_txt) .setTitle(R.string.preference_option_read_me) .setIcon(android.R.drawable.ic_dialog_info) .setPositiveButton(android.R.string.ok, new OnClickListener() {

public void onClick(DialogInterface dialog, int which) { dialog.cancel(); } }); return builder.create(); }}

Page 47: もう、Ruputerは卒業だぁ! SmartWatchアプリを作ろう/すまべん関西#20

47

RegistrationInformationクラス

/** * Provides information needed during extension registration */public class SampleRegistrationInformation extends RegistrationInformation {

final Context mContext;

/** * Create control registration object * * @param context The context */ protected SampleRegistrationInformation(Context context) { if (context == null) { throw new IllegalArgumentException("context == null"); } mContext = context; }

@Override public int getRequiredControlApiVersion() { return 1; }

@Override public int getRequiredSensorApiVersion() { return 0; }

@Override public int getRequiredNotificationApiVersion() { return 0; }

@Override public int getRequiredWidgetApiVersion() { return 0; }

どのAPIを使うか

Page 48: もう、Ruputerは卒業だぁ! SmartWatchアプリを作ろう/すまべん関西#20

48

RegistrationInformationクラス

/** * Get the extension registration information. * * @return The registration configuration. */ @Override public ContentValues getExtensionRegistrationConfiguration() { String iconHostapp = ExtensionUtils.getUriString(mContext, R.drawable.icon); String iconExtension = ExtensionUtils.getUriString(mContext, R.drawable.icon_extension); String iconExtensionBw = ExtensionUtils.getUriString(mContext, R.drawable.icn_18x18_black_white_sample_control);

ContentValues values = new ContentValues();

values.put(Registration.ExtensionColumns.CONFIGURATION_ACTIVITY, SamplePreferenceActivity.class.getName()); values.put(Registration.ExtensionColumns.CONFIGURATION_TEXT, mContext.getString(R.string.configuration_text)); values.put(Registration.ExtensionColumns.NAME, mContext.getString(R.string.extension_name)); values.put(Registration.ExtensionColumns.EXTENSION_KEY, SampleExtensionService.EXTENSION_KEY); values.put(Registration.ExtensionColumns.HOST_APP_ICON_URI, iconHostapp); values.put(Registration.ExtensionColumns.EXTENSION_ICON_URI, iconExtension); values.put(Registration.ExtensionColumns.EXTENSION_ICON_URI_BLACK_WHITE, iconExtensionBw); values.put(Registration.ExtensionColumns.NOTIFICATION_API_VERSION, getRequiredNotificationApiVersion()); values.put(Registration.ExtensionColumns.PACKAGE_NAME, mContext.getPackageName());

return values; }

@Override public boolean isDisplaySizeSupported(int width, int height) { return ((width == SampleControlSmartWatch.getSupportedControlWidth(mContext) && height == SampleControlSmartWatch .getSupportedControlHeight(mContext)) || (width == SampleControlSmartWirelessHeadsetPro .getSupportedControlWidth(mContext) && height == SampleControlSmartWirelessHeadsetPro .getSupportedControlHeight(mContext))); }}

登録する情報をセットしている

Page 49: もう、Ruputerは卒業だぁ! SmartWatchアプリを作ろう/すまべん関西#20

49

BroadcastReceiverクラス

/** * The extension receiver receives the extension intents and starts the * extension service when it arrives. */public class ExtensionReceiver extends BroadcastReceiver {

@Override public void onReceive(final Context context, final Intent intent) { Log.d(SampleExtensionService.LOG_TAG, "onReceive: " + intent.getAction()); intent.setClass(context, SampleExtensionService.class); context.startService(intent); }}

インテントにサービスとして呼び出すクラスをセットしている

Page 50: もう、Ruputerは卒業だぁ! SmartWatchアプリを作ろう/すまべん関西#20

50

ExtensionServiceクラス

public class SmartWatchTest00Service extends ExtensionService {

public static final String EXTENSION_KEY = "com.sonyericsson.extras.liveware.extension.samplecontrol.key";

public static final String LOG_TAG = "SmartWatchTest00";

 public SmartWatchTest00Service() {  super(EXTENSION_KEY); }

/** * {@inheritDoc} * * @see android.app.Service#onCreate() */ @Override public void onCreate() { super.onCreate(); Log.d(SmartWatchTest00Service.LOG_TAG, "SmartWatchTest00: onCreate"); }

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

LiveWareマネージャ登録クラス生成

Page 51: もう、Ruputerは卒業だぁ! SmartWatchアプリを作ろう/すまべん関西#20

51

ExtensionServiceクラス

 @Override protected boolean keepRunningWhenConnected() { return false; }

@Override public ControlExtension createControlExtension(String hostAppPackageName) { final int controlSWWidth = SmartWatchTest00.getSupportedControlWidth(this); final int controlSWHeight = SmartWatchTest00.getSupportedControlHeight(this);

for (DeviceInfo device : RegistrationAdapter.getHostApplication(this, hostAppPackageName) .getDevices()) { for (DisplayInfo display : device.getDisplays()) { if (display.sizeEquals(controlSWWidth, controlSWHeight)) { return new SmartWatchTest00(hostAppPackageName, this, new Handler()); } } } throw new IllegalArgumentException("No control for: " + hostAppPackageName); }}

メインの処理クラスの生成

SmartWatchの画面サイズなどをチェックしている

Page 52: もう、Ruputerは卒業だぁ! SmartWatchアプリを作ろう/すまべん関西#20

52

メイン処理クラス

ControlExtensionクラスpublic final void start()public final void resume()public final void pause()public final void stop()public final void destroy()public void onDoAction(int requestCode, Bundle bundle)public void onDestroy()public void onStart()public void onStop()public void onPause()public void onResume()public void onError(final int code)public void onKey(final int action, final int keyCode, final long timeStamp)public void onTouch(final ControlTouchEvent event)public void onSwipe(int direction)

protected void startRequest()protected void stopRequest()protected void showImage(final int resourceId)protected void showBitmap(final Bitmap bitmap)protected void showBitmap(final Bitmap bitmap, final int x, final int y)protected void setScreenState(final int state)protected void startVibrator(int onDuration, int offDuration, int repeats)protected void stopVibrator()protected void startLedPattern(int id, int color, int onDuration, int offDuration, int repeats)protected void stopLedPattern(int id)protected void clearDisplay()protected void sendToHostApp(final Intent intent)protected long getHostAppId()protected boolean hasVibrator()

Page 53: もう、Ruputerは卒業だぁ! SmartWatchアプリを作ろう/すまべん関西#20

53

メイン処理クラス

WidgetExtensionクラス

public final void startRefresh()public final void stopRefresh()public final void destroy()public abstract void onStartRefresh()public abstract void onStopRefresh()public void onScheduledRefresh()

protected void scheduleRepeatingRefresh(long triggerAtTime, long interval, String extensionKey)protected void scheduleRefresh(long triggerAtTime, String extensionKey)protected void cancelScheduledRefresh(String extensionKey)

public void onDoAction(int requestCode, Bundle bundle)public void onDestroy()public void onTouch(final int type, final int x, final int y)

protected void sendImageToHostApp(final int resourceId)protected void sendToHostApp(final Intent intent)protected void showBitmap(final Bitmap bitmap)

Page 54: もう、Ruputerは卒業だぁ! SmartWatchアプリを作ろう/すまべん関西#20

54

メイン処理クラス

画面を作る例 // Extract the last part of the host application package name. String packageName = mHostAppPackageName .substring(mHostAppPackageName.lastIndexOf(".") + 1);

// Create background bitmap for animation. mBackground = Bitmap.createBitmap(width, height, BITMAP_CONFIG); // Set default density to avoid scaling. mBackground.setDensity(DisplayMetrics.DENSITY_DEFAULT);

LinearLayout root = new LinearLayout(mContext); root.setLayoutParams(new LayoutParams(width, height));

LinearLayout sampleLayout = (LinearLayout)LinearLayout.inflate(mContext, R.layout.sample_control, root); ((TextView)sampleLayout.findViewById(R.id.sample_control_text)).setText(packageName); sampleLayout.measure(width, height); sampleLayout.layout(0, 0, sampleLayout.getMeasuredWidth(), sampleLayout.getMeasuredHeight());

Canvas canvas = new Canvas(mBackground); sampleLayout.draw(canvas);

showBitmap(mBackground);

Bitmapを生成

画面のレイアウトを生成画面のレイアウトを生成

レイアウトに書き込み

レイアウトをBitmapに書き込む

画像を送信するインテントを発行している

Page 55: もう、Ruputerは卒業だぁ! SmartWatchアプリを作ろう/すまべん関西#20

55

メイン処理クラス

画面を作る例 // Extract the last part of the host application package name. String packageName = mHostAppPackageName .substring(mHostAppPackageName.lastIndexOf(".") + 1);

// Create background bitmap for animation. mBackground = Bitmap.createBitmap(width, height, BITMAP_CONFIG); // Set default density to avoid scaling. mBackground.setDensity(DisplayMetrics.DENSITY_DEFAULT);

LinearLayout root = new LinearLayout(mContext); root.setLayoutParams(new LayoutParams(width, height));

LinearLayout sampleLayout = (LinearLayout)LinearLayout.inflate(mContext, R.layout.sample_control, root); ((TextView)sampleLayout.findViewById(R.id.sample_control_text)).setText(packageName); sampleLayout.measure(width, height); sampleLayout.layout(0, 0, sampleLayout.getMeasuredWidth(), sampleLayout.getMeasuredHeight());

Canvas canvas = new Canvas(mBackground); sampleLayout.draw(canvas);

showBitmap(mBackground);

Bitmapを生成

画面のレイアウトを生成画面のレイアウトを生成

レイアウトに書き込み

レイアウトをBitmapに書き込む

画像を送信するインテントを発行している

インテントで画像を送信すると知ったとき、

Page 56: もう、Ruputerは卒業だぁ! SmartWatchアプリを作ろう/すまべん関西#20

56

メイン処理クラス

画面を作る例 // Extract the last part of the host application package name. String packageName = mHostAppPackageName .substring(mHostAppPackageName.lastIndexOf(".") + 1);

// Create background bitmap for animation. mBackground = Bitmap.createBitmap(width, height, BITMAP_CONFIG); // Set default density to avoid scaling. mBackground.setDensity(DisplayMetrics.DENSITY_DEFAULT);

LinearLayout root = new LinearLayout(mContext); root.setLayoutParams(new LayoutParams(width, height));

LinearLayout sampleLayout = (LinearLayout)LinearLayout.inflate(mContext, R.layout.sample_control, root); ((TextView)sampleLayout.findViewById(R.id.sample_control_text)).setText(packageName); sampleLayout.measure(width, height); sampleLayout.layout(0, 0, sampleLayout.getMeasuredWidth(), sampleLayout.getMeasuredHeight());

Canvas canvas = new Canvas(mBackground); sampleLayout.draw(canvas);

showBitmap(mBackground);

Bitmapを生成

画面のレイアウトを生成画面のレイアウトを生成

レイアウトに書き込み

レイアウトをBitmapに書き込む

画像を送信するインテントを発行している

ついに、BinderがBluetoothを超えたか!!

Page 57: もう、Ruputerは卒業だぁ! SmartWatchアプリを作ろう/すまべん関西#20

57

メイン処理クラス

画面を作る例 // Extract the last part of the host application package name. String packageName = mHostAppPackageName .substring(mHostAppPackageName.lastIndexOf(".") + 1);

// Create background bitmap for animation. mBackground = Bitmap.createBitmap(width, height, BITMAP_CONFIG); // Set default density to avoid scaling. mBackground.setDensity(DisplayMetrics.DENSITY_DEFAULT);

LinearLayout root = new LinearLayout(mContext); root.setLayoutParams(new LayoutParams(width, height));

LinearLayout sampleLayout = (LinearLayout)LinearLayout.inflate(mContext, R.layout.sample_control, root); ((TextView)sampleLayout.findViewById(R.id.sample_control_text)).setText(packageName); sampleLayout.measure(width, height); sampleLayout.layout(0, 0, sampleLayout.getMeasuredWidth(), sampleLayout.getMeasuredHeight());

Canvas canvas = new Canvas(mBackground); sampleLayout.draw(canvas);

showBitmap(mBackground);

Bitmapを生成

画面のレイアウトを生成画面のレイアウトを生成

レイアウトに書き込み

レイアウトをBitmapに書き込む

画像を送信するインテントを発行している

そんなことはありませんでした。

Page 58: もう、Ruputerは卒業だぁ! SmartWatchアプリを作ろう/すまべん関西#20

Smart Extension Emulator

を使う

Page 59: もう、Ruputerは卒業だぁ! SmartWatchアプリを作ろう/すまべん関西#20

59

Extensions

エミュレータには、

 Extendions

 Events

 Widgets

 Controls

の4つの画面があります。

登録・動作しているアプリ情報一覧

Page 60: もう、Ruputerは卒業だぁ! SmartWatchアプリを作ろう/すまべん関西#20

60

Extension settings

Menuボタンを押す

→Extension preferences

アプリ一覧が表示される

Page 61: もう、Ruputerは卒業だぁ! SmartWatchアプリを作ろう/すまべん関西#20

61

Extension settings

PreferenceActivityが

呼ばれる

Page 62: もう、Ruputerは卒業だぁ! SmartWatchアプリを作ろう/すまべん関西#20

62

Events

イベントの内容を表示してくれます。

アプリ別にも出せます

Page 63: もう、Ruputerは卒業だぁ! SmartWatchアプリを作ろう/すまべん関西#20

63

Widgets

SmartWatchの

Widget画面

Page 64: もう、Ruputerは卒業だぁ! SmartWatchアプリを作ろう/すまべん関西#20

64

Controls

SmartWatchの

アプリ動作画面

Up Swipeイベント

Down Swipeイベント

Left Swipeイベント

Right Swipeイベント

Pauseイベント

Page 65: もう、Ruputerは卒業だぁ! SmartWatchアプリを作ろう/すまべん関西#20

何、作ろうか?

Page 66: もう、Ruputerは卒業だぁ! SmartWatchアプリを作ろう/すまべん関西#20

66

何、作ろうか

・SmartWatch用 スクリプト

Page 67: もう、Ruputerは卒業だぁ! SmartWatchアプリを作ろう/すまべん関西#20

67

何、作ろうか

・SmartWatch用 スクリプト

・Ruputer エミュレータ

Page 68: もう、Ruputerは卒業だぁ! SmartWatchアプリを作ろう/すまべん関西#20

68

Ruputer エミュレータ

Page 69: もう、Ruputerは卒業だぁ! SmartWatchアプリを作ろう/すまべん関西#20

69

何、作ろうか

・SmartWatch用スクリプト

・Ruputer エミュレータ

・ひとり AR

Page 70: もう、Ruputerは卒業だぁ! SmartWatchアプリを作ろう/すまべん関西#20

70

ひとりAR

Page 71: もう、Ruputerは卒業だぁ! SmartWatchアプリを作ろう/すまべん関西#20

71

何、作ろうか

・SmartWatch用スクリプト

・Ruputer エミュレータ

・ひとり AR

Page 72: もう、Ruputerは卒業だぁ! SmartWatchアプリを作ろう/すまべん関西#20

おしまい