HybridAuth を触ってみた

FacebookでTwitterやFacebookへのログイン機能をこれ1個で実装できるPHPライブラリ「HybridAuth」:phpspot開発日誌っていう面白そうな記事が回ってきたから触ってみた。備忘録もかねてできたことを列挙してみる。

ダウンロード

以下のページのダウンロードって書いてるところからダウンロード

ファイルの中身

簡略化して列挙すると以下。

├─examples
│  ├─facebook_integration
│  ├─hello_world
│  ├─signin_signup
│  ├─social_hub
│  └─widget_authentication
└─hybridauth
    └─Hybrid

中身を見ると多分こんなかんじと思われる。僕は簡単に認証出来るだけでよかったからhallo_wordしか触ってない。ほかはざっと読んだだけだから間違ってるかも

  • facebook_integrationがFacebookでやる場合の簡単な使い方
  • hallo_worldが一番簡単な使い方
  • single_signupがMVCで分けてかける簡単なアプリを作るための雛形っぽい。DBまである
  • social_hubがマルチコネクトの管理までやってくれそう。SNS的なやつを作る雛形っぽい
  • widget_authenticationがボタンが並んだ認証画面を作る奴っぽい
  • hybridautoが本体

config.phpを変更

config.phpで以下の部分を弄る必要がある

  • base_urlをhybridauthを配置したURLを記載。ファイルの中身の「hybridauth」フォルダのURLを書くことになる。
  • providersで使うやつをenabledをtrueにして必要なkeyを入力

動かしてみる

とりあえずtwitter認証をやってみたかったから自分のアプリケーションIDとかをconfig.phpに入力して、index.phpに書いてある相対パスとか変更してhollo_world/index.phpを動かしてみると案外あっさり認証が動いた。これは便利。

試したURL。しばらくしたら消すかもしれないけど、Twitterで認証走ってsatohu20xxAppTestのアプリ名で「HybridAuthの日本語テストですぞ!!!」ってつぶやかれる。Tokenとかとってないからお試しにどうぞ。

ポストのテスト

せっかく認証まで言ったのでついでにポストも動かしてみる。

<?php
        $twitter->setUserStatus( "hogehoge" ); 
?>

みたいに書くと↓のように出力される。日本語もバッチリ出力されるんだけど、文字コードがShiftJISになっていたせいでエラーが返答され続けてちょっと悩んだ。。。

他にもAPIはあるみたい。Token取る奴もあるみたいだからいざとなればTokenとっちゃって色々やれば別にAPIがなくても問題ない。

http://hybridauth.sourceforge.net/apidoc.html
 hybridauth.sourceforge.net 

まとめ

Twitterしか試してないけどこれは便利。コードもわかりやすく書いてあるし、読みやすくてなにか起こった時でも自分で直せそう。これ使っていつかなんか作る。

PV至上主義っていい加減やめてほしくない?

あれって使ってる側としては何もいいことないよね。

確かにすごくわかりやすい評価だよね。目に見えて何回広告が表示されましたとか言いやすいし指標として分かりやすさは抜群。でもユーザが求めてるのって使いやすさとか表示速度の速さとかそっちじゃないですか。無料サービスとして使わせてもらってる立場で文句をいうのはなんだけど、このPV至上主義のせいでページを無駄に分割してるサイトが多すぎると思うんだよね。特にスマホ関連のサイトの無駄な分割っぷりったらありゃしない。画面が小さいってことと、回線が遅いってことを言い訳にしてるんだろうけど、たかだか文字を数百文字読み込んだところで1画像と転送量は変わらないんだからそんなねーだろってなる。

読み込み直したら新しい広告が出るから押し直すかもしれないじゃないとかそういう考え方もあるのかもしれないけどさ、次のページに行っても同じ広告とか出てる時があるわけでそれ全く意味が無いと思うんだよね。広告を出している側にしても見られもしないものに対してお金を払いたくないだろうし、ページを見に来ているユーザにとっても無駄な画面遷移が増えて読み込みの時間にいらいらするだけじゃない。まぁ、言ってもこっちはお金を払わずに見させてもらっている立場なんだから強く言えるわけないんだけど、最近は本当に無駄に記事を分割しているサイトが多すぎてめんどくさくなるんだよね。

もういっそのこと広告業者が同じIPから~秒以内にアクセスされた場合1PVとして数えます!みたいに宣言してくれれば無駄なページ遷移が減ると思うんだよなー。PV数は減るけどそのかわり1PVの重み付けは前よりも重くすれば別にWebページを作っている側も問題ないわけじゃない。どうせ入ってくるお金は一緒なんだったら使う人のことを考えて一回でもうちょっと文字を読み込んだほうがいいよなーって思ってくれるかもしれないわけじゃない。そうなってくれればもっと快適なネット環境になりそうだなというただの妄想。

僕がよく見るサイトとかが文字が多いサイトだから言えるだけのことで画像とか多いサイトだったら分割しないといけないんだろうし、広告出してる人も馬鹿じゃないから分割したほうがクリック率が上がるとかそういう統計的なものを調べてるんだろうけどね。ふと思ったから書いてみただけで特に落ちはない。

SASSを触ってみた

第16回 勉強会でのSASSがすごく便利そうだったので触ってみた。使い方の感想とメモ。

インストール

Macだったら以下のコマンド一発でOK。楽勝

sudo gem install sass

既存のCSSをSCSSファイルのコンバート

今までは生のCSSを記載していたから、どれだけの精度があるのか試しがてらCSSからSCSSへとコンバートしてみた。css2sassってコマンドがあるみたいだけど、お試しだから以下のウェブサービスで変換してみた。

No such app
 css2sass.heroku.com 

変換後のファイルと変換前のファイルを比べてみた感想としては、classとかidのネストを検出して変換しているように見える。僕としてはインデントとカッコの綴じ方とかが気に食わなかったけど、どういうふうに書けるのか?っていうのをCSSとSCSSとで比較できるという意味でかなり便利だと思う。

SASSファイルを監視して自動でCSSファイルに変換

これもコマンド一発。以下のコマンドで変換できる。

sudo sass input.scss:output.css

ディレクトリ指定とかコンパイルしたものを出力とか改行をちゃんと入れて出力とか色々オプションがあるらしい。詳しくは以下のURLの3を参考に。

mixinを書いてみる

mixin書くだけで十分捗ると言われていたので、mixiをとりあえず書いてみた。よくdivのbackgroundに画像を入れるたびに同じ事を書いていたのでまずはそこを変換してみた。

@mixin mixin-background-image($imageUrl:””, $size:contain) { background-image: url($imageUrl); background-position: center center; background-repeat: no-repeat; background-size: $size; }

使う場所には以下のように記載する。

@include mixin-background-image(“../img/arrow_sub.png”, contain); }

毎回書いている部分がちょっと減るからすっきりする。最初からSASSで記載していればもうちょっと共通的に使える部分をmixinで切り出すことで変更に強いCSSがかけるのかなぁという印象。ベンダープレフィックスをわざわざ書くのがめんどくさいのでそこら辺のmixinを書けばもっと楽になると思う。

まとめ

大体1時間ぐらいしか触ってないんだけど、SCSSで記載すればちょっと便利なCSSだと思って書くことができると思う。他にもいろいろ便利な機能はあるんだろうけど、とりあえずSASSとしてファイルを作ってみて同じ部分だけmixinで記載するってだけでも十分導入する価値はあると思う。今まで生のCSSを書いていた人は、今まで記載していたCSSの拡張子だけ変えてこれから先で弄る部分だけmixinで記載するって感じで使うのがいいのかなー。デザイナさんでもmixinしか使わないとかいうルールでやれば問題も発生しにくそう。ただ、watchでコマンド叩いてもらわないといけないってのがちょっときついかも。shell作るにしても「これ叩いて初めてくださいね。」みたいなルールが必要になるからちょっとだるい。

無限Swipeを実装してみる(ViewPager編)

無限にSwipeできる画面ってどうやって実装しているのかなぁと考えたのが事の発端。無限だったり循環だったりどっちでもいいんだけど、左はじまでいったら右はじに戻る奴だったり何個表示するかわからないものをSwipeで実装したりする場合を考えてみる。ぱっと思いつくのは以下の2つ。

  1. FrameLayoutで次のやつをずらしたりして頑張る
  2. ViewPagerでページ数をほぼ無限にする

ほんとうの意味で無限といえるのはFrameLayoutでtouchイベント拾ってScrollイベントをOverrideするやつなんだろうけど、数が増えるとLayoutの管理を自分で実装しないとメモリをばかみたいに食うことになるから手間がかかる。ということで、今回はViewPagerを使ってさっくりと組んでみた。

MainActivity.java

public class Main extends FragmentActivity {

    private InfinateSwipeViewPagerAdapter mPagerAdapter;
    private ViewPager mViewPager;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        mPagerAdapter = new InfinateSwipeViewPagerAdapter(getSupportFragmentManager());

        mViewPager = (ViewPager)findViewById(R.id.viewpager);
        mViewPager.setAdapter(mPagerAdapter);
    }

    @Override
    protected void onResume() {
        super.onResume();
        mViewPager.setCurrentItem(InfinateSwipeViewPagerAdapter.MAX_PAGE_NUM/2);
    }
}

InfinateSwipeViewPagerAdapter.java

public class InfinateSwipeViewPagerAdapter extends FragmentPagerAdapter {

    public static final int MAX_PAGE_NUM = 1000;
    private static final int OBJECT_NUM = 3;

    public InfinateSwipeViewPagerAdapter(FragmentManager fm) {
        super(fm);
    }

    @Override
    public Fragment getItem(int position) {
    	Fragment fragment;
    	int diff = (position - (MAX_PAGE_NUM / 2)) % OBJECT_NUM;
    	int index = (0 > diff) ? (OBJECT_NUM + diff) : diff;
    	switch(index) {
    	case 0:
    		fragment = new FirstFragment();
    		break;
    	case 1:
    		fragment = new SecondFragment();
    		break;
    	case 2:
    		fragment = new ThirdFragment();
    		break;
    	}
        return  fragment;
    }

    @Override
    public int getCount() {
        return MAX_PAGE_NUM;
    }
}

解説

今回の例は3つのFargmentが循環する例。ポイントは以下の3点。

  1. PagerAdapterのgetCountでそんなにSwipeできないだろーって数を与える(*1)。
  2. MainActivityのonResumeでPositionを真ん中に持ってくることで最初から左にもSwipeできるようにする。
  3. Positionは初期値をonResume()で変えてるからgetItem()で渡されるpositionを元に初期値からどれだけ移動したかを計算してInstanceを返答する。

注意点

実装する上で気をつけなければならないのは以下の3点。

  1. getItem()で返答するInstanceはPositionごとに別のものを返さなければならない。そうしないとAndroidが怒って落ちちゃう。開放をAndroidがやってくれてるからだめなんだと推測される。
  2. 毎回NewしてるからNewするコストがかかる。
  3. 循環しているとはいえ実際は別のInstanceが返答されてるから前に変更した値が循環して表示した時には初期値に戻る。

まとめ

ViewPagerでやるとAndroidが勝手に表示しているViewの左右1つを作ってくれてそれ以外は開放してくれるからメモリ管理がひたすら楽。循環じゃない場合はindexをFragmentのコンストラクタに渡してごちゃごちゃやってやればうまくいくんじゃないかと。気が向いたらFrameLayoutで実装してみるかも。まぁ、使えるところはCalenderとかそのへんだろうから、わざわざFrameLayoutとかで実装しないでViewPagerでやるほうが無難だと思う。

*1: Integer.MAX_VALUEとか本当はやりたいんだけど、それやるとViewPagerが許容してくれなくてバグるみたいだから適当な値を入れる。

LinearLayoutをタップ時にBackgroundの色を変えたい(詳細)

せっかくコメントを頂いたので詳細版を。

作るもの(左:押す前、右:押した後)

/res/layout/main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/lnrButton"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:gravity="left|center"
    android:clickable="true"
    android:background="@xml/linear" >

    <ImageView
        android:id="@+id/imgBefore"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:duplicateParentState="true"
        android:src="@xml/img" />

    <TextView
        android:id="@+id/txtTitle"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:gravity="center"
        android:duplicateParentState="true"
        android:textColor="@xml/text"
        android:text="Sample Title" />

    <ImageView
        android:id="@+id/imgAfter"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:duplicateParentState="true"
        android:src="@xml/img" />

</LinearLayout>

/res/xml/linear.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >

    <item android:state_pressed="true" >
        <color android:color="#555" />
    </item>
    <item android:state_pressed="false">
        <color android:color="#000" />
    </item>

</selector>

/res/xml/text.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >

    <item android:state_pressed="true"
        android:color="#FF0" />

    <item android:state_pressed="false"
        android:color="#FFF" />

</selector>

/res/xml/img.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >

    <item
        android:state_pressed="true"
        android:drawable="@android:drawable/btn_star_big_on" />

    <item
        android:state_pressed="false"
        android:drawable="@android:drawable/btn_star_big_off" />

</selector>

ざっくり解説

各要素でタップ時に変更したい要素についてselector要素を指定している。selector要素のstate_pressedが押されているかどうか。trueなら押されていて、falseなら押されていない。それぞれで設定したい値をitemに書き込む。後は前回書いたようにclickできるようにしてあげればきちんと動く。本当はSelectorのxmlファイルはdrawableフォルダに入れてあげたほうがいいのかもしれないけど、ごちゃごちゃしてわかりにくくなるから僕はxmlフォルダに入れる派(*1)。itemの各状態についてはここらへんが参考になるかも。

一応動作確認したので動くはずです。もしもっといいやり方があれば教えてください。

*1: 別にこだわりがあるわけじゃないからすぐに辞めるかも

プロセスにこだわるのは悪なのか?

例えば彼女を作りたいって考えたとする。彼女を作るために多くの人と出会ったほうが確率が高いと考えて合コンに明け暮れる。もしくは一人に絞ったほうがいいから誰か一人に全ての時間を費やしたほうがいいと考えて一人の人に時間をかける。目標は同じであってもアプローチの仕方が全然違う。どっちが正解かはやってみなければ分からない。けど、目標に至るまでのプロセスをすごく考えてしまって、これをやるぐらいならこっちをやったほうが効果が上がるのではないか?とかいうことをよく考える。

目標に向かっているという事実はどちらも変わりない。けど両方を取ることはできない。多くの人と会う時間を作るということは一人の人と会う時間が少なくなるということだし、一人の人に時間を使うということは多くの人と会う機会を減らいているということだ。それじゃあどっちに進めばいいの?って迷ったり考えたりする。どちらかの手段を選んだからといって、その一方しか使えないというわけではないから合コンしながら一人の女性とあってもいいし、一人の女性を口説きながら合コンに行ったりすればいい。けど、どちらかを選んでいる状態で他方のことをやると「それって時間の無駄じゃね?」って思ってしまう。

どちらの道が正解というのはなくてやってみても正解がわからないことのほうが多いということは頭ではわかっている。けれども「もっといい方法があるのではないか?」とか「もっと視点を変えれば別の考えが出てくるんじゃないのか?」とか考えてしまう。例えば彼女を作りたいっていう考えは一人でいる時間が寂しいっていうことだったり話し相手が欲しいってことだったり結婚がしたいってことだったりその先の何かを求めるための一つの施策なのかもしれない。それなら、そっちの目標に向かって別の視点で考えたほうが効率がいいのではないのか?って今度はそっちに考えが堂々めぐりしだす。

これが人生の話で僕一人だけで完結するのであれば別に問題ない。回り道は回り道でそれなりに楽しいし、なにもやらないよりやったほうが絶対マシだし考えることすら無駄なんじゃないかと思う。けど、仕事となると話が違う。僕の行動にはお金が払われていてそれに見合った価値を出さなければならないし出したいと思っている。1時間でできることを10時間でやる人間より1時間でできることを1分でできる人間のほうがいいに決まってる。それは間違いない。だから僕は目標に向かっていくためのプロセスにこだわってしまうし目標を明確にして作業を行わなければならないんじゃないかと考えてしまう。

一人でやっているときは自分なりに目標とそれに至るまでのプロセスを明確にして考えたとおり進めばいいだろう。けど複数人でやるときはどうなんだろうか?僕が思い描くプロセスと他の人が思い描くプロセスが違った場合はどちらを尊重すべきなんだろうか?プロセスと目標が決まるまで動かずに話し合いを続けるべきなんだろうか?プロセスにこだわって何もやらないのは悪だと思うが、全くプロセスにこだわらずに作業を行うのもなにか違う気がする。それはそれで時間に対する無頓着さっていう点で悪だとみなされてもしょうがないのではなかろうか。プロセスと目標の明確化は複数人でやるときの肝だとは思うが、それに引きずられすぎられすぎて作業が行えないという状況は避けたい。だけど、ただ闇雲に進みたくはないというこのジレンマ感の解消法はどこかにあるんだろうか?

書いてるうちに結論が出るかと思ったけど別段結論は出ない。みんなその人なりに考えた結果のベストなプロセスを主張していて、最短距離で目標に向かって進もうとしているということだけは間違いない。それが疑いようもない事実としてそこにあるからそれでいいんだろう。目標が同じであればそれぞれが思い描くプロセスに向かって全力で進めばいい結果が出るんだろう。っという短絡的で楽観的な結論が今のところの僕の中での答えだ。

この考えを踏まえた結果、僕は彼女を作るという考えを伴侶を作るという考えに改めて、両刀になることで幅を広げるという試作に出てみることにする。これなら間違い無いだろう。これはモテる。

LinearLayoutをタップ時にBackgroundの色を変えたい

LinearLayoutを使用してちょっと凝ったボタンみたいなのを作った時に有効。クリックした時に色を変えてちゃんとこいつがクリックされてますよーってのがわかるようにする。

selectorを作る必要があるけど、そこの説明は省略。こことか参考になる

<?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="wrap_content"
    android:clickable="true"
    android:background="@drawable/button_sample_background" >

    <ImageView
        android:id="@+id/imgIcon"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:duplicateParentState="true"
        android:src="@drawable/button_sample_icon" />

    <TextView
        android:id="@+id/txtTitle"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:duplicateParentState="true"
        android:textColor="@drawable/button_sample_title" />

</LinearLayout>

重要なのはLinearLayoutのclickableと子Viewに設定しいるduplicateParentState。

clickable
trueを設定するとClickを察知するようになる。
duplicateParentState
trueを設定すると親ViewのClickを優先的に動くようになる。要は親ViewをClickすると子Viewにもそれが伝わる。

この2つを設定することで、LinearLayoutのClickイベントを子Viewに伝えて文字の色を変えたり、画像を差し替えたりしてちょっと凝ったボタンを作ることができる。duplicateParentStateがわからなかったなー。

ギャラリーの共有からアプリを呼び出す方法

Androidのgalleryで画像を選択して共有を押した時にアプリを呼び出したい場合はIntent-filterをActivityに設定してあげればいい。

<intent-filter>
	<action android:name="android.intent.action.SEND" />
	<category android:name="android.intent.category.DEFAULT" />
	<data android:mimeType="image/*" />
</intent-filter>

複数選択したものを取得したい場合はactionを変更する。

<intent-filter>
	<action android:name="android.intent.action.SEND_MULTIPLE" />
	<category android:name="android.intent.category.DEFAULT" />
	<data android:mimeType="image/*" />
</intent-filter>

mimeType=image/*だと動画まで取得してしまう。写真だけ撮りたい場合はmimeType=pngとか色々設定してあげるといい。

<intent-filter>
	<action android:name="android.intent.action.SEND" />
	<category android:name="android.intent.category.DEFAULT" />
	<data android:mimeType="image/jpeg" />
	<data android:mimeType="image/jpg" />
	<data android:mimeType="image/png" />
	<data android:mimeType="image/bmp" />
	<data android:mimeType="image/bitmap" />
</intent-filter>

こんな感じで大丈夫。以下、参考になったURL。

スマートフォンの画面で表示されている高さを取得する

UserAgentを取得して高さをUserAgent毎にごちゃごちゃやると上手くいく。

    // スマホ種別判定
    var ua = navigator.userAgent;
    if(ua.indexOf('Android') > 0) {
        var nPageH = document.height > document.width ? document.height : document.width;
        var nViewH = window.outerHeight > window.outerWidth ? window.outerHeight : window.outerWidth;
        if (nViewH > nPageH) {      
            nViewH = nViewH / window.devicePixelRatio;
            $('body').css('height', nViewH + 'px');
        }
    } else if(ua.indexOf('iPhone') > 0) {
        var nViewH = document.documentElement.clientHeight > document.documentElement.clientWidth ?
                                document.documentElement.clientHeight : document.documentElement.clientWidth;
        if (ua.indexOf('iPhone') && !window.navigator.standalone) nViewH += 60;
        $('body').css('height', nViewH + 'px');
    } else {
        return;
    }

これでやると結果的に高さがnViewHに入る。

パチンコから学ぶコンプガチャに変わる試作3つ

先に行っておくと、僕はカードゲームを作っている中の人でもなんでもない単なるパチンコ好きのカードゲーム嫌い。だからこれから書くことは、法律云々でやっちゃダメなことかもしれないし、既にやってることかもしれない。

ガチャを引く台を自分で決めれるようにする

台によってレアカードが出る確率が違うふうなことを記載して、自分で台が選べるようになると引く人も増えるんじゃないだろうか。自分で選んだ台だからレアカードが出なかったのは違う台を選ばなかったからじゃないのか?っと錯覚させることで次に別の台でガチャを引くっていう動作につながるかもしれない。

台の直近で出たカード履歴を出す

今まで出たカードの履歴を出すことによって、クズカードが続いたから今度はレアカードが出るんじゃないかと錯覚してガチャを回してしまう。俗に言われるギャンブラーの誤謬ってやつ。これに台選択の自由まで与えると、クズカードが出続けた台でやればレアカードが出るんじゃないの派とレアカードがいっぱい出てるほうがレアカードが出る確率がいいんじゃないのか派に分かれてガチャを引く人が増えそう。

確率変動を設ける

何分の1の確率で確率変動に入るようにする。確率変動中は今まで30分の1だったのが2分の1で引けるようになりますよみたいな触れ込みを書いておく。こうするとこれまで使ったものも確率変動一発でレアカードがじゃんじゃん出るんじゃないのか?と錯覚してクズカードを引きまくる人が出てくる。台選択の自由を出しておくと、レアカードが出てすぐだと、これは確率変動にいるんじゃないのか?と錯覚してガチャを回してしまう。

まとめ

ざっくりとすぐに思いつくものを書くと↑の3つぐらいだけど、これ以外にも「天井制度」とか「フリーガチャカード」とか色々浮かんでくる。ということは結局ガチャがあるカードゲームってパチンコと作りはあまり変わらないんじゃないのかなーっておもったりもする。僕個人としてはあまりカードゲームは好きではないので(*1)、これを気に単純なカードゲームは全部潰れてしまってみんなが楽しめるゲームがもっと流行ってくれるといいなぁと思う。

*1: クリックするだけで進むやつね。マジック・ザ・ギャザリング的なのは好き