月別アーカイブ 4月 2019

takahashi 著者:takahashi

最早HTMLのコーディングは不要に!?絵を描くだけでDOMを生成してくれるホームページ作成ツール”teleportHQ”

先日Twitterを見ていたらこんな投稿が。

何これ凄い…
ホワイトボードに書いた要素がそのままコード上でリアルタイムに再現されています。

かなりラフなワイヤーフレームでも、それぞれどの種類のDOMかを瞬時に判断できるようです。

ホワイトボードだけでなく、こんな風にペーパーに書かれていても認識できるようですね。

いよいよ誰でも簡単にWebサイトを作成できる時代がやってくるかもしれません。

興味のある方は是非公式サイトをチェックしてみてください。

teleportHQ


  • この記事いいね! (0)
著者:ym

やっぱり VMware 。VMware と Hyper-V 切り替え

昔ながらの BIOS マシンを使用しているので、以下のコマンドで切り替えられます。

VMware を使いたい場合

bcdedit /set hypervisorlaunchtype off
その後 OS 再起動


Hyper-V を使いたい場合

bcdedit /set hypervisorlaunchtype auto
その後 OS 再起動

HDD マシンだから再起動したら 30 分以上かかる。どうにかならんのか、これ。

  • この記事いいね! (0)
村上 著者:村上

【Cordova】「Please fix the version conflict either by updating the version of the google-services plugin」エラーの対処法

昨日紹介した、Cordova のプラグイン「google-analytics-plugin」をインストールした際に発生したエラーについてです。
ちなみに、プラットフォームは Android です。

昨日の記事はこちらから。

【Cordova】アプリのアクセス解析を行えるプラグイン「google-analytics-plugin」
https://cpoint-lab.co.jp/article/201904/9282/

 

エラー全文はこちら。

Please fix the version conflict either by updating the version of the google-services plugin (information about the latest version is available at https://bintray.com/android/android-tools/com.google.gms.google-services/) or updating the version of com.google.android.gms to 9.0.0.

Google 翻訳に突っ込んだところ、「google-servicesプラグインのバージョンを更新することで、バージョンの競合を修正してください(最新バージョンについての情報はhttps://bintray.com/android/android-tools/com.google.gms.google-services/にあります)。 またはcom.google.android.gmsのバージョンを9.0.0に更新する。」とのこと。

結果から言うと、build.gradle を下記のように修正すればOKでした。

dependencies {
    ...
    compile 'com.google.android.gms:play-services:9.0.0'
}

バージョンの競合とか面倒くさそうなことを書いてあったので、手こずるかと思いましたが、そもそも解決方法がエラーに書いてありましたね。
今まで、エラー文に書いてある解決策って動かないこともあるので、若干半信半疑で試しましたが、今回は上手くいったようです。

 

以上、「google-analytics-plugin」導入時に発生したエラーの対処法についてでした。
今回はあっさり解決できたので、よかったです。

  • この記事いいね! (0)
asaba 著者:asaba

【androidJava】ads.MobileAdsInitProvider(ADMOB)を使おうとしてはまったこと

MobileAdsInitProviderは、アプリに広告を表示させることができるライブラリで、ブログやショッピングサイトを取り扱うアプリではよくお目にかかります。

今回はこのライブラリが必要になったので導入してみたのですが、下のエラーを出した後に落ちてしまいました。

 


java.lang.RuntimeException: Unable to get provider com.google.android.gms.ads.MobileAdsInitProvider: java.lang.IllegalStateException

 

どうやら、今までのライブラリと違い単にグレイドルにいれただけでは使えないもよう。

調べてみるとMobileAdsInitProviderを使うには、マニフェストへの記述が必要みたいです。アプリケーションタグを閉じる前に

こんな感じでいれてあげれば解決できます。

 


<meta-data
android:name="com.google.android.gms.ads.AD_MANAGER_APP"
android:value="true"/>

 

こちらの記事のurlを参考にしました

グレイドル関係のエラーが出るたびにこのブログに載せている気がします。ですがグレイドル関係の記事は数が少ないのに対して同じよう

なエラーで困っている人が多くいるので少しでも助けになれたらなと思っております。

なお、日本語版の公式ではこの記事の対策方法が書いていないので注意してください。(見るなら英語版で)

  • この記事いいね! (0)
著者:杉浦

【Laravel】LaravelのソースコードでよくあるArrayAccessを実装するClass設計

 Laravelのソースコード内を

implements[^\n]+ArrayAccess

という正規表現でググるとArrayAccessを満たすClassを軒並み見つけられます。この記事ではこれらのClassで使われているArrayAccessの実装方法とその設計について述べます。
 ArrayAccessというのはPHPの組み込みインタフェースの一つです。
PHP: ArrayAccess – Manual
 このインタフェースを満たしたClassのインスタンスは配列として値を呼び出せるようになります。例えば次です。

<?php
class obj implements ArrayAccess {
    private $container = array();

    public function __construct() {
        $this->container = array(
            "one"   => 1,
            "two"   => 2,
            "three" => 3,
        );
    }

    public function offsetSet($offset, $value) {
        if (is_null($offset)) {
            $this->container[] = $value;
        } else {
            $this->container[$offset] = $value;
        }
    }

    public function offsetExists($offset) {
        return isset($this->container[$offset]);
    }

    public function offsetUnset($offset) {
        unset($this->container[$offset]);
    }

    public function offsetGet($offset) {
        return isset($this->container[$offset]) ? $this->container[$offset] : null;
    }
}

$obj = new obj;

var_dump(isset($obj["two"]));
var_dump($obj["two"]);
unset($obj["two"]);
var_dump(isset($obj["two"]));
$obj["two"] = "A value";
var_dump($obj["two"]);
$obj[] = 'Append 1';
$obj[] = 'Append 2';
$obj[] = 'Append 3';
print_r($obj);

 配列として呼び出し、代入、isset()、empty()、unset()が使えるようになります。注意するのは配列となっているわけではないことです。上のコードの続きで

array_pop($obj);

などとした場合、引数がArray型でないと怒られ、PHPが致命的なエラーを起こします。

 Laravelのソースコード中のいくつかのClassではこのArrayAccessを実装しています。例えばデータベース定義を行うクラスであるFluentでは次の様になっています。

    /**
     * Determine if the given offset exists.
     *
     * @param  string  $offset
     * @return bool
     */
    public function offsetExists($offset)
    {
        return isset($this->attributes[$offset]);
    }

    /**
     * Get the value for a given offset.
     *
     * @param  string  $offset
     * @return mixed
     */
    public function offsetGet($offset)
    {
        return $this->get($offset);
    }

    /**
     * Get an attribute from the fluent instance.
     *
     * @param  string  $key
     * @param  mixed   $default
     * @return mixed
     */
    public function get($key, $default = null)
    {
        if (array_key_exists($key, $this->attributes)) {
            return $this->attributes[$key];
        }

        return value($default);
    }

    /**
     * Set the value at the given offset.
     *
     * @param  string  $offset
     * @param  mixed   $value
     * @return void
     */
    public function offsetSet($offset, $value)
    {
        $this->attributes[$offset] = $value;
    }

    /**
     * Unset the value at the given offset.
     *
     * @param  string  $offset
     * @return void
     */
    public function offsetUnset($offset)
    {
        unset($this->attributes[$offset]);
    }

 いずれもattributesへのアクセス方法です。attributesにはカラムの定義が羅列されます。
 ブラウザに返すためのwebページを定義するクラスViewでは次の様になっています。

    /**
     * Determine if a piece of data is bound.
     *
     * @param  string  $key
     * @return bool
     */
    public function offsetExists($key)
    {
        return array_key_exists($key, $this->data);
    }

    /**
     * Get a piece of bound data to the view.
     *
     * @param  string  $key
     * @return mixed
     */
    public function offsetGet($key)
    {
        return $this->data[$key];
    }

    /**
     * Set a piece of data on the view.
     *
     * @param  string  $key
     * @param  mixed   $value
     * @return void
     */
    public function offsetSet($key, $value)
    {
        $this->with($key, $value);
    }

    /**
     * Add a piece of data to the view.
     *
     * @param  string|array  $key
     * @param  mixed   $value
     * @return $this
     */
    public function with($key, $value = null)
    {
        if (is_array($key)) {
            $this->data = array_merge($this->data, $key);
        } else {
            $this->data[$key] = $value;
        }

        return $this;
    }

    /**
     * Unset a piece of data from the view.
     *
     * @param  string  $key
     * @return void
     */
    public function offsetUnset($key)
    {
        unset($this->data[$key]);
    }

 いずれもdataへのアクセス方法です。dataにはHTMLコードのテンプレートファイルに渡す変数が羅列されます。
 ここで挙げたのは二例ですが、Collection、Modelなど他にも同様の実装はあります。この実装の方針は、Classの中に主目的のデータらを格納した配列を持ち、その配列を直接扱う方法の一つとしてArrayAccessを実装、というものです。このため次の様にClassを作るとLaravel内のコードと違和感なく扱えるままClassを拡張していくことができます。

class MyModel implements ArrayAccess
{
    /** @var array 主データ */
    public $data;

    //
    // $dataを操る色々
    //

    /**
     * {@inheritdoc}
     * @param  mixed $offset
     * @return bool
     */
    public function offsetExists($offset)
    {
        // この実装は疑問。LaravelではoffsetExistsの返り値がarray_key_existsの返り値であることがしばしばある。
        // しかしArrayAccessの実装によってisset($this[$offset])とした時、$this->offsetExists($offset)が評価される。
        // Laravelに従った場合、$this->data[$offset]=nullの時にisset($this->data[$offset])===false、isset($this[$offset])===trueとなる。
        // この実装の場合、isset($this->data[$offset])===isset($this[$offset])が担保できる。
        return isset($this->data[$offset]);
    }

    /**
     * {@inheritdoc}
     * @param  mixed $offset
     * @return mixed
     */
    public function offsetGet($offset)
    {
        return $this->data[$offset];
    }

    /**
     * {@inheritdoc}
     * @param  mixed $offset
     * @param  mixed $value
     * @return void
     */
    public function offsetSet($offset, $value)
    {
        return $this->data[$offset] = $value;
    }

    /**
     * {@inheritdoc}
     * @param  mixed $offset
     * @return void
     */
    public function offsetUnset($offset)
    {
        unset($this->data[$offset]);
    }
}

 このやり方はリレーショナルデータベース以外のデータリソースを参照するModelを作る時などで割と便利です。EloquentをそのままExtendすると不意にクエリビルダが走る事故が起きますが、この書き方なら起きません。また適切に拡張した場合、Controller等のModelを外部から参照する際に他のEloquentModelと記述上の区別なしに扱うことができます。

  • この記事いいね! (1)
takahashi 著者:takahashi

EclipseのDBViewerPluginでMySQLに接続する方法

以前の記事でEclipseにDBViewerPluginをインストールする方法についてご説明しました。

今回は実際に接続できるようにするところまでご説明したいと思います。

前回の時点で下記の画像のようにDBViewerPluginが表示されているかと思います。

左上の”DBViewerPlugin”を右クリックし、”登録”をクリックします。

すると、下記のようなウインドウが開きます。

ここで、EclipseがDBを直接扱えるようにするための”ドライバ”を指定する必要があります。

今回はMySQLを例にして説明します。
MySQLのEclipse(Java)用のドライバは下記URLから入手できます。

Download Connector/J – MySQL

Windowsの場合はzip形式の方が扱いやすい(専用ソフトなしで解凍できる)と思います。

ダウンロードしたら、Eclipseからいつでも参照できる場所に保存します。
(自分の場合は、Eclipseのフォルダの中に”drivers”フォルダを作成してそこに配置しました。)

ドライバを配置したら、Eclipse上の先ほどの画面で”ファイルの追加”をクリックし、ドライバの場所を指定します。

ドライバを指定したら次へをクリックします。

JDBC Driverに”com.mysql.jdbc.Driver”を選択します。

OKをクリックします。

すると接続文字列にサンプルの文字列が入るので、<host>の部分をMySQLサーバーのホスト名、<database>の部分をDB名にそれぞれ置き換え、さらにMySQLのユーザー名とパスワードを入力します。

ここまで出来たら”テスト接続”をクリックしてエラーが出なければ接続設定はOKです。

次へをクリックします。

最後に接続設定(読み込むテーブルや文字コードの指定など)が出てくるので、必要があれば指定し、完了をクリックします。

これで設定は完了です。
この時点でEclipse上からDBへのアクセスが可能になっているかと思います。

EclipseでMySQLをお使いの方は参考にしてみてください。

  • この記事いいね! (0)
村上 著者:村上

【Cordova】アプリのアクセス解析を行えるプラグイン「google-analytics-plugin」

今回は、Google Analytics を Cordova アプリで使うためのプラグイン「google-analytics-plugin」についての紹介です。
そう言えば入れてなかった…と気づき、実装。

GitHub のページはこちらから。

https://github.com/danwilson/google-analytics-plugin
https://github.com/danwilson/google-analytics-plugin

 

実装方法については、こちらのサイトが分かりやすいかと。

Google Analyticsプラグインを使ってアプリの行動分析を行おう|モナカプレス
https://press.monaca.io/atsushi/447

まず下記のコマンドでプラグインをインストールします。

cordova plugin add https://github.com/danwilson/google-analytics-plugin.git
// または
cordova plugin add cordova-plugin-google-analytics

インストールが終わったら、下記のコードを deviceready イベントのタイミングで実行します。

window.ga.startTrackerWithId('[トラッキングID]');

画面を追跡するには下記のコードを利用します。

window.ga.trackView('[画面名]')

また、ボタンを押したり、検索を実行したタイミングなどでイベントを記録したい場合には、下記のコードを追加します。

window.ga.trackEvent('Category', 'Action', 'Label', Value);

Label と Value はオプションで、Value には数値が入ります。

意外と簡単!と思ったのですが、実は最初のトラッキング ID の指定から躓いております。
Google Analytics のページで、新しいプロジェクトを追加したのですが、モバイルアプリを選択すると、「トラッキングIDの発行」ではなく「アプリの追加」になっていて、ここでは ID が取得できないのかも?
ならどこに?と探しているのですが、未だ見つけられておりません。

で、色々見て調べていたのですが、そもそも、プロジェクト作成時に Firebase のプロジェクトと連携させたんですよね。
…これは、Google Analytics ではなく、Firebase のアナリティクスを使った方が早いのでは…!
ということで、その方向で進めてみたいと思います。

 

以上、Google Analytics を Cordova アプリに導入するためのプラグイン「google-analytics-plugin」のご紹介でした。

  • この記事いいね! (0)
asaba 著者:asaba

【ButterKnife】バターナイフは明示的にgradleに書くべき

viewのメソッドを簡潔にかくことが出来るライブラリです。一般的なviewを使いたい時は、findViewByIdで紐付けるだけで使うことが

できますが、これが複数のviewとなると、同じようなコードができてしまいこれでは可読性に欠けてしまいます。

バターナイフは、このダブつくview定義を事前に定義させることでsetContentViewの下からviewの操作を可能にしてくれるので、複数の

ビューを使いたいけど管理が大変なエンジニアさんには重宝されています。こんな感じ↓

class ExampleActivity extends Activity {
@BindView(R.id.title) TextView title;
@BindView(R.id.subtitle) TextView subtitle;
@BindView(R.id.footer) TextView footer;

@Override public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.simple_activity);
ButterKnife.bind(this);
// TODO Use fields...
}
}

 

今自分が開発しているアプリもバターナイフを使って管理しているのですが、グレイドル(また出たなお前)のバージョンを上げたら

やっぱりというべきかエラーに通せんぼされてしまいました。

 


Error:Execution failed for task ':app:javaPreCompileDebug'.
&gt; Annotation processors must be explicitly declared now. The following dependencies on the compile classpath are found to contain annotation processor. Please add them to the annotationProcessor configuration.
- butterknife-6.1.0.jar (com.jakewharton:butterknife:6.1.0)
Alternatively, set android.defaultConfig.javaCompileOptions.annotationProcessorOptions.includeCompileClasspath = true to continue with previous behavior. Note that this option is deprecated and will be removed in the future.
See https://developer.android.com/r/tools/annotation-processor-error-message.html for more details.

訳してみました。

プロセッサは明示的に宣言されなければなりません。次のコンパイルクラスパスへの依存関係に、注釈プロセッサが含まれています。 annotationProcessor設定にそれらを追加してください。

 

どうやらバターナイフはグレイドルのバージョンに合わせてannotationProcessorとして定義しなければいけないみたいです。グレイドル

アップデート前は普通に定義しなくても使えていたのに・・・。

まあもうできたのが6年前なので仕様が変わっていても不思議じゃないですよね。という訳でannotationProcessorにバターナイフを定義してあと残り

なく解決です。

 

annotationProcessor "com.jakewharton:butterknife:6.1.0"
compileOnly "com.jakewharton:butterknife:6.1.0"

このライブラリに変わるものがすでに出てきているか分かりませんが、ライブラリとしては書くことが少なく学習コストも低いので

いとまがあれば使ってみたいと思います。

  • この記事いいね! (0)
著者:杉浦

ハインリッヒの法則とコード量とバグの量

 ハインリッヒの法則とは次の様な経験則です。

ハインリッヒの法則は、労働災害における経験則の一つである。1つの重大事故の背後には29の軽微な事故があり、その背景には300の異常が存在するというもの。

 要は極低確率で危険な事態に陥ることがあるならばいずれは致命的な事態が起きる、というものです。
 コーディングにおけるコード量とバグの量の関係にも似たことが言えます。稀にバグが起きるような記述を大量に行うならばいずれバグが起きる、ということです。この問題に対処する方策は主に二つ。一つは全くバグの起きない記述を行うことです。バグの起きる確率が0%ならばいくら重ねても問題ありません。二つ目は記述の量を少なくする方法です。僅かなバグの発生率はわずかなままにとどまり、バグが起きることは滅多にありません。
 コードを関数やクラスなどの部品にして組み合わせていくプログラミング手法(構造化プログラミングの系譜)はこの両方を満たすための手法として有効です。小さな部品ならばバグがないことを保証することができるほどのテストを行うことが可能であり、その様な部品を呼ぶことは全くバグの起きない記述を行うことです。部品を繰り返し呼ぶならば全体のコード量は繰り返されたコピペの改変コードの様な雑多なものに比べて格段に少なくなります。

  • この記事いいね! (0)
takahashi 著者:takahashi

Ubuntu 18.04で廃止されたgksuを使わずに、GUIアプリを管理者権限で実行する方法

Linuxに置いてのGUIアプリを管理者権限で起動する方法に”gksu”というコマンドを経由するという方法が以前はありました。

ターミナルからであれば非推奨ながらも “sudo -H” コマンドなどで起動できたのですが、例えばGNOMEなどから直接ショートカットで実行したい場合などでは、ターミナルが開かないためパスワードが入力できないという問題があります。

gksuコマンドではsudoと同じように権限の昇格を行ってくれる上、GUIのフロントエンドも表示してくれるので、ターミナルを経由せずに管理者権限でアプリやコマンドを実行させることが可能でした。

ところが、このgksuが本家debianのリポジトリから削除されたことに伴い、Ubuntu でも バージョン18.04で削除されてしまいました。

$ sudo apt install gksu
[sudo] hoge のパスワード: 
パッケージリストを読み込んでいます... 完了
依存関係ツリーを作成しています                
状態情報を読み取っています... 完了
パッケージ gksu は使用できませんが、別のパッケージから参照されます。
これは、パッケージが欠落しているか、廃止されたか、または別のソース
からのみ利用可能であることを意味します。

E: パッケージ 'gksu' にはインストール候補がありません

よって今後は、gksuコマンドを使ってGUI上から管理者権限でアプリを起動することができません。

これでは困ってしまうので、代替策をいろいろ調べたところ、下記記事を発見。

Linux Mint 19: 「’gksu’ not found」 廃止された gksu の代わりの方法 – 221B Baker Street

どうやら、代わりに”pkexec”コマンドを利用すればいいようです。

ただし、このコマンドをgksuのようにGUIで利用できるようにするには

pkexec env DISPLAY=$DISPLAY XAUTHORITY=$XAUTHORITY コマンド

のようにする必要があるようです。

しかし、これを毎回打つのはかなり面倒なので、aliasへ登録しておきます。
上記の記事では

alias pkexec='pkexec env DISPLAY=$DISPLAY XAUTHORITY=$XAUTHORITY'

のようにpkexecを上書きすることをお勧めされていましたが、これだとオプション無しの”pkexec”コマンドが使えなくなってしまいますので、僕の場合はこのようにしました。

alias gksu='pkexec env DISPLAY=$DISPLAY XAUTHORITY=$XAUTHORITY'

こうしておけば、もはや存在しなくなったgksuコマンドでオプション付きのpkexecが呼び出せますし、新しいコマンドを覚える必要もないので便利です。

aliasの効果は一時的なので、永続化させるためにこの記述を、

~/.bashrc

ファイルの最終行あたりに追記しておきます。

こうすることで、ログインするたびに.bashrcに記述したaliasコマントが実行されるので、常に使用することが可能になります。

ただし.bashrcはGNOMEのようなデスクトップ環境から直接呼び出されないので、
(例えばショートカットを作成してダブルクリックだけで起動したい場合などで) GUIから直接aliasで作ったgksuコマンドをたたいても、先ほどのaliasが設定されていない為存在しないコマンドとなり実行できません。

そこで、先ほどのオプション付きpkexecコマンドをシェルスクリプトファイルに書き、パスが通っている場所(/usr/local/binなど)に置いて、普通のコマンドとして扱えるようにしてしまいます。

例えば、

vi /usr/local/bin/gksu

のようにして、次のように記述して保存します。

#!/bin/bash

pkexec env DISPLAY=$DISPLAY XAUTHORITY=$XAUTHORITY $1

こうすることで、gksu コマンド を実行したときに、コマンドが$1に渡されるので目的の動作をさせることができますし、パスが通ったディレクトリに置くことで、どのディレクトリからもコマンドとして実行できます。

つまり、GNOMEのようなデスクトップ環境上でも、直接自作の”gksu”コマンドが実行できるようになります。

gksuが使えなくてお困りの方は是非一度試してみてください。

  • この記事いいね! (0)