1. 程式人生 > >androidの桌面小控制元件(1)—電池狀態顯示

androidの桌面小控制元件(1)—電池狀態顯示

桌面小控制元件的實現是基於Broadcast的形式實現的,因此,每一個桌面小控制元件都對應於一個BroadcastReceiver類。Android系統提供了一個AppWidgetProvider類(它就是BroadcastReceiver的子類),這個類很關鍵,你在寫桌面小控制元件時只需繼承這個類就行。繼承了AppWidgetProvider類之後,你可以根據自己的需要覆蓋它的不同的生命週期的方法,來達到自己的目的。AppWidgetProvider類的主要提供如下不同生命週期的方法:

void onUpdate(Context context, AppWidgetManager appWidgetManager,int[] appWidgetIds) { } 
// 這個方法字面意思是負責更新桌面小控制元件,但貌似只有在小控制元件被使用者放到桌面上時被呼叫了一次,讀者可以自己通過輸出Log來測試 
// 實現桌面控制元件是通常都會考慮重寫該方法 

void onDeleted(Context context, int[] appWidgetIds) 
// 在小控制元件被刪除時呼叫該方法 

void onUpdate(Context context, AppWidgetManager appWidgetManager,int[] appWidgetIds) { }
// 這個方法字面意思是負責更新桌面小控制元件,但貌似只有在小控制元件被使用者放到桌面上時被呼叫了一次,讀者可以自己通過輸出Log來測試
// 實現桌面控制元件是通常都會考慮重寫該方法 

void onDeleted(Context context, int[] appWidgetIds)
// 在小控制元件被刪除時呼叫該方法

一般來說,開發桌面小控制元件只需要定義一個AppWidgetProvider的子類,並重新寫它的pnUpdate方法即可。

2. 示例講解

先定義一個AppWidgetProvider子類。。
public class AppWidet extends AppWidgetProvider {
	private static int currentBatteryLevel;
	private static int currentBatteryStatus;
	public void onUpdate(Context context, AppWidgetManager appWidgetManager,int[] appWidgetIds) {
		super.onUpdate(context, appWidgetManager, appWidgetIds);
		// 啟動自動更新電池資訊的service
		context.startService(new Intent(context, updateService.class));

		//為AppWidget設定點選事件的響應,啟動顯示電池資訊詳情的activity
		Intent startActivityIntent = new Intent(context,BatteryInfoActivity.class);
		PendingIntent Pintent = PendingIntent.getActivity(context, 0,startActivityIntent, 0);
		RemoteViews views = new RemoteViews(context.getPackageName(),R.layout.other_layout);
		views.setOnClickPendingIntent(R.id.imageView, Pintent);
		appWidgetManager.updateAppWidget(appWidgetIds, views);
	}

	// 自動更新電池資訊的service ,通過AlarmManager 實現定時不間斷的傳送電池資訊
	public static class updateService extends Service {
		// 定義機器人圖片
		Bitmap bmp;
		@Override
		public IBinder onBind(Intent intent) {
			return null;
		}

		// 定義一個接受電池資訊的broadcastReceiver
		private BroadcastReceiver batteryReceiver = new BroadcastReceiver() {
			@Override
			public void onReceive(Context context, Intent intent) {
				// 獲取當前電量
				currentBatteryLevel = intent.getIntExtra("level", 0);
				// 獲取當前電池狀態
				// 電池狀態,返回是一個數字
				// BatteryManager.BATTERY_STATUS_CHARGING 表示是充電狀態
				// BatteryManager.BATTERY_STATUS_DISCHARGING 放電中
				// BatteryManager.BATTERY_STATUS_NOT_CHARGING 未充電
				// BatteryManager.BATTERY_STATUS_FULL 電池滿
				currentBatteryStatus = intent.getIntExtra("status", 0);
			}
		};

		public void onStart(Intent intent, int startId) {
			super.onStart(intent, startId);
			// 註冊監聽電池資訊廣播
			registerReceiver(batteryReceiver, new IntentFilter(
					Intent.ACTION_BATTERY_CHANGED));
			// 定義一個AppWidgetManager物件
			AppWidgetManager manager = AppWidgetManager.getInstance(this);
			// 定義一個RemoteViews,實現對AppWidget的控制
			RemoteViews views = new RemoteViews(getPackageName(),
					R.layout.other_layout);
			// 當正在充電或充滿電時,顯示充電的圖片
			if (currentBatteryStatus == 2 || currentBatteryStatus == 5) {
				.......
			} else { // 未進行充電
				.......
			}
			// 設定AppWidget上顯示的圖片和文字的內容
			views.setImageViewBitmap(R.id.imageView, bmp);
			views.setTextViewText(R.id.tv, currentBatteryLevel + "%");
			// 將AppWidgetProvider子類例項包裝成ComponentName物件
			ComponentName thisWidget = new ComponentName(this, AppWidet.class);
			// 使用AlarmManager實現每隔一秒傳送一次更新提示資訊,實現資訊實時動態變化
			long now = System.currentTimeMillis();
			long pause = 1000;
			Intent alarmIntent = new Intent();
			alarmIntent = intent;
			PendingIntent pendingIntent = PendingIntent.getService(this, 0,
					alarmIntent, 0);
			// 定時傳送更新提示
			AlarmManager alarm = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
			alarm.set(AlarmManager.RTC_WAKEUP, now + pause, pendingIntent);
			manager.updateAppWidget(thisWidget, views);
		}
	}
}

然後是點選桌面外掛顯示介面。
public class BatteryInfoActivity extends Activity {
	..........
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		this.requestWindowFeature(Window.FEATURE_NO_TITLE); // 設定activity無標題
		setContentView(R.layout.main_layout); // 使用newlayout的佈局
		tvBatteryStatus = (TextView) findViewById(R.id.tvBatteryStatus);
		tvBatteryLevel = (TextView) findViewById(R.id.tvBatteryLevel);
		tvBatteryHealth = (TextView) findViewById(R.id.tvBatteryHealth);
		tvBatteryTemperature = (TextView) findViewById(R.id.tvBatteryTemperature);
		tvBatteryVoltage = (TextView) findViewById(R.id.tvBatteryVoltage);
		tvBatteryTechnology = (TextView) findViewById(R.id.tvBatteryTechnology);
		flag = true; // 提示service的標誌位置為true
		infoReceiver = new BroadcastReceiver() // 提示資訊接收器的定義
		{
			@Override
			public void onReceive(Context context, Intent intent) {
				setText(); //收到intent,就及時修改TextView資訊,使得Activity顯示時,電池資訊也能動態顯示  
			}
		};

		//註冊提示資訊的intentFilter 
		IntentFilter filter = new IntentFilter();
		filter.addAction("com.wyl.example.broadcast");
		registerReceiver(infoReceiver, filter);

		// 啟動提示service
		Intent startService = new Intent(this, updateService.class);
		startService(startService);
	}

	//點選螢幕任意位置,關閉電池資訊Activity
	public boolean onTouchEvent(MotionEvent event) {
		this.finish();
		return true;
	}

	@Override
	protected void onDestroy() {
		flag = false;
		unregisterReceiver(infoReceiver);
		super.onDestroy();
	}

	//及時動態修改Activity上文字資訊的函式
	public static void setText() {
           。。。。
	}

	/** 提示資訊變化的service,約每隔一秒,就傳送intent, 
     * 提醒activity更新電池資訊,主要為了檢測電池狀態的變化, 
     * 例如連上充電時,狀態會從“未在充電”變為“正在充電” 
     * 通過呼叫plugged方式,還能判斷是AC方式充電還是USB方式充電 
     */  
	public static class updateService extends Service {
		@Override
		public IBinder onBind(Intent intent) {
			return null;
		}

		/** 定義得到電池資訊的BroadcastReceiver,提取出關鍵資訊,存入變數中 */
		private BroadcastReceiver batteryReceiver = new BroadcastReceiver() {
			@Override
			public void onReceive(Context context, Intent intent) {
				currentBatteryStatus = intent.getIntExtra("status", 0);
				currentBatteryLevel = intent.getIntExtra("level", 0);
				currentBatteryHealth = intent.getIntExtra("health", 0);
				currentBatteryTemperature = intent
						.getIntExtra("temperature", 0);
				currentBatteryVoltage = intent.getIntExtra("voltage", 0);
				currentBatteryTechnology = intent.getStringExtra("technology");
				currentBatteryPlugged = intent.getIntExtra("plugged", 0);
			}
		};

		public void onStart(Intent intent, int startId) {
			registerReceiver(batteryReceiver, new IntentFilter(
					Intent.ACTION_BATTERY_CHANGED));

			/** 啟動一個執行緒,約每隔一秒就傳送intent提醒Activity更新電池資訊 */ 
			new Thread() {
				public void run() {
					while (flag) {
						Intent sendInfoToActivity = new Intent();
						sendInfoToActivity
								.setAction("com.wyl.example.broadcast");
						sendBroadcast(sendInfoToActivity);
						try {
							Thread.sleep(1000);
						} catch (Exception ex) {
							ex.printStackTrace();
						}
					}
				}
			}.start();
			super.onStart(intent, startId);
		}
	}
}