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

Post on 28-May-2015

6.071 Views

Category:

Technology

0 Downloads

Preview:

Click to see full reader

TRANSCRIPT

もう、Ruputerは卒業だぁ!

SmartWatchアプリを作ろう

たろサ(@momoonga)

2

自己紹介

和歌山県有田市

太刀重太刀重

ご当地名産

最近作ったスマホアプリ

最太刀重一丁!

内 容

(1)SmartWatchについて

(2)SmartWatchの開発環境

(3)SmartWatch用アプリの作成

(4)何、作ろうか?

SmartWatch MN2について

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

5

SmartWatch MN2発売

Bluetooth

Android SmartWatch

LiveViewの後継機

6

SmartWatch MN2発売

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

切れ!

7

SmartWatch MN2発売

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

切れ!

8

SmartWatch MN2発売

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

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

9

SmartWatch MN2発売

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

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

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

10

SmartWatch MN2発売

Testanova(発表のみ発売せず)

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

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

11

SmartWatch MN2発売

Testanova(発表のみ発売せず)

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

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

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

12

SmartWatch MN2発売

Ruputer

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

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

13

SmartWatchのスペック

SmartWatch

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

14

SmartWatchのスペック

SmartWatch

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

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

15

SmartWatchのスペック

SmartWatch

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

16

SmartWatchのスペック

SmartWatch

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

確かに小さいです。

17

SmartWatchのスペック

SmartWatch

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

18

SmartWatchのスペック

SmartWatch

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

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ディスプレイは屋外でたいへん見にくいです。

20

SmartWatchのスペック

SmartWatch

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

21

SmartWatchのスペック

SmartWatch

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

CR2025×2

22

SmartWatchのスペック

SmartWatch

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

23

SmartWatchのスペック

SmartWatch

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

リストモの方がブルブル

SmartWatchの開発環境

25

EDK 2.0のインストール

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

26

AVDの作成

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

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

28

AVDの作成

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

29

ASmart Extension Emuの設定

SmartWatchを選ぶ

30

Smart Extension SDKのダウンロード

Smart Extension SDKを選ぶ

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

31

Smart Extension SDKのダウンロード

SmartExtensionAPISmartExtensionUtils

SampleControlExtensionSampleNotificationExtensionSampleSensorExtensionSampleWidgetExtension

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

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

Eclipseにインポートします

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

SmartWatch用

アプリの作成

33

SmartWatchアプリの仕組み

LiveWareマネージャ

SmartWatch

Bluetooth

SmartWatchアプリ(1)

サービスとして常駐

SmartWatchアプリ(2)

SmartWatchアプリ(3)

SmartWatchアプリを管理

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

イベント

画面データ

タッチデータ

34

SmartWatchアプリの仕組み

LiveWareマネージャ

SmartWatch

Bluetooth

SmartWatchアプリ(1)

サービスとして常駐

SmartWatchアプリ(2)

SmartWatchアプリ(3)

SmartWatchアプリを管理

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

イベント

画面データ

タッチデータ

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

35

SmartWatchアプリの仕組み

LiveWareマネージャ

SmartWatch

Bluetooth

SmartWatchアプリ(1)

サービスとして常駐

SmartWatchアプリ(2)

SmartWatchアプリ(3)

SmartWatchアプリを管理

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

イベント

画面データ

タッチデータ

画像のみの送信

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" />

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>

38

プログラムの概要

39

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

・PreferenceActivityクラス 

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

・ExtensionServiceクラス

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

・BroadcastReceiverクラス

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

  ためのクラス

・メイン処理クラス

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

・RegistrationInformationクラス

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

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

40

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

・PreferenceActivityクラス 

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

・ExtensionServiceクラス

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

・BroadcastReceiverクラス

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

  ためのクラス

・メイン処理クラス

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

・RegistrationInformationクラス

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

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

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

41

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

・ControlExtensionクラス 

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

・WidgetExtensionクラス

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

メイン処理のクラス

42

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

・ControlExtensionクラス 

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

・WidgetExtensionクラス

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

メイン処理のクラス

振舞うクラス?

43

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

・ControlExtensionクラス 

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

・WidgetExtensionクラス

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

メイン処理のクラス

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

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

44

プログラムの概要

PreferenceActivityクラスを継承

RegistrationInformationクラスを継承

BroadcastReceiverクラスを継承

ExtensionServiceクラスを継承

メイン処理のクラス

ControlExtensionクラスを継承している

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; } });

}

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(); }}

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を使うか

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))); }}

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

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); }}

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

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マネージャ登録クラス生成

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の画面サイズなどをチェックしている

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()

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)

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に書き込む

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

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に書き込む

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

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

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を超えたか!!

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に書き込む

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

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

Smart Extension Emulator

を使う

59

Extensions

エミュレータには、

 Extendions

 Events

 Widgets

 Controls

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

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

60

Extension settings

Menuボタンを押す

→Extension preferences

アプリ一覧が表示される

61

Extension settings

PreferenceActivityが

呼ばれる

62

Events

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

アプリ別にも出せます

63

Widgets

SmartWatchの

Widget画面

64

Controls

SmartWatchの

アプリ動作画面

Up Swipeイベント

Down Swipeイベント

Left Swipeイベント

Right Swipeイベント

Pauseイベント

何、作ろうか?

66

何、作ろうか

・SmartWatch用 スクリプト

67

何、作ろうか

・SmartWatch用 スクリプト

・Ruputer エミュレータ

68

Ruputer エミュレータ

69

何、作ろうか

・SmartWatch用スクリプト

・Ruputer エミュレータ

・ひとり AR

70

ひとりAR

71

何、作ろうか

・SmartWatch用スクリプト

・Ruputer エミュレータ

・ひとり AR

おしまい

top related