神記逸天プログラマーブルリーデイズ

行き詰まったことをメモっておく中二プログラマーのブログ。スマホアプリとかゲームアプリ関係が多い

新しい大地に立った時の高揚感は癖になる (訳:FuelPHP使い始めました)

「我を待つのは混沌の希望か安息の絶望か」

今週から新しい案件やってるー!

cocos2dxは一時おやすみだよ。個人開発ではずっと触ってるけど個人でやってる時って自分のやりたいことしかやらないから、あまり成長する部分がないので、ブログに書いておく必要がそこまでない。


さてさて!
今年から触り始めたFuelPHP

サーバ側の案件ですよ、奥さん!
サーバなんて完全に素人なのでクライアント様から教えてもらいながらお金もらってますよ、まずいですよ。

ってなわけで、最近は仕事以外でもPHPをなるべく触るようにしてクライアント様に迷惑がなるべくかからないように勉強中。


今までバリバリ、クライアント側(クライアント様と言葉がごっちゃになってわかりづらい)の人間だったのでサーバで少し何かしようとすると苦戦してばかり。
その分、学んだこともあるから、メモしとくよ!

MAMPっていうのが超便利!
MAMP、マジかっこいい! ちょちょいとやったらmacの中にサーバ出来上がっていた。ほんとだよ!MySQLまで設定なんかしてくれちゃって。
案件が始まる前にサーバ作らないとと思っていたらこんないいものが。。。
きっと常識なんだろうなぁ、と思いつつも、今から追いつくからね!
今まで、ちょっとしたPHPを組むのにいちいちレンタルサーバにアップして確認していたのがばからしくなったよ!
マジ、愛してる。
http://www.mamp.info/en/index.html


memcachedって言うのがあるよ!
環境構築で一番苦戦したのがこれ。

最初は一時的なテーブルを使って、プログラム間のデータの受け渡しをしようと思ったのだけど「さすがにそれは負荷がかかりすぎる」とクライアント様にご指摘をいただきました(そりゃそうだ)、memcachedがあるから使ってみて、と言われました。
すごい! こんなのがあるんだ! そりゃあるよね、あるだろうということは予想できてた。 ただ、知らなかったよ。。。

で、最初はmacportsで入れようとしたんだけど、なんか全然上手くいかなくて、調べてみるとMAMPとは違うところではmemcachedが走っていた。
つまりMAMPPHPをインストールしちゃったから、なんか入れようとしたらMAMPっぽいことをしないといけないってことだな! 全くわからん!

と探していたら、いいのが見つかった。

http://sousaku-memo.net/php-system/896

すごい! 神様! MAMP神!
ページを見つけて2秒でmacportsをアンインストールして、ここに書いてあるとおおおりにやりました。
できました。

ふふふ、これで環境が整ったよ!
始まる! ついにPHPバリバリかけるようになってソシャゲ案件でもなんでもやってこい! ってなれる! むしろソシャゲ作ってやるー!


FuelPHP
それでFuedlPHPというものを使っているということだったので、早速サイトに行ってみてみた。
全くわからなかった。
なんだこれ……知ってるPHPと違う(←アンケートフォームを作れる程度の能力

まあ、しかし、言ってもプログラム。
書いた通りにしか動かないものなんだから、書いてあることを理解すれば書けるようになるはず。

と、とにかくだね、modelとviewとcontrollerを分けてるMVCだかMVPだかっていうあれだってのは、うん。なんとなくわかった。


もう、昨日、今日と初歩的なところしか触ってないからメモするほどでもないのかもしれないけど、PHPを普段触らないから忘れてしまった時用に明日からもちゃんとメモするぞー!

高い壁を越えた向こうにこそ、約束のエデンがある (訳:Androidの署名付きExportでつまづきました)

「月は地へ堕ちる瞬間に淡く、しかし力強く光を放つ」

案件の提出日だったー!

いろいろ勉強になることばかりの案件だったよ!


主にJavaC++の受け渡しをやったのだけど、これどんなツールでも必要なんじゃないかなっていう基本的な機能を結構実装した!

クリップボードにコピー
http://techbooster.org/android/application/3633/
そのままずばりのコードが結構ゴロゴロとあるのだけど、自分用メモに書いていた方が探しやすいのでペタリ

ClipboardManager clipboard = (ClipboardManager)activity.getSystemService(CLIPBOARD_SERVICE);  
clipboard.setText(text);  

これだけ。
ただし、API11(3.0)以降では非推奨らしい。API11以降ではこんな感じ

//クリップボードに格納するItemを作成
ClipData.Item item = new ClipData.Item(text);
//MIMETYPEの作成
String[] mimeType = new String[1];
mimeType[0] = ClipDescription.MIMETYPE_TEXT_PLAIN;
//クリップボードに格納するClipDataオブジェクトの作成
ClipData cd = new ClipData(new ClipDescription("text_data", mimeType), item);
//クリップボードにデータを格納
ClipboardManager cm = (ClipboardManager)activity.getSystemService(Activity.CLIPBOARD_SERVICE);
cm.setPrimaryClip(cd);

ちょっと、長くなった。
……なんで長くなるのだろう。いろんなことをできるようにしようと思ったら長くなるのかな?

▼いざ、Export!
ドキュメントを書くのって大変だけど大切だよね!
いつもドキュメントを書かないで実装に着手するから、着地点がわからなくなって迷走するんだ!ちゃんとドキュメントを書こう!
というわけで、実装した機能や注意点を記載して提出……しようと思ったら署名付きでAPKが書き出せない! 何故!?

同じような現象に引っかかってる人がいた!
http://blog.makotoishida.com/2012/12/eclipseandroid.html
Build AutomaticallyをOFFにすべし

結局何故かわからなかったけど、書き出せるようになった!


やたー! あとは確認待って、次の案件だー! 頑張るぞー!

二人は一身のようで、だけどけして一つではなくて (訳:CPPとJavaでアプリ内課金連携しました)

「二人の距離がどれだけ離れても、虚空に浮かぶ星を目指せば再び会える」


今日は、cocos2d-xからAndroid Javaを呼び出すところを実装。

なんてことはない部分のはずだったのだけれど、いろいろと手間取ってしまったよ!
アプリ内課金については前回の日記で書いた通り、Android単体ではとりあえず動くような感じになった。

今日はそれをcocos2d-xから呼び出す部分。

Javaとcppを行ったり来たり

ただ、Javaを呼ぶだけのやつはTwitterやLINEで最近実装したので、すぐ出来た。
こんな感じ。

void CCBilling::buyStart(int itemid){
	JniMethodInfo methodInfo;
	JNIEnv* pEnv = getJNIEnv();
	if(pEnv == 0){
	    return;
	}
	if(JniHelper::getStaticMethodInfo(methodInfo,CLASS_NAME,"buyStart","(I)V")){
	    methodInfo.env->CallStaticVoidMethod(methodInfo.classID, methodInfo.methodID,itemid);
	    methodInfo.env->DeleteLocalRef(methodInfo.classID);
	}
}

なんだけど、Javaからccpに戻って来る方法がわからなかった!
Androidでは、課金の手続きをした後にonActivityResultなるメソッドが非同期で呼ばれるので、そこからなんとかしてcppに戻ってきてアプリ側に「課金終わったー」という通知をしてあげないといけない。
どうしたものか。

google先生に聞いてみるとJavaからcppの呼び出しは修飾子という言葉を使うらしい!
そしてまたまやわかりやすい記事を発見!

http://symfoware.blog68.fc2.com/blog-entry-829.html

ここを参考にしながらJava側に

protected static native void buySuccess();

と技術して、cpp側には

extern "C"
{
	JNIEXPORT void JNICALL Java_com_sample_billingtest_MyActivity_buySuccess(JNIEnv* env, jclass cls, jobject obj){
		CCLog("成功したよ!");
	}
}

と記述。
こうするとJava側でbuySuccessが呼ばれた時にcpp側に戻ってこれるみたい!
いいね! いいね!
これでまたやれることが増えた!


課金については
AppC Cloudやsoomlaなどを入れたら早いけれど、こうやったjavaとcppの連携はいたる場所で使うので完全に身につけておきたい。
https://app-c.net/
http://soom.la/

その場しのぎをしたって、結局いつかはツケを払わされるのさ (訳:Androidの古いアプリ内課金と新しいアプリ内課金の話)

「滴る血で足跡を染め、辿り着いた先に待っていたのは君ではなく、冷たい牢獄だった」

今日もメモメモ!
いろいろネタを貯めておいて、ブログを書く時にネタに困らないようにしとくんだ!

けれど、コンピュータの知識って数ヶ月すると古くなるからこういうネタのストックってあまり意味がない気がしなくもないけど、まあいいやいいや、楽しければいいや。

今日は、前回に引き続きアプリ内課金のことと、いきなり遭遇したエラーのことをメモ!

▼アプリ内課金って途中で変わったんだね!

この前お仕事でアプリ内課金のことを調べたものだから、以前自分が作ったアプリも、もう少しわかりやすいコードの変更しようと思って引っ張りだしてきた。
2年以上前に出したほとんどダウンロードなんてされないアプリなんだけど、未だに月数万は売り上げていて時々google playの有料ランキングだかなんだかにランクインしているので、これを期に一度真面目にコードを書き直そう!とか気合いを入れちゃったわけです。

それで、コードを眺めていたら、この前調べたIInAppBillingServiceの文字がないではないですか。
おかしい! 何か夢か幻でも見ているんじゃないかと一生懸命コードを読んで行くとIMarketBillingServiceというものを発見。

なんだこれは!

なんと、どこかのタイミングで変わってしまっていたらしい。
同じように「変わっちゃってるー!」ということをおっしゃっている記事もいくつか

http://blog.kshoji.jp/2012/12/in-app-billing-version-3.html
http://d.hatena.ne.jp/creativeability/20130313/1363189286

しかし、この変更でずいぶんとアプリ内課金の実装が楽になったんだとか。
たしかに今回アプリ内課金を実装したけど、あんまり大変じゃなかった気がする。(記事のおかげ!

昔参考にしたのはこっち
http://www.atmarkit.co.jp/ait/articles/1104/28/news147.html


というわけで動いているコードを触って「課金してもアイテムもらえない!返金しろ!」とか言われると泣きたくなるので、触らずに月数万を黙って受け取る道を選びました。
身の丈にあった行動をしないとね!


▼しかし、罠が潜んでいた
そんなアプリ内課金について調べながら土日を満喫して、本日。
さーてお仕事頑張るぞー!とeclipseを起動したところ。


先週末まで動いていたソースコードが動かない……!!!!


なんで!? 何をした!?
ああ、そうかちゃんとソースコードを修正せずに、せせこまと月数万を受け取ろうなんざ甘い!とお怒りになった魔王サタン様が与えられた罰なんだ!
人様に課金させるなら常に最新のコードにしておけってことなんだーーーーー!!

出たエラーはこれ。

[2013-11-02 08:26:51 - SearchViewDemo] Dx
trouble writing output: already prepared

どういうこと!? これどういうことーーー!
さっそくgoogle大先生に質問すると、こんな答えが返ってきました!

http://www.nico-maas.de/wordpress/?p=863

『最新のSDK以外全部消せ』(誤訳

な、、、なんだってーーーーー!
それは困ります、先生! だって未だにAPI8をメインターゲットにしたふるーーーいアプリもたまにだけどメンテナンスしてるんですから!
消したくない! API8とまだ、別れたくないんだ!
何か、何か手があるはずだ!


古いSDKを消せば直るってことは、SDKの参照が間違ってるんじゃないかな?
そこをちゃんと指定しなおしてあげれば、大好きなAPI8と別れなくて済むんじゃないかな。


はい、その通りでした。

Project Build TargetがAPI8になってました。
そんな古いAPIだと最新の課金ライブラリが動かないんだ、きっと。いや、よくわからないけど。

なんでそんなことになったかというと、
IMarketBillingService
こいつのせい。

土日にこいつと格闘している時に「そうだ、このアプリAPI8とかの頃に作ったやつだからProjectBuildTargetを8にすればいいんじゃない?」と思って切り替えたのをそのままにしてました。


無駄な時間をすごしたーーー。魔王サタン様の罰怖いーーー。



今日は、あんまり成長しなかった気がするけれど、明日は新しい技術をちゃんと学べますように!
納期まで余裕だったのに、1日無駄にしたせいでちょうどいい感じの納期になってしまった。

目覚めよ、アプリ内課金。 奔れ、課金処理! (訳:ひたすらアプリ内課金の実装をしてました)

「さすれば汝に、蒼き力を与えよう!」


今日も頑張った! 頑張って勉強したよ!


いあ、お仕事請けながらお勉強してたら怒られそうだけど、けれど人生、日々勉強だと思うから、それでいいよ!
たくさん勉強して、毎日成長して、結果、ちゃんとしたものを納品できればそれで良い。うん。



Androidで課金
前にAndroidのアプリ内課金に挑戦したのは1年半以上前のこと。
書籍とかなかったし、ネット上も英語のページばかりひっかかって「うわーーむりーーー!」ってなって、結局2ヶ月くらいぐずぐずやりながら、ようやく無料版を有料版にアップグレードするだけのアプリ内課金を実装したところ、無料版有料版を並べて配布してた時に比べて収益が3倍くらいに(と言っても小額)跳ね上がって、アプリ内課金すごーーいってなった気がするけど、もうやり方忘れた。


けれどお仕事でAndroidの課金やってーって言われたから久しぶりに触ったら、たっくさん資料があって嬉しかった! のでメモしておく。


超わかりやすくてオシャレなページ
http://web-terminal.blogspot.jp/2013/05/androidgoogleplay.html
今回はここをメインで参考にして実装した。


あと、ここもとてもわかりやすかった!
http://php6.jp/android/2013/05/16/android%E3%82%A2%E3%83%97%E3%83%AA%E5%86%85%E8%AA%B2%E9%87%91-v3api-version3%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6/
さっきのページで行き詰まった時にこっちも参考にして実装した!



この2つのページを参考に実装して、よし、いざ購入テスト!
と思ったら
「このバージョンのアプリは、Google Playを通じたお支払いはご利用になれません。詳しくはヘルプセンターをご覧ください。」


うわあーーー、なんだこれーーー! 上のページの人が書いてる通りにしたのにー!!!
と思ったら、自分が単純にバカなだけだった。


http://engineer-arise.blogspot.jp/2013/06/v3.html


ちゃんと署名をしてテストしないといけないらしいです。
テスト→修正→テスト→修正、を繰り返しながら作っていく自分には結構面倒な気がする。
いっそのこと、テストapkをアップロードすれば良かったのかも……。



明日はそこら辺を調べてみよう!
きっとすごい人がすごく便利な方法を考えてくれていると思うから、そういうのをちゃんと吸収して、そのうち誰かの役に立てるような知識を身につけるんだー!

10M動画「assetsはオレの居場所ではないし、addContextViewされても簡単には姿を見せない」

「闇の焔に抱かれて消えろぉぉぉ!」

今日からメモを残そうと思った!


日記として世に出しても恥ずかしくなさそうな内容だったら、公開用のブログに載せて、いろいろ指摘してもらったりなんだとかして、いつかは誰かの役に立つブログを作ってみたい。

なので、今のうちから毎日気づいたことを自分用にメモをしておくのだ!

とりあえずメモ用のブログなので、今日、調べたことと、思いついた言葉をそのまま書き記していく予定! 何日続くかな! 将来の自分、頑張れー!


今日調べたこと


▼assetsに1M以上の非圧縮ファイルは置けないらしい。
請けてる案件で動画を再生する必要があって、10Mくらいあるのだけど、それをassetsに入れて再生しようとしたら全然上手くいかず。

res/rawに入れれば再生できるという記事を何個か見つけたんだけど、cocos2dxだとResourceのファイルってassetsに保存されるから、なんとかしてassetsから再生したかったのだけれど、どうしても「この動画は再生できません」って出ちゃう。涙が出ちゃう。

大人しくres/rawから再生することに。
調べるとすごく丁寧に解説されている記事があって、やっぱり涙が出ちゃう。今度は嬉し涙。

http://techbooster.jpn.org/andriod/multimedia/5683/

いつか、こんな風にすごいブログ書くんだ・・・。


▼VideoViewで音しかならない!?
VideoViewをaddContextViewして動画を表示したところ、音楽だけ聴こえて来た!

videoView = new VideoView(this);
if(videoLayout == null){
  videoLayout = new FrameLayout(this);
  addContentView(videoLayout, new ViewGroup.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
  videoLayout.setFocusable(true);
  videoLayout.setFocusableInTouchMode(true);
}
videoLayout.addView(videoView, new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT, Gravity.NO_GRAVITY));

動画表示への道は険しいようで。
試しにWebViewとかをaddContextViewするとちゃんと表示される。
おかしい、おかしい。 きっとおかしいのは自分だ、と思って調べたらありました。

http://stackoverflow.com/questions/7991091/videoview-show-on-glsurfaceview

mVideoView.setZOrderOnTop( true );

多分、基本的なことなんだろうな。。。
WebViewやButtonを配置したらこれをやらなくても表示されたってことは、きっとViewごとにZOrderの初期値がある程度決まってるのかも。
とにかく、この1行を入れるだけで解決。


今日もちょっとだけ成長!
明日も頑張るぞー!