Wowgineer Notes

WowTechエンジニアの徒然開発日記

Wowgineer Notes

〜新たな"Wow"を生み出す〜

WowTalkでウィジェット開発する際のポイント

今回初めて本ブログの執筆を担当することになりました、ラジタです。

今年の初めに入社し、現在アプリ開発チームでAndroidの開発を担当しております。近年IOSやAndroidにおいて、ウィジェット機能が注目されています。ワウトークはチャットでやり取りするユーザが多いため、ホーム画面からすぐにチャットに入れる様、Androidワウトークアプリ開発の新機能として、お気に入り連絡先ウィジェットをリリースする予定です。

今回はこの開発を通じて得た知見をもとに、ウィジェット機能を実装する際のポイントについて簡単に紹介していきます。

 

目次

 ウィジェットとは

 基本情報

 Android Studio から簡単にウィジェット作りましょう

 自動に追加されるウィジェット設定確認しましょう

 ウィジェット追加する場合のクラスの役割

 困った点

 まとめ

 

ウィジェットとは

ウィジェットは、ホーム画面上に常に表示されるアプリのショートカット機能のことです。近年IOSでもAndroidでも流行してきているホーム画面のカスタマイズに不可欠な要素です。アプリの特に重要なデータや機能を「ひと目で」確認できるようにし、そうしたデータや機能にユーザーのホーム画面から直接アクセスできるようにするもの、ということができます。ユーザーはウィジェットをホーム画面のパネルからパネルへ移動したり、(サポートされていれば)好みに合わせてサイズを変更してウィジェットに表示される情報量を調整したりできます。Androidスマホにおける利便性の要となる機能といっても過言ではないでしょう。

基本情報

Androidウィジェットを作成するには、以下のものが必要です。

  • AppWidgetProviderInfo オブジェクト
  • AppWidgetProvider クラスの実装
  • ビューのレイアウト

詳細参照:https://developer.android.com/guide/topics/appwidgets?hl=ja

Android Studio から簡単にウィジェット作りましょう!!

New > Widget > AppWidget からウィジェット追加画面を開けます。

項目名 設定
Class Name ウィジェットの名前
Placement [Homescreen, Keyguard,Both] 中から選んでください。
Resizable [Both , Horizontal , Vertical , none] ウィジェットのサイズ変更できる方法の設定
Minimum Width ウィジェットの最小幅はセルカウントで追加してください
Minimum Height ウィジェットの最小高さはセルカウントで追加してください
Configuration Screen ウィジェット設定画面追加
Source Language ウィジェットに使用する言語

自動に追加されるウィジェット設定確認しましょう

ウィジェットを作成した時にウィジェット設定ファイルが追加されます。

例:project/res/xml/favorite_contact_widget_info.xml

<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="<http://schemas.android.com/apk/res/android>"
    android:description="@string/app_widget_description"
    android:initialKeyguardLayout="@layout/test"
    android:initialLayout="@layout/test"
    android:minWidth="110dp"
    android:minHeight="40dp"
    android:previewImage="@drawable/example_appwidget_preview"
    android:resizeMode="horizontal|vertical"
    android:updatePeriodMillis="86400000"
    android:widgetCategory="home_screen" />
項目名 説明
minWidth、minHeight サイズ。セルをdpで変換して指定
updatePeriodMillis 更新間隔をミリ秒で指定。AlarmManagerなどで自力で更新かける場合は省略可
previewImage ウィジェット選択一覧画面に表示する画像を指定。省略した場合はアプリアイコンが使用される
initialLayout 表示するレイアウトxmlを指定
configure 配置直後に起動されるActivityを指定。ウィジェット設定画面がない場合は省略可
resizeMode ホーム画面に配置されたウィジェットをロングタップすることでサイズ変更する場合に指定
widgetCategory Android 5未満ではロック画面にも配置できたが現在はホーム画面のみの指定

ウィジェット追加する場合のクラスの役割

ユーザーからウィジェット追加する際のフローになります。WidgetConfigureActivityでユーザからの追加設定をSharedPreferencesに保存しFavoriteContactWidgetクラスを呼びます。FavoriteContactWidgetで追加情報取得して、AppWidgetManagerへウィジェットの更新を依頼します

 

  説明
WidgetConfigureActivity.kt Widgetの設定管理Activity
getPendingIntent() 別のActivityから情報取得
updateWidget() AppWidgetProviderに情報渡す
Widget.kt AppWidgetProviderクラス
onUpdate() appWidgetManagerからWidgetId取得
updateAppWidget() RemoteViewを更新(WidgetUIの更新)

 

別のActivityからウィジェットアップデートを呼ぶ方法

intentにsetActionとAppWidgetManager.ACTION_APPWIDGET_UPDATEを設定し、AppWidgetManagerからidsを取得してブロードキャストでWidgetクラスに渡します。

FavoriteContactWidgetクラスのonUpdate関数でidsを受け取って各ウィジェットの新しい情報を取得しウィジェットUI更新依頼をAppWidgetManagerに渡します。

public void updateWidgets(){
    Intent intent = new Intent(this, FavoriteContactWidget.class);
    intent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
    int[] ids = AppWidgetManager.getInstance(this).getAppWidgetIds(new ComponentName(this, FavoriteContactWidget.class));
    intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, ids);
    sendBroadcast(intent);
}

実装時に困った点

①ウィジェット自動更新はどのタイミングで行うのか

今回のワウトークに追加したウィジェットの情報(連絡先ユーザのプロフィル写真、名前)は更新が必要でしたので、どのタイミングで自動更新されるか困ったので詳しく調べてみました。

AppWidgetProviderInfo.xmlの中のandroid:updatePeriodMillis="86400000"でミリ秒設定しても上手く行きませんでした。どのタイミングからカウントされるのか分からず、自動更新されるタイミングがバラバラだったので、詳しく調べてみました。

調査した結果としては”実際の更新が正確に行われるとは限りません”とオフィシャルAndroid仕様書に書いてありました。

自分の中で実装を確認したところ、ウィジェット追加したタイミングから開始するケースが多かったです。

参照:https://developer.android.com/develop/ui/views/appwidgets#other-attributes

② ウィジェット情報はどこに保存すれば良いのか

複数お気に入りウィジェット追加した場合にそのウィジェットに関しての情報どこで保存した方が良いか悩んでました。

時計などのウィジェットの場合は、別に情報を保存する必要がありません。しかし、今回開発したワウトークのお気に入りの連絡先ウィジェットでは、ユーザの名前と画像を表示することと、タップした瞬間にお気に入りの連絡先のルームを開くことができる様にするための実装だったので、ユーザーのIDとWidgetIDを保存する必要がありました。

ウィジェット情報の保存方法は二通りあります。

⑴ ローカルデータベースに保存する(詳しく複数の情報を保存する)

⑵ SharedPreferencesに保存する(IDや少ない値を保存する)

ID2つほどでしたら、データベースに入れるよりも、SharedPreferencesに保存することが推奨されています。

③ ウィジェット設定からMainアプリの別のActivityを開く際、MainActivityを開けたりしまうこと

今回はウィジェット設定の画面で別のContactActivityを開いてからお気に入りコンタクトの情報を選択する方法であり、ウィジェット設定開く時はアプリ全体(MainActivity)を開けてしまう問題が発生した上で下の方向で解決できました。

ウィジェット設定から呼び出すActivityのAndroidManifest中のLaunchMode設定はandroid:launchMode="singleTask"にする必要がありました。

修正前               修正後     

               

参照:https://developer.android.com/guide/topics/manifest/activity-element

④ウィジェット追加リスト画面のサイズ

ウィジェット追加リスト画面でウィジェットの各サイズのプレビュー画像で表示する必要がありました。画像を作成する際にどのサイズで作成する知らなかったので調べてみました。

選択一覧でホーム画面に配置できるウィジェットにはサイズが記載されており、以下の画像の2x4や4x6などがそれに当たります。 これらのサイズはセルという単位で、1x1でホーム画面のアプリアイコン1個分のサイズです。

ウィジェット追加する時はウィジェットのサイズセルで設定します。ウィジェットに表示する画像のサイズ確認するために下の計算が使います。

実装時はdpで指定するため次の式でdpへ変換します。

70 x n - 30

例えば1x1のウィジェットを作成する場合はn=1で計算して40dpx40dpで指定することとなります。

まとめ

Androidアプリ開発してたんですが、ウィジェット開発は初めてで問題なく開発段階完了できたのは嬉しいです。これからもユーザ体験高くなる新しいウィジェット開発したいと思います。

ワウテックには、多くの学びを得る機会と挑戦させてもらえる環境があります。
随時新メンバーを大募集中ですので、一緒に働ける方をお待ちしております!

f:id:wowtech-dev:20190313163146j:plain