メモ2ブログ

メモtoウェブログ。旧ブログはこちら。 http://sakebook.blogspot.jp/

続・Androidアプリ開発を学生に教えた話

再び

以前と同じく、TrunkAndroid開発のトレーニングを請け負いました。

sakebook.hatenablog.com

今回は、1ヶ月でカメラアプリを作成してストアへ申請するというものでした。 1ヶ月と言っても、1回3時間の講義を4回行うという形式です。 前回の反省を踏まえ、一度の講義の時間を長くしています。

前回と異なり、スキルを身につけるというより、作り上げることをテーマにしていました。

対象は、学校やインターンJavaを習った方限定としました。

募集

前回、知識レベルに差があったのが教えにくかったので、前提として、Javaの文法がわかる程度の学生を対象としました。 参加枠は4人でしたが、応募してきた方は半分の2人でした。。

第1回

speakerdeck.com

狙い

  • Android Studioでプロジェクトを作成した時にいろいろファイルが生成されるが、どれが自分で編集するもので、どれが編集しなくても良いものか。それぞれの役割を知る。
  • 開発環境を使いこなし、ボイラープレートの手入力を避ける。
  • デバッグ方法を知ることで、問題箇所の特定をできるようにする。

主に前回のスライドをベースに作成しました。説明として余計と思った、テーマ周りなどは省略しました。

実際

開発環境は事前に構築しておく前提だったのですが、構築ができていませんでした。 参加者のうち、Surfaceの方がいてびっくりしました。幸いなかはWindowsだったので、無事環境は作ることができました。もう少し早くにBashが来てほしかった。。

Gitの扱いも、講義の内容に入れていたのですが、Gitは片手間で教えられるものではないと感じました。 というのも、「ただソースコードをバージョン管理できるよ!」と言っても、実際経験がないと響かないし、実際に触ってみないと理解してもらうのは難しいと思いました。 でもこの部分は僕の教え方の問題も大きいと思います。

また、参加者の知識レベルも、想定していたのと異なり、独学で勉強中という方でした。

デバッグ周りは、実際にエラーを起こさせて、エラーの読み方をはじめに教えるべきでした。 Breakpointなどを教える前に、Stacktraceのどの部分が自分に関係あるもので、エラーの原因ぽいところなのか。ということを教えないといけないと今更気付きました。ここは講義内容で実習にして体験してもらうなどが必要です。

写真加工部分は、Adobe Creative SDKを使いました。Retrolambda環境を構築する必要があり、時間がかかると思っていたのですが、幸いAndroid Studioの環境構築を当日一緒に行ったために、思っていたほど苦戦しませんでした。

以前より講義の時間を長く取っていたのですが、環境構築とGitの説明で、今回も1時間オーバーしてしまいました。。

第2回

speakerdeck.com

狙い

  • 自分で好きなレイアウトを構築できるようになる。
  • 好きなWidgetにイベントハンドリングを設定できるようになる。

同じく前回のスライドを流用しています。 Activityのライフサイクルは、触れておいた方がいいと思い入れた程度です。

実際

参加した学生がどちらもiPhoneユーザで、Androidの実機を持っていなかったため、UIを考えるのも難しかったようでした。 戻るボタン周りなど、iPhoneと比較したAndroidの特徴の話をはじめに入れておくと良かったかもしれないなと思いました。

RelativeLayoutとLinearLayoutを使いこなせるように、ライブコーディングの形でxmlを編集し、「この場合どうなるか?」というのをいくつもこなしました。自分の回答と比較できることで、理解が進んだように見えました。ただスライドを写経するより、一度考えたうえでコードを書くほうが理解を促進させると思いました。

イベントハンドリングは、ちょっと冗長になってしまいました。GitHubや検索してでてくるサンプルコードを見た際に、いろんなパターンでも理解ができるようにと思って前回から教えていたのですが、逆に複雑になっているのでは?と講義を聞いていた同期に指摘されました。 確かに、次週その辺りで苦戦しているように感じたので、振り返るとちょっと冗長だったなと思います。

第2.5回

実際は第3回の内容を行うつもりでしたが、宿題としていた

  • 作りたいアプリのレイアウトを作る
  • 各ボタンでイベントハンドリングを行う

ができていませんでした。 また、当日は一人しか参加できなかったので、宿題の部分を教えることで3時間が終わりました。 時間がかかった理由としては、極力自分で考えて実装してもらったのと、Javaに慣れていない部分が多々あったからです。

全4回の想定でしたので、翌週に第3回と第4回を繋げて行うことで調整しました。

第3回

speakerdeck.com

狙い

  • 各機能をメソッド化することで自在に呼びさせるようにする。
  • onActivityResultを使った、他のComponentとの連携を理解する。

レイアウトとイベントハンドリングはできているので、好きな箇所で自由に機能をつけられるようにさせようと考えました。 説明の内容を刷新しました。

実際

他のカメラアプリを暗黙的Intentで呼ぶ構成上、メンバ変数を持たせたのが難しかったみたいでした。 ただ、事前のレイアウトやイベント周りはできていたので、一つずつ挙動を確認しながら組み込めたのは良かったと思います。

onActivityResultの中で暗黙的Intentを呼んでいたので、再度onActivityResultを通るというところが、なかなか理解が進まないところでした。 図説したところ、少しずつ組み合わせられるようになりました。コードでの説明より、グラフィカルに入出力を捉えることで機能単位で考えやすくなったのかなと思います。

f:id:sakebook:20160406033645j:plain

実機がなかったのでエミュレータで開発していたのですが、シェア周りもエミュレータでは聞き馴染みのあるものがなく、うまく対応してくれるアプリがなかったので、実際に動かす感動は薄いようでした。この辺りは自身がAndroid端末を持っているかどうかがモチベーションに関わると感じました。

第3回のスライド分の講義の中でずっと触ってきた暗黙的Intentに疑問を抱くかと思い、暗黙的Intentに対応するにはどうすればいいのか?というのを蛇足的に入れていたのですが、本当に蛇足となり終わりました。実際に触る部分以外の知識は触れないようにしたほうがいいと痛感しました。

第4回

speakerdeck.com

狙い

  • ストア申請に必要な情報を把握する。
  • 申請に必要なapkの作成できるようになる。

実際

第3回と連続して行った第4回です。 振り返ると署名周りが冗長だったなと思います。 申請自体は、レーティングや説明文など、やることがありましたが間違えるようなものでもなく、淡々とできました。

アイコンや宣伝用画像は、Trunkの別のトレーニングを受けている学生が作ってくれました。

第3回の分で、大幅に時間が押していたため、第4回の分を巻いても、合計7時間という長丁場となりました。。

振り返って

前回が通信やカスタムリストビューなど、実践的な知識を身につけることをテーマにしていたのと比べて、今回は画面一つで済ませるもの、かつ、作り切ることをテーマにしていたので、難易度は低めになっていました。 しかしそれでも、アプリを作り切るのだと、Javaの文法がわかっているレベルでないと教えるのも理解するのも難しいです。 その前提を合わせないと、資料作りや教え方にも影響してきます。

また、いかに教えないかが重要だと学びました。 答えを教えるのではなく考えさせること。今集中して覚えるべきこと以外のことをそぎ落とすこと。 必要な知識を必要な時に提供することが大事です。言われてみると至極当たり前のように感じるのですが、実際教える立場になってみると、すっかり抜け落ちていました。 わりと、効率よくもれなく学ばせようとしていました。

スライドやサンプルアプリはGitHubに公開していたのですが、あまり活用されていないようでした。 復習できる形だからしてるよね?課題にしたからしてるよね?というのは教える側のエゴなのかと思いました。 学生はいとも簡単に想像を超えてきます。学生に対して教える立場になるときは、その心構えが必要です(そういえば自分も入社時の課題をこなせなかったことを思い出しました。)。

自分の中での課題は明確になったので、続・続があれば挑戦したいです。 これから開発を始める方や、同じような境遇の人の参考になればいいなと思います。

github.com

参考

Androidアプリ開発を学生に教えた話 / メモ2ブログ

すべてのトレーニングを無料で、すべての学生に。 / Trunk

米マイクロソフトがBash on Windowsを発表、その目的は / @IT

Adobe Creative SDK / Adobe

gradle-retrolambdaを使ってビルドした時に you must set the path to jdk8 エラーが出た時の対処法 / Qiita

training-android-camera-sakebook / GitHub

都道府県の情報を簡単に扱うためのライブラリをKotlinで作った。

都道府県コード都道府県名を変換するようなことをJavaで書いたのが非常に辛かった。 もう同じことをしないでいいように、使いまわせる形にした。

Javaでリスト操作ができなかったのでKotlinでさっと操作したいと思ったのがモチベーションです。

実際Kotlin要素はほぼないのでタイトルは若干釣りです。

Zipangu

ライブラリ名が思いついたので、作りました。

github.com

Maven Centralにも登録したので、 dependenciesに一行追加だけでいけます。

compile 'com.github.sakebook:Zipangu:0.1.0@aar'

使い方

都道府県コードや都道府県名から逆引きができます。

Zipangu.code(1) // return prefecture 北海道
Zipangu.code("北海道") // return prefecture 北海道

八地方区分と、気象庁の分類の一部に対応しています。

Zipangu.area(Area.中部) // return prefectures 中部地方
Zipangu.segment(Segment.North) // return prefectures 北日本

nullを返したくなかったので、逆引きに失敗した時はダミーのPrefectureを返します。

ダミーのPrefectureは初期化の際に設定できます。 Mutableなので取得した際に変更もできます。

Zipangu.beginning(this, Prefecture(0, "県外", "県外", Segment.None))

使用上の注意

一応Javaから使うサンプルと、Kotlinから使うサンプルを置いてありますが、基本一行なのでほぼ同じです。

作ってからわかったのですが、JavaからKotlinのライブラリを呼び出す際は、プロジェクトがKotlinを使えるように設定していないとエラーが出て使えません

次のようなエラーがでました。

Could not find class 'kotlin.reflect.KProperty[]', referenced from method com.sakebook.android.library.zipangu.Zipangu.<clinit>
java.lang.VerifyError: com/sakebook/android/library/zipangu/Zipangu
java.lang.NoClassDefFoundError: kotlin.jvm.internal.Intrinsics

作成上の小話

データはassetsのjsonにアクセスしています。

始めはjsonを細かくし、並列に読み込めるようにして、変更しやすい、コントリビュートしやすい作りにしようとしたのですが、そもそもどんな区分で分けるか?明確に決まったものが少ない上に、ファイルアクセスのオーバヘッドの方が大きいと思ったので、シンプルにしました。

MavenCentralに上げる際に、先人と同じようにjavadocの生成で失敗しました。これもまた先人と同じように回避したので、javadocは空です。。

まとめ

これから都道府県の情報を扱うことになる人にとっては、一手間省けるものになると思うので、Kotlinを使う第一歩にしてもらえればと思います。

参考

全国地方公共団体コード / Wikipedia

全般気象情報などに用いる地域名 / 気象庁

KotlinでAndroidライブラリを作ってリリースする / Qiita

Kotlinのライブラリをbintray-releaseを使ってアップロードするときにハマったこと / Qiita

Android Support Library 23.2で追加されたChrome Custom TabsのBottom barを試してみた。

Chrome Custom Tabs

Webページを自分のアプリ内ブラウザで開くかのごとく、Chromeを使って開くことができる機能です。 利用するにはChromeのバージョンが45以上であることが必要です。

Chrome Custom Tabs自体は23.1.0から提供されていた機能ですが、新たにBottom barが提供されました。

今まではアクションボタンが一つしか置けない制約があったのですが、今回の更新でBottom barにItemが置けるようになったのでその機能を試してみました。

Bottom bar

色の変更とItem(5つまで)の設置ができます。

Bottom barと紹介してきましたが、中ではsecondaryToolbarと呼ばれています。

次のメソッドで色を指定できます。デフォルトではToolbarと同じ色が使われます。

  • public CustomTabsIntent.Builder setSecondaryToolbarColor(@ColorInt int color)

Itemの追加は次のメソッドです。一つも追加しない場合、Bottom barが表示されません。

  • public CustomTabsIntent.Builder addToolbarItem(int id, @NonNull Bitmap icon, @NonNull String description, PendingIntent pendingIntent) throws IllegalStateException

Itemを5つ以上追加するとIllegalStateExceptionが発生します。

idはItem間でユニークなものでないと、後から追加しようとしたものは追加されないので注意が必要です。

descriptionは、Itemを長押しした際に表示されるToastで使われます。

複数追加した場合、 後から追加したものが右側に追加されます。

Toolbarはスクロールに合わせて見え隠れするのですが、 Bottom barは表示されっぱなし なのでWebViewの表示領域が若干狭くなります。

サンプル

適当ですが、次のような感じです。

dependencies {
    compile 'com.android.support:appcompat-v7:23.2.0'
    compile 'com.android.support:customtabs:23.2.0'
}
    public static void launch(Activity activity, String url) {
        Intent dummyIntent = new Intent();
        CustomTabsIntent.Builder customTabsIntentBuilder = new CustomTabsIntent.Builder();

        PendingIntent pendingIntent =
                PendingIntent.getActivity(activity.getApplicationContext(), 100, dummyIntent, PendingIntent.FLAG_ONE_SHOT);
        Bitmap icon = BitmapFactory.decodeResource(activity.getResources(), android.R.drawable.ic_menu_share);
        customTabsIntentBuilder.setSecondaryToolbarColor(ContextCompat.getColor(activity, android.R.color.holo_purple));

        customTabsIntentBuilder.addToolbarItem(1, icon, "1", pendingIntent);
        customTabsIntentBuilder.addToolbarItem(2, icon, "2", pendingIntent);
        customTabsIntentBuilder.addToolbarItem(3, icon, "3", pendingIntent);
        customTabsIntentBuilder.addToolbarItem(4, icon, "4", pendingIntent);
        customTabsIntentBuilder.addToolbarItem(5, icon, "5", pendingIntent);

        CustomTabsIntent customTabsIntent = customTabsIntentBuilder.build();
        customTabsIntent.launchUrl(activity, Uri.parse(url));
    }

f:id:sakebook:20160227033748p:plain

f:id:sakebook:20160227033817p:plain

f:id:sakebook:20160227033824p:plain

f:id:sakebook:20160227033831p:plain

f:id:sakebook:20160227033840p:plain

実際に動きを見たい方はこちらのアプリで見れます。早速対応してみました。(v1.6.0)

play.google.com

条件

Support Libraryを23.2.0に上げることはもちろんですが、Chromeのバージョンが 49以上でないと表示されません。

それ未満の場合は、何も表示されないだけで、今までのChrome Custom Tabsと同じように使うことができます。

まとめ

49未満でも組み込んでも支障ないので、今までの制約に苦しんでいた人は積極的に組み込んでいいと思います。

未対応の場合表示されないので、右上の設定内に置いていたものを追加でBottom barに出すのがいいんじゃないかなと思います。

今後もできることが増えていくはずなので、楽しみ!

参考

Android Support Library 23.2 / Android Developers Blog

Chrome Custom Tabs / Chrome

Support Library Features / Android Developers