awacleberryの備忘録

アナログ人間のデジタル日記。

【Android】View の id とエントリ名の変換

エントリ名から id を取得

hoge というエントリ名から、R.id.hoge という id の数値を取得するなら、

int viewId = getResources().getIdentifier("hoge", "id", getPackageName());

この viewIdfindViewById(viewId) できる。for で連番しているエントリ名などから View を取得するのに便利。

id からエントリ名を取得

逆に、id の数値からエントリ名を取得するなら、

String viewIdStr = getResources().getResourceEntryName(viewId);

View から getId() とかで id さえ取得していれば、それを上記のようにエントリ名へ変換して正規表現でチェックとかできる。

他のリソース

View の id 以外でもできる。

int strId = getResources().getIdentifier("hoge", "string", getPackageName());

注意点

getIdentifier について、ドキュメント曰く、

Note: use of this function is discouraged. It is much more efficient to retrieve resources by identifier than by name.

オススメできない方法とのこと。

getIdentifier

Mac の ターミナルで tree を表示

tree をインストー

brew install tree

tree を表示

当該ディレクトリで、

tree

パスを指定するなら、

tree .

など。日本語が文字化けする際は、

tree . -N

でOK。表示するディレクトリの深さをしていするなら、

tree -L LEVEL

次のような感じに表示される。

.
├── CHANGELOG.md
├── LICENSE
├── README.md
├── assets
│   ├── fonts
│   ├── images
│   ├── javascripts
│   └── stylesheets
├── eyeglass-exports.js
└── package.json

パスを書く必要がある際には便利。他、使いそうなオプションは、

オプション
-a 隠しファイルも表示
-d ディレクトリのみ表示
-P 正規表現にマッチするものを表示
-F ディレクトリ末尾にスラッシュを表示
-o 書き出し

Android の apk 出力で Unsupported major.minor version 52.0 エラー

出力する apk ファイルの量が多いので、コマンドラインから gradle 使ってビルドをすることが多いけど、今回急に次のエラーが出て戸惑った。

A problem occurred evaluating project ':app'.
> java.lang.UnsupportedClassVersionError: me/tatarka/RetrolambdaPlugin : Unsupported major.minor version 52.0

結論だけ言えば、java8 を使えば解消される。 以下が詳しくて助かった。

Androidアプリのビルドで「Unsupported major.minor version 52.0」のビルドエラーが発生する

webpack をサクッと使う手順


webpack の基本操作 にて述べた方法で、効率良く開発環境を整える手順を改めてまとめておく。

要件は、

  • js モジュールの統合と単一書き出し
  • sass の 統合と css 単一書き出し
  • compass の読み込み
  • js, css のミニマイズ
  • js, css の map ファイルの生成
  • ES6 -> ES5 トランスパイル(コンパイル
  • jquery の読み込み
  • watch で変更を監視

完成後のディレクトリ構成(ビルド前)は次のようになる。

project/
    ├── _css
    │     ├── entry.sass
    │     └── sub.sass
    ├── _js
    │     ├── entry.js
    │     └── sub.js
    ├── css
    ├── js
    ├── node_modules
    ├── package.json
    ├── webpack_index.html
    └── webpack.config.js
  • ビルド前の各モジュールは _(アンダースコア)から始まるディレクトリに入れる
  • ビルド後のファイルは、それぞれ js, css ディレクトリに格納される
  • webpack_index.html は確認用の html

0. ディレクトリとテストファイルの準備

# 各ディレクトリ
mkdir {_css,_js,css,js}
# テスト用 html
echo '<html><link rel="stylesheet" media="all" href="./css/style.css"><body><h1></h1></body><script src="./js/bundle.js"></script></html>' > webpack_index.html
# entry.scss
echo '@import "compass"; @import "sub"; h1 { @include inline-block; color: #f00; }' > _css/entry.scss
# sub.scss
echo '@import "compass"; h1 { background-color: #000; }' > _css/sub.scss
# entry.js
echo 'var $ = require("jquery"); $(function(){$("h1").text(require("./sub.js"));});' > _js/entry.js
# sub.js
echo 'module.exports = "OK";' > _js/sub.js
  • webpack_index.html ではビルド後の js と css の読み込みの他、h1 タグを用意しておく
  • entry.scss では sub.scss を読み込む他、h1 を赤字に、また compass で inline-block にする
  • sub.scss では h1 の背景を黒にする
  • entry.js では jquery の読み込みの他、sub.js の出力を h1 にセットする
  • sub.js は “OK” を返す
  • ビルド後のイメージは次の感じ

スクリーンショット 2017-06-01 6.41.20.png

1. package.json を作る

-y オプションを付けて対話をせずに、初期化する。

npm init -y

2. devDependencies に追加する

npm install --save-dev webpack babel-loader babel-core babel-preset-es2015 node-sass style-loader css-loader sass-loader extract-text-webpack-plugin compass-mixins

それぞれ、

  • webpack 本体

    • webpack
  • ES6 対応

    • babel-loader
    • babel-core
    • babel-preset-es2015
  • sass 対応
    • node-sass
    • style-loader
    • css-loader sass-loader
  • sass -> css 書き出し対応
    • extract-text-webpack-plugin
  • compass 対応

3. dependencies に追加する

npm install jquery --save

4. package.json を修正

...
"private": true,
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "webpack --optimize-minimize"
  },
...
  • プライベート用にして警告排除
  • "private": true
  • ビルドファイルのミニマイズ設定
  • "build": "webpack --optimize-minimize"

5. webpack.config.js を置く

var path = require('path');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
module.exports = [
    /**
     * js
     */
    {
        entry: "./_js/entry.js",
        watch: true,
        output: {
            path: path.join(__dirname, './js'),
            filename: "bundle.js"
        },
        module: {
            loaders: [{
                test: /\.js[x]?$/,
                exclude: /node_modules/,
                loader: 'babel-loader?presets[]=es2015'
            }]
        },
        devtool: 'source-map'
    },
    /**
     * Sass
     */
    {
        entry: './_css/entry.scss',
        watch: true,
        output: {
            path: path.join(__dirname, './css'),
            filename: 'style.css'
        },
        module: {
            loaders: [{
                test: /\.scss$/,
                loader: ExtractTextPlugin.extract({
                    use: [{
                            loader: 'css-loader'
                        },
                        {
                            loader: 'sass-loader',
                            options: {
                                includePaths: ['node_modules/compass-mixins/lib']
                            },
                        }
                    ],
                    fallback: 'style-loader'
                })
            }]
        },
        plugins: [
            new ExtractTextPlugin('style.css')
        ],
        devtool: 'source-map'
    }
];

6. ビルドして確かめる

npm run build

実行後、webpack_index.html をブラウザで開き、

スクリーンショット 2017-06-01 6.41.20.png

と表示されれば、js, sass ともにビルドができている。

また、js/bundle.js, css/style.css はそれぞれミニマイズされていて、かつ同階層に map ファイルも出力されていれば問題ない。

webpack の基本設定

webpack を初めて触ったので、調べたことなどを備忘録として残しておく。webpack のインストールから、ES6, jQuery, Sass, compass の対応まで。

1. npm の準備

package.jsonを作る。

npm init

2. ローカルに webpack をインストー

package.json に書き込みたいので、--save-dev オプションをつける。

npm install webpack --save-dev

No repository field. と怒られた場合、一先ず、package.json"private": true を追加すれば警告は消える。

ドキュメントに依ると、

If you set “private”: true in your package.json, then npm will refuse to publish it.

This is a way to prevent accidental publication of private repositories. If you would like to ensure that a given package is only ever published to a specific registry (for example, an internal registry), then use the publishConfig dictionary described below to override the registry config param at publish-time.

要は公開用のリポジトリじゃなく、プライベートなリポジトリのみで使うっていう設定。これを指定すれば、repository field の指定がなくても許される。

3. ローカルにパスを通す

このままだと、webpack コマンドは動かないので、パスを通す。

export PATH=$PATH:./node_modules/.bin

以下でバージョンが確認出来る。

webpack -v

もちろん、パスを通す必要がないなら、直接、

node_modules/.bin/webpack -v

でも良い。

4. webpack でビルドをテストする

適当に、sub.js を作る。

module.exports = ["a", "b", "c"]; 

module.export は return 的なやつ。これを app.js で読み込み、出力する。

console.log(require("./sub.js")); 

これを bundle.js としてビルドする。

webpack app.js bundle.js

実行すると、

Version: webpack 2.6.1
Time: 81ms
    Asset     Size  Chunks             Chunk Names
bundle.js  2.78 kB       0  [emitted]  main
   [0] ./sub.js 34 bytes {0} [built]
   [1] ./app.js 34 bytes {0} [built]

こんな感じの実行結果と bundle.js が書き出されている。

この bundle.js を実行すると、次のような結果になる。

[ 'a', 'b', 'c' ]

なお、npm の実行時にこれも一緒にビルドして欲しいので、build: の項目を設け、そこに追加する。

  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "webpack app.js bundle.js"
  },

そうすれば、

npm run build

でビルドしてくれる。

5. webpack.config.js からビルドする

そもそも webpack 実行時に js のビルドも自動的にしてほしいので、webpack.config.js にその設定を書く。

まずは、package.jsonbuild: 項目を webpack だけにして、

  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "webpack"
  },

以下のように webpack.config.js を作成。entryoutputfilename 指定する。

module.exports = {                                                     
    entry: "./app.js",
    output: {
    filename: "bundle.js"
    }
}

そうすれば、先ほどと同様に、

npm run build

でビルド出来る。ディレクトリパスを別途指定するなら、path モジュールを読み込んで、

var path = require('path');
module.exports = {                                                     
    entry: "./js/modules/app.js",
    watch: true,
    output: {
        path: path.join(__dirname, './js'),
        filename: "bundle.js"
    }
}

のようにする。

6. watch モードにする

ファイルを監視させて、変更時に自動ビルド。コマンドラインから設定するなら、

webpack --watch

一方、webpack.config.js で指定するなら、watch: を設けて、true にする。

module.exports = {
  watch: true,
  entry: "./app.js",
  ...省略...

7. jquery を使う

まずは、npm で jquery をダウンロード。プロダクトでもつかうので、 オプションは --save

npm install jquery --save
var $ = require("jquery");
$(function(){

});

件の通り、$ に jquery をつっこむだけ。

8. ES6 に対応させる

ES6 を ES5 にコンパイルというかトランスパイルというか、とにかく変換する場合は、babel-loader を使う。

開発用なので、オプションは --save-dev でインストールする。

npm install babel-loader babel-core babel-preset-es2015 --save-dev

webpack.config.js に以下を追加する。

...省略...
  module: {
    loaders: [{
      test: /\.js[x]?$/,
      exclude: /node_modules/,
      loader: 'babel-loader?presets[]=es2015'
    }]
  }
...省略...

正規表現で node_modules を除く js 系の拡張子を対象にしている。

試しに app.js を次のように書き換え、

/*jshint esversion: 6 */
var $ = require("jquery");
$(function(){
    "use strict";
    const hoge = "!!!!";
    $("body").text(hoge);
});

ビルドすると、bundle.js では、

...省略...

/*jshint esversion: 6 */
var $ = __webpack_require__(0);
$(function () {
    "use strict";

    var hoge = "!!!!";
    $("body").text(hoge);
});

...省略...

const -> var の変換がされている。

9. js を minimize する

圧縮したいなら、packege.jsonbuild:--optimize-minimize のオプションをつける。

ただ、このままだとデバッグし難いので、更に --devtool source-map のオプションもつけて、デベロッパーツールから圧縮前を見れるようにする。

...省略...
"scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "webpack --optimize-minimize --devtool source-map"
  },
...省略...

これで、Chrome デベロッパーツールの Sources タブに webpack:// のディレクトリが表示される。

source-map は webmap.config.js でも指定できる。

末尾に devtool: の項目を追加し、source-map を指定する。

...省略...
  module: {
    loaders: [{
      test: /\.js[x]?$/,
      exclude: /node_modules/,
      loader: 'babel-loader?presets[]=es2015'
    }]
  },
  devtool: 'source-map'
...省略...

10. Sass の設定をする

まずは、必要なモジュールをインストール。

npm install --save-dev node-sass style-loader css-loader sass-loader extract-text-webpack-plugin

css の出力も可能にするため、extract-text-webpack-plugin も入れている。

webpack.config.js の exports の対象をオブジェクト({})からオブジェクトの配列([{},{}])形式にして、次のように変更する。

var path = require('path');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
module.exports = [
    /**
     * js の設定
     */
    {
        entry: "./js/modules/app.js",
        watch: true,
        output: {
            path: path.join(__dirname, './js'),
            filename: "bundle.js"
        },
        module: {
            loaders: [{
                test: /\.js[x]?$/,
                exclude: /node_modules/,
                loader: 'babel-loader?presets[]=es2015'
            }]
        },
        devtool: 'source-map'
    },
    /**
     * Sass の設定
     */
    {
        entry: './css/modules/style.scss',
        watch: true,
        output: {
            path: path.join(__dirname, './css'),
            filename: 'app.css'
        },
        module: {
            loaders: [{
                test: /\.scss$/,
                loader: ExtractTextPlugin.extract('css-loader!sass-loader')
            }]
        },
        plugins: [
            new ExtractTextPlugin('app.css')
        ],
        devtool: 'source-map'
    }
];

これで、複数指定ができる。なお、出力先のディレクトリなども整理してある。

11. compass を使う場合

まずは、compass-mixins をインストール。

npm install --save-dev compass-mixins

sass-loader の includePaths に compass-mixins/lib を指定して読み込ませる。

    /**
     * Sass の設定
     */
    {
        entry: './css/modules/style.scss',
        watch: true,
        output: {
            path: path.join(__dirname, './css'),
            filename: 'app.css'
        },
        module: {
            loaders: [{
                test: /\.scss$/,
                loader: ExtractTextPlugin.extract({
                    use: [{
                            loader: 'css-loader'
                        },
                        {
                            loader: 'sass-loader',
                            options: {
                                includePaths: ['node_modules/compass-mixins/lib']
                            },
                        }
                    ],
                    fallback: 'style-loader'
                })
            }]
        },
        plugins: [
            new ExtractTextPlugin('app.css')
        ],
        devtool: 'source-map'
    }

下の config ファイルを参考にさせてもらった。

https://github.com/iliran11/react-cordova-boilerplate/blob/2b68ade24c9a56512140ff2c3419d401afd0737b/bin/get-webpack-config.js


参考 - Webpackを使って、Sassをコンパイルする方法 2017年4月版

wkhtmltopdf で HTML を PDFにする

wkhtmltopdf のインストー

以下よりインストーラーをダウンロードして、インストー

wkhtmltopdf

コマンド確認

wkhtmltopdf -h

上手くインストールされていれば、なんか色々表示される。

PDF に変換

試しに google.com を PDF 出力する。

wkhtmltopdf http://google.com google.pdf

これで簡単に出力できてハッピーなはずが……

スクリーンショット 2017-05-30 18.37.56.png

ちっさ。サイズがひどいことになってる……。

サイズが小さい問題の対処

--disable-smart-shrinking というオプションを付ければ良さそうという記事を読んで、さっそくトライするも、変わらず。このオプションは最適化してくれるものだけど、この出力は最悪化されているので、まぁ、違うだろう。

で、もう少し調べ、ようやく同じ事例を発見。

https://stackoverflow.com/questions/40814680/wkhtmltopdf-generates-tiny-output-on-mac

ここで問題が報告されている Mac OS のバージョンが自分のものと一致していて、少し、面倒臭い雰囲気がする……。なお、この時点の環境は、

  • OS バージョン: 10.11.6(15G31)
  • wkhtmltopdf バージョン: 0.12.4

手動で wkhtmltopdf を消し去って、別バージョンを入れてみる。インストール先に wkhtmltoimage もあって、一緒にインストールされたものなのでこれも消す。

以下から新しく 0.12.3 のインストーラーを落としてインストール。

https://downloads.wkhtmltopdf.org/0.12/0.12.3/

改めて、出力する。

スクリーンショット 2017-05-30 18.41.29.png

はい、ハッピーになれた。

PHP Composer の導入

installer のダウンロード

curl -sS https://getcomposer.org/installer | php

コマンドの確認するなら、

php composer.phar

local/bin/compoer に移動しておく。

mv composer.phar /usr/local/bin/composer

~/composer/composer.phar とかにしている人もいるので、ここじゃなきゃいけない、みたいなのはないのかな。分からなくなったら、

which composer

とかすればいい。

プロジェクトを作る

新しくプロジェクトを作るなら、

composer init

で、対話形式に composer.json が作れる。最初に、

Package name (<vendor>/<name>)

ベンダー名/パッケージ名 が聞かれるので、このスラッシュ形式で指定。

Description

プロジェクトの説明を記入。

Author

name <mail address> の形式で指定。

Minimum Stability

最小限の「安定度合い」的なものを聞かれるので、dev, alpha, beta, RC, and stable から適時選択。デフォルトは、stable

Package Type

プロジェクトなら project としてれば良さそう。デフォルトは library

License

オプショナルだけど、ドキュメントは、

Optional, but it is highly recommended to supply this.

と言っている。まぁ、そうだな。

Search for a package: 

いよいよパッケージ。例えば、phpunit など。

[0] phpunit/phpunit
[1] eher/phpunit
[2] jbzoo/phpunit
[3] sugared-rim/phpunit
[4] hiqdev/php-units
[5] task/phpunit
[6] phpunit/phpunit-mock-objects
[7] phpunit/phpunit-selenium
[8] phpunit/phpunit-story
[9] phpunit/phpunit-skeleton-generator
[10] phpunit/dbunit
[11] phpunit/phpunit-dom-assertions
[12] phpunit/phpcov
[13] phpunit/phpunit-mink-trait
[14] phpunit/php-timer

ばーっと候補がでるので、0 を入力。

Enter the version constraint to require (or leave blank to use the latest version)

最新版を使うなら、そのまま return で進む。

Using version ^6.1 for phpunit/phpunit
Search for a package: 

うっす。もういらないので、return で進む。

{
    "name": "hoge/composer-test",
    "description": "this is a test.",
    "type": "project",
    "require-dev": {
        "phpunit/phpunit": "^6.1"
    },
    "authors": [
        {
            "name": "hoge",
            "email": "hoge@huga.com"
        }
    ],
    "require": {}
}

Do you confirm generation [yes]? 

こんな json ができれば、OK。yes で終了。ls で確認すれば、composer.jsonディレクトリに作成されている。

パッケージのインストー

さっそく json で定義したものをインストー

composer install

と、手元の環境の PHP5.5.36 だったので、

  Problem 1
    - phpunit/phpunit 6.1.4 requires php ^7.0 -> your PHP version (5.5.36) does not satisfy that requirement.
    - phpunit/phpunit 6.1.3 requires php ^7.0 -> your PHP version (5.5.36) does not satisfy that requirement.
    - phpunit/phpunit 6.1.2 requires php ^7.0 -> your PHP version (5.5.36) does not satisfy that requirement.
    - phpunit/phpunit 6.1.1 requires php ^7.0 -> your PHP version (5.5.36) does not satisfy that requirement.
    - phpunit/phpunit 6.1.0 requires php ^7.0 -> your PHP version (5.5.36) does not satisfy that requirement.
    - Installation request for phpunit/phpunit ^6.1 -> satisfiable by phpunit/phpunit[6.1.0, 6.1.1, 6.1.2, 6.1.3, 6.1.4].

composer.json を編集して、phpunit のバージョンを phpunit-4.8.35.phar とする。

"require-dev": {
    "phpunit/phpunit": "4.8.35"
},
Loading composer repositories with package information
Updating dependencies (including require-dev)
Package operations: 21 installs, 0 updates, 0 removals
  - Installing symfony/yaml (v3.2.8): Downloading (100%)         
  - Installing sebastian/version (1.0.6): Downloading (100%)         
  - Installing sebastian/global-state (1.1.1): Downloading (100%)         
  - Installing sebastian/recursion-context (1.0.5): Downloading (100%)         
  - Installing sebastian/exporter (1.2.2): Downloading (100%)         
  - Installing sebastian/environment (1.3.8): Downloading (100%)         
  - Installing sebastian/diff (1.4.3): Downloading (100%)         
  - Installing sebastian/comparator (1.2.4): Downloading (100%)         
  - Installing doctrine/instantiator (1.0.5): Downloading (100%)         
  - Installing phpunit/php-text-template (1.2.1): Downloading (100%)         
  - Installing phpunit/phpunit-mock-objects (2.3.8):Downloading (100%)         )
  - Installing phpunit/php-timer (1.0.9): Downloading (100%)         
  - Installing phpunit/php-file-iterator (1.4.2): Downloading (100%)         
  - Installing phpunit/php-token-stream (1.4.11): Downloading (100%)         
  - Installing phpunit/php-code-coverage (2.2.4): Downloading (100%)         
  - Installing webmozart/assert (1.2.0): Downloading (100%)         
  - Installing phpdocumentor/reflection-common (1.0): Downloading (100%)          - Installing phpdocumentor/type-resolver (0.2.1): Downloading (100%)         
  - Installing phpdocumentor/reflection-docblock (3.1.1): Downloading (100%)      - Installing phpspec/prophecy (v1.7.0): Downloading (100%)         
  - Installing phpunit/phpunit (4.8.35): Downloading (100%)         
symfony/yaml suggests installing symfony/console (For validating YAML files using the lint command)
sebastian/global-state suggests installing ext-uopz (*)
phpunit/php-code-coverage suggests installing ext-xdebug (>=2.2.1)
phpunit/phpunit suggests installing phpunit/php-invoker (~1.1)
Writing lock file
Generating autoload files

依存モジュールもまとめて、いっぱい。 ls すると、

composer.json    composer.lock   vendor

lock ファイル と vendor ディレクトリができている。vendor という名前のディレクトリに外部の依存モジュールが格納されるので、.gitignore にこのディレクトリを指定しておけば OK。

なお、phpunitphp バージョンの対応は、

PHPUnitとPHPのバージョン対応表

を参考。

パッケージの追加

composer require cebe/markdown

require で追加できる。composer.json と lock ファイルも更新される。バージョン指定する場合は、

composer require hoge/huge:1.1.11

みたいにする。


参考