2015年3月24日 星期二

Android的小工具(App Widget)

App Widget就是我們很常見到的Android桌面小工具,要製App Widget需要有一些步驟,這裡也一個有三個按鈕的小工具來做示範:

  1. 製作要給小工具用的Layout,程式碼如下所示

  2. appwidgetlayout.xml :
    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical" >
    
        <Button
            android:id="@+id/buttonToToast"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="按下後跳出訊息(Toast)" />
    
        <Button
            android:id="@+id/buttonToNotify"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="按下後發送通知(Notification)" />
    
        <Button
            android:id="@+id/buttonToOpenActivity"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="按下後前往另一個Activity" />
    
    </LinearLayout>
    
    
  3. 製作小工具的設定檔,在其中設定最小高及寬(公式為:格數*70dp-30dp)、並在initialLayout中指定小工具要用的Layout(即步驟一建立的appwidgetlayout.xml)並將之放到res資料夾下的xml資料夾中,程式碼如下:
  4. <?xml version="1.0" encoding="utf-8"?>
    <appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
        android:initialLayout="@layout/appwidgetlayout"
        android:minHeight="180dp"
        android:minWidth="320dp" /> 
  5. 建立Reciver,在AndroidMainfest.xml的<application>節點內區域中,設定Reciver,程式碼如下,其中"MainActivity"可以更換至特定的AppwidgetProvider:
  6. <receiver android:name="MainActivity">
       <intent-filter>
        <action android:name="android.appwidget.action.APPWIDGET_UPDATE"/>
       </intent-filter>
       <meta-data android:resource="@xml/button_widget_provider" android:name="android.appwidget.provider"/>
      </receiver>
  7. 建立上一步AndroidManifest.xml中,Reciver定義的名子同名的AppwidgetProvider類別,並Override想要的方法,在這裡我們Override兩個方法,分別為onUpdate()及onRecive(),程式碼如下:
  8. MainActivity.java (注意這不是Activity,是Reciever):
    package com.example.appwidget_example;
    
    import android.app.Notification;
    import android.app.NotificationManager;
    import android.app.PendingIntent;
    import android.appwidget.AppWidgetManager;
    import android.appwidget.AppWidgetProvider;
    import android.content.Context;
    import android.content.Intent;
    import android.widget.RemoteViews;
    import android.widget.Toast;
    
    public class MainActivity extends AppWidgetProvider {
     final String showToast = "showToast";
     final String showNotification = "showNotification";
    
     @Override
     public void onUpdate(Context context, AppWidgetManager appWidgetManager,
       int[] appWidgetIds) {
      super.onUpdate(context, appWidgetManager, appWidgetIds);
      // 得到RemoteViews,用來控制及設定App Widget的控件,如按鈕等
      RemoteViews remoteViews = new RemoteViews(context.getPackageName(),
        R.layout.appwidgetlayout);
      // 建立各個按鈕要進行的動作意圖(Intent),並利用putExtra()塞入資訊
      Intent intentOfButtonToToast = new Intent(context, MainActivity.class);
      intentOfButtonToToast.setAction(showToast);
      intentOfButtonToToast.putExtra("Message", "送出Toast");
    
      Intent intentOfButtonToNotify = new Intent(context, MainActivity.class);
      intentOfButtonToNotify.setAction(showNotification);
      intentOfButtonToNotify.putExtra("Message", "送出Notification");
    
      Intent intentOfButtonToOpenActivity = new Intent(context,
        Activity2.class);
      // 將建立好的Intent塞到Pending Intent中
      // 因為是要接收自訂的"showToast"廣播(Broadcast),使用getBroadcast()
      PendingIntent pendingIntentOfButtonToToast = PendingIntent
        .getBroadcast(context, 0, intentOfButtonToToast, 0);
    
      PendingIntent pendingIntentOfButtonToNotify = PendingIntent
        .getBroadcast(context, 0, intentOfButtonToNotify, 0);
      // 因為是想要前往另一個Activity,使用getActivity()
      PendingIntent pendingIntentOfButtonToOpenActivity = PendingIntent
        .getActivity(context, 0, intentOfButtonToOpenActivity, 0);
      // 將PendingIntent設定到remoteViews中
      // 因為是按鈕按下才要執行的動作,使用setOnClickPendingIntent()
      remoteViews.setOnClickPendingIntent(R.id.buttonToToast,
        pendingIntentOfButtonToToast);
      remoteViews.setOnClickPendingIntent(R.id.buttonToNotify,
        pendingIntentOfButtonToNotify);
      remoteViews.setOnClickPendingIntent(R.id.buttonToOpenActivity,
        pendingIntentOfButtonToOpenActivity);
      // 使用onUpdate()傳入的addWidgetManager來執行更新App Widget的動作,
      // 並將remoteViews當參數傳入
      appWidgetManager.updateAppWidget(appWidgetIds, remoteViews);
     }
    
     @Override
     public void onReceive(Context context, Intent intent) {
      // TODO Auto-generated method stub
      super.onReceive(context, intent);
      switch (intent.getAction()) {
      case showToast:
       Toast.makeText(context, intent.getStringExtra("Message"),
         Toast.LENGTH_LONG).show();
       break;
      case showNotification:
       Toast.makeText(context, intent.getStringExtra("Message"),
         Toast.LENGTH_LONG).show();
       //開始發送通知
       PendingIntent contentIntent = PendingIntent.getActivity(context, 0, intent, 0);
       NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
       Notification notification = new Notification(R.drawable.ic_launcher,"通知被發送",System.currentTimeMillis());
       notification.setLatestEventInfo(context, "通知Title", intent.getStringExtra("Message"), contentIntent);
       notificationManager.notify(1,notification);
    
       break;
      }
     }
    }
    

  9. 其中因為有要跳轉到Activity2,所以不要忘記加入要跳轉的Activity2。而因為MainActivity是Reciever不是Activity,所以記得不要在AndroidManifest中設定其為Activity。

沒有留言 :

張貼留言