メモ2ブログ

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

スプラッシュにはActivityはいらない

スプラッシュ

iOSだとLaunchScreenとか言われる、起動時に出てくる画面です。

Androidだと、ユーザに無駄な待ち時間を与えるということで不要だと言われてたのですが、最近はGoogle製のアプリが、軒並みスプラッシュを入れてきています。

Bottom Navigationのことといい、考え方が変わってきたのでしょう。 Android開発を行う以上、プラットフォームが出すガイドラインに合わせるのが、結果的にユーザに良い体験を与えることにつながります。

スプラッシュについては、iOSと同様に、LaunchScreenというPatternで紹介されています。その実装方法を紹介します。

Activityあり

f:id:sakebook:20160601030423g:plain

SplashActivityなどを用意して、起動時に呼び出します。 なんらかの処理や、一定時間を経過した後にメインのActivityを起動させます。

  • DelaySplashActivity.java
public class DelaySplashActivity extends AppCompatActivity {

    private final static int SPLASH_TIME = 1500;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_delay_splash);
        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                Intent intent = new Intent(DelaySplashActivity.this, MainActivity.class);
                startActivity(intent);
                finish();
            }
        }, SPLASH_TIME);
    }

    /**
     * バックキー無効。
     * */
    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK) {
            return false;
        }
        return super.onKeyDown(keyCode, event);
    }
}

この方法だと、次のような特徴があります。

長所

  • DelaySplashActivityを起動させている間に処理を実行することができる
  • 複雑なアニメーションなどを表現できる

短所

  • 起動時間が若干遅くなる
  • LaunchModeをうまく指定しないとメインのActivityが重複する
  • 起動時に数瞬ブランクが表示される

Activityなし

f:id:sakebook:20160601030502g:plain

新たにActivityは追加しません。 Themeを指定します。

    <style name="SplashTheme" parent="Theme.AppCompat.Light.NoActionBar">
        <item name="android:windowBackground">@drawable/background_splash</item>
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
    </style>

親となるテーマのActionBarの有無は用途によって変えてください。
重要なのは android:windowBackground属性にdrawableを指定していることです。

background_splashは次のように設定しています。

  • background_splash.xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:opacity="opaque">

    <item
        android:drawable="@color/colorPrimaryDark"/>

    <item
        android:gravity="center">
        <bitmap
            android:gravity="center"
            android:src="@mipmap/ic_launcher"/>
    </item>
    <item
        android:gravity="bottom"
        android:bottom="@dimen/large_margin">
        <bitmap
            android:gravity="center"
            android:src="@mipmap/ic_launcher"/>
    </item>

</layer-list>

layer-listで作成します。

文字は追加できないのですが、Verctor画像で文字を作れば設定できます
その場合はstyleをv21以降と以前で分ける必要があります。

起動するActivityに作成したテーマを設定します。

  • AndroidManifest.xml
        ...
        <activity
            android:name=".SplashActivity"
            android:label="SplashCold"
            android:theme="@style/SplashTheme">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>

                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
        ...

Splash専用のActivityを追加しなくても、スプラッシュが追加できています!

この方法だと次のような特徴があります。

長所

  • 起動時間が通常とほぼ変わらない
  • 既存のアプリに追加しやすい
  • 起動時に数瞬ブランクが表示されない

短所

  • 事前の処理が行えない
  • 表現できることに制約がある

まとめ

スプラッシュの目的はplaceholder UIBranded launch screensです。

特に理由が無ければ、Acitvityを追加しないSplashの実装で上記の目的を達成するのが良いと思います。
ただし、事前の処理を行っておくことで結果的にユーザ体験を良くできるならば、Activityを追加する実装でも良いと思います。
その場合はbackgroundの要素を指定しておきましょう。

サンプルです。

github.com

参考

Android UI/UX アンチパターン / nein37’s diary

Launch screens / Google design guidelines

プレースホルダ 【 placeholder 】 / IT用語辞典 e-Words

Splash Screens the Right Way / Big Nerd Ranch

Avoiding cold starts on Android / Saúl Molinero

GenymotionにGooglePlayを入れようとするとAn error occured while deploying the fileが発生する

Genymotionについては以前触れたのでこちらで。

sakebook.hatenablog.com

An error occured while deploying the file.

GooglePlayを入れるための準備をしていると次のエラーが発生しました。

f:id:sakebook:20160525022243p:plain

Genymotionのバージョンは2.6.0でした。

エミュレータを作り直したりカスタムしてSDカードを生成したりしてもうまくいかなかったのですが、次のようにすることで解決しました。

ADB tool connection settings

おそらく、Genymotionの設定画面を開いて、User custom Android SDK toolsにチェックが入っているので、 defaultの方へ変更します。

これで解決しました。以上。

参考

Genymotion Android 6.0 に Play Store をインストールして Google Map を利用する / Qiita

wbroek/genymotionwithplay.txt / gitHub gist

Androidエンジニアが企画展に作品を出した話

2016/4/30~2016/5/15、2週間と1日、「CreativeAdventure」という、企画展がARTnSHELTERで開催されました。 そこで「Indoor Street」という作品を展示しました。企画展に作品を出すという経験での学びや感想をつらつらと書きます。

きっかけ

大学時代にU-moaという集団で活動をしていました。そのメンバーが社会人となり、徐々に東京に人が集まってきたので、当時のつながりや社会人になってからの新しいつながりを含めて、何か面白いことができないかとU-moaの代表が発起したのがきっかけです。

テーマ

企画展を行うにあたり、今回のテーマが「冒険」ということでした。 その他の参加メンバーの顔ぶれから、インタラクティブなものが求められると感じたのではじめは尻込みしていたのですが、せっかくのきっかけだしやってみようと思い参加をすることにしました。

作品

作品テーマ

冒険 ≒ 旅と捉え、昨今の旅では必需品となるスマホを関連させる意味付けを行いました。

スマホアプリエンジニアで何ができるだろうか?と考えたときに、やはりスマホやアプリの要素を切り離せないと思いました。それらを軸に、インタラクションを与えられないかと考えました。

インタラクションと言えばわかりやすいのがVRだったのですが、企画展内で被りそうだったので、スマホの何かしらの情報を何かしらで飛ばして何かしらに変化を与えるという風にすることにしました。

作品概要

アプリで場所を検索すると、目の前に投影されてるスクリーンにその場所が表示され、スマホを持って歩くとその場所の中を歩けるという作品です。

f:id:sakebook:20160522184835j:plain

アーキテクチャ

リモコンとなるスマホアプリと、場所を表示するWebがあります。

スマホアプリ

  • Geocoder
    • 目的地の緯度経度の取得に用います。
  • Step Detector Sensor
    • 歩行検知に用います。
  • Accelerometer sensor
    • 端末の傾きを検知するのに用います。
  • Magnetic field sensor
    • 端末の傾きを検知するのに用います。
  • Open Sound Control
    • Webへ情報を送るのに用います。
    • 目的地の緯度経度、検知した歩行と傾き情報を送信します。

Android 4.4から歩行センサーが付いたのを知ったので、そのAPIを使うことにしました。

Web

  • Node.js
    • サーバやモジュールのimportに用います。
  • Express
    • Webページの作成に用います。
  • Socket.io
    • NodeサーバでOSCを経由して受け取った情報をWebへ送ります。
  • Google Maps JavaScript API
    • Street Viewの表示・制御に用います。

以前OSCを用いてWebと連携を行ったことがあったので、その方法で行うことにしました。

展示準備

会場にプロジェクターとスクリーン(壁)はあったので、必要なものは常設に必要なPCでした。

常設できるPCを持っていなかったので、メンバーに借りることにしました。 設置する作業よりも、借りたPCに環境構築をする方が大変でした。

作品を出す機会があれば、環境構築の手順を明確にしておくことと、実際に展示に使うであろうものを自分で用意しておかないとダメだなと思いました。

アプリをユーザに入れてもらう想定だったので、Google Playにアプリを公開しました。QRを読み込んでストアへ遷移し、入れてもらう想定だったのですが、もちろんiPhoneに対応していません。

楽しめないユーザがいるのでアプリを入れた状態のAndroidスマホを展示会場に置いておくことにしました。こちらも、配慮が足りなかったのと、端末を自分で用意していない点が至らなかったと思います。

展示中

展示して翌日に問題がありました。作品が展示されていませんでした。

起動方法がterminalに入ってディレクトリ移動してnpm startとか、明らかにエンジニア以外に優しくない形だったので、.commandファイルを作成してファイルをダブルクリックで起動できるようにしました。 初めての展示で、この辺りも配慮が足りていなかったです。

また.commandファイルにリポジトリの更新も含めておいたので、展示中に変更があっても翌日には反映されるようにしました。 完成された作品なら不要かもしれませんが、変更が想定される作品の場合、更新する手段を入れておくと良いと思います。

はじめの想定では来場者の端末にアプリを入れてもらう想定だったので、トップページを作成し、そこに説明文とQRコードを用意していたのですが、これはうまくいかなかったです。 前述の通りiPhoneユーザは体験できないことと、QRコードを読み取ってアプリをインストールし、会場のIPを取得するためにもう一度QRコードを読み取ってアプリを起動するというフローが必要だったので、誰もそこまでしてくれないし理解してくれませんでした。

そこで、展示会場に合わせて置いたスマホを、あえて接続状態にし、スクリーンにはトップページではなくどこかにつないだ状態の画面を表示するようにしました。 こうすることで、見た目的にもキャッチーで、展示会場のスマホをいじることですぐに体験できるようになりました。 如何に自分の意図通りに来場者に触ってもらうのか?というところの敷居を下げる必要があると強く感じました。

振り返って

作品が展示されていなかったり、来場者に触ってもらえないなどもありましたが、来て頂いた方々には思ったより楽しんでもらえていたよう良かったです。 自分の行ってみたいところや、家の近く、思い出の場所などに行く人が多かったです。

連携部分の詰めが甘くて操作には癖があったのですが、それ込みでワイワイ楽しんでもらえていたのは嬉しくもあり助かった部分でもありました。

しかし、やはり理解するまでの敷居が高かったです。 Androidユーザで4.4以上の端末で会場のwifiにつないでQRコードを読み取りアプリをインストールして再びQRコードを読み取ってアプリを起動しないと遊べないので、スカイツリーより高いと揶揄されました。
実際その通りで、企画展に作品を出す場合は、アプリを入れてもらうということより、如何にして体験してもらうかが重要です。
敷居が高い作品の場合は、どうやってその敷居を下げることができるか?を考える必要があります。
技術的な制約により変更できないものがある場合は、事前準備を省くなどが良いと思います。
今回に関して言えば、作品を楽しめるアプリがインストールされているスマホを用意しておくことと、スクリーンに画面を投影させておくことが策に当たると思います。

スマホアプリエンジニア脳で、入れてもらった後のことばかり考えていました。

来場者とつながったり、終わった後の達成感、また、普段使わない技術に挑戦(場合によってはまずいかも)できるので、機会があればまた何かしたいと思いました。

ひとまずはPCとKitkat以降のスマホを購入してからにしたいです。

参考

CreativeAdventure / 企画展CreativeAdventure

ARTnSHELTER / ARTnSHELTER

U-moa / U-moa