IonicでCrosswalk

IonicがCrosswalkに対応しました。
Crosswalk comes to Ionic

Crosswalkを組み込んでbuildを行うと、アプリ内にレンダリングエンジンを持つことができます。
通常、WebViewをレンダリングするのに、端末のデフォルトのレンダリングエンジンが使われます。しかし、OSのバージョンごとにレンダリングエンジンの振る舞いが微妙に違います。また、古いOSだと最新のものと比べてレンダリング速度が遅いです。
Crosswalkは、高速なレンダリングエンジンBlinkを搭載しており、それらの問題点を改善できます。
ただし、Crosswalkが対応しているのはandroid4.x以降だけです。iOSおよび古いandroidは未対応です。

既存のandroidアプリにCrosswalkを組み込んでみました。

IonicにCrosswalkを組み込むのは、すごく簡単です。
Ionicのプロジェクトディレクトリ直下で以下を実行するのみです。

ionic browser add crosswalk

ただこれだと、古いバージョンのCrosswalkが組み込まれてしまったので、バージョンを指定して以下のように実行しました。

ionic browser add crosswalk@10.39.235.15

注意すべきなのは、これを実行するとplatformsディレクトリ以下を大きく書き換えてしまいます。あらかじめ、プロジェクトディレクトリのバックアップを取っておくとか、バージョン管理で元に戻せるようにしておく必要があります。

で、build&installします。

ionic run android

作成されたapkファイルを見ると、Crosswalk非搭載の時はapkファイルが8MBだったのに、40MBもありました。

BUILD_MULTIPLE_APKS=true ionic build android

とやると、x86とARMそれぞれのapkが生成され、サイズは25MB程度でした。

アプリを実行します。実行端末はXPERIA Z1(android4.4.2)です。
読み込みに時間がかかるので、起動が若干遅くなっています。

他、気づいた点

  • 今まで<input type=date>にあった以下の不具合がなくなった

    • 値をセットしているにもかかわらず、datepickerのデフォルト値が今日の日付
    • datepickerの枠外をクリックし表示を消した後、再度datepickerを表示できない
  • スプラッシュスクリーンが出なくなった
  • 今までファイルのアップロードができていたのに出来なくなった(何でだろう)

結構、変わっています。
速度的には、どうだろう・・・。少なくとも劇的には速くなってないですね。

Facebooktwitterlinkedintumblrmail

Socket.IO:マルチプロセスのnode.jsで、Roomに入室したクライアント一覧を取得する

チャット等で、Roomに誰が入室しているのかを知る際の方法です。
Roomに入室したクライアント(socket id)一覧の取得は、socket.io 1.0以降では以下で取得できます。

io.nsps[yourNamespace].adapter.rooms[roomName]

ただしnode.jsをマルチプロセスで実行している場合、自プロセス以外のクライアント一覧は取得できないです。
そのためRedisのKVSを使い、以下のようにしました。

1.Roomに入室:
 RedisのKVSに、各プロセス毎に、各ルームに入室したクライアント(socket id)一覧をセット

redisClient = redis.createClient(redisPort, redisIp, {})
process_name = localIp + 'p' + port # プロセス名:プロセスのIPとポート番号を結合した文字列

#
# socketをroomにjoinし、且つRedisにsetする
#
join = (socket, room)->;
  socket.join room    # socketをroomにjoin
  key = room + ':' + process_name

  value = []
  if io.of('/').adapter.rooms[room]?
    for socketId of io.of('/').adapter.rooms[room]
      value.push socketId
  redisClient.set key, JSON.stringify(value) # JSONの文字列として値をセット
  
 
roomName = 'works#' + work_id
join socket, roomName

下記のような感じでRedisにセットされます。

redis 127.0.0.1:6379[1]> keys *
1) "users#558:10.0.2.15p1338"
2) "works#1016:10.0.2.15p1337"
3) "works#1016:10.0.2.15p1338"
4) "users#10:10.0.2.15p1337"
redis 127.0.0.1:6379[1]> get works#1016:10.0.2.15p1337
"[\"1ZFRYWVeyrMPaiqOAAAD\"]"
redis 127.0.0.1:6379[1]> get works#1016:10.0.2.15p1338
"[\"vuturxDpPBL2ZHuLAAAK\"]"

2.クライアント一覧を取得:
 RedisのKVSからワイルドカードを使ったkeysコマンドで該当するキーをすべて取得後、mgetコマンドで値を取得

#
# roomIDからsocket.idのリストを取得し、コールバック関数実行
#
clients = (room, cb, opts) ->
  key = room + ':*'
  redisClient.keys key, (err, replies)->
    redisClient.mget replies, (err, vals)->
      socketIds = []
      for val in vals
        socketIds = socketIds.concat JSON.parse val
      cb(socketIds, opts)


roomName = 'works#' + work_id
clients roomName, (socketIds)->
  console.log 'Roomに入室しているクライアント一覧:' + socketIds.join(',')

3.Roomから退室:
 RedisのKVSの値を変更または削除

#
# socketをroomからleaveし、且つredisにsetする
#
leave = (socket, room)->
  socket.leave room
  key = room + ':' + process_name

  value = []
  if io.of('/').adapter.rooms[room]?
    for socketId of io.of('/').adapter.rooms[room]
      value.push socketId
  if value.length > 0
    redisClient.set key, JSON.stringify(value)
  else
    redisClient.del key

roomName = 'works#' + work_id
leave socket, roomName

一応これで実現可能ですが、クライアント一覧取得するためだけにredisのKVSを使うというのは、無駄にリソースを使っている感じであまりいい方法ではないように思います。

また、以下のような感じでプロセス終了時にredisのデータを全て削除する必要があります。

for signal in ['SIGINT', 'SIGHUP', 'SIGTERM']
  process.on signal, ->
    key = '*:' + process_name
    redisClient.keys key, (err, replies)->
      async.each replies, (reply)->
        redisClient.del reply
      process.exit 1
      return

もっといい方法があれば、誰が教えて頂けたらと思います。

Facebooktwitterlinkedintumblrmail

RoundCube1.0で追加されていたCanned Responses

定型文的な使い方を想定していると思われる、Canned Responsesと言う機能が1.0辺りで追加されたようです。メール作成画面の署名の隣に回答が見えると思います。

canned_response01

※言語を英語に設定しているとResponsesと表示されます。

この投稿の続きを読む »

Facebooktwitterlinkedintumblrmail

Android-ProgressDialogFragmentというライブラリを作りました。

1.Android-ProgressDialogFragmentというライブラリを作りました。
https://github.com/YuichiUchida/Android-ProgressDialogFragment
 ロード中はこういう感じになります。
1

2.今まではこういう感じに作っていました。
2
ListFragmentなどがこういう実装になっていますね。

この方式は下の画像のように2つの画面を重ね
ロード中にはコンテンツ部分を消し、プログレス画面を表示し、
ロードが終るとコンテンツを表示し、プログレス画面を消すという方式になっています。
3

長所としては、できあがった奇麗な画面だけを表示できることですが
たくさんの画面に使うと動作が重く感じるようになってきます。

このライブラリは、やり方はほとんど同じですが
コンテンツ部分を常に表示し、プログレス画面だけを制御します。

3.使い方
Gradleに下記のように追記します。

support-v4ライブラリを使う場合

dependencies {
    compile 'me.yuichi0301:pdfragment:1.1.+'
}

ライブラリを使用しない場合

dependencies {
    compile 'me.yuichi0301:pdfragment-native:1.1.+'
}

あとはProgressDialogFragment継承して使用します。

public class SampleFragment extends ProgressDialogFragment {
    // your code of fragment
}

ActionBarSherlockを使う場合

dependencies {
    compile 'com.android.support:support-v4:21.0.3'
    compile('me.yuichi0301:sherlockpdfragment:1.1.+') {
        exclude module: 'support-v4'
    }
}
public class SampleFragment extends SherlockProgressDialogFragment {
    // your code of fragment
}
Facebooktwitterlinkedintumblrmail

Mac基本のキ:アプリを32ビットモードで起動する

仕事始めの朝に食らいまいした。あけましておめでとうございます。

今回のように64ビットアプリでトラブルにあったときに32ビットモードで起動すると回避出来たりすることがありますので覚えておくといいことがあるかもしれません。

そして忘れてずっと32ビットモードで暮らしてしまうかもしれません。使えないよりはいいですけどね。

設定方法はつぶやいてるとおりですが、わかりやすいようにキャプチャとってみました。

contextMenu

右クリックして「情報を見る」

Thunderbird_app_の情報

そして「32ビットモードで開く」にチェック。

Facebooktwitterlinkedintumblrmail

雑用係、来年もよろしくお願いしますm(_ _)m

文書を作る。
雑用係の仕事のひとつです。

法律用語とか雑用係にはよくわかりません。
仕事してる人なら当たり前に使うビジネス用語も使い分けに苦労します。
難しいです。
高卒の上に、高校ではデザインなんか勉強してたので、高3の頃なんか授業に理科系科目すらありませんでした(笑)

強いて言えば、本読みが好きなのと、小説家を目指していた黒歴史(´д`)があるので、一時期文章の勉強してたり、昔から割と平均的な読解力はあった方なので、なんとかやってます。

てことで。
言葉のマジックを少々。

この投稿の続きを読む »

Facebooktwitterlinkedintumblrmail

Jenkinsでphpcsする。

1.今回は、Jenkinsでphpcsを使う手順を書いていきます。
  最近CakePHPの仕事をやっているのでcakephp-codesnifferを使用します。

2.phing、phpcs、cakephp-codesnifferのインストール
  とりあえず、以下の作業はjenkinsユーザーで行いました。
  phing、phpcsのインストール
  phpcsはphingと一緒に入ります。

composer global require 'phing/phing:2.*'

  cakephp-codesnifferのインストール

composer global require 'cakephp/cakephp-codesniffer'

  全ユーザーでコマンドを使えるように/etc/profileに以下の行を追加
  (composer globalだと対象ユーザーのホームの.composerにインストールされます。)

export PATH="$PATH:/var/lib/jenkins/.composer/vendor/bin"

  phpcsでcakephp-codesnifferを使えるようにします。

/var/lib/jenkins/.composer/vendor/bin/phpcs --config-set installed_paths /var/lib/jenkins/.composer/vendor/cakephp/cakephp-codesniffer

  以下のコマンドでCakePHPが表示されればOKです。

phpcs -i

3.phingの設定
  Jenkinsの管理→システムの設定を押下
  Phingの追加を押下し、以下のように入力します。
5

4.Jenkinsのプラグインのインストール
  以下のプラグインをインストールします。
  Checkstyle Plugin
  Phing Plugin
  PHP Plugin
  Git Plugin

5.ジョブの実行手順
  ①gitでプロジェクトを取得
  ②phingでphpcsを実行

  プロジェクトの構成は以下のようになります。
4
  appがCakePHPのプロジェクトディレクトリで
  build.xmlがphingのbuildファイル
  buildディレクトリにphpcsの設定ファイルを入れています。

  phingのbuildファイルは以下のようにしました。
build.xml




    
    
    
    

    
    

    
    
        
            
            
            
            
        
    


  上記の設定の場合次のコマンドを実行するのと同じになります。

phpcs --standard=${basedir}/build/phpcs.xml --report=checkstyle --report-file=${logdir}/phpcs-report.xml ${appdir}

  変数を展開すると以下のような感じ

phpcs --standard=/var/lib/jenkins/jobs/phpcs-test/workspace/build/phpcs.xml --report=checkstyle --report-file=/var/lib/jenkins/jobs/phpcs-test/workspace/build/logs/phpcs-report.xml /var/lib/jenkins/jobs/phpcs-test/workspace

phpcsの設定ファイルは以下のようにしました。
phpcs.xml




    
    

    
    *database.php
    *i18n.php
    *core.php
    */app/Config/*
    */app/Console/*
    */app/Lib/*
    */app/Plugin/*
    */app/tmp/*
    */app/Vendor/*
    */app/webroot/*
    */app/Test/*
    */app/View/Helper/*
    

6.新規ジョブの作成
  新規ジョブ作成を押下します。
  ジョブ名を入力し、「フリースタイル・プロジェクトのビルド」を選択します。
  ソースコード管理を設定後、ビルド手順の追加で「Phingの呼出し」を選択します。
1
  使用するPhingでmyphingを選択
  Phingの呼出しに「phpcs」と入力します。
6
  設定ファイルとの関連は次のようになります。
7

7.試してみる
  以下のようにメソッドを追加してビルドを試してみます。

log('hoge', LOG_DEBUG);
}
}

以下のように出力されました。
8

コメントでhogeと@return voidの間に1行必要
hoge(){でhoge()と{の間にスペースが必要とでています。

難しい・・。

8.sublime-phpcsを使ってみる
  package controllでPhpcsをインストールします。
9

  ローカルで以下のコマンドを実行します。

composer global require 'phing/phing:2.*'
composer global require 'cakephp/cakephp-codesniffer'
~/.composer/vendor/bin/vendor/bin/phpcs --config-set installed_paths ~/.composer/vendor/bin/vendor/cakephp/cakephp-codesniffer

Preferences→Package Settings→PHP Code Sniffer→Settings – Userと開きます。
以下のように記述します。

{
"phpcs_executable_path": "/ユーザーのホームディレクトリ/.composer/vendor/bin/vendor/bin/phpcs",
    "phpcs_additional_args": {
        "--standard": "CakePHP"
    },
}

これでだめなところを表示してくれるようになりました。

11

Facebooktwitterlinkedintumblrmail

iOSでプッシュ通知時の挙動を確認したい

今回はiOSアプリを開発している際にプッシュ通知時の挙動を確認したい時に使えそうな「houston」というライブラリを紹介したいと思います。

nomad/houston

1. インストール

gem install houston

2. 送信用のrubyファイルを用意

ほぼREADMEにあったサンプルの通りのものです。
また、事前に開発用の「push_dev.pem」を同じディレクトリに置いています。

push.ruby

require 'houston'

# Environment variables are automatically read, or can be overridden by any specified options. You can also
# conveniently use `Houston::Client.development` or `Houston::Client.production`.
APN = Houston::Client.development
APN.certificate = File.read("push_dev.pem")

# An example of the token sent back when a device registers for notifications
token = "<《ここにプッシュ通知を送信したい端末のデバイストークンを指定します》>"

# Create a notification that alerts a message to the user, plays a sound, and sets the badge on the app
notification = Houston::Notification.new(device: token)
notification.alert = "ハロー, ワールド!"

# Notifications can also change the badge count, have a custom sound, have a category identifier, indicate available Newsstand content, or pass along arbitrary data.
notification.badge = 1
notification.sound = "sosumi.aiff"
notification.category = "INVITE_CATEGORY"
notification.content_available = true
notification.custom_data = {foo: "bar"}

# And... sent! That's all it takes.
APN.push(notification)

3. push通知を送信

ruby push.ruby

以上で、指定した端末にプッシュ通知が飛びます。
READMEにはデバイストークンの取得方法や証明書の作成方法なども載っておりすごく分かりやすいです。
この他にもコマンドラインからプッシュ通知を送信することが出来るようです。

apn push "<デバイストークン>" -c /path/to/apple_push_notification.pem -m "Hello from the command line!"
Facebooktwitterlinkedintumblrmail

GradleでAndroid部品を社内共有しよう!

1.はじめに
  Androidの開発をやっていると、前のプロジェクトで使った部品を次のプロジェクトでも
  使いたいなんてことがでてくると思います。しかし、公開されているリポジトリに
  登録できるような内容の部品じゃないということはよくあると思います。
  ということで、社内のリポジトリにGradleでAndroid部品を共有する内容を書いていきます。

2.手順
  ①gitlabにリポジトリを作成(社内ではgitlabを使っているため)
  ②ライブラリプロジェクトを作成し、AARをリポジトリに登録
  ③②のライブラリを使うプロジェクトの作成

3.gitlabにリポジトリを作成
  テスト的にこういう画像のカスタムビューを持つライブラリにします。
  ということでプロジェクト名は「Android-BaseLine」にしました。
  1

4.BaseLineライブラリを作成します。
  EclipseだとAARが使えないためAndroid Studioを使用します。

5.BaseLineViewはこんな感じ

package com.lancard.baseline;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.View;

public class BaseLineView extends View {

    public BaseLineView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        Paint paint = new Paint();
        paint.setColor(Color.rgb(0, 49, 236));
        //paint.setStrokeWidth(5);

        int height = getHeight();
        int width = getWidth();

        int y = 0;
        while(y

6.AAR作成用にbuild.gradleを書きます。
  ここのbuild.gradleになります。
2

元のソース

apply plugin: 'com.android.application'

android {
    compileSdkVersion 21
    buildToolsVersion "21.1.1"

    defaultConfig {
        applicationId "com.lancard.baseline"
        minSdkVersion 18
        targetSdkVersion 21
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        release {
            runProguard false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
}

次のように書き換えます。

apply plugin: 'android-library'
apply plugin: 'maven-publish'

android {
    compileSdkVersion 21
    buildToolsVersion "21.1.1"

    defaultConfig {
        applicationId "com.lancard.baseline"
        minSdkVersion 18
        targetSdkVersion 21
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        release {
            runProguard false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
}

android.libraryVariants
publishing {
    publications {
        maven(MavenPublication) {
            groupId 'com.lancard.lib'
            artifactId 'baseline-aar'
            version '1.0'
            artifact source: file("${project.buildDir}/outputs/aar/${project.name}-release.aar")
        }
    }
    repositories {
        maven {
            url "file:${projectDir}/maven-repo"

        }
    }
}

  <やっていること>
  ①apply plugin: 'com.android.application'→apply plugin: 'android-library'で
   アプリケーションプロジェクトからライブラリプロジェクトに
  ②apply plugin: 'maven-publish'を追加しMaven Publishプラグインを使えるようにする。
  ③ publishingを追加し、公開するファイルの設定をします。

  (ちなみにURLはリポジトリ管理ツールで運用されていれば
    直接転送できgit pushする必要はありません。)

7.Gradleのタスクを実行します。
  Maven Publishプラグインを使用すると、「maven(MavenPublication) 」の名前から
  publishMavenPublicationToMavenRepositoryというタスクができるので実行します。
3

  以下のようにmaven-repoというディレクトリができますので全て
  3.で作成したgitリポジトリにpushします。
4

  このようになったでしょうか。
5

8.BaseLineViewを使うプロジェクトを作成し、build.gradleを以下のように追記し、buildタスクを実行します。

apply plugin: 'com.android.application'

android {
    compileSdkVersion 21
    buildToolsVersion "21.1.1"

    defaultConfig {
        applicationId "com.lancard.hoge"
        minSdkVersion 18
        targetSdkVersion 21
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        release {
            runProguard false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
    lintOptions {
        abortOnError false
    }
}

repositories {
    maven {
        url "https://{社内gitlab}/{username}/android-baseline/raw/master/maven-repo"
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.lancard.lib:baseline-aar:1.0'
}

lintはとりあえず、オフにしています。

9.以下のように「com.lancard.baseline.BaseLineView」を使用するxmlを書いて実行できれば成功です。



    


10.バージョンがあがっていくとリポジトリはこのようになります。

6

11.SSLクライアント認証している場合
  社内のリポジトリがSSLクライアント認証している場合が多いと思います。
  SSLクライアント認証している場合は、gradleラッパーのJVMオプションで
  証明書のパスを設定する必要があります。
  プロジェクト配下にあるgradlewのDEFAULT_JVM_OPTSを以下のように書き換えます。

7

DEFAULT_JVM_OPTS=" \
-Djavax.net.ssl.keyStore=証明書のパス \
-Djavax.net.ssl.keyStoreType=pkcs12 \
-Djavax.net.ssl.keyStorePassword=証明書のパスワード \
"

  あとはgradleコマンドではなくgradlewを実行するようにします。

./gradlew build
Facebooktwitterlinkedintumblrmail

雑用係、OSX Yosemiteインストールに苦戦する

雑用係、生意気にもMac使いです(´∀`)

IMG_6637
※ 職場の机はMacBookAir11と私物のiPadAirでこんな感じ。自宅はPro15。某マンガ&アニメキャラは無視してね。

もちろん、Yosemiteがリリースされてからサクッとアップデートしました。
んまー、フラットデザインけっこーイケるわぁーなんてホクホクしてました。

でもって、あまり機械モノが得意じゃない友人にも毎度のことと「とりあえず無料だから、今回もちゃんとアップデートしとけよ〜」と言ってしまったのが、題目の原因です(×_×)

メッセがきました。
友人A「インストール失敗しました、って、でるんだけど」

でるんだけど、と言われましても、失敗したことないので、雑用係には原因が全くわかりません。そもそも、私は単なる雑用係であって我が社の精鋭技術者のようなスキルはないんですYO!

メッセや電話で、どういう状況なのか、あれやってみてー、これやってみてーとやれども、同様の状況になったことのない雑用係は、何が一体どうなってるのかサッパリぽんです(´・ω・`)

仕方ないので、休みの日に友人Aの家へ出向きました。
奮闘の始まりです(´д`)

この投稿の続きを読む »

Facebooktwitterlinkedintumblrmail