読者です 読者をやめる 読者になる 読者になる

kurukuru-papaのブログ

主に、ソフトウェア開発に関連したメモを書き溜めたいと思います。

Androidアプリ「アプリ間共有の助け Ver.1.3」公開

Android

f:id:kurukuru-papa:20150219230436p:plain f:id:kurukuru-papa:20150219230450p:plain
2015/5/9に、自作Androidアプリ「アプリ間共有の助け」のバージョン1.3を公開しました。今回は、クリップボードの内容を他のアプリに共有する機能を追加しました。よろしければ、お使いください!

変更点概要

  • クリップボードの内容を他アプリに共有する機能を追加しました。(当機能では、端末起動時に通知を表示します。そのため「端末起動時に開始」のアクセス許可が必要となります。)
  • 細かな機能改善を行いました。

動作環境

対象OS:Android 4.0以降
動作確認済み端末:docomo Galaxy S4(SC-04E)

Androidアプリ「アプリ間共有の助け」公開

Android

f:id:kurukuru-papa:20150219230436p:plain f:id:kurukuru-papa:20150219230450p:plain
このほど、自作Androidアプリ「アプリ間共有の助け」というアプリを公開させていただきました。Androidにおけるアプリ間のデータ共有を少しだけ便利にするアプリです。よろしければ、お使いください!

はじめに

みなさん、Android端末のスマホを使っていると、ちょっとだけ使いにくいな~と思うような機能の1つや2つありますよね? 私は、各アプリの共有メニューを選択し、共有先のアプリを選択するダイアログが出たときに、ちょっとだけ使いにくいな~と、いつも思っていました。ダイアログでは、沢山のアプリが綺麗に並んでいるのですが、私が選択したいアプリは、ずいぶんと下の方にあったりするのです。毎回、スクロールさせるのが煩わしいのです。

そして、Google Playを探すと、共有メニューをカスタマイズできるアプリがいくつもあることを知り、使ってみました。ですが、カスタマイズする手間が煩わしかったりして、自分にはしっくりきませんでした。

であれば、作ってしまえ! ということで今回のアプリを作成しました。(そんなわけなので、かなり自分勝手なアプリですね。)

主な特徴

共有先アプリの選択時に、よく使用するアプリを先頭に表示します。(Android標準機能では、使用頻度を考慮してくれません。)

f:id:kurukuru-papa:20150219230541p:plain

特定の共有先アプリを「標準」として設定することで、選択画面をスキップして、共有先アプリを起動します。標準設定は、共有元アプリ、共有の種類ごとに設定可能です。(Android標準機能では、共有元によらず、共有の種類のみでしか設定できません。)

標準設定した共有先アプリを解除するのも簡単です。

詳細&ダウンロードは、こちらです。

プログラム

このアプリですが、プログラムをGitHubで公開しています。よろしければ、ご覧下さい。

AndroidでOAuth認証をしたい

Android Java

タイトルのまんまなのですが、Androidで、OAuth2.0認証をしたくなったので、調べてみました。なかなか理解できませんでしたが、何とか実装することができました。自分が理解したことをまとめてみたいと思います。
なお、私は、WebアプリケーションでOAuth1.0認証を行った経験はありましたので、OAuthの概要については、理解しているつもりでした。

難しかったところ

簡単に沢山の情報が見つかり、それぞれ分かりやすく具体的に書かれていましたが、どれも実装方法が異なり、どの実装方法を参考にすれば良いか、わかりませんでした。
実装方法が異なるのは、アプリケーションの形態や、ユーザーへの見せ方、使用ライブラリなどが異なるためでした。

実装パターン一覧

調べてみた実装方法について、自分なりに解釈した内容を表にまとめてみました。今回は、Androidアプリの実装方法に注目していますが、比較のため、Webアプリケーションとコンソールアプリケーションも記述しています。私がざっと調べて見つけた実装方法のみ記述していますので、探せば他にも色々あると思います。

パターン番号 アプリケーション形態 接続先 認証画面UI ライブラリ ユーザ操作
1 Androidアプリ Webサービス(コールバック) WebView 未使用 or 各種ライブラリ ID・パスワード入力
2 ブラウザアプリ
3 Webサービス(OOB) ブラウザアプリ ID・パスワード入力。PINのコピー&ペースト。
4 Googleサービス ブラウザアプリ Google APIs Client Library for Java ※1,2 ID選択。パスワード不要。
5 Googleサービスのみ? Android OS Android SDK (AccountManager) ID選択。パスワード不要。
6 Webアプリケーション Webサービス(コールバック) ブラウザ 未使用 or 各種ライブラリ ※2 ID・パスワード入力
7 コンソールアプリケーション Webサービス(OOB) ブラウザ ID・パスワード入力。PINのコピー&ペースト

※1 「Google APIs Client Library for Java」と同様のライブラリとして「Google Data Java Client Library(gdata-java-client)」というものもありました。「Google Data Java Client Library(gdata-java-client)」は、2012年3月頃で開発が止まっているようで、「Google APIs Client Library for Java」の前世代のライブラリのようでした。

※2 「Google APIs Client Library for Java」は、Androidアプリでも、Webアプリケーションでも使えます。たぶん、コンソールアプリケーションでも使えると思います。使う場合は、Androidアプリの場合、GoogleAccountCredentialクラス、GoogleAuthUtilクラスを使います(GoogleAccountCredentialクラスは内部でGoogleAuthUtilクラスを使用)。Webアプリケーションの場合、GoogleAuthorizationCodeFlowクラスを使います。

Androidアプリにおける実装パターン1~5について、画面イメージは次のようになります。

実装パターン1

アプリケーション形態:Androidアプリ
接続先:各Webサービス(コールバック)
認証画面UI:WebView
ライブラリ:未使用、各種ライブラリ使用のいずれでも実装可能
ユーザ操作:ID・パスワード入力

自作アプリです。OAuth認証を行うきっかけを用意しておきます。ここでは、開始ボタンを用意しました。
https://qiita-image-store.s3.amazonaws.com/0/24511/b51f0e00-4cb4-95c3-3383-09a63c228be1.png

自作アプリの内部に、WebViewを使用して、各Webサービスの認証画面を表示します。ここでは、Twitterの認証画面を表示しています。認証画面を表示する時には、コールバックURLを設定します。コールバックURLは、認証完了後に呼ばれるURLで、自作アプリ用のURLを設定しておきます。ユーザは、アカウントのIDとパスワードを入力し、アクセス権限を確認します。
https://qiita-image-store.s3.amazonaws.com/0/24511/dceb44bb-2612-fe93-512b-37ce918a38fc.png

認証後、自作アプリから、各Webサービスの情報にアクセスできるようになります。ここでは、アカウント情報を取得し、画面表示してみました。
https://qiita-image-store.s3.amazonaws.com/0/24511/e618b935-f02c-75d1-c49d-5dcb60fcddba.png

この実装パターンは、Androidアプリでもよく見かける気がしますし、Webアプリケーションにおいても同じ流れになりますので、ユーザーにとっては、慣れている操作手順かもかもしれません。

ただし、セキュリティ的な危険性を指摘するブログなどを見かけました。悪意ある開発者であれば、自作アプリ内のブラウザで入力されたアカウントのIDとパスワードを盗み取ってしまえるらしいです。ですが、個人的には、自作アプリなり、開発チームや会社などが、ユーザから既に信頼を得られているのであれば、この方式でも概ね受け入れられている気がします。

実装パターン2

アプリケーション形態:Androidアプリ
接続先:各Webサービス(コールバック)
認証画面UI:ブラウザアプリ
ライブラリ:未使用、各種ライブラリ使用のいずれでも実装可能
ユーザ操作:ID・パスワード入力

基本的には、実装パターン1と同じですが、WebViewの替わりに、Android端末内にインストールされているブラウザアプリを呼び出す方式です。

自作アプリです。開始ボタンをタップするとブラウザアプリを起動します。
https://qiita-image-store.s3.amazonaws.com/0/24511/ffed62ff-172b-fcf3-b24c-5130846b3f9f.png

端末内に複数のブラウザアプリがインストールされ、デフォルトが決められていない場合、ブラウザアプリを選択するダイアログが出ます。認証完了後に自作アプリが呼ばれるように実装しておきます。
https://qiita-image-store.s3.amazonaws.com/0/24511/bb2c3b0e-df4d-aa1a-3af2-d4560908ac61.png https://qiita-image-store.s3.amazonaws.com/0/24511/280f0bb1-ea3e-7d1e-8dd5-9353e5f14718.png

認証後、各Webサービスの情報にアクセスできます。
https://qiita-image-store.s3.amazonaws.com/0/24511/67bd2fe9-6839-90f9-97b6-4ac2e758435b.png

この実装パターンは、WebViewを使った時と比べて、セキュリティ面が改善されています。ブラウザアプリに入力されたアカウントのIDとパスワードを盗み取ることが困難なためです。

実装パターン3

アプリケーション形態:Androidアプリ
接続先:各Webサービス(OOB)
認証画面UI:ブラウザアプリ
ライブラリ:未使用、各種ライブラリ使用のいずれでも実装可能
ユーザ操作:ID・パスワード入力と、PINのコピー&ペースト

実装パターン2と比較して、各Webサービスの画面から、自作アプリへの戻り方が異なります。

自作アプリです。ここでは、連携確認ボタンをタップするとブラウザが起動するようにしました。
https://qiita-image-store.s3.amazonaws.com/0/24511/3c397072-7079-6546-e9df-4864b87382b9.png

Webサービスで認証後、PINと呼ばれるコードが払い出されます。ユーザにPINをコピーしてもらい、自作アプリへ戻ってもらいます。
https://qiita-image-store.s3.amazonaws.com/0/24511/d41e1289-a421-752b-04cc-f8acd9a65c43.png https://qiita-image-store.s3.amazonaws.com/0/24511/cdb0f83d-62e3-e9f0-bb22-b9f89ebf6400.png https://qiita-image-store.s3.amazonaws.com/0/24511/4aa5149a-db65-aaef-88d6-b5f08245264c.png

自作アプリに先ほどのPINを貼り付けてもらいます。このPINを使って、各Webサービスに接続し、情報にアクセスできるようになります。
https://qiita-image-store.s3.amazonaws.com/0/24511/6550e54c-81bb-6f74-78ee-5aa13765fe74.png https://qiita-image-store.s3.amazonaws.com/0/24511/61c36ee9-b360-0600-2532-735027e56bf4.png

PINを使うことで、各Webサービスと自作アプリの連携が少なくなりますので、セキュリティ面が安全になるようです。ただし、ユーザの操作性が悪くなるため、個人的にはあまり使いたくない実装パターンだと思います。

なお、ブラウザアプリの替わりに、WebViewを使用して実装することもできます。しかしながら、PINを使うことのセキュリティ面のメリットが失われてしまいますので、あまり意味がないと思います。

実装パターン4

アプリケーション形態:Androidアプリ
接続先:Googleサービス
認証画面UI:ブラウザアプリ
ライブラリ:Google APIs Client Library for Java 使用
ユーザ操作:ID選択。パスワード不要。

実装パターン4は、今まで説明した実装パターンとは、だいぶ異なります。
この実装パターンが使えるのは、Android端末で、Googleアカウントのみです。

自作アプリです。
https://qiita-image-store.s3.amazonaws.com/0/24511/2ac1b499-0c11-5441-abb1-ecf15bb52604.png

まず、認証に使用するGoogleアカウントを決定します。ここでは、Android SDKのAccountManagerを使用し、Androidの機能を呼び出して、端末に登録されているGoogleアカウントから、今回使用するアカウントを選択してもらいました。新規にGoogleアカウントを端末に追加して、使用することもできるようです。Googleアカウントを選択するだけで、パスワードの入力は不要です。(なぜ、パスワードがいらないのだろう?あまり理解できていないです。)
https://qiita-image-store.s3.amazonaws.com/0/24511/36bb592c-5bbe-d3f1-70e8-b29766dae4bc.png https://qiita-image-store.s3.amazonaws.com/0/24511/d2fc224f-6f64-e14d-6312-8760550415f4.png

認証後、Googleサービスの情報にアクセスできます。
https://qiita-image-store.s3.amazonaws.com/0/24511/0fbcddc0-ce76-b9fe-dd4f-f98199babfb5.png

この実装パターンでは、ユーザ操作がかなり簡単ですね。文字を入力することがなく、数回タップするだけです。
ただし、セキュリティ面はどうでしょう?端末を紛失して、悪意ある人に使われてしまうと、勝手に認証操作を行われてしまいそうです。とはいえ、端末を奪われた時点で、もっと大きな問題が発生するでしょうから、他者に操作される懸念は別の観点で考えたほうがよいのではないでしょうか。

実装パターン5

アプリケーション形態:Androidアプリ
接続先:Googleサービスのみ?
認証画面UI:Android OS
ライブラリ:Android SDKのAccountManager使用
ユーザ操作:ID選択。パスワード不要。

実装パターン5は、ユーザにとって、実装パターン4と似たように見えるかもしれませんが、実装は別物です。認証情報が管理される場所も異なります。実装パターン1~4では、各Webサービスのサーバ側で認証情報が管理され、各WebサービスがWeb上で提供しているアカウント管理画面から認証を解除することができました。しかし、実装パターン5では、Android端末側で管理されるようです。Web上のアカウント管理画面を見ても、自作アプリとアカウントが紐づいていることが分からない状態となっていました。どうしたら認証状態を確認できるのか、どうしたら解除できるのか、わかりませんでした。

自作アプリです。
https://qiita-image-store.s3.amazonaws.com/0/24511/38e9d8c4-8740-8ea9-650e-7bdab22aab25.png

AccountManagerが、必要に応じて、Account選択ダイアログを出したり、認証ダイアログを表示してくれます。Googleアカウントを選択するだけで、パスワードの入力は不要です。
https://qiita-image-store.s3.amazonaws.com/0/24511/f5ae6251-d997-c562-366b-401aa82d4c41.png https://qiita-image-store.s3.amazonaws.com/0/24511/3ab1dea8-0ae4-3523-e0f6-11d88a183d25.png

認証後、Googleサービスの情報にアクセスできます。
https://qiita-image-store.s3.amazonaws.com/0/24511/691df30f-b3a8-91ab-35f0-6760bc887f2e.png

この実装パターンでも、実装パターン4と同様に、ユーザ操作がかなり簡単ですね。文字を入力することがなく、数回タップするだけです。

セキュリティ面では、実装パターン4と同じ問題がありまそうです。Androidが進化を続けても、この実装パターンは、使い続けられるのでしょうか?よくわかりません。私の理解不足が多分にあるため、どう扱うべきか決めかねています。

まとめ

以上のように、AndroidアプリにおけるOAuth認証の実装方式は、すくなくとも5パターンありました。しかも、探せばもっと他の実装パターンもあるかもしれません。Webアプリケーションでは、概ね1パターンであったのと比べるとかなり違いますね。

説明した実装パターンについて、比較してみます。

パターン番号 適用範囲 操作性 セキュリティ
1
2
3
4
5

Googleサービスのみを使う場合は、実装パターン4で実装すると、使い勝手がよさそうです。実装パターン5も同様ですが、私があまり理解できていないので選択肢から外しています。Googleサービス以外のサービスを使う場合は、実装パターン2がよさそうです。

以上、ひとまず自分の理解をまとめてみました。もし、誤りなどありましたら、コメント頂けるとありがたいです。

動作確認

確認環境

確認用プログラム

変更履歴

2014/11/21 実装パターン5(AccountManager使用)を追加しました。

JAXBでネームスペース付加・XMLスキーマ検証もできました

Java

JAXB(Java Architecture for XML Binding)で、ネームスペースを付加したり、XMLスキーマ検証をしてみました。少し悩んだところもありましたが、問題なく動作確認できました。

続きを読む

JAXBで日本語タグも使えました

Java

JAXB(Java Architecture for XML Binding)で、日本語のタグも使えることを動作確認してみました。フツーに使えますね。

ポイントは、変換元/先オブジェクトのクラス定義で、@XmlRootElement、@XmlElementアノテーションを付けることですね。

文字コードも指定できました。

続きを読む

JAXBを使ってみました

Java

JAXBを使ってみたのでメモしておきます。

はじめに

JAXB(Java Architecture for XML Binding)とは、Java SE 1.6 以降に含まれるライブラリで、Javaのオブジェクトと、XMLを、相互に変換することができます。

似たようなライブラリには、ApacheのXMLBeansがあるようですね。

続きを読む

「レガシーコード改善ガイド」読書メモ(その2)

Java メモ

「レガシーコード改善ガイド」という書籍を読み、自分の解釈した内容をメモしています。

前回は、コードを改善する考え方をまとめました。
今回は、実際のテストコードについて書きます。

書籍では、テストコードの書き方について、第2部、第3部で書かれていました。第2部は多くのページを割き、実際の開発現場における数々の実例を端的に説明していて、面白かったです。第3部は、第2部で色々説明していた内容を「手法」としてまとめ、リファレンス的に説明していました。

主に第3部の内容について、利用頻度が高そうな「手法」をメモしました。

レガシーコード改善ガイド (Object Oriented SELECTION)

レガシーコード改善ガイド (Object Oriented SELECTION)

続きを読む