iT邦幫忙

第 11 屆 iT 邦幫忙鐵人賽

DAY 27
0
Mobile Development

iOS Developer Learning Android系列 第 27

iOS Developer Learning Android. Lesson 27 - APP Widget (讓user不用開你的APP就能用你的APP)

Widget,又稱小部件或小工具,是一個在OS裡可以操作App的另一個地方
Android的widget跟iOS的widget在操作上就很不一樣⚠️⚠️⚠️
iOS是在第一個主畫面的左邊會有一個列表,全部的widget都必須集中在這邊
Android則是在任意主畫面的地方都可以新增widget,畫面大小也可任意調整,更靈活也更方便
在開發部分:
雖然在iOS跟Android都是寄生於Host App裡(也就是App刪了,widget也被刪了)☘️☘️☘️
但iOS的widget是一個Target(Today Extension),有自己的bundleID,算是跟App同一級
但Android的widget只是一個component,繼承於BroadcastReceiver

本日效果

說明

  1. 新增方式
    1. File > New > Widget(拉到最下面) > AppWidget
      1. Placement:可以決定是否讓widget顯示在鎖定畫面,但目前試不出來
      2. resizeable:就像開頭講的,可以決定讓widget是否可以調整大小
      3. 要注意一定要有Target source set這個選項,不然就是你可能在錯誤的地方右鍵new,可能會讓你搬檔案搬到手軟
      4. configuration Screen:可以讓widget在新增的時候開啟一個Activity用以設定,像這樣

  2. 主要檔案組成
    1. Widget.java:Widget的程式邏輯
    2. widget.xml:Widget的畫面佈局
    3. widget_info.xml:Widget的一些參數設定,在AS新增時的選項都可以從這邊調整
    4. example_appwidget_preview.png:user新增widget時會看到的預覽畫面
  3. 生命週期
    1. onEnabled
      加入第一個widget時呼叫
    2. onUpdate
      只要加入widget時就會呼叫
      另外在widget_info.xml的updatePeriodMillis還有設定多久會呼叫一次(我是試不出來)

The updatePeriodMillis attribute defines how often the App Widget framework should request an update from the AppWidgetProvider by calling the onUpdate() callback method. The actual update is not guaranteed to occur exactly on time with this value and we suggest updating as infrequently as possible—perhaps no more than once an hour to conserve the battery.
https://developer.android.com/guide/topics/appwidgets#MetaData

   3. onDeleted
     只要刪除widget時就會呼叫
   4. onDisabled
     刪除最後一個widget時呼叫
   5. onReceive
     因為是繼承BroadcastReceiver,所以也可以發廣播給它
4. 畫面處理
   1. 佈局只支援FrameLayout、LinearLayout、RelativeLayout、GridLayout
   2. 元件只支援AnalogClock、Button、Chronometer、ImageButton、ImageView、ProgressBar、TextView、ViewFlipper、ListView、GridView、StackView、AdapterViewFlipper(連子類也不行)
   3. 因為現在不是對Activity寫邏輯了,所以什麼findViewByID、onClick都不能用了
跟畫面的溝通就必須要一個RemoteViews類來處理

        RemoteViews views = new RemoteViews(context.getPackageName(), com.example.idla.R.layout.new_app_widget);
        views.setTextViewText(com.example.idla.R.id.appwidget_text, widgetText);
        appWidgetManager.updateAppWidget(appWidgetId, views);

如果是按鈕,這樣可以點了就開Activity
把PendingIntent.getActivity換成PendingIntent.getBroadcast可以讓widget收到onReceive

        remoteView.setOnClickPendingIntent(com.example.idla.R.id.appwidget_btn, PendingIntent.getActivity(context,0,new Intent(context, Lesson22Activity.class),0));
  1. 發廣播給widget
        Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
        intent.putExtra("message",editText.getText().toString());

        PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, intent, 0);
        try {
            pendingIntent.send();
        } catch (PendingIntent.CanceledException e) {
            e.printStackTrace();
        }

問題

  • 目的:希望可以在Activity按下按鈕時,更新widget畫面上的資料
  • 狀況:Android不像iOS widget可以用UIViewController⚠️⚠️⚠️,是沒有Activity可以用的
    在現有的生命週期裡,似乎找不到每次看到widget一定會call的function
    所以沒辦法先把資料存起來,再讓widget主動去抓最新的資料
    那麼我就想要由Activity通知,widget再被動更新
    但onReceive是拿不到appWidgetIds的
    所以也就不知道要更新哪個元件
    現在是卡在這
    找了一些資料目前還沒看到解法
    之後研究出來再來補充

參考資料

今天的範例程式

可以去 https://github.com/mark33699/IDLA 看一下順便給顆⭐️


如果你喜歡我的影片別忘了按讚分享加訂閱,開啟紅色的小鈴鐺,我們明天見~


上一篇
iOS Developer Learning Android. Lesson 26 - FCM Notification (Service & BroadcastReceiver)
下一篇
iOS Developer Learning Android. Lesson 28 - 伸縮Banner + 瀑布流 + CardView (首頁大改造)
系列文
iOS Developer Learning Android30

尚未有邦友留言

立即登入留言