Android開發Widget之提高篇

        在上一篇博客Android開發Widget之入門篇我們已經介紹了創建一個widget的流程。但是像這樣的widget沒什麼實際用途,widget主要是爲了顯示一些信息,這樣很方便,不用我們專門去啓動應用查看信息,那麼現在教大家做一個顯示時間的widget。

      效果如下:

      

      這個與之前的widget不同的就是,它是啓動了一個後臺服務,服務註冊了廣播監聽時間變化,當發生變化時就接受到廣播然後更新時間。像之前的流程一樣還是分三步。

 一.建一個widget的佈局。

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingTop="@dimen/widget_marginTop" 
    android:paddingBottom="@dimen/widget_marginBottom" >

    <TextView
        android:id="@+id/appwidget_time"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:gravity="center"
        android:contentDescription="@string/appwidget_text"
        android:textColor="@color/appwidget_view_time"
        android:textSize="@dimen/appwidget_view_time"/>
     
</RelativeLayout>
二.在xml目錄下新建一個 widget的配置文件。     
<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
    
    android:initialLayout="@layout/time_widget"
    android:minHeight="72dp"
    android:minWidth="142dp"
    android:previewImage="@drawable/example_appwidget_preview"
    android:resizeMode="horizontal"
    android:updatePeriodMillis="86400000" >

</appwidget-provider>
三.編寫代碼

     新建一個TimeApplication繼承自Application,調用TimeUpdateService的onReceive方法,在widget一啓動就接受時間更新時間,然後啓動TimeUpdateService.

public class TimeApplication extends Application {
	@Override
	public void onCreate() {

		TimeUpdateService.mTimeTickReceiver.onReceive(getApplicationContext(),
				null);
		getApplicationContext().startService(
				new Intent(getApplicationContext(), TimeUpdateService.class));
    }
}
    TimeUpdateService裏註冊廣播,接受廣播就更新時間.  
public class TimeUpdateService extends Service {
	//獲取Calendar對象
	private static Calendar mCalendar = Calendar.getInstance(TimeZone.getDefault());
	
	//時間廣播接收者
	public static BroadcastReceiver mTimeTickReceiver = new BroadcastReceiver() {

		@Override
		public void onReceive(Context context, Intent intent) {
			 //時區改變則重新獲取Calendar
			if (intent != null) {
	            if (intent.getAction().equals(Intent.ACTION_TIMEZONE_CHANGED)) {
	                String tz = intent.getStringExtra("time-zone");
	                mCalendar = Calendar.getInstance(TimeZone.getTimeZone(tz));
	            }
			}
            //設置當前時間           
            mCalendar.setTimeInMillis(System.currentTimeMillis());
			//設置時間格式
			boolean is24 = DateFormat.is24HourFormat(context);
			SimpleDateFormat format = new SimpleDateFormat(is24 ? "H:mm" : "h:mm", Locale.getDefault());
			String time = format.format(mCalendar.getTime());
		    //更新時間		
			TimeWidget.updateAppWidget(context, time);
		}
	};

	@Override
	public IBinder onBind(Intent intent) {
		
		return null;
	}
	
	@Override
	public void onCreate() {
		super.onCreate();
        //註冊這個廣播,當系統時間改變時就會發送廣播
		IntentFilter filter = new IntentFilter();		
		filter.addAction(Intent.ACTION_TIME_TICK);
		filter.addAction(Intent.ACTION_TIME_CHANGED);
		filter.addAction(Intent.ACTION_DATE_CHANGED);
		filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
	  	getApplicationContext().registerReceiver(mTimeTickReceiver, filter);		
	}
	
	@Override
	public void onDestroy() {
		super.onDestroy();
        //註銷廣播
		if (null != mTimeTickReceiver) {
			getApplicationContext().unregisterReceiver(mTimeTickReceiver);
		}
	}
}
     最後新建TimeWidget繼承自AppWidgetProvider.
public class TimeWidget extends AppWidgetProvider {
	 
	//時間
	private static String  mTime;
	 
	@Override
	public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
		super.onUpdate(context, appWidgetManager, appWidgetIds);		 
		//如果時間不爲空,那麼更新時間
		if (mTime!=null) {
			TimeWidget.updateAppWidget(context, mTime);
		}
	}

	@Override
	public void onEnabled(final Context context) {
		super.onEnabled(context);	  	
		//啓動後臺服務檢測時間變化
		context.startService(new Intent(context, TimeUpdateService.class));
	}

	@Override
	public void onDisabled(Context context) {
		//當最後一個widget被移除時停止服務 		
		context.stopService(new Intent(context, TimeUpdateService.class));
	}
    
	//更新widget
	static void updateAppWidget(Context context, String time) {
		//給mTime賦值
		mTime = time;	 
		//如果time不爲null則更新
		if (null != time) {
			//widget管理者
			AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
			//遠程view視圖
			RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.time_widget);
   			//設置視圖中的顯示
			views.setTextViewText(R.id.appwidget_time, time);
	 		//指定要啓動的組件
			ComponentName mComponentName = new ComponentName(context, TimeWidget.class);
		 	//更新
			appWidgetManager.updateAppWidget(mComponentName, views);
		}
	}
	
}
       

      這樣就完成了時間widget,很簡單的。如果你要做一個界面很複雜的widget你就要注意了,widget只支持部分View,像Button,AnalogClock,TextView,ImageView等,那麼那些複雜,酷炫的widget是怎麼實現的呢,這就要在framework層下去修改了,位置在frameworks/base/core/java/android/widget裏面,資源文件存放在frameworks/base/core/res/res 裏,感興趣的朋友可以自己研究下。

    最後附上Demo地址:點擊打開鏈接



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章