furuyamah

furuyamah

  • MySQL5.5以降 sjis環境でDATETIMEにindexが効かず遅い

    MySQLを5.6にバージョンアップした際に、一部のクエリがやたら遅くなってしまい困りました。 散々ggった結果、ヒットした情報が以下。

    character_set_connection = sjis でDATETIME型のカラムにインデックスがきかないはなし

    http://bugs.mysql.com/bug.php?id=74449

    なんと、character_set_connection = sjis の場合に限ってDATETIME型,DATE型カラムに誤った型変換が行われるらしい。 sjisなんてやめなはれ、は正論ですが、残念ながらsjisを捨てられるシステムではないので、以下のようにCASTで対処。

    date型の場合

    AND dl.date >= '2014-08-10'
    ↓
    AND dl.date >= cast('2014-08-10' as date)
    

    datetime型の場合

    AND dl.date >= '2014-08-10'
    ↓
    AND dl.date >= cast('2014-08-10' as datetime)
    

    ご参考まで。

    ...
  • Google Glass Word Lens と Play game

    Google Glassレポートその2です。

    前回は借り物でしたが、今回は Google Glass Explorer Edition Ver 2.0 を自社で購入してのレビューです。
    すごい!代表カッコイイ!!!

    まず、借りていたver1と今回のver2の違いについて。

    ggっても明確な情報は捕まりません。

    Google Glass 2 offers minor but important hardware updates

    一番よくまとまっていると思われたのが、↑のサイト。

    で、その情報によれば

     

    • イヤホンが付いてくる

    Glassはメガネのツルにあたる部分に骨伝導スピーカーが付いています。
    大体はこれで事足りると思うのですが、聞こえない場合の手段が追加された形だと思います。
    より万人向けに。素晴らしいことです。

     

    • 処理速度10%向上

    ほんの少しですがパフォーマンスが向上している模様。
    イイネ!

     

     

    overheat

    ちなみに重たいアプリを動かしていると熱くなり使用を控えるようメッセージが出るのは変わりませんでした。
    残念…

     

     

    続いて前回おざなりなレビューをした2つのアプリの使い方について

     

     

    device-2014-06-11-170958

    OK glass が表示されている状態で、Glassの右こめかみのあたりをタップ。
    インストールされているアプリを切り替えられる状態になります。
    メガネのツルの部分を左右にスワイプし目的のアプリを探します。

     

     

    translate_title
    Word Lensを見つけたら、すかさずタップ。

    ...
  • Google Glass ファーストインプレッション

    噂のGoogle Glass。USでは既にかなり楽に入手できるようになっています。
    んが、日本では買えません。なぜ買えないんだぁー!
    リスクのある並行輸入業者に頼めということでしょうか。
    いや、無理です。(Glassのお値段的に)

    でも、持っている人は持っているんですよねぇ。
    Early Adopterな方々との情報格差がまた広がる…そんな絶望感を抱えながら、我社の代表にダメ元で相談したところ、期間限定ではありますが、Glassをお知り合いの方から借りてくれるとのこと!
    ありがとうございます!さすがです!!

    そんなこんなで触らせて頂いたGoogle Glassの感想です。
    120%私見です。ご容赦下さい。


    さて、メガネ型のウェラブルデバイスといえば、どうしても期待してしまうのがAR。
    拡張現実ではないでしょうか。

     

    AR1

    ↑こんなの。

    現実を上書きし、世界の有り様を拡張してしまう….サイバー!!(鼻血ブー
    Google Glassはどこまでそんな世界を引き寄せてくれるのでしょうか?
    ワクワクしながら、試してみました。

    結果:
    Google Glassは ARを実現するツールではない。

    まあ、ある程度分かっていた事ではあるのですが、Glassは視界の右上に小さなディスプレイを追加するものです。
    決して存在しないものをあたかも存在するかのように感じさせてくれるデバイスではありません。
    ただ、それでもなお、この製品が市場に受け入れられ順調に成長を続けていけば、いずれは万人が思い浮かべるARの世界を実現するようなデバイスにたどり着くかもしれない…そんな可能性は感じました。

    このデバイスの可能性を試すには、アプリを追加する必要があります。
    ところがアプリを追加するために必要なAndroidアプリ、MyGlassは日本からはダウンロードできません。
    なってこった。

    しょうがないので野良アプリをインストールします。
    私は以下からダウンロードしました。

     

    Download Latest MyGlass APK

    あくまで自己責任でお願いします。

    アプリを起動しBluetoothでペアリングすれば準備完了。
    ワシワシアプリをインストールしましょう。

    私がインストールしたアプリの中で特に気になったのは以下の2つです。

    Mini Games

    首の動きで操作するのが新しい!そして若干ARぽい。

     

    Word Lens

    見たものを翻訳できる!
    これは…未来ぽい!

    ...
  • Android Expansion files(拡張ファイル) アップロード

    拡張ファイルのアップロード方法がわかりません。
    Devleloper Consoleのヘルプを見ると

    注: 現在のところ、新しい Google Play デベロッパー コンソールの制限により、新しいアプリをアップロードする最初の APK ファイルに拡張ファイルを追加することはできません。この問題を回避するには、まず APK ファイルのみをアップロードし、必要に応じて拡張ファイルを追加した APK ファイルで置き換えてください。これらの操作はドラフト状態の APK でも行えますので、既存ユーザーや潜在ユーザーに影響が及ぶことはありません。

    どうやら拡張ファイルを追加できない事はわかります。しかし回避するための方法がわかりません。
    「拡張ファイルを追加したAPKファイルで置き換えてください」?
    それじゃあ、APKと拡張ファイルが一体化しているじゃないですか!

    頑張って調べてみると

    http://stackoverflow.com/questions/15109191/how-to-upload-apk-expansion-files-in-new-developer-console

    がヒット。

    it’s a dummy apk. When you first upload your apk you will not have any option for the expansion files. From second apk onwards you will have that option. It looks weird

    ...
  • TortoiseGit + GitHub + port 443

    TortoiseGitとGitHubで快適にGit生活を送っていたのですが、ある日突然pullできなくなりました。
    どうも GitHubとの22番ポート経由での通信ができなくなった模様。

    なぜ?

    22番といえばsshのポート。AWS上のサーバーにもガシガシsshしているので、社内ネットワークの
    どこかで閉じているとは考えられません。GitHub側から締め出しをくらったのかなぁ?
    仮にも有料プランユーザーなのにそんなことあるの??

    結局原因不明ながらも 443番ポート経由で通信するように環境を変更することで対応しました。
    TortoiseGitとGitクライアントはインストールされている前提です。

    インストール方法は以下にとっても良くまとまっています。

    TortoiseGitを日本語化するまでの手順

    - ssh クライアントを切り替える

    0 右クリックしコンテキストメニューを開き、そこからTortoiseGitの設定を開きます。

    1
    左ペインのネットワークを選択し、右ペインに表示されたsshクライアントが以下でなければ変更します。

    C:\Program Files (x86)\Git\bin\ssh.exe

    - 鍵を再作成する
    TortoiseGitを使っている場合おそらく標準であろうTortoisePlink.exeをSSHクライアントに設定している場合
    証明書に自動的にパスフレーズが設定されるらしく他のsshクライアントでは再利用できないので、再作成します。

    2
    $ ssh-keygen -t rsa -C “メールアドレス”

    - GitHubに公開鍵を登録する

    3
    GitHubのサイトに行き先程作成した公開鍵(*.pub)の内容をコピペします。

     

    - ssh設定ファイルを作成する
    以下のファイルを作成します。

    ...
  • Android アプリに設定されたパーミッションを取得する

    もしmanifestに設定されていないパーミッションが必要な機能を使うと無慈悲なSecurityExceptionが発生します。
    それはもう、catch節をスルーするくらい無慈悲です。
    
    このExceptionが発生するという事は、manifestとコードが不一致だということなので、コード直せボケ!
    なのかもしれませんが、やはりコード内でパーミッションをチェックして条件分岐したい事もあるものです。
    例えばライブラリとして公開する場合とか。
    
    そんなわけで、パーミッションのリストを取得するメソッドと、お目当てのパーミッションがmanifestに存在するのか確認するメソッドをお届けします。
    [code lang="java" light="true"]
       /**
         * 指定されたパーミッションがmanifestに記載されているかどうか確認します。
         * 
         * @param checkPermission 調査するパーミッション
         * @param context コンテキスト
         * @return true:記載されている /false:記載されていない
         */
        public boolean hasPermission(String checkPermission, Context context) {
            if (checkPermission == null || context == null) {
                // 引数が渡されていないケース
                return false;
            }
            String[] requestedPermissions = getPermissionList(context);
            if (requestedPermissions == null) {
                // manifestに一件もpermissionが設定されていないケース
                return false;
            }
            for (String str : requestedPermissions) {
                if (str.equals(checkPermission)) {
                    // 調査するパーミッションが存在したケース
                    return true;
                }
            }
            // 調査するパーミッションが存在しなかったケース
            return false;
        }
    
        /**
         * manifestに記載されているパーミッションのリストを返します。
         * 
         * @return パーミッションのリスト
         */
        public String[] getPermissionList(Context context) {
            PackageManager packageManager = context.getPackageManager();
            PackageInfo packageInfo = null;
            try {
                packageInfo = packageManager.getPackageInfo(context.getPackageName(), PackageManager.GET_PERMISSIONS);
            } catch (NameNotFoundException e) {
                return null;
            }
            return packageInfo.requestedPermissions;
        }
    [/code]
    
    
    
    
    使い方
    
    [code lang="java" light="true"]
    String checkPermisson = "android.permission.READ_PHONE_STATE";
    
    if (hasPermission(checkPermisson, context)) {
        Log.d("TAG", checkPermisson + " exist!");
    } else {
        Log.d("TAG", checkPermisson + " not exist!");
    }
    [/code]
    
    
    
    お役に立てば。
    
    ...
  • Android : WebView と HttpClient 間で セッションを同期する

    WebViewでログインした後、HttpClientを呼び出すと・・・あれログインしていないジャン! 逆もまたしかり。

    Androidの中ではWebViewとHttpClientは、例えれば別のブラウザとして扱われるようです。

    この件についてはあちらこちらで説明されています。

    [Android]WebView、HTTPClientでSessionを共有する

    HttpClientとWebViewの連携

    が、更になんも考えないで済むように同期だけを行うクラスを作成してみました。よかったらどうぞ。

     

     

     

    [code lang=“java” light=“true”] package your.package;

    import java.util.List;

    import org.apache.http.client.CookieStore; import org.apache.http.cookie.Cookie; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.impl.cookie.BasicClientCookie;

    import android.webkit.CookieManager; import android.webkit.CookieSyncManager;

    /** * HttpClient, WebView間でセッションを同期するためのクラス */ public class SessionSync {

    // COOKIEの送出するドメインを指定します
    private static final String YOUR_DOMAIN = "your.domain";
    
    // COOKIE取得用のドメイン(.をつけてサブドメインもカバーします)
    private static final String COOKIE_DOMAIN = "." + YOUR_DOMAIN;
    // COOKIEを送出するURL
    private static final String COOKIE_URL = "http://" + YOUR_DOMAIN;
    
    // セッションIDを格納するパラメータ名を指定します
    // これはPHPの例
    private static final String SESSID = "PHPSESSID";
    
    /**
     * HttpClient側のセッションIDをWebViewに同期します
     * 
     * @param httpClient セッションを同期するHttpClient
     */
    public static void httpClient2WebView(DefaultHttpClient httpClient) {
        CookieStore store = httpClient.getCookieStore();
        List<Cookie> cookies = store.getCookies();
        CookieManager cookieManager = CookieManager.getInstance();
        for (Cookie cookie : cookies) {
            if (cookie.getDomain().indexOf(COOKIE_DOMAIN) < 0) {
                continue;
            }
            if (!SESSID.equals(cookie.getName())) {
                continue;
            }
            // ここで削除するとsyncしたタイミングでsetしたcookieも
            // 消える場合があるので削除は見合わせ
            // cookieManager.removeSessionCookie();
            String cookieStr = cookie.getName() + "=" + cookie.getValue();
            cookieManager.setCookie(COOKIE_DOMAIN, cookieStr);
            CookieSyncManager.getInstance().sync();
        }
    }
    
    /**
     * WebView側のセッションIDをHttpClientに同期します
     * 
     * @param httpClient セッションを同期するHttpClient
     */
    public static void webView2HttpClient(DefaultHttpClient httpClient) {
    
        String cookie = CookieManager.getInstance().getCookie(COOKIE_URL);
        String[] cookies = cookie.split(";");
        for (String keyValue : cookies) {
            keyValue = keyValue.trim();
            String[] cookieSet = keyValue.split("=");
            String key = cookieSet[0];
            String value = cookieSet[1];
            if (!SESSID.equals(key)) {
                continue;
            }
            BasicClientCookie bCookie = new BasicClientCookie(key, value);
            bCookie.setDomain(COOKIE_DOMAIN);
            bCookie.setPath("/");
            CookieStore store = httpClient.getCookieStore();
            store.addCookie(bCookie);
        }
    }
    

    } [/code]

    ...
  • パスワード管理アプリ(Android版)

    パスワードは使い回してはいけない。パスワードは一定の文字数以上でなければならない。パスワードは定期的に変更しなければならない…そんなの覚えるの無理でしょ!

    というわけで、社内向けに作成したパスワード管理アプリを公開します。

    既に山ほどのパスワード管理アプリがgoogle playで絶賛公開中ですが、それらのアプリを採用しなかった理由は

    • (社内用としては)不要な権限を要求するアプリが多い
    • 必要な機能がない
    • マルウェアをつかんでしまう可能性がある

    といったためです。

    今回作成したアプリの特徴は

    • ランダムパスワード自動生成機能搭載
    • 要求する権限はSDカード読み書きのみ(バックアップのため)
    • 2ヶ月以上更新していないパスワードを警告
    • 充実したソート機能
    • マッシュルーム対応
    • マッシュルーム対応していないIME向けに、クリップボードコピーも対応
    • Android 4系のカッコイイUIを2.2以上にご提供
    • マルウェアではない(自己申告になりますが…)

    ぜひお試し下さい。

    インストール方法:

    1. [設定] > [アプリケーション] > [不明な提供元]チェックボックスをON
    2. 以下のリンクをクリックしてapkをダウンロード
    3. インストールする

    PassBox ver 0.9.5

    ...
  • AndroidのLogCatのTagにクラス名、メソッド名、行番号を表示するクラス

    たとえデバッカがあってステップ実行が出来ようとも、デバックログの手軽さは手放せません。Androidの場合、標準のLogクラスを使えば、その目的を達成できるのですが、できたらTagに、クラス名、メソッド名、行番号が出たら嬉しいと思う人が多いはず!

    と思ってぐぐってみたら、実現している方がいました。

    [

    AndroidのLogCatのTagで「クラス名.メソッド名:行番号」と表示するには?

    ](http://kinsentansa.blogspot.jp/2012/06/androidlogcattag.html)

    せっかくなんで、これを即使えるようにクラス化してみました。

    [code lang=“java” light=“true”] package jp.fuga.hoge.android.app;

    import java.util.regex.Pattern; import jp.fuga.hoge.android.app.BuildConfig; import android.util.Log;

    /** * ログ出力クラス。
    * ログを出力する場合には必ず本クラスを使用すること。
    * リリース時には、デバックログを出力しないよう設定される。 * */ public class L {

    /**
     * デバック用ログを出力する。 本番リリース時は出力されない。
     * 
     * @param msg 出力するメッセージ
     */
    public static void d(String msg) {
        if (!BuildConfig.DEBUG) return;
        Log.d(getTag(), msg);
    }
    
    /**
     * エラー用ログを出力する。 <br>
     * catchの中や想定外の動作でログを出力する場合に使用すること。<br>
     * 本番リリース時も、起きたエラーを解析するために本ログは出力される想定。
     * 
     * @param msg 出力するメッセージ
     */
    public static void e(String msg) {
        Log.e(getTag(), msg);
    }
    
    /**
     * 同上
     * 
     * @param msg
     * @param t
     */
    public static void e(String msg, Throwable t) {
        Log.e(getTag(), msg, t);
    }
    
    /**
     * タグを生成する
     * 
     * @return className#methodName:line
     */
    private static String getTag() {
    
        final StackTraceElement trace = Thread.currentThread().getStackTrace()[4];
        final String cla = trace.getClassName();
        Pattern pattern = Pattern.compile("[\\.]+");
        final String[] splitedStr = pattern.split(cla);
        final String simpleClass = splitedStr[splitedStr.length - 1];
    
        final String mthd = trace.getMethodName();
        final int line = trace.getLineNumber();
        final String tag = simpleClass + "#" + mthd + ":" + line;
    
        return tag;
    }
    

    }

    ...
  • Android(java)で電話番号にいい感じに'-'(ハイフン)を入れる方法

    電話番号って

    [市外局番] - [市内局番] - [顧客番号]

    みたいにハイフン2つで番号を区切る構造になっていますが

    0312345678

    みたいな、ハイフンが入っていない番号にハイフンを入れようと思うと、これが案外難しいです。

    市外局番は、2桁の時もあれば、3桁、4桁の時もあるし、携帯は3桁だし、ちょっと自分でなんとかするのは手に余ります。

    ウィキペディアの市外局番の項

    こんな時は長いものにまかれましょう、という事で信頼できそうなとこが提供しているライブラリを活用です。
    本家googleがライブラリを出してました。

    libphonenumber

    トップページ

    ダウンロード

    基本的には一番新しいものをダウンロードして、Android projectのlibsに放りこめば準備完了です。

    ※apkを作る時にエクスポートするライブラリにチェックを付けるのをお忘れなく。

    使い方は極めて簡単。

    [code lang=“java” light=“true”] /** * 数字が羅列された電話番号をハイフン付きの電話番号に変換する * @param incomingNumber * @return ハイフン付き電話番号 */ private String getFormattedPhoneNumber(String incomingNumber) { PhoneNumberUtil phoneUtil = PhoneNumberUtil.getInstance(); try { PhoneNumber pn = phoneUtil.parse(incomingNumber, “JP”); incomingNumber = phoneUtil.format(pn, PhoneNumberFormat.NATIONAL); } catch (NumberParseException e) { Log.e(“app tag”,“電話番号をフォーマットできませんでした”, e); } return incomingNumber; }[/code]

    ...
  • Encrypted Http Live Streaming

    自社サイトでiPhone向け動画を配信するにあたり、採用した手法です。

    • 参考

    HTTP Live Streaming(Encrypt)
    ここが詳しいですが、暗号化するとうまく再生できないのでアレンジしています。

    iPhone, iPad, iPod – HTTP Live Streaming (HLS) with free tools on Windows
    エンコードのオプション等が参考になります。

    • 方針

    元動画

    mpeg2ts

    分割

    暗号化

    再生

    • プラットフォーム

    Ubuntu 12.04

    ffmpeg は apt-get でインストール。

    ...