カテゴリーアーカイブ 言語

村上 著者:村上

【Cordova】cordova-plugin-media使用時の音楽ファイルパスの指定について

dちょっとハマりかけたので、備忘録としてまとめ。
昨日ご紹介した、Cordova アプリで音楽ファイルを扱うためのプラグイン「cordova-plugin-media」の音楽ファイルのパスの指定方法についてです。

なお、昨日の記事はこちらから。

【Cordova】音声ファイルを扱うためのプラグイン「cordova-plugin-media」

 

で、ハマりかけたのは、Android での音楽ファイルのパスの指定方法についてです。
単純に、画像ファイルなんかと同じように、www ディレクトリ以下のパスを指定すればOKかと思ったら、それでは動かず、Code: 1 のエラーが発生しました。
なお、エラーコード 1 は、MediaError.MEDIA_ERR_ABORTED というエラーとのことです。
Aborted は「中止」という意味なので、エラーで途中で中断したという感じかな?

で、色々検索したところ、下記の記事がヒットしました。

【Monaca】Mediaプラグインを使う時に気をつけたいこと【Cordova】|webico
https://blog.webico.work/monaca-cordova02

その中で、下記のようにファイルパスを取得している関数があり、それを音楽ファイルの頭につけていたので、それを参考に修正しました。

// パス取得の関数
function getPath() {
    let str = location.href;
    let i = str.lastIndexOf('/');
    return str.substring(0, i+1);
}

私の場合、Android の時は音楽ファイルの頭に file:///android_asset/www/ を付けるようにしたら問題なく動作するようになりました!
なお、iOS の場合、単に www ディレクトリからのパスだけでOKだったので、cordova-plugin-device を利用して、プラットフォームごとに処理を切り替えるようにしましょう。

最終的なコードは下記のようになりました。

playMedia() {
  let src = '[www からの音楽ファイルのパス]';
  if (window.device.platform == 'Android') {
    src = 'file:///android_asset/www/' + src;
  }
  let media = new window.Media(src);
  media.play();
}

なお、前の記事でも書きましたが、Android の場合はリリースの処理をきちんと行いましょう。
私は…今から追加します。

 

以上、cordova-plugin-media の音楽ファイルのパスの指定方法でした。
お困りの方がいましたら、参考にしていただければと思います。

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

【Cordova】音声ファイルを扱うためのプラグイン「cordova-plugin-media」

Cordova アプリで効果音を出したいという要望があったので、メディアプラグイン「cordova-plugin-media」をインストールしました。
HTML5 の audio タグを使用する方法もありますが、iOS では動作しない可能性もあるとのことでしたので、プラグイン導入を選択しました。

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

GitHub – apache/cordova-plugin-media: Apache Cordova Plugin media
https://github.com/apache/cordova-plugin-media

 

実装方法ですが、まずプラグインをインストールします。

cordova plugin add cordova-plugin-media

で、下記のように使用したい音声ファイルや、成功/失敗時に実行する関数などを定義します。

const media = new Media('[音声ファイルのパス]', [成功時の処理], [失敗時の処理], [ステータス変化時の処理]);

なお、音声ファイルのパス以外はすべてオプションなので、必要がなければ定義しなくてもOKです。

あとは、呼び出したいメソッドを任意のタイミングで実行するだけ!
私は単に音楽ファイルを再生したいだけだったので、下記を実行しました

media.play();

なお、OS のオーディオリソースを開放する release メソッドもあります。

media.release();

特に Android の場合、メディア再生に割り当てることができるインスタンスの数に限りがあるため、Media リソースが不要になった場合には必ず上記を実行しましょう。

 

以上、メディアを扱うための Cordova プラグイン「cordova-plugin-media」のご紹介でした。
どなたかの参考になれば幸いです。

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

【android WebView】webViewに被せたアクションバーに処理を実装する方法

最近になってまたWebViewを触り始めました。webViewってjavascriptとかのイメージが強いですがandroidでも頑張れば実装できるみたい

ですね。しかもこっちはネイティブだから処理速度も安定しているときたので使いこなせれば開発の引き出しが増えそうですね。

今回はそのwebviewを使っていて、アクションバーの中のアイコンをタップしたときに何らかの処理をするメソッドを載せていきます。

 

タップしたアイコンに応じて処理を切り分けるには、onOptionsItemSelected(MenuItem item)メソッドを使う必要があります。

このメソッドは、ヘッダーに当たるアレ。即ちアクションバーに配置したアイコンに応じて処理をswitchで分岐させる役割を

担っています。

例えば、switchの引数idの中身がhomeだった場合は、finish();で終了させてホームボタンにバックさせます。

 

<pre>@Override
public boolean onOptionsItemSelected(MenuItem item) {
    
    int id = item.getItemId();
    WebView webView = (WebView) findViewById(
            R.id.webView);
    switch (id) {
        case android.R.id.home:
            finish();
            break;
        case R.id.menu_share:
            ShareCompat.IntentBuilder builder = ShareCompat.IntentBuilder.from(this);

            String url = webView.getUrl();
            
            builder.setText(url);
            builder.setType("text/plain");
            
            builder.startChooser();
            break;
        case R.id.reload:
            webView.clearCache(true);
            webView.reload();
            break;
    }
    return super.onOptionsItemSelected(item);
}</pre>

 

このように、一般的なアプリのアクションバーにあるページ更新やシェア機能も切り分けて実装することができます。

 

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

【JavaScript】デザインを崩さずに任意の要素を角丸四角で囲うスニペット

 この記事で紹介するコードで描く角丸四角はあっさり壊れる角丸四角です。とにかく元のデザインを崩さずその場の画面で囲えればよい、という目的の際に有効に使えます。具体的には、テスト結果やwebページの説明で何かを囲って強調したい時です。
 実装は次のコードです。

targetSelector='#hogehoge';// ここに対象のセレクタを代入
// 対象の要素の位置と大きさを取得
targetTop = document.querySelector(targetSelector).getBoundingClientRect().top  + window.pageYOffset;
targetLeft = document.querySelector(targetSelector).getBoundingClientRect().left  + window.pageXOffset;
targetWidth = document.querySelector(targetSelector).getBoundingClientRect().width;
targetHeight = document.querySelector(targetSelector).getBoundingClientRect().height;
// 角丸四角の作成開始
div = document.createElement('div');
// 対象より少し大きめの大きさを指定する
div.style.width = 'calc(' + targetWidth + 'px + 2em)';
div.style.height = 'calc(' + targetHeight + 'px + 2em)';
// 対象より少し左上を要素の開始地点に指定する
div.style.top = 'calc(' + targetTop + 'px - 1em)';
div.style.left = 'calc(' + targetLeft + 'px - 1em)';
// 既にある画面のデザインと関係ないレイヤーに要素を配置すると指定
div.style.position = 'absolute';
// 背景色を完全透過に指定
div.style.background = '#FFF0';
// 境界線を太い赤線にすると指定
div.style.border = 'solid 3px';
div.style.borderRadius = '2em';
div.style.borderColor = 'red';
// モーダルの様なポップアップ相手でも上に乗せられると指定
div.style.zIndex = '100000';
// bodyの末尾に実体化させる
document.querySelector('body').appendChild(div);

 テストコード中にJavaScriptを実行させるようにして、テスト対象のセレクタをtargetSelectorに代入、このコードを実行、それからスクリーンショットを取る。そうするとテスト部分を強調したスクリーンショットが出来上がります。
 ブックマークレットにする場合は次のコードです。先ほどのコードを_surround関数としてグローバルスコープに定義し、グローバルスコープ中の変数targetSelectorを引数にした_surround関数を実行するブックマークレットです。

javascript:
_surround = (targetSelector) => {
targetTop = document.querySelector(targetSelector).getBoundingClientRect().top  + window.pageYOffset;
targetLeft = document.querySelector(targetSelector).getBoundingClientRect().left  + window.pageXOffset;
targetWidth = document.querySelector(targetSelector).getBoundingClientRect().width;
targetHeight = document.querySelector(targetSelector).getBoundingClientRect().height;
div = document.createElement('div');
div.style.width = 'calc(' + targetWidth + 'px + 2em)';
div.style.height = 'calc(' + targetHeight + 'px + 2em)';
div.style.top = 'calc(' + targetTop + 'px - 1em)';
div.style.left = 'calc(' + targetLeft + 'px - 1em)';
div.style.position = 'absolute';
div.style.background = '#FFF0';
div.style.border = 'solid 3px';
div.style.borderRadius = '2em';
div.style.borderColor = 'red';
div.style.padding = '0.5em';
div.style.zIndex = '100000';
document.querySelector('body').appendChild(div);
};
_surround(targetSelector);

 あらかじめコンソールでtargetSelector変数に対象のセレクタを代入してから実行します。例えば次の様に動かせます。

 ブラウザの開発者ツールに要素のセレクタを作ってもらい、コンソールで代入、実行としたわけです。こういったコードを使うとテストや説明書作りが多少は楽になります。

  • この記事いいね! (1)
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)
村上 著者:村上

【JavaScript】LocalStorageを扱う上での注意点

うっかり忘れそうなので、自戒も込めてまとめ。
ローカルにデータを無期限に保存できる便利な LocalStorage の注意点です。

 

知っている人には、そんなこと?と思われそうですが、LocalStorage は値は必ず 文字列 で保存されます。
私は、つい Boolean 型をそのまま格納してしまい、若干ハマりかけました。

参考にさせていただいたサイトはこちらから。

localStorage 使い始めてハマりがちな罠 – #生存戦略 、それは – subtech
http://subtech.g.hatena.ne.jp/secondlife/20091201/1259631283

こちらでも書かれているように、LocalStorage は自動で型変換が行われます。
で、console.log で確認すると、きちんと true または false が格納されているのですが、これは Boolean 型ではなく文字列なので要注意。
ログで見るだけだと、正しい値が保持されているように見えてしまうんですよね…。
なので、if 文等で比較をして結果がおかしい場合は、型の確認までするようにしましょう。

 

以上、LocalStorage を利用する際の注意点についてでした。
皆様もご利用の際はお気を付けください。

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

【JavaScript】JSDocからドキュメントページを作成するJSDoc 3の紹介

jsdoc – npm
jsdoc3/jsdoc: An API documentation generator for JavaScript.
 JSDoc 3はJSDocを読み取り、JSDocに従ってからドキュメントを表すHTMLページを作成してくれます。インストールはnpm installでプロジェクトに追加するだけです。
 実行方法は設定を決めて、コマンドを叩く。コマンドはカレントディレクトリをプロジェクトのルートにして

./node_modules/.bin/jsdoc [対象ファイル、フォルダのパス] -r -d [出力先のパス] -c [設定ファイルのパス]

です。-rはrecursiveのRであり再帰的にフォルダを見るオプションです。
 設定ファイルは必要になることがそれなりあります。これはJavaScriptはJavaScriptそのままで書かれないことがそれなりにあるためです。TypeScriptなどのAltJSやVue.jsなどの独自の形式を持つフレームワークが良く用いられます。そういった素のJavaScriptでない環境のためにプラグインが開発され、それを読み込み、設定するためにjson形式の設定ファイルが必要になります。
 例えばVue.js用の設定ファイルは次になります

{
  "plugins": ["node_modules/jsdoc-vuejs"],
  "source": {
    "includePattern": "\\.(vue|js)$"
  },
}

 読み込むプラグインを決定し、拡張子vueのファイルも読み込むという風に設定しています。
 こうして出来上がったページが次の画像です。

 JSDoc 3にはテンプレートが用意され、拡張されています。テンプレートのうちのいくつかのデモは次のサイトから見ることが出来ます。
jsdoc3 template list examples

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