ページ

2016年4月29日金曜日

PhoneGapを使用する 2 - PhoneGap + Grunt で自動化 -


最近仕事でお世話になっているPhoneGap
タイトルがPhoneGapを使用する 2 となってますが、
実は随分前にPhoneGapを触っていた事があります。
その時から全然触ってなかったら、npmのバージョンが
$ npm -v
1.4.28
古い・・・古いすぎる!!
早速バージョンアップ
$ npm update -g npm
$ npm -v
3.8.7
すごいバージョンの差 ^^;
そんなこんなで今回はPhoneGapをタスクツールのGruntと
組み合わせてやってみたいと思います。

ちなみに・・・

PhoneGapと並んでよく出てくるワードでCordovaというのがあります
両者の違いですが、公式のFAQでは
PhoneGap is an open source distribution of Cordova. Think about Cordova’s relationship to PhoneGap like WebKit’s relationship to Safari or Chrome.
となっています。
CordovaをWebkitに例えるならば、PhoneGapはWebKitから派生したSafariやChromeみたいなもので、PhoneGapはCordovaを内包してるようなイメージです。
実際、PhoneGapはCordovaの全ての機能が使えます。

環境セットアップ

※ ここではPhoneGapのコマンドラインツールであるPhoneGap CLIを使用します!!
↑のnpmのアップデートをやりましたが、最初からセットアップする場合、
Node.jsのインストールが必要です。
次に最新のPhoneGap CLIをインストールします。
$ npm install -g phonegap@latest
プロジェクト作成から実行まで

次にプロジェクト作成〜実行まで一気にやりたいと思います。
# プロジェクトの作成
$ phonegap create <path> --id <id> --name <projectname>
# プラットフォームの追加(ios や androidなど)
$ phonegap cordova platform add <ios/android> --save
# ビルド
$ phonegap cordova build <ios/android>
# 実行
$ phonegap cordova run <ios/android>
※ と思ったらphonegapコマンドで以下のようなエラーが・・・
module.js:340
    throw err;
          ^
Error: Cannot find module 'phonegap-build-api'
    at Function.Module._resolveFilename (module.js:338:15)
    at Function.Module._load (module.js:280:25)
    at Module.require (module.js:364:17)
    at require (module.js:380:17)
    at Object.<anonymous> (/usr/local/lib/node_modules/phonegap/node_modules/phonegap-build/lib/phonegap-build/login.js:6:14)
    at Module._compile (module.js:456:26)
    at Object.Module._extensions..js (module.js:474:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:312:12)
    at Module.require (module.js:364:17)
やっぱりアップデートが極端だったから?
色々試してもダメだったので、phonegapを再インストールしてみ他ところエラーがなくなりました。
$ sudo npm uninstall -g phonegap
$ npm install -g phonegap
エラーがなくなった所でビルドと実行をGruntのタスク化にしてみたいと思います。
タスク化するにあたりgruntgrunt-execをインストールします。
$ npm install -g grunt-cli
$ npm install grunt --save-dev
$ npm install grunt-exec --save-dev
プロジェクトのビルドと実行をタスク化してみたいと思います。
module.exports = function(grunt) {
  grunt.loadNpmTasks('grunt-exec');

  grunt.initConfig({
   exec: {
      build: {
         command: 'phonegap cordova build'
      },
      run: {
         command: 'phonegap cordova run'
      }
   }
  });

  grunt.registerTask('default', ['exec:build', 'exec:run']);
};
これで
$ grunt
とするとビルドと実行が可能になりました^^。

2016年4月23日土曜日

普段お世話になっている便利なWebツール紹介


今回はちょっと嗜好を変えて、
筆者が普段使っている便利なWebツールをご紹介します。


・簡易エディッタ

Webツールでエディッタって何?
と思われるかもしれませんが、ブラウザ上でメモが取れるので便利です。

使い方はURLに
data:text/html, <html contenteditable>
と入力すると文字が入力できるようになります。
リッチな事は出来ませんがサクッとメモが取れるのが良いところです。


・draw.io



こちらは無料で使えるフローチャート描画ツールです。
ログインなども必要なく、すぐ使えるのが嬉しい所です^^

テンプレートも豊富にあり、↓のような図も普通に書けます。




・Placehold.jp





こちらはダミー画像を生成してくれるWebツールです。
サイズや色、画像内の文字なども指定できるので、まだ画像が決まってない場合に
とりあえずダミー画像を載せておく時などに便利です。

こちらも無料で使えます^^

2016年4月21日木曜日

Butterknifeを使ってみる 1



Androidでリソースや動作の紐づけ(DI)をアノテーションでやってくれる
Butterknifeを使ってみます。
  • 環境
IDE : AndroidStudio2.0
ビルドツール : gradle

インストール


build.gradleのdependenciesに
compile 'com.jakewharton:butterknife:7.0.1'
を追加するだけ。簡単^^

実際に使ってみる


単純にEditTextのリソースとメンバ変数mEditTextを紐づけて値を設定してみます。
・レイアウトxml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <EditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/editText" />

</LinearLayout>
・MainActivity.java
package com.app.sample.sampleapp;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.EditText;

import butterknife.Bind;
import butterknife.ButterKnife;

public class MainActivity extends AppCompatActivity {

    @Bind(R.id.editText)
    EditText mEditText;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ButterKnife.bind(this);

        mEditText.setText("Sample");
    }
}
  • 実行結果



EditTextに値が設定されているのが分かるかと思います。
やっている事としては、
@Bind(R.id.editText)
EditText mEditText;
でレイアウトxmlで定義した
android:id="@+id/editText"
のidを指定して変数mEditTextに結び付けています。
次にonCreateで
ButterKnife.bind(this);
をやる事で結び付けが行われます。
次にボタンをクリックした時の動作を設定してみたいと思います。
・レイアウト.xmlファイルにボタンを追加
<Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Sample"
    android:id="@+id/buttonSample"
    android:layout_gravity="right" />

このボタンをクリックした時の動作を以下のように設定してやります。
@OnClick(R.id.buttonSample)
void onClickSample() {
    Toast.makeText(MainActivity.this, mMessage, Toast.LENGTH_LONG).show();
}
OnClickアノテーションでボタンのリソースIDを指定し、紐づけるメソッド つまりボタンがクリックされた時実行されるメソッドを記述しています。
ここで出てきたmMessageですが、以下のようにしてstring.xmlに設定した文字を紐づけています
@BindString(R.string.hello)
String mMessage;
・ボタンをクリックした時

ん〜実に実装する手間が省けて便利です^^

2016年4月14日木曜日

MechanizeでWeb操作 3 - GithubのトレンドをKindleで読む -


前回の続きで、 今回は収集した情報をKindle端末にメール送信してみたいと思います。

メール送信


メール送信するに当たりGemfileに以下のgemを追加します。
gem "mail"
main.rbで追加したgemをrequireします
require 'mail'
メール送信部分の処理を追加します。gmailを使って送信を行います。
# 送信先メールアドレス(Kindle端末)
SEND_TO = 'XXXXXXX@kindle.com'.freeze
# 送信元メールアドレス(Gmail)
GMAIL_ADR = 'XXXXXXX@gmail.com'.freeze
# Gmailアカウントのパスワード
PASSWORD = 'XXXXXXXXXXXX'.freeze
# メール件名
SUBJECT = 'Github trends for a week.'.freeze

# メール送信メソッド
def send_mail

  # Gmail用のsmtpオプション
  options = {
            :address              => "smtp.gmail.com",
            :port                 => 587,
            :domain               => "smtp.gmail.com",
            :user_name            => GMAIL_ADR,
            :password             => PASSWORD,
            :authentication       => :plain,
            :enable_starttls_auto => true  }

  mail = Mail.new
  mail.to = SEND_TO
  mail.from = GMAIL_ADR
  mail.subject = SUBJECT
  mail.delivery_method(:smtp, options)
#  mail.add_file(※添付ファイル)

  mail.deliver
end
メールアドレスやパスワードは置き換えて下さい。
Net::SMTPAuthenticationErrorが発生した場合は認証の設定が必要です。
セキュリティ上、不明なアプリからのログインは通常認められていない為、
  • 安全性の低いアプリからのアクセスを許可する
  • 2段階認証をONにしてアプリ用のパスワードを発行する
のいずれかを行う必要があります。
アカウント設定から設定できます。

メールに添付するhtmlドキュメント作成


Kindleに送信するメールの添付ファイルとして今回はhtmlドキュメントを
添付します。※添付可能なフォーマットは前回を参照
処理としては、Mechanizeで取得したトレンドデータをストックし、
erbを使ってhtmlに展開します。
# Hashキー : リポジトリ名
KEY_REPOSITORY = :repository.freeze
# Hashキー : 作者名
KEY_AUTHOR = :author.freeze
# Hashキー : readme
KEY_README = :readme.freeze

# テンプレートファイル名
TEMPLATE_FILE = 'trends.html.erb'.freeze
# 作成htmlドキュメントファイル名
OUTPUT_FILE = 'trends.html'.freeze

# htmlドキュメント作成メソッド
def gen_html(trends)
  erb = ERB.new(File.read(TEMPLATE_FILE), nil, '-')
  ret = erb.result(binding)
  File.open(OUTPUT_FILE, "w:utf-8") do |f|
    f.write(ret)
  end
end

agent = Mechanize.new
agent.verify_mode = OpenSSL::SSL::VERIFY_NONE
page = agent.get('https://github.com/trending?since=weekly')

trends = []
page.search('h3 a').each do |link|
  trend = {}
  array = link.text.gsub(/(\s)/,"").split('/')
  # リポジトリ名の取得
  trend[KEY_REPOSITORY] = array[1]
  # 作者名の取得
  trend[KEY_AUTHOR] = array[0]

  # リポジトリのページへ遷移
  url = "#{GITHUB_TOP}#{link[:href]}"
  next_page = agent.get(url)
  # readmeの情報取得
  readme = next_page.at('#readme')
  trend[KEY_README] = readme
  # 配列に追加
  trends << trend
end

# html作成
gen_html(trends)
  • テンプレートファイル
<!DOCTYPE HTML>
<html>
  <head>
    <meta charset="utf-8">
    <title>Github trends.</title>
  </head>
  <body>
<% trends.each do |trend| -%>
  <h1><%= trend[:repository] %></h1>
  <p><%= trend[:author] %></p>
  <hr>
  <pre><%= trend[:readme] %></pre>
  <br>
<% end -%>
  </body>
</html>

完成


これで一通りできたので、実際に試してみます。
Kindle端末に送信されれば成功です。
  • 送信されたドキュメントを開いた様子



画像やgifなどが表示されないのが残念な感じですが ><;
一応トレンドのリポジトリとreadme一覧がKindleで読めます^^;
今回はテストでやってみましたが、今後色々と改良していきたいと思います。
  • 完成したソース
# coding: utf-8
require 'erb'
require 'mail'
require 'mechanize'

GITHUB_TOP = 'https://github.com'.freeze

# Hashキー : リポジトリ名
KEY_REPOSITORY = :repository.freeze
# Hashキー : 作者名
KEY_AUTHOR = :author.freeze
# Hashキー : readme
KEY_README = :readme.freeze

# テンプレートファイル名
TEMPLATE_FILE = 'trends.html.erb'.freeze
# 作成htmlドキュメントファイル名
OUTPUT_FILE = 'trends.html'.freeze

# 送信先メールアドレス(Kindle端末)
SEND_TO = 'XXXXXXX@kindle.com'.freeze
# 送信元メールアドレス(Gmail)
GMAIL_ADR = 'XXXXXXX@gmail.com'.freeze
# Gmailアカウントのパスワード
PASSWORD = 'XXXXXXXXXXXX'.freeze
# メール件名
SUBJECT = 'Github trends for a week.'.freeze

# メール送信メソッド
def send_mail

  # Gmail用のsmtpオプション
  options = {
            :address              => "smtp.gmail.com",
            :port                 => 587,
            :domain               => "smtp.gmail.com",
            :user_name            => GMAIL_ADR,
            :password             => PASSWORD,
            :authentication       => :plain,
            :enable_starttls_auto => true  }

  mail = Mail.new
  mail.to = SEND_TO
  mail.from = GMAIL_ADR
  mail.subject = SUBJECT
  mail.delivery_method(:smtp, options)
  mail.add_file(OUTPUT_FILE)

  mail.deliver
end

# htmlドキュメント作成メソッド
def gen_html(trends)
  erb = ERB.new(File.read(TEMPLATE_FILE), nil, '-')
  ret = erb.result(binding)
  File.open(OUTPUT_FILE, "w:utf-8") do |f|
    f.write(ret)
  end
end

agent = Mechanize.new
agent.verify_mode = OpenSSL::SSL::VERIFY_NONE
page = agent.get('https://github.com/trending?since=weekly')

trends = []
page.search('h3 a').each do |link|
  trend = {}
  array = link.text.gsub(/(\s)/,"").split('/')
  # リポジトリ名の取得
  trend[KEY_REPOSITORY] = array[1]
  # 作者名の取得
  trend[KEY_AUTHOR] = array[0]

  # リポジトリのページへ遷移
  url = "#{GITHUB_TOP}#{link[:href]}"
  next_page = agent.get(url)
  # readmeの情報取得
  readme = next_page.at('#readme')
  trend[KEY_README] = readme
  # 配列に追加
  trends << trend
end

# html作成
gen_html(trends)
# メール送信
send_mail