Googleの電話番号を扱うライブラリlibphonenumberを使ってみたのでメモ

Androidアプリの開発で電話番号を扱いたくて、googleのlibphonenumberを使ってみたのでまとめます。

電話番号について

まずは、電話番号そのものについてちょっと調べてみました。
例えば、080-1234-5678なんていう番号があったとします。海外からこの電話番号にかけようとすると、+81-80-1234-5678となります。
これは、ITU-T(International Telecommunication Union Telecommunication Standardization Sector)が勧告するE.164に沿っていて、調べてみると意外と奥が深かったりします。

ドキュメントはここに落ちているので、気合いの入った方は是非読んでみてください。
(E.164 : The international public telecommunication numbering plan)
https://www.itu.int/rec/T-REC-E.164-201011-I/en

とりあえずパースしたい僕としては、ドキュメントのこの図だけ分かっておけば十分そうです。

f:id:t-miliya612:20180414190859p:plain
Figure 1 – International ITU-T E.164-number structure for geographic areas - ITU-T Rec. E.164 (11/2010) The international public telecommunication numbering plan

総務省の資料もありました。これだけで十分でしたね。
(電気通信番号制度概要) http://www.soumu.go.jp/main_sosiki/joho_tsusin/policyreports/joho_tsusin/bango/pdf/061012_4_s8.pdf

結局、必要そうな情報は以下の三点です。

  • 電話番号には世界共通の勧告がある
  • 先頭には1〜3桁のCC(国番号)が必要
    • 国際番号を除けば海外と電話番号が被る可能性がある?
  • 電話番号は最大で15桁

libphonenumber

github.com

ようやく本題です。Google Internationalizationが提供するライブラリで、電話番号をパースするのに必要なことをよしなにやってくれます。
Android限定というわけではなく、JavaC++、JS向けのライブラリのようです。

何ができるの

電話番号のパースをしたい

# パース
fun libphonenumberTest_parse() {
    var msn = "08012345678"
    println(phoneNumberUtil.parse(msn, "JP"))
    msn = "818012345678"
    println(phoneNumberUtil.parse(msn, "JP"))
    msn = "+818012345678"
    println(phoneNumberUtil.parse(msn, "JP"))
    msn = "+81 80 1234 5678"
    println(phoneNumberUtil.parse(msn, "JP"))
    msn = "+81-80-1234-5678"
    println(phoneNumberUtil.parse(msn, "JP"))
    msn = "080(1234)5678"
    println(phoneNumberUtil.parse(msn, "JP"))
    msn = "080.1234.5678"
    println(phoneNumberUtil.parse(msn, "JP"))
}
# => Country Code: 81 National Number: 8012345678
# => Country Code: 81 National Number: 8012345678
# => Country Code: 81 National Number: 8012345678
# => Country Code: 81 National Number: 8012345678
# => Country Code: 81 National Number: 8012345678
# => Country Code: 81 National Number: 8012345678
# => Country Code: 81 National Number: 8012345678

fun libphonenumberTest_parse_withInvalidRegion() {
    val msn = "+818012345678"
    println(phoneNumberUtil.parse(msn, "US"))
}
# => Country Code: 1 National Number: 818012345678 

電話番号のフォーマットをしたい

# フォーマット
fun libphonenumberTest_format() {
    /*
      public enum PhoneNumberFormat {
        E164,
        INTERNATIONAL,
        NATIONAL,
        RFC3966
      }
      */
    val msn = phoneNumberUtil.parse("08012345678", "JP")
    println("E164: " + phoneNumberUtil.format(msn, PhoneNumberUtil.PhoneNumberFormat.E164))
    println("INTERNATIONAL: " + phoneNumberUtil.format(msn, PhoneNumberUtil.PhoneNumberFormat.INTERNATIONAL))
    println("NATIONAL: " + phoneNumberUtil.format(msn, PhoneNumberUtil.PhoneNumberFormat.NATIONAL))
    println("RFC3966: " + phoneNumberUtil.format(msn, PhoneNumberUtil.PhoneNumberFormat.RFC3966))
}
# => E164: +818012345678
# => INTERNATIONAL: +81 80-1234-5678
# => NATIONAL: 080-1234-5678
# => RFC3966: tel:+81-80-1234-5678

電話番号のタイプを知りたい: getNumberType

固定電話、携帯電話、フリーダイヤル、、、など、電話番号のタイプ判別ができます

fun libphonenumberTest_getNumberType() {
    val mobile = phoneNumberUtil.parse("08012345678", "JP")
    val fixed = phoneNumberUtil.parse("81312345678", "JP")
    val free = phoneNumberUtil.parse("0120123456", "JP")
    println("mobile: " + phoneNumberUtil.getNumberType(mobile))
    println("fixed: " + phoneNumberUtil.getNumberType(fixed))
    println("free: " + phoneNumberUtil.getNumberType(free))
}
# => mobile: MOBILE
# => fixed: FIXED_LINE
# => free: TOLL_FREE

電話番号の一致をチェックしたいisNumberMatch

2つの番号が同一かどうか、その信頼性を判断します。どのスケールでなら一致しているかを判断してくれるみたいですね。

fun libphonenumberTest_isNumberMatch() {
    println(phoneNumberUtil.isNumberMatch("+81334311234", "+81334311234"))
    println(phoneNumberUtil.isNumberMatch("+81334311234", "0334311234"))
    println(phoneNumberUtil.isNumberMatch("+81334311234", "34311234"))
    println(phoneNumberUtil.isNumberMatch("+81334311234", "+818012345678"))
    println(phoneNumberUtil.isNumberMatch("+81334311234", "0"))
}
# => EXACT_MATCH
# => NSN_MATCH
# => SHORT_NSN_MATCH
# => NO_MATCH
# => NOT_A_NUMBER

電話番号のバリデーションをしたい: isPossibleNumber, isValidNumber

電話番号の長さだけを見て、電話番号として成立しているかどうかを判断します。
isPossibleNumberは電話番号の長さを、isValidNumberは加えてprefixまで見ているらしく、前者の方が速いみたいです。

fun libphonenumberTest_isPossibleNumber() {
    val msn = phoneNumberUtil.parse("08012345678", "JP")
    val justNumber = phoneNumberUtil.parse("00000", "JP")
    val just15Numbers = phoneNumberUtil.parse("000000000000000", "JP")
    println(phoneNumberUtil.isPossibleNumber(msn))
    println(phoneNumberUtil.isPossibleNumber(justNumber))
    println(phoneNumberUtil.isPossibleNumber(just15Numbers))
}
# => true
# => false
# => true

fun libphonenumberTest_isValidNumber() {
    val msn = phoneNumberUtil.parse("08012345678", "JP")
    val justNumber = phoneNumberUtil.parse("00000", "JP")
    val just15Numbers = phoneNumberUtil.parse("000000000000000", "JP")
    println(phoneNumberUtil.isValidNumber(msn))
    println(phoneNumberUtil.isValidNumber(justNumber))
    println(phoneNumberUtil.isValidNumber(just15Numbers))
}
# => true
# => false
# => false

終わりに

今回紹介したものはほんの一部で、他にもダミーの電話番号を生成してくれたり、文章中から電話番号を抽出してくれたり、など至れり尽くせりなライブラリになっています。
電話番号というと、個人情報の中でもなかなか扱いづらく収集しづらいものに分類されてしまいがちなので、なかなかさわる機会ってないのがちょっと残念です。
ついでに、先日、キャリアがRCS準拠のサービスを始めるとのニュースがありました。

www.nttdocomo.co.jp

news.kddi.com

www.softbank.jp

これ使って遊べたら面白そうだなぁ。

おまけ

電話番号がどの企業に割り当てられているか、が一覧になっています。携帯の電話番号だとMNPのために判断が難しくなっていますが。。。 (電気通信番号指定状況) http://www.soumu.go.jp/main_sosiki/joho_tsusin/top/tel_number/number_shitei.html

雰囲気でカンバンやってませんか - 『カンバン仕事術』を読んだ

 結構長い間、『カンバン仕事術』という本を読んでいます。

カンバン仕事術

カンバン仕事術

 数ヶ月前、業務でカンバンツールを取り入れる機会を得ました。近くの部署の方々に話を聞いたりパブリックになっているカンバンを眺めながらなんとなーく運用をしてきたのですが、今のところあまりうまくいっていません……。
 正直カンバンツールを入れれば自然と上手くいくじゃろ、と思っていた節もあり、なんとかしようと思っていた所この本と出会いました。まだ読み終わってはいないのですが、途中までのまとめと現時点での感想・反省を書き残しておきたいと思います。続編として書くかはまだ決めていませんが、この溢れ出る思いをなんとか今のうちに書き残しておきたい……と待ちきれなくなり書き始めてしまいました。

チームについて

  • 開発者3人(自分含む)、マネジメント層数人
  • 運用作業はまだない
  • カンバンツール導入まではGithub issueベースのタスク管理をしていた
  • カンバンツールとしてTrelloを導入

本について

 大きく3章で構成されています。

  • 第I部 カンバンの学習
    • 開発プロセスに悩むチームが、カンバンを実際に導入する(したくなる?)までの流れが物語形式で書かれています。
    • カンバンの紹介です
    • チームメンバーのうち何人かには、本書を回してとりあえずこの章だけは読んでもらいました。
  • 第II部 カンバンの理解
    • カンバンの生まれてきた背景や概念について説明しています。
    • 第I部で出てきた用語が詳しく紹介されていきます。
  • 第III部 カンバンの応用
    • まだ読んでません!

学び

カンバン導入のメリットは「改善の機会」を洗い出すこと

 冒頭で、カンバンツール導入があまりうまくいっていないと書きました。具体的には、途中からみんながカンバンに状況を反映しなくなったり、手元のお気に入りのツールにメモしてしまったりで、カンバンに情報が集まらなくなってしまったんです。
 そもそも、本来カンバンツールって何?ってところから考える必要がありました。
 導入時には「タスク管理ツール」として、以下のようなメリットを想定していました。

  • タスクの進捗が見えやすくなる
  • Excelを達成し、キレイなUIでモチベが上がる
  • Githubのコードとの連携が楽

 要は、Excelで作った職人技ガントチャートを脱して、少しでもナウい開発現場を作ろうとしていました。ガントチャート作成の手間やら管理の手間やらを減らし、少しでも長くコーディングの時間を確保したかったんです。
 ところが、結果は先程書いたとおりです。各自お気に入りのタスク管理方法があったため、なかなか情報がカンバン上に集まってきませんでした。

 この本では、カンバン導入の効果はチームの「改善の機会」(問題のこと。本書の中ではこのような表現を意図的に用いているようでした)を可視化することだとありました。つまり、ただタスク全体を見やすくして期限までに全ての作業を完了させるだけではありません。
ただタスクを全部終わらせて満足ではなく、常にその時その時の状況に応じて最適化へ向けて変化し続けるチームを作る/になること。配属以来なかなか意識できていませんでした……。

レーンの決定は真似すればいいものじゃない

 何となく導入したカンバンを見ると、大抵は「Backlog」「Ready」「OnGoing」...などのレーンが並んでいるはずです。僕のいる部署のことです。出処は色々あると思いますが、とりあえず始めてみようかーといってざっくりレーンを作ると大抵こんな感じになるのではないでしょうか。
 結論から言うと、この時点で使われないカンバン作りは完成です。使われないどころか、何も業務を見せてくれないカンバンが出来上がります。業務の流れを勝手に想像で決めてしまうと、見えるはずのものも見えなくなってしまいます。業務と業務の間にある隠れタスクを洗い出すこともカンバンの大きな役割でした。
 カンバンを使って業務を流れとして明確にすること。これって、Rx系のStreamの定義と近いところがあるように思えます。データ(タスク)の流れを定義する。どこかで処理が失敗したり、バッファから溢れそうなときはちゃんとエラー処理をする。コードやシステム上であれば想定しやすいし、完全にはできなくても考える意識は持てるはずです。何より、開発メンバーにはこっちの方が響くような気がしています!(明日伝えてみよう)

イケてるツールがカンバンツールの全てではない

 カンバンツールと聞くと、TrelloやらZenhubやら、最近だとGithub projectが上がってくると思います。カンバンを導入した際も、これらの中から検討して現在はTrelloを使っています(最低限の機能はありながら、あまり縛りがない点が気に入っています)。
 ですが、これらって結局カンバンの電子ツールの側面でしかないんですよね。立派なツールでなくても、ホワイトボードと付箋さえあればカンバンは始められます。今いる会社は業務上の都合上、電子ツールを選択するしかありませんでした。結果的にセーフでしたが、ツールの使用許可が下りず断念するくらいなら、カッコつけておしゃれなツールを使う必要はないということは覚えておきたいです。

反省

  • カンバンでタスク管理だけをやろうとしない。チーム全体の隠れ作業を暴き出そう。
  • カンバンのカラムはチーム全員で決めよう。その辺のボードを真似して終わりではない!
  • PCやスマホ、ネット環境がなくてもカンバンは始められる!

おわりに

 本当はカンバンの原則を紹介したり、WIP制限などの具体的なカンバン運用の話をしたほうがいいのかもしれません。が、憧れだとか前の現場で使ってたからだとかで導入する際に躓いたこと、といった観点でまとめてみました。カンバン運用などについてはその先にある話だと思います。
 試行錯誤をしながら作り変えていくものなので、なかなかみんなが気持ちいい形に落ち着くことはできなさそうですが……。早めに数字として結果を計測できるようにしていくことが大事ですね。今後も本書は手元に置きつつ、定期的に見直していきたいと思います。

 また、本書ではカンバン運用のみならず、TDDやBDDなどの開発手法、さらには上手な付箋の剥がし方(!)まで触れられています。普段技術書しか買わない、といった方も、意外な発見があるかもしれません。

今だから読みたい -「Androidアプリ開発の教科書 なんちゃって開発者にならないための実践ハンズオン」を読んだ

 Androidの開発に携わるようになって半年ほど経過しました。RxJavaやDaggerなどのライブラリ、ナウい設計のフレームワークなど、様々な技術要素に揉まれながら何とかやってきましたが、いまいちAndroidと仲良く慣れたような気がしません……。
 一度基礎からやり直そうかと思っていたところ、今年発売の新しい入門書が出ていたので読んでみました。『基礎&応用力をしっかり育成! Androidアプリ開発の教科書 なんちゃって開発者にならないための実践ハンズオン』です。
 2月に発売されたばかりで、もちろんAndroidStudio3対応です。

基礎&応用力をしっかり育成!  Androidアプリ開発の教科書 なんちゃって開発者にならないための実践ハンズオン (CodeZine BOOKS)

基礎&応用力をしっかり育成! Androidアプリ開発の教科書 なんちゃって開発者にならないための実践ハンズオン (CodeZine BOOKS)

目次と学べること

  1. Androidアプリ開発環境の作成
  2. はじめてのAndroidアプリ作成
    • Androidプロジェクトの作成方法について
  3. ビューとアクティビティ
    • ViewのそれぞれのXMLタグの意味、使用方法
    • ViewのXMLでよく使う属性
  4. イベントとリスナ
  5. リストビューとダイアログ
    • リストビューの生成と描画(ArrayAdapter)
    • リストへのクリックイベントの設定
    • Toastの生成と表示
    • Dialogの生成と表示
    • Contextについて
  6. ConstraintLayout
    • ConstraintLayoutの概要、使い方
  7. 画面遷移とIntentクラス
    • リストビューの生成と描画(SimpleListAdapter)
    • Activityの追加方法
    • インテントを使った画面(Activity)遷移
    • Activity間のデータの受け渡し
    • Activityのライフサイクル
    • AndroidのLogについて
  8. オプションメニューとコンテキストメニュー
    • オプションメニューの生成と描画
    • コンテクストメニューの生成と描画
  9. フラグメント
    • Fragmentの生成
    • Fragmentのライフサイクル
    • Activityへのアタッチ
    • Fragmentの遷移とデータの受け渡し
    • Fragmentを使った複数サイズの画面対応
  10. データベースアクセス
    • SQLiteデータベースを使ったデータ永続化
  11. 非同期処理とWeb API連携
    • AsyncTaskを使った非同期処理とスレッド
    • AndroidでのHTTP通信(外部ライブラリの使用は無し)
  12. メディア再生
    • 音楽ファイルの再生、停止
    • 音楽ファイルのループ再生
    • 音楽ファイルの巻き戻しと早送り
    • 素敵なフリー素材サイト(!)
  13. バックグラウンド処理と通知機能
    • サービスを用いたバックグラウンド処理
    • 通知の生成とActivityの外部起動
  14. 地図アプリとの連携とGPS機能の利用
    • 暗黙的インテントの使い方
    • 位置情報の取得方法
    • Permissionの確認と取得時のハンドリング
  15. カメラアプリとの連携
  16. マテリアルデザイン
    • マテリアルデザインの概要
    • ScrollViewの使い方
    • ToolBarの使い方
    • スクロールに応じて動的に変化するToolBar
  17. リサイクラービュー
    • ScrollViewとRecyclerViewの違い
    • RecyclerViewの使い方

いざ洗い出してみるとすごい量です。。。

経歴

  • 2017年新卒
  • Android開発歴は半年
  • 学生時代はお手伝いとしてSpringとRailsでバックエンド開発を2年ほど

所要時間

 けっこう時間をかけてゆっくり読み込んだのですが、コードを写経しながらでも3日ほどで終わりました。
 ただ、多くの題材を扱うのであまり急いでやっても仕方がないかも……?

感想

 Android開発を始めるとき、この本があればかなりスタートダッシュを決められたのでは……?と思うほど、僕にはぴったりでした。
 Android開発の入門書というと、初めにViewの説明があったりなかったりした直後にActivity, そのライフサイクルの話がいきなりくるパターンが多いイメージです。
 この本では、作るアプリのイメージ→写経用のコード→解説の順番に章が立てられています。中でも、コード→解説をかなり細かい単位で繰り返しているのが印象的でした。頭ではなく体で覚えるタイプの僕には大変ありがたかったです。
 ちなみに、本のコードには省略されている箇所があるので、全部をこなそうとするとサンプルソースは必須です。
 また、上を読んでもらえればわかりますが、目次以上の内容が盛りだくさんです。個人的にはここがかなり有難くて、例えばContextなんてなかなか理解に手間取るポイントだと思います。このあたりのきめ細やかさもよかったです。

よかった章

 本を通して読んでみて、個人的に結構抜け漏れがあったのがリスト操作の章でした。リスト操作周りの処理を何回も一気に書く機会って実際の開発フェーズだとそんなに無いような気がするので、まとめて理解して手になじませるにはいい機会だったなと!
 また、マテリアルデザインの章も今この時期にはかなり貴重な学習材料だと思います。Android開発の中で、View周りのpropertyとかThemeの継承関係とかって何となくやりがちな分野ではないでしょうか?(そんなことないのだろうか) 短いサイクルでプラットフォームであるAndroidOSが新しくなっていく中で、最新版のOSの話題が本で手に入る今だからこそより一層価値がある章のはずです!

気になったこと

褒めてばかりでもステマっぽくなってしまうので、2点指摘しておきます。

誤字

初版ということもあるかと思いますが、ちらほら誤字脱字が見受けられました。ただ、理解を妨げるようなものは無かったはず。

カメラの章について

 かなり限られた用途かもしれませんが、業務上ここでのカメラの用途だと不十分でした……。
 本の中では、Intentを使ってAndroid標準のカメラアプリを使って写真を撮影する方法が推奨されています。(Googleもこの方法を薦めているようですね)
 一方、カメラ機能としてQRコードやバーコードを読み込みたい、といった要望って少なからずあるような気がしています。GoogleからBarcodeAPI(https://developers.google.com/vision/android/barcodes-overview)として提供されていますが、これのハンズオンとは言わずとも、紹介はあってもよかったのかな、と!

推奨読者層

 始めてプログラミングを始める人にはちょっと厳しいと思います。本の帯にも、対象はJava言語の学習者、とあります。Javaの解説は無く、基本的に関心はAndroidです。
 一方、ある程度プログラミング言語を触ったことがあるけどAndroid開発は初めて!という人には是非オススメしたいです。特に、プログラミング経験がほとんど無いなかで会社の研修を終えた方なんかには最適だと思います。「会社の研修」っていうのがミソです。特にそれを感じたのが、DBの章。SQLの知識はもちろんですが、JavaのDB周りを触ったことがないと調べることになりそうな箇所がいくつかありました。

 僕はそれだけでなく、数ヶ月ほどAndroidを開発したことがある人にもこの本を読んで写経してほしいです。皆さん、上の学べること、全部説明(とは言わずとも、イメージ)できますか?
 最近のAndroidでホットな話題だと、冒頭で書いたような設計やライブラリなどのものが多いように感じます。その中で、体系的にしっかり腰を据えてAndroidの学習を進める機会ってなかなか得られるものではないように思えます。この本のタイトルにもある通り、「なんちゃって開発者にならないため」には、Android StudioのNew Projectをした数がものを言うこともあるはずです。機能追加とリファクタリングだけでは経験が偏る、っていうのは僕がここ最近ひしひしと感じていることです。。。

合わせて読みたい記事、本など

まとめ

  • Android8.0が最新の今だからこそ読んで欲しい!
  • 手を動かしながら学びたい人におすすめ