Kuwapp's Blog

Android と Flutter やってます

Flutter Meetup Tokyo #1 でLTしてきた

↓これ

flutter-jp.connpass.com

LT内容

Flutterで画面遷移を検知する という内容で発表した。

内容は RouteObserver というクラスを使えば簡単に画面遷移を検知できるよというもの。 alpha版では1つのRouteにつき1つのリスナーしか登録できなかったので複数登録できるものを自作した知見を発表予定だったのだが、いつの間にか複数登録できるようになっていた。 資料作成中に気づき、「Flutterは日々進化する」で雑にまとめた。

ちなみに複数登録できないとイベントを引き回す必要があるのでちょっとツライ。 Androidでいえば Activity でしかライフサイクルがとれないみたいな状況。Fragmentに引き回さなきゃならなくてツライみたいな。

感想

  • 外部のイベントで発表するのは楽しい
    • 反応があると嬉しいし、モチベも上がる
    • この規模のイベントでLTするのは初だった
  • Flutter やっている or 興味ある人こんなにいっぱいいたんだとびっくりした
  • 単に勉強になった

Flutter界隈盛り上げていきたい

ツイキャスの視聴用のAndroidアプリ作って公開してみた。

作ったもの

Casee-シンプルなツイキャス視聴アプリ - Google Play の Android アプリ

シンプルなツイキャスの視聴用アプリです。
今はツイキャスを見てコメント投稿するぐらいの機能しかありません。
今後いくつか機能を追加する予定です。
YouTubeのアプリを真似て動画を見つつ放送を探せるようにしました。
アプリ名は TwitcastingのCasと英語の見るのSeeを合わせました。

なぜ作ったのか

主に3つの理由です。
・ツイキャスのAndroidアプリのUIが自分には使いづらかった
・外部と通信を行うアプリが作りたい
・自分の能力を示すためのアプリが欲しかった

ツイキャスのAndroidアプリのUIが自分には使いづらかった

既存のツイキャスのアプリはリストスクロール時にかくついたり
動画を再生しながら他の動画を探せなかったりと不便な部分がありました。
ツイキャスはAPIも公開されていたので自分で勉強がてら作ってみようと思い開発しました。

外部と通信を行うアプリが作りたい

通信が必要なアプリは今まで単語帳を他人と共有するアプリを作ったことしかありませんでした。
単語帳の共有アプリはユーザーが入力したワードを単語帳に紐付けてアップロードし
そのワードを誰かに教えることで他のユーザーも単語帳をダウンロードできるというものでした。
このアプリはかなり単純なものだったので、技術力向上のためにも新しく何か作ってみようと思いました。

自分の能力を示すためのアプリが欲しかった

前職ではcocos2d-xやUnityでのゲームの開発を行っていたので
Javaで開発するAndroidアプリの業務経験がありません。
次はゲーム系以外で働きたい思いもあったので自分の能力を示せるポートフォリオ的なものが欲しいと思いました。

技術的なこと

技術的な部分で困ったこととか

動画の再生がうまくいかない

はじめは動画部分をWebViewでhtml5のビデオタグで再生していました。
いろいろ試行錯誤するとAndroid5.1では上手く動くようになったのですが
別の端末で試してみると自動で動画は再生されなかったりとかなりはまりました。

そんなときにVideoViewを知り実装。
こちらだと問題なく再生自体はできたのですが
VideoViewはSurfaceViewを使用しているのでアニメーションが上手く動かず断念。。
(SurfaceViewはViewというよりただのWindowだったりします。)
なんとかならないかググるとTextureViewなるものを発見。
動的にレイアウト移動できたりするようで、GitHubにもTextureVideoViewというライブラリがあったので早速使用。
最高でした!

github.com

ログインのAPIが非推奨になっていた

ログイン用のAPIが非推奨になっていました。
クッキーの中身を見るとログイン成功時にユーザーIDとセッションIDを保持しているようだったので
WebViewでログインさせページ遷移時にクッキーにユーザーIDとセッションIDの2つの情報が含まれているかでログインの判定を行うようにしました。
ログインが必要な通信はこれら2つのIDをヘッダに追加して行うようにしました。

コメント投稿のAPIが停止していた

コメント投稿のAPI自体は公開されていたのですが、停止しているようでした。
Webのソースを見てどうやってコメント投稿してるか見て実装しました。
Webはあまり詳しくないので、かなり試行錯誤しました。。

今後

既存のアプリのUIが自分には使いづらいかったため作りましたが、現状は既存のアプリより使いづらいです。。
というのも放送の検索や、放送のバックグラウンド再生、お気に入りのユーザーの放送開始を伝える通知などの機能が存在しません。
検索はAPIで提供されていないのでどうしようかなーと考え中。
サーバー立ててスクレイピングすることになるのかな?
あと個人的にChromecastよく使用してて便利だなーと思ってるのでそっちの対応もしてみたいなと思ってます。
ということで以下の機能を追加予定
・ライブの検索
・ユーザーの検索
・バックグランド再生
・横画面対応
・PUSH通知
・Chromecast対応

感想

とりあえず公開できて満足してます!
自分で何か作るのはやっぱ楽しいし、また他にも何か作っていきたいなーと思ってます。
いろいろとエラー処理が甘かったり、コードが汚かったりする場所があったけど次のアプリではそういうところも改善していきたいなー。

ViewCompatでsetUpdateListenerを読んでも更新時に呼ばれない

調べてみた。
リファレンスでsetUpdateListenerを見るとなんと「Added in API level 19」でした。

ViewPropertyAnimator setUpdateListener

とくに警告も出ていなかったので気付かなかったー。

ObjectAnimatorを使用して解決しました。

ObjectAnimator animator = ObjectAnimator.ofFloat(v, View.ALPHA, v.getAlpha(), alpha);
animator.setDuration(duration);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
    @Override
    public void onAnimationUpdate(ValueAnimator animation) {
        //処理
    }
});
animator.start();

cocos2d-xでプロジェクト作成時にいつも自分が行っている作業

プロジェクトの作成

cocos new MyGame -p com.kuwapp.mygame -l cpp -d ~/Projects
  • MyGame プロジェクト名
  • -p com.kuwapp.mygame パッケージ名
  • -l cpp 言語
  • -d ~/Projects ディレクトリ

gitignoreを追加

# Mac
.DS_Store

#Java
*.class

# XCode
*.moved-aside
build/*
*.xcworkspace
*.mode1v3
*.mode2v3
*.pbxuser
!default.xcworkspace
!default.mode1v3
!default.mode2v3
!default.pbxuser
*.perspectivev3
profile
xcuserdata
.idea/*

#Cocoa pods
*.old
Pods/*

#cocos2d-x
libs/
bin/
obj/
assets/
gen/
out/
.classpath
.project
.cproject

# backup files
*.bak
*.bak[0-9][0-9]
*.orig
*.orig[0-9][0-9]

# source packages - anywhere
*.tar.bz2
*.tar.gz
*.tar
*.tgz
*.gtgz

local.properties

project.propertiesのtargetを最新のAndroidSDKのapi levelに変更

target=android-22

cppファイルをコンパイル時に全て読み込めるようAndroid.mkを変更する

cppファイルを追加するごとにAndroid.mkに記述していくのは面倒なので自動で読めるようにする

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

$(call import-add-path,$(LOCAL_PATH)/../../cocos2d)
$(call import-add-path,$(LOCAL_PATH)/../../cocos2d/external)
$(call import-add-path,$(LOCAL_PATH)/../../cocos2d/cocos)

LOCAL_MODULE := cocos2dcpp_shared

LOCAL_MODULE_FILENAME := libcocos2dcpp

CPP_FILES := $(shell find $(LOCAL_PATH)/../../Classes -name *.cpp)

LOCAL_SRC_FILES := hellocpp/main.cpp
LOCAL_SRC_FILES += $(CPP_FILES:$(LOCAL_PATH)/%=%)

LOCAL_C_INCLUDES := $(shell find $(LOCAL_PATH)/../../Classes -type d)

# _COCOS_HEADER_ANDROID_BEGIN
# _COCOS_HEADER_ANDROID_END


LOCAL_STATIC_LIBRARIES := cocos2dx_static

# _COCOS_LIB_ANDROID_BEGIN
# _COCOS_LIB_ANDROID_END

include $(BUILD_SHARED_LIBRARY)

$(call import-module,.)

# _COCOS_LIB_IMPORT_ANDROID_BEGIN
# _COCOS_LIB_IMPORT_ANDROID_END

参考:http://ichiokumanyen.hatenablog.jp/entry/2013/10/05/220232

std::to_stringなどを使用できるようApplication.mkを変更する

std::to_stringやstd::stoiはそのままでは使用できないのでApplication.mkを改良する

APP_STL := c++_static
NDK_TOOLCHAIN_VERSION=clang
APP_PLATFORM := android-9

APP_CPPFLAGS := -frtti -DCC_ENABLE_CHIPMUNK_INTEGRATION=1 -std=c++11 -fsigned-char
APP_LDFLAGS := -latomic


ifeq ($(NDK_DEBUG),1)
  APP_CPPFLAGS += -DCOCOS2D_DEBUG=1
  APP_OPTIM := debug
else
  APP_CPPFLAGS += -DNDEBUG
  APP_OPTIM := release
endif

参考:http://discuss.cocos2d-x.org/t/i-cannot-call-stdlib-functions-like-to-string-stoi-etc/19405/3

WebViewで「net::ERR_CACHE_MISS」と表示される問題 【Android】

WebViewでページ読み込み時に「net::ERR_CACHE_MISS」と表示されてページが読み込めませんでした。
AndroidManifestのパーミッションを確認するとインターネット接続のパーミッションが大文字でした。
AndroidStudioの補完で記述した気がするんだけど・・

<uses-permission android:name="ANDROID.PERMISSION.INTERNET"/>


以下のように修正すると問題なくページの読み込みができました。

<uses-permission android:name="android.permission.INTERNET"/>

無駄にはまった。。。

WebViewでHtml5のvideoタグを使ったときにはまったこと【Android】

動画関連のアプリを開発しているのですが、開発中にいくつかはまったので記事にします。
動作確認端末はNexus5でOSはAndroid5.1です。
他の端末やバージョンでは試していないのでどうなるか不明・・です。
もし情報あれば教えていただけると助かります。

autoplay属性を指定しても自動で再生されない

次のようにautoplay属性を指定しても自動で動画が再生されませんでした。

<video src="xxxx.mp4" width="320" height="240" autoplay controls></video>

対策としてloadstart時にplayを呼び出して再生するようにしました。

<video src="xxxx.mp4" width="320" height="240" autoplay controls></video>
<script>
   var video = document.getElementsByTagName('video')[0];
   video.addEventListener("loadstart", function(){video.play();}, false);
</script>

ただ、これだけではなぜか動かずJava側でWebSettingsクラスのsetMediaPlaybackRequiresUserGestureを呼び出すことで解決しました。

int SDK_INT = android.os.Build.VERSION.SDK_INT;
if (SDK_INT > 16) {
    webView.getSettings().setMediaPlaybackRequiresUserGesture(false);
}

参考 http://stackoverflow.com/questions/15946183/android-webview-html5-video-autoplay-not-working-on-android-4-0-3

controls属性を指定したときに表示されるUIにフルスクリーンボタンがない

なぜか再生ボタン・シークバー・経過時間・音のONOFFしか表示されませんでした。
WebChromeClientを継承したクラスにonShowCustomViewonHideCustomViewをオーバライドさせてそれをsetWebChromeClientでWebViewに設定すると表示されました。

webView.setWebChromeClient(new WebChromeClient() {

    @Override
    public void onShowCustomView(View view, CustomViewCallback callback) {
        super.onShowCustomView(view, callback);
    }
    
    @Override
    public void onHideCustomView() {
        super.onHideCustomView();
    }
});

ただ自分の環境だとフルスクリーンボタンは表示されますが、フルスクリーンになりませんでした。
解決策は次へ。

フルスクリーンにならない

フルスクリーンボタンが押されるとWebChromeClientクラスのonShowCustomViewの第一引数にフルスクリーンの動画を貼ったviewが渡されてくるようです。
そのviewを自分でaddViewしなければならないみたい?
けっこう簡単に書いてますが、動画再生終了時の処理とか他にもいろいろ書く必要があると思います。
Githubに良さそうなリポジトリがあったのでそれ見ると良いかもしれません。
フルスクリーンボタンがなかったのはこれらをオーバーライドしてないのでフルスクリーンの動画を表示できなかったからなのかな。

webView.setWebChromeClient(new WebChromeClient() {

    private View mVideoView;

    @Override
    public void onShowCustomView(View view, CustomViewCallback callback) {
        super.onShowCustomView(view, callback);
        mVideoView = view;
        videoContainer.addView(mVideoView);
    }
    
    @Override
    public void onHideCustomView() {
        super.onHideCustomView();
        videoContainer.removeView(mVideoView);
        mVideoView = null;
    }
});

参考 https://github.com/cprcrack/VideoEnabledWebView

余白を消す

動画の再生とは関係ないですが、WebView内全体に収まるよう表示しているはずが余白があったのでcssでマージン0にすると解決しました。

<style type="text/css">
body {
  margin: 0px;
}
</style>

2015年7月にやることのまとめ

ここ最近ダラダラテレビを見たり、ぼーっとしたり無駄に時間を過ごしている。
このままではまずいので今月やることをまとめ時間を効率的に使えるよう考えてみる

やること

  • Walleterのアップデート
  • APIが公開されているサービスと連携したアプリを作る
  • EffectiveJavaを読み切る
  • 珠玉のプログラミングを読み切る

Walleterのアップデート

昨年リリースしたお小遣い帳アプリ。
要望フォームに要望がいくつかきていた。
実際に取り入れたほうが良いと思う要望もあり、直したい不具合もあるため近いうちアップデートしたいと思っている。
内部がかなり複雑になっているので、コードを直しつつ機能を追加することになり少し時間がかかりそう。

APIが公開されているサービスと連携したアプリを作る

2年前に単語帳を共有するアプリを作って以来、通信を使用したAndroidアプリを開発していなかったので作りたくなった。
以前作ったアプリはDefaultHttpClientを使って通信部分をゴリゴリ書いてたけど、今はいろいろ良いライブラリがありそうなのでそれらを勉強したいという理由もある。

EffectiveJavaを読み切る

半年ほど前にEffectiveJavaを購入した。
今までは実装時にここはどうしたら良いのかなと思った時にパラパラ見る程度だったので一度全てにしっかり目を通したい

珠玉のプログラミングを読み切る

アルゴリズムについてあまり知識がないので勉強するために最近購入した。
これも読み切って能力を上げたい

やることを達成するためにどうするか

テレビのコンセントを抜く

テレビは1度見始めるとダラダラと見てしまうので、コンセントを抜いて見れないようにした。

その日やることをまず決める

その日やることを事前に決めてそれらのタスクに集中して取り組むようにする。
何をするか決めずダラダラいろんなことをしてしまうと効率が悪そう

とりあえずPCに向かう

起きたと同時にmacを立ち上げAndroidStudioを起動させて、コードを書くことをより習慣化させる。



以上です。
実際にどうだったか来月振り返りたいと思います。
頑張ろう。