Shinjuku.aar第1回に参加した
Shinjuku.aarとは
Shinjuku.aarは、新宿界隈のAndroid技術者たちが 技術ネタで気軽にワイガヤできる コミュニティです。
発表ごとにディスカッションタイムを設けており、発表中の質問やツッコミも随時ウェルカム! さらに、ディスカッションが盛り上がるよう、発表者には参加者に向けた 問いかけを一つ入れるようお願いしています 。
もちろんその後は懇親会も用意しておりますので、思う存分ワイガヤしましょう!
http://shinjuku-aar.connpass.com/event/35434/
第1回で、新宿ということもあり参加してみました。
Few command line tools for help Android development
@tomorrowkeyさんの発表です。
www.slideshare.net
adbのコマンドと自作コマンドラインツールの紹介でした。 自分はapkの生成・配布以外はAndroid Studioでだいたい作業していたのですが、ビルドを途中で停止したり、アプリの設定を初期化したりなど、確かにAndroid Stuidoではなかなかやりにくいこともできるので、徐々に比率を移行していきたいなと思いました。
恥ずかしながらiTermのHotKeyを知らなかったのですが、設定すると切り替えが非常に楽で、移行に前向きになりました。
Chrome Custom Tabsを使いこなそう
自分の発表です。
会場ではChrome Custom Tabsを使っている人が思ったより少なかったです。 24.0.0からの機能の紹介で、知らなかったという声も上がっていたので一安心しました。
AutoValue for Easier Life
@Shaunkawano さんの発表です。
ボイラープレートを無くしていこう、ボイラープレートを書かないでいこう、という、決め事を掲げてチームで取り組むという姿勢が良いなと思いました。
AutoValueは知らなかったのですが、目的に即していると思いました。
DownloadProviderを改めて読む
@YusukeIwaki さん
資料は見つかりませんでした。。
Android標準のコンポーネントであるDownloadProviderの設計を、別の所でも使おうというお話。
雑感
会場の雰囲気作りとして、はじめに皆が自己紹介するという形式で、人数もそこまで多くなかったのでやりやすさはありました。 また10分の発表は初めてだったのですが、質問とかしながらしていく雰囲気もあり、時間があまるという感じにはなりませんでした。
他の発表者の方たちのスライドが皆英語のスライドで、デザイン性も高かったので次発表する機会があれば、英語でスライドを作ってみようと思いました。 英語で作ると、日本人以外でも見れるようになるし、スライドをただ読み上げることもなくなる気がします。
MashwmallowでqueryIntentActivitiesの挙動が変わってた
Chrome Custom Tabsを使っていて、公式のサンプルにあるCustomTabsHelperを流用していたのですが、Mashwmallowでうまく動かないことがありました。
CustomTabsHelper内で、PackageManager#queryIntentActivities
を使っているのですが、その挙動がMashwmallow以前と以降で異なっていたのが原因でした。
どう変わったのかと、回避方法を紹介します。
Mashwmallow以前
次のように呼ぶことで、引数のIntentに対応できるActivityを持つアプリを取得できます。
PackageManager pm = this.getPackageManager(); List<ResolveInfo> resolvedActivityList = pm.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
queryIntentActivities(Intent intent, int flags)
の第二引数のflags
には、PackageManager.MATCH_DEFAULT_ONLY
を指定します。こうすることで、 android.intent.category.DEFAULT
を持つActivityのみを反応させることができます。
どんなIntentかにもよりますが、次のようにするとブラウザ系のアプリの一覧が表示されると思います。
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.example.com"));
Mashwmallow以降
Mashwmallow以降で同じように呼ぶと、そのIntentに対応するActivityを「常時」で規定で開く設定にしている場合、結果が変わります。
結果は、 規定で開く設定にしているActivityしか返さない ようになります。
規定で開くの設定を解除すると、Mashwmallow以前と同じになります。
Mashwmallow以前と等しい挙動で取得するためにはqueryIntentActivities(Intent intent, int flags)
の第二引数のflags
を、PackageManager.MATCH_ALL
を指定します。
PackageManager pm = this.getPackageManager(); List<ResolveInfo> resolvedActivityList = pm.queryIntentActivities(intent, PackageManager.MATCH_ALL);
PackageManager.MATCH_ALL
はAPI Level 23から追加されたflagです。
Querying flag: if set and if the platform is doing any filtering of the results, then the filtering will not happen.
とあるので、フィルタリングされたくない時に使うようです。
バージョン対応
共存させるには、バージョンでflags
を切り替えれば良いです。
例えば次のような感じです。
int flag; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { flag = PackageManager.MATCH_ALL; } else { flag = PackageManager.MATCH_DEFAULT_ONLY; } ResolveInfo info = pm.resolveActivity(intent, flag);
CustomTabsHelperの場合は、公式のサンプルにPullRequestがきてるので、それに習うといいと思います。
まとめ
Mashwmallow以降以前で挙動が変わる場合があるので、バージョンを見てflagsを切り替えましょう。
しかし、API Level 23未満で、PackageManager.MATCH_ALL
を指定したところ、クラッシュも発生せず同じように取得できていたので、最悪PackageManager.MATCH_ALL
のほうだけ使っておけば良いのかもしれません。。
参考
Chrome Custom Tabs / Google Chrome
GoogleChrome/custom-tabs-client / GitHub
custom-tabs-client/CustomTabsHelper.java / GitHub
Intent Resolving in Android M / Medium
Android:IntentFilterにDEFAULT_CATEGORYが必要な理由 / Yukiの枝折
スプラッシュにはActivityはいらない
スプラッシュ
iOSだとLaunchScreenとか言われる、起動時に出てくる画面です。
Androidだと、ユーザに無駄な待ち時間を与えるということで不要だと言われてたのですが、最近はGoogle製のアプリが、軒並みスプラッシュを入れてきています。
Bottom Navigationのことといい、考え方が変わってきたのでしょう。 Android開発を行う以上、プラットフォームが出すガイドラインに合わせるのが、結果的にユーザに良い体験を与えることにつながります。
スプラッシュについては、iOSと同様に、LaunchScreenというPatternで紹介されています。その実装方法を紹介します。
Activityあり
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なし
新たにActivityは追加しません。 Themeを指定します。
- styles.xml
<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 UIかBranded launch screensです。
特に理由が無ければ、Acitvityを追加しないSplashの実装で上記の目的を達成するのが良いと思います。
ただし、事前の処理を行っておくことで結果的にユーザ体験を良くできるならば、Activityを追加する実装でも良いと思います。
その場合はbackgroundの要素を指定しておきましょう。
サンプルです。
参考
Android UI/UX アンチパターン / nein37’s diary
Launch screens / Google design guidelines
プレースホルダ 【 placeholder 】 / IT用語辞典 e-Words