読者です 読者をやめる 読者になる 読者になる

熊小屋日誌

Windows 10 UWPやXamarin, Python、mbed/NetMF/Arduino/Edison, Azureなどぼちぼちと。たまにPCや勉強会、セミナーなどの話題も

Xamarin.Forms入門中~UWPアプリのライブタイルの置き換え①~

Windows 10 UWPアプリのタイル通知を、Androidではウィジェットに置き換える方法を調べてたので、そのメモ。

XamarinでのAndroidウィジェット作成

作成方法

調べた範囲では、プラットフォーム固有機能のAndroidウィジェットは Xamarin.Formsで作成できなくて、公式サンプルのSimple Widgetのように、Xamarin.Androidで作成できる模様。

サンプルの構成

重要なファイルは以下の模様。

  • Resources/xml/widget_word.xml

ウィジェットの設定をするファイル。更新間隔はandroid:updatePeriodMillisで指定する。

<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
    android:minWidth="294dip"
    android:minHeight="72dip"
    android:updatePeriodMillis="86400000"
    android:initialLayout="@layout/widget_message" />
  • Resources/layout/widget_word.xml

ウィジェットのレイアウトを定義するファイル。

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/widget"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:focusable="true"
    style="@style/WidgetBackground">
    <ImageView
        android:id="@+id/icon"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:src="@drawable/star_logo" />
   ...
</RelativeLayout>
  • WordWidget.cs

Android.Appwidget.AppWidgetProviderを継承したクラスで、更新時に呼ばれるOnUpdateを定義。更新処理はAndroid.App.Serviceを継承したUpdateServiceで実装している。

using System;
using Android.App;
using Android.Appwidget;
using Android.Content;

namespace SimpleWidget
{
    [BroadcastReceiver (Label = "@string/widget_name")]
    [IntentFilter (new string [] { "android.appwidget.action.APPWIDGET_UPDATE" })]
    [MetaData ("android.appwidget.provider", Resource = "@xml/widget_word")]
    public class WordWidget : AppWidgetProvider
    {
        public override void OnUpdate (Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds)
        {
            // To prevent any ANR timeouts, we perform the update in a service
            context.StartService (new Intent (context, typeof (UpdateService)));
        }
    }
}
  • UpdateService.cs

Android.App.Serviceを継承している。OnStartで更新処理を実装。

f:id:kumar:20161201072941p:plain:w300

Xamarin.Formsとの共存

新しいプロジェクトの追加>Visual C#>Windowsから"クラスライブラリ(iOS、Android、Windowsのポータブル)"を選択して追加したPCLを、Xamarin.Androidから参照して利用できるので、Xamarin.Formsで作成するアプリ本体とXamarin.Androidのウィジェットで共通利用するライブラリの実装は問題なさそう。

f:id:kumar:20161130073630p:plain:w300

詳しい検証は週末にコードを書いて検証してみます。

データの更新方法

Resources/xml/widget_word.xmlで指定した時間間隔で定期的に呼ばれてウィジェットを更新するのですが、UWPのライブタイルのようにアプリからデータを更新したいのですが、それは調査中です。

Androidアプリの一般的な話になると思うので、程なく情報を見つけられそうです。

Xamarin.Forms入門中~ソリューション作成~

Xamarin Visual Studio 2015

Windows 10 MobileとAndroidの両方にアプリをリリースできるよう、Xamarin.Formsを学習してます。 その学習で得たことを書いていきます。

ソリューションの作成

新しいプロジェクト>テンプレート>Visual C#>Prismから"Prism Unity App (Xamarin.Forms)"を選択する。

f:id:kumar:20161130073233p:plain:w300

表示されない場合、Xamarin.Forms Templateの拡張機能が必要かも。

f:id:kumar:20161130074116p:plain:w300

ライブラリの追加

アプリから共通に使うライブラリは、PCLとして追加する。新しいプロジェクトの追加>Visual C#>Windowsから"クラスライブラリ(iOS、Android、Windowsのポータブル)"を選択する。

f:id:kumar:20161130073630p:plain:w300

これをXamarin.Formsアプリの共通ライブラリプロジェクトから参照すればよいが、このままではエラーが出るので、ターゲットを合わせる必要がある(Silverlightを追加)

f:id:kumar:20161130073444p:plain:w300

Xamarin.Forms入門中~IntelliSenseを使う方法~

Xamarin Visual Studio 2015

Windows 10 MobileとAndroidの両方にアプリをリリースできるよう、Xamarin.Formsを学習してます。 その学習で得たことを書いていきます。

IntelliSenseを使う方法

Visual Studio 2015 Update3で作成したXamarin.Forms(v2.3.3.168)のソリューションで、XAMLでのIntelliSenseが効かなくて困ってたのですが、Twitterでぼやいてたところ、こんな返事が。

早速試してみました。

f:id:kumar:20161129202112p:plain:w350

f:id:kumar:20161129201826p:plain:w350

f:id:kumar:20161129201831p:plain:w350

たしかにIntelliSenseが使えます。

田淵さんのツイートをみるに、Xamarinのバグなのかもしれません。

GR-CITRUSのワークショップに参加して

GR-CITRUS

11月19日に豊洲のルネサス半導体トレーニングセンターにて、GR-CITRUS発売記念のワークショップに参加してきました。

gadget.renesas.com

当日は、GR-CITRUSと、WiFiとSDカードスロットを搭載した拡張モジュールのWA-MIKAN、あと温度などのセンサーを借りて、GR-CITRUSでのプログラミングを体験しました。その感想と、今後やりたいことをまとめてみます。

f:id:kumar:20161119140318j:plain:w250

GR-CITRUSの機能

GR-CITRUSのピン配置を見ると、シリアル4個/I2C 5個/SPI1個(共用あり)、あとアナログ入力4ピン/アナログ出力7ピン/デジタル入出力が20ピン(共用あり)と入出力端子はこれで十分かなと思います。

f:id:kumar:20161127140618p:plain:w250

GR-CITRUSに書き込んだプログラムは、ボード上のジャンパーをショート(ハーフピッチのスイッチを取り付けると便利なようです)させるとPCから切り離して動作させられるようです。

開発環境

GR-CITRUSのプログラミングは3種類あるようです。

  1. WebコンパイラでのArduinoスケッチ開発

  2. IDE for GRでのオフラインでのArduinoスケッチ開発

  3. Rubicを使ったmrubyでの開発

今回は3番目のRubicを使った開発が主でしたが、mrubyを使って非常に手軽に開発できたのが印象的でした。

以下は、照度センサーから読み取ったアナログ値をRubicのログ欄に表示するスクリプトですが、ピンへのアクセスが直感的ですし、Rubyの言語機能を使えばデータの処理も楽そうに思いました(まだ複雑な処理を実装していませんが)。

#!mruby
usb = Serial.new(0)
pinMode(14, 2) #INPUT_PULLUP
100.times do
    usb.println(analogRead(14).to_s)
    delay(100)
end

Wi-Fiへのアクセスも標準で用意されていて、WA-MIKANを使ってIFTTTと連携したりして、GR-CITRUSの応用できる範囲は広そうです。

#!mruby

pinMode(5,1)
digitalWrite(5,0) # LOW:Disable
delay 500
digitalWrite(5,1) # LOW:Disable

Usb = Serial.new(0,115200)
if( System.useWiFi() == 0) then
    Usb.println "WiFi Card can't use."
    System.exit() 
end

Usb.println WiFi.disconnect
Usb.println WiFi.setMode 3
Usb.println WiFi.ipconfig
Usb.println WiFi.connect("ap-xxxxxx","abcdefgh")
Usb.println WiFi.ipconfig
Usb.println WiFi.multiConnect 1
Usb.println WiFi.httpGet("maker.ifttt.com/trigger/citrus/with/key/xxxxx").to_s
Usb.println WiFi.disconnect

これ以外にも、GR-CITRUS特設クラス、メソッド早見表にあるように、I2C、サーボ、RTC、SDカードにアクセスする手段も用意されていて、外部のモジュールを操作したり、IFTTTと連携したりして、いろいろと面白いことができそうです。

個人的にはmbedをよく使っていて、オンラインコンパイラもしくはオフラインの開発環境でC++を使ったプログラミングに慣れていますが、mrubyでの開発も面白いかもしれません。

ワークショップの内容

ワークショップは大きく3つに分かれていて、GR-CITRUS特設サイトの解説ワークショップ進行のガイドを見て、ガイダンスを受けながら進めていきました。解説がしっかり書かれているので、ガイダンスなしでも進めていける内容でした。

  1. GR-CITRUSのmrubyプログラミング → mrubyプログラミング環境の設定、文法学習、Lチカ

  2. センサーネットワークを作ってみる → センサーの読み取り(I2Cとか)、IFTTT

  3. MP3プレーヤー作成デモ+自由時間 → Webコンパイラを使っての作業

センサーの利用はArduinoやmbedと変わらないなという印象です。

f:id:kumar:20161119151133j:plain:w250

(左から照度、温湿度、加速度、角速度、地磁気センサ)

f:id:kumar:20161119154458j:plain

(温度センサーで温度・湿度を取得中)

時間の都合で最後のMP3プレーヤーはやり切れなかったですが、時間があるときに続きをしようかと思います。

今後やりたいこと

ワークショップでやったこと(Lチカ、センサー、IFTTT、MP3(スピーカ出力、SDカード))以外で何かを作ろうと考えてましたが、まずはLCDでの表示(文字、グラフィックそれぞれ)でしょうか。

GR-CITRUSを単独で動作するガジェットにしたとき、状態の表示にLEDが使えますが、より細かい情報を表示するためにLCDを使いたくなります。

LCDの操作はmrubyには用意されていないので、Webコンパイラで提供されているLiquidCrystalライブラリを使うことになりそうですが、手持ちのキャラクタLCD(ACM1602NI-FLW-FBW-M01)がI2C接続なので、ライブラリを少しいじる必要がありそうです。

時間があればmrubyにLCDアクセスを組み込むことができるのか調べてみようかと思います。

FalconでWeb API開発

Python Falcon

先日にWeb APIを実装したとき、FalconというPython向けのWebフレームワークを使ったのでメモ。

falconframework.org

Flanconを使った感想は、Web APIの処理の実装に集中できる、でしょうか。 PythonでWebアプリを実装するとき、Flask、BottleなどのWebフレームワークを使うのですが、これらのWebフレームワークはWeb APIには不要な画面表示のテンプレートを扱う機能が含まれています。

FlanconはWeb APIに特化していて、処理の実装に集中できるのが特徴です。

Flanconでの実装例

FalconはHTTP verbに応じたメソッド(on_get, on_post, ...)を定義して、 引数のHTTP requestを処理して引数のHTTP responseに結果を返す処理を記述します。

例えば、JSONデータを返すGETメソッドを定義した例が以下になります。 GETメソッドの記述だけを考えればいいので、見通しがよく、書きやすいです。

# -*- coding: utf-8 -*-
import falcon
import json

class HelloAPI:
    def on_get(self, req, resp):
        resp.status = falcon.HTTP_200
        result = { 'message':'hello world', 'lang':'en' }
        resp.body = json.dumps(result)

api = falcon.API()
api.add_route('/hello', HelloAPI())

FalconのAPIはWSGIサーバで実行できるので、実行するときはgunicornなどを使って

$ pip install falcon
$ pip install gunicorn
$ gunicon hello:api 

とすれば動きます。 Windowsではgunicornがfcntlモジュールの問題で動作しないため、waitressを使う方法があります。

> pip install waitress 
> waitress-serve hello:api
Serving on http://DESKTOP-A9B9C9D:8080

curlコマンドなどでGETアクセスしてみると、実装した通りJSONデータが帰ってくるのが分かります。

$ curl -XGET http://localhost:8080/hello
{"message": "hello world", "lang": "en"}

POST/PUT/DELETEやファイルなどのデータの処理はまた別途まとめます。

Xamarin Dev Days Tokyoに参加してきて~Please install packageエラー

Xamarin

Xamarin Dev Days Tokyoに参加してきました。午前中はXamarinやXamarin.Formsの概要についてのセッション、午後は課題を各自で解くハンズオンでした。

Xamarinは以前にもハンズオンに参加して簡単なアプリを作ったことがあるのですが、それ以降アプリの作成時間が取れず放置してました。

今日のXamarin Dev Days Tokyoに参加して、Xamarin、特にXamarin.Formsでアプリを作る方法が掴めたように感じます。 Android版を出したいと思っていたアプリがいくつかあるので、そろそろXamarinのプロジェクトを起こして、開発を進めていこうかと思います。

Please install packageエラー

今日のハンズオンではまっていたことを。

正確な発生条件を把握してないのですが、初回のビルド時にAndroid版のプロジェクトをビルドするために、Classファイルが含まれたZIPファイルをダウンロードするようです。

そのサイズが200MBあって、ビルドを開始してからVS2015の出力に何も表示されない状況がしばらく続いて、ついキャンセルしてしまったのですが、それ以降、ビルドをすると"Please install package: 'Xamarin.Android.Support.…' available in SDK installer"というエラーが大量に出て失敗する現象が発生しました。

これは、ダウンロード中だったZIPファイルが不完全な状態で残っていて、そこから必要なClassファイルを取得できないことが原因でした。

後から詳しく調べてみたら、田淵さんのブログにこの現象と対応策が書かれていました。

Xamarinの開発環境の準備

Xamarin VS2015

11/12(土)に開催されるXamarin Dev Days Tokyoでハンズオンがあるため、6月に購入した新ノートPCにXamarinの開発環境を整備してました。

前のVaio Duo 11には構築してあったのだけど、すっかり移行を忘れてました。

そろそろAndroidとWindows 10 UWPの両プラットフォームにXamarinを使ってアプリを出していく予定なので、ちょうどよい機会でした。

参考にしたドキュメント

Xamarinの開発環境の設定手順は、田淵さんが以下で公開されているドキュメントが分かりやすいと思います。

XamarinHOL/XamarinHandsOn_Prepare_JXUG.pdf at master · ytabuchi/XamarinHOL · GitHub

Xamarinのセットアップ、かなり前にAndroid SDKをVSから起動するとSDKをDLできない(Program Files配下なので)トラブルがあったような記憶があるのだけど、今は権限を変えて起動してるようで問題ないですね。

自分がはまったポイント

(1) AndroidプロジェクトのビルドでUnsupportedClassVersionErrorエラー

これはJava8のSDKをインストールすると解消しました。 Android SDKの新しいバージョンだとJava8が必要のようです。

(2) Java8 SEをOracleのサイトからダウンロードしようとすると、Due to your country location, we are unable to process your request.とエラーが出てダウンロードできない。

これは、OracleのWebサイトの問題だったようで、翌日には解消されていました。

(3) VS2015でソリューションを新規作成したとき、XamarinのBlank、Portable Formsを選択したとき、WinPhoneとWindowsのサブプロジェクト作成でエラーダイアログが出る。

f:id:kumar:20161112104103j:plain:w250f:id:kumar:20161112104108j:plain:w250

これはUWPのプロジェクトでNuGetパッケージの管理を実行して、パッケージを更新したら解消しました。

f:id:kumar:20161112104111j:plain:w300

無事にAndroidアプリをデプロイ

Nexus5xはGoogle USB DriverでPCにUSBデバッグで接続できました。

作成したXamarinソリューションのコードを変更せずそのままビルドして、アプリをデプロイして実行すると…

f:id:kumar:20161112104114j:plain:w300

無事にAndroidアプリを実行できました。