android桌面widget
『壹』 如何在Android實現桌面清理內存簡單Widget小控制項
我們經常會看到類似於360、金山手機衛士一類的軟體會帶一個widget小控制項,顯示在桌面上,上面會顯示現有內存大小,然後會帶一個按鍵賣亮功能來一鍵清理內存,殺死後台進程的功能,那麼這個功能是如何實現的呢,我們今天也來嘗試做一個類似的功能的小控制項。
效果圖:
一、UI部分的編寫:
參照Google的文檔,首先在建立一個類繼承 AppWidgetProvider
import android.appwidget.AppWidgetProvider;
public class MyWidget extends AppWidgetProvider {
}
然後在清單文件中申明它,我們必須注意到,AppWidgetProvider實際上是BroadcastReceiver,所以要注冊成一個receiver,然後還有一些其他的東西需要注意:
<receiver android:name="com.alexchen.widget.MyWidget" >
<intent-filter>
<action android:name="困配蠢android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="@xml/example_appwidget_info" />
</receiver>
android.appwidget.action.APPWIDGET_UPDATE
表明這個receiver能夠接受一個APPWIDGET_UPDATE的廣播,而且在這里,只能加入這一個action。
android.appwidget.provider 表明數據類型時widget提供者提供的數據, example_appwidget_info 表明這個widget的參數配置文件名和位置
那麼接下來就需要在res目錄下建立一個xml文件夾,並且在其中建立一個 example_appwidget_info.xml 的配置文件,Google的文檔中給出了示例有很多參數,實際上關鍵的參數只有下面的4個:
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:minWidth="94dp"
android:minHeight="72dp"
android:updatePeriodMillis="86400000"
android:initialLayout="@layout/example_appwidget">
</appwidget-provider>
其中, minWidth 和 minHeight 代表這個widget控制項所佔據的最小空間,這個空間一般來講不需要太大,因為太大的話,一個屏幕可能都沒辦法放下,Google的官汪陪方文檔的說法是大於4x4的就可能無法顯示。
updatePeriodMillis 代表數據更新的時間,這里86400000毫秒實際上是24小時,可能最開始看到這個參數會想我能否將其設的很小,每一秒刷新很多次?, 實際上對於 updatePeriodMillis 這個參數而言, 即算你設的再小也沒用,Google設定widget控制項這個參數控制的最短update時間為30分鍾,就算將其設置在30分鍾以內也會以30分鍾的頻率來更新數據。
initialLayout 參數代表的是本widget空間的布局文件。
那麼下一步就是定義出一個對應的布局文件。我們可以簡單的在layout目錄下建立一個布局文件example_appwidget.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="200dp"
android:layout_height="80dp"
android:background="@android:color/white"
android:gravity="center_vertical"
android:orientation="vertical" >
<TextView
android:id="@+id/tv_widget"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="widget控制項測試"
android:textColor="@android:color/black"
android:textSize="15sp" />
<Button
android:id="@+id/btn_clear"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="清理內存"
android:textColor="#ff000000" />
</LinearLayout>
『貳』 如何開發android 桌面widget 源代碼
參考如下內容:
AppWidgetProvider類
AppWidgetProvider 繼承自 BroadcastReceiver,它能接收 widget 相關的廣播,例如 widget 的更新、刪除、開啟和禁用等。
AppWidgetProvider中的廣播處理函數如下:
onUpdate()
當 widget 更新時被執行。同樣,當用戶首次添加 widget 時,onUpdate() 也會被調用,這樣 widget 就能進行必要的設置工作(如果需要的話) 。但是,如果定義了 widget 的 configure屬性(即android:config,後面會介紹),那麼當用戶首次添加 widget 時,onUpdate()不會被調用;之後更新 widget 時,onUpdate才會被調用。
onAppWidgetOptionsChanged()
當 widget 被初次添加 或者 當 widget 的大小被改變時,執行onAppWidgetOptionsChanged()。你可以在該函數中,根據 widget 的大小來顯示/隱藏某些內容。可以通過 getAppWidgetOptions() 來返回 Bundle 對象以讀取 widget 的大小信息,Bundle中包括以下信息:
OPTION_APPWIDGET_MIN_WIDTH – 包含 widget 當前寬度的下限,以dp為單位。
OPTION_APPWIDGET_MIN_HEIGHT – 包含 widget 當前高度的下限,以dp為單位。
OPTION_APPWIDGET_MAX_WIDTH – 包含 widget 當前寬度的上限,以dp為單位。
OPTION_APPWIDGET_MAX_HEIGHT – 包含 widget 當前高度的上限,以dp為單位。
onAppWidgetOptionsChanged() 是 Android 4.1 引入的。
onDeleted(Context, int[])
當 widget 被刪除時被觸發。
onEnabled(Context)
當第1個 widget 的實例被創建時觸發。也就是說,如果用戶對同一個 widget 增加了兩次(兩個實例),那麼onEnabled()只會在第一次增加widget時觸發。
onDisabled(Context)
當最後1個 widget 的實例被刪除時觸發。
onReceive(Context, Intent)
接收到任意廣播時觸發,並且會在上述的方法之前被調用。
總結,AppWidgetProvider 繼承於 BroadcastReceiver。實際上,App Widge中的onUpdate()、onEnabled()、onDisabled()等方法都是在 onReceive()中調用的,是onReceive()對特定事情的響應函數。
『叄』 安卓桌面小部件Widget的局限性及適用性
一、Widget並不支持所有的控制項跟布局,而僅僅只是支持Android布局和控制項的一個子集。(當然也不支持自定義View)
1.支持的布局:
2.支持的控制項:
二、Widget不支持Animation動畫。
1.可以通過Bitmap、layoutAnimation和幀動畫實現動畫效果:
用這些方式雖然可以實現簡單的動效,但是非常容易產生內存溢出問題,導致OOM和閃退。歸根結底,Widget的設計是主打輕量化,需要長期放在桌面的Widget如果有大量動效,將會耗費大量系統性能和電量,這與它的設計初衷是相違背的。
2.動畫效果和方位感測器測試:
動效:使用 setImageViewBitmap 方法設置簡單的旋轉動畫,動畫會在兩基吵乎分鍾後停止播放。
感測器:在應用進入後台,執行 onStop 方法時,方位感測器會在一分鍾後停止監聽回調,此時後台Service正常運行,Widget時間正常更新,但是方位傳碰正感器不再回調監聽。(經測試,開啟前台Service才可以正常監聽)
總結:非常不建議Widget需要動畫或者調用感測器展示,在部分手機上會提示耗電異常,強制殺死程序。
三、進程保活:
進程保活涉及到的問題搏悉非常復雜,且越來越嚴格。測試了三款APP:
順歷:清除後台任務後Widget時間停止更新。
萬年歷:正常更新。
中華萬年歷:正常更新。
總結:順歷未設置保活方案,或保活失敗。
萬年歷與中華萬年歷監聽了系統時區改變廣播、時間手動設置廣播,在手動設置時間或時區後這兩個Widget也同步更新。同時還有一個時間正常流逝的廣播,系統每分鍾會發送一次,但是這個廣播在8.0系統以後不允許靜態注冊,也就是只能在APP運行的情況下才能監聽這個廣播。尚不清楚這兩個APP如何保活,或是如何在8.0以上系統監聽這個廣播,達到即便殺死後台,也能每分鍾刷新Widget時間的目的。
關鍵詞「輕量化」
1.因為Widget主打輕量化,對動效支持較差,所以Widget界面以靜態界面為主。
2.支持的布局和控制項非常少,不支持自定義View,界面以簡易布局為主。(如圖片+文字)
3.實時性要求不高。(如每日一首古詩)
4.與用戶簡單互動。(如播放器的播放、暫停、下一曲)
『肆』 androidwidget有用嗎
1.身材微:它們一般都很小,在終端上嵌入非常方便,運行快速。
2.形式多:Widget可以以多種形式呈現出來,幻燈秀、視頻、地圖、新聞、小游戲……
3.功能巨:別看它們小,卻服務周到,它可以為你報告新聞、幫你買東西、列出你最喜歡的樂隊,還有你最近看的視頻。另外,它還是一個殷勤的管家,你不必親自去Flickr或者天氣預報網站,Widget會將信息主動帶給你。
4.姿容麗:它們可以稱得上玉面飛龍、以色服人。只要你願意,你可以把它變成任何你想要得樣子。它的出現,無異於一枚「桌面炸彈」,狹窄而單調的IE窗口將被更為廣闊和絢麗的桌面空間所取代。
5.個性化:Widget更像一個屬於我們每個人的魔方,任由用戶聚合。你可以根據自己喜好,將多個Widget,隨心所欲的去精心組裝你的網路世界。通過Widget,可以用戶把一切在「網」中的內容打亂重來,並按照用戶希望看到的樣子重新排列組合一個屬於自己的互聯網。比如說一個由微件搭建個人空間,可以包括來自新浪的體育新聞,來自論壇的一個板塊,來自權威財經網站的一則隨時更新的股票信息 ——這些以往需要用戶同時分別進入幾個網站才能看到的信息,現在由一個個微件將其轉變為用戶個人空間的一部分,從而可以直接在同一個頁面中並存。傳統互聯網訪問方式處於分裂狀態的後Web2.0時期,多樣性、炫酷且更具個性化的Widget流行,或許能引領一個新的潮流。
6.易製作:製作 Widget 部件並不復雜,只需要熟悉三方面的知識:圖像處理、HTML/XML、java,就可以按照開發站點里的教程做出漂亮的部件來。Widget能夠流行的一個要點在於開放製作,UGC應用帶來爆炸式地增長。
那麼,什麼是android widget呢?
在Android 1.5 SDK preview中,我們看到了一系列功能和API上的變化變化,包括軟鍵盤、桌面Widget和Live Folder API、視頻錄制API,藍牙功能升級等,Google近來對於這些全新功能的解析使得Android開發者blog變得異常活躍。上周,Jeff Sharkey就有一篇對於Android桌面widget和AppWidget框架的簡介,以「Word of the day」的一個例子講述了桌面Widget的運作機制。昨天他又在個人blog上放出了一個天氣預報Widget的例子,事實上這已經是一個真正實用的程序了。它每天更新4次天氣預報,我們可以添加多個Widget來關注多個城市的天氣情況,另外,點擊Widget後我們還可以看到今後幾天的詳細預報。
這讓我想起了HTC Source的Nick Gray上周的一篇文章Android Widgets, Unlimited Potential中提到的幾類可能會大受歡迎的Android桌面Widget。
Android本身已經自帶了時鍾、音樂播放器、相框和Google搜索4個Widget程序,不過這並不能阻止大家開發自己更加美觀,功能更豐富的版本。另外,微博客、RSS訂閱、股市信息、天氣預報這些Widget也都有流行的可能。
微博客Widget:Twidroid是Android上迄今為止最棒的Twitter客戶端,大家顯然都期待著它會推出支持桌面Widget的版本,另外像國內比較受歡迎的飯否、嘀咕、嘰歪等應該也會有類似的Widget推出。對於一個微博客類的Widget來說,有兩個方面是必不可少的,一是用來發布消息,另一個則是用來瀏覽。
RSS訂閱Widget: 盡管微博客(尤其是Twitter)已經完全蓋過來RSS訂閱的風頭,越來越多的人用Twitter來跟蹤站點的更新,不過RSS訂閱也並非完全沒有了市場,像分類訂閱這樣的功能還是需要RSS來幫忙,另外站點管理員也未必會在Twitter上發布所有的更新。
股市信息Widget:對於炒股的人來說,大概沒有什麼能比在手機桌面上放上幾個所關注股票的實時股價更有運籌帷幄的感覺了吧。
天氣預報Widget:對於我這樣成天窩在辦公室或者家裡的人來說,有一個Widget能夠讓我了解當前的天氣和近1、2天的天氣是非常有用的,這大概會大大減少我下了樓又跑回去拿雨傘的幾率。如果能加上像TouchFLO 3D中那樣的UI效果,當然就更酷了。
這只是我現在想到的一些Widget,得益於Android 1.5為我們提供的Widget API為我們的手機桌面帶來的無限的可能,我們的手機桌面無疑將會更有趣。
對國內G1的用戶,如果想體驗Android 1.5的桌面Widget,可以看看Haykuro的blog,他正在為製作G1可用的Android 1.5 ROM而努力。另外,T-Mobile已經計劃在五月向德國的T-Mobile G1用戶推送1.5的更新了,所以即使到時候沒有官方的G1簡體中文1.5 ROM,相信Haykuro的 1.5 ROM for G1也能非常接近官方的成熟度。
Widget應用目前在Android手機上得到了廣泛的應用。由於其方便小巧,所以得到了很多的應用,像天氣,微博,信息,歌曲,時間等等。
關於android Wpp widget:
應用程序窗口小部件(Widget)是微小的應用程序視圖,可以被嵌入到其它應用程序中(比如桌面)並接收周期性的更新。你可以通過一個App Widget provider來發布一個Widget。可以容納其它App Widget的應用程序組件被稱為App Widget宿主。下面的截屏顯示了一個音樂App Widget。
『伍』 Android桌面小部件AppWidget開發
在Android我們經常可以看到各種桌面小部件,比如時鍾、天氣、音樂播放器等等。我們可以使用AppWidgetProvider來實現小部件的開發。
開發一個桌面小部件的步驟:
在res/layout/下新建一個布局文件,名稱和內容自定義,看你想把小工具做成什麼樣。需要注意的是系統默認的小工具布局中只支持以下這些標簽,如果用了列表以外的標簽,會導致小工具載入錯誤:
比如,我們創建了一個名為widget_layout.xml的布局文件:
定義小部件的配置信息需要在res目錄下新建一個xml目錄,然後在res/xml/目錄下創建一個配置文件,配置文件名稱隨意。新建app_widget_provider_info.xml:
上面的參數意義很明確,initialLayout指小部件的初始化布局,一般與最終布局相同;minHeight和minWidth定義了小部件的最小寬高,與小部件所佔網格大小有關;previewImage可以指定在添加小部件時看到的預覽圖;updatePeriodMillis指定了小部件的自動更新周期,單位為毫秒。
其中minHeight和minWidth的定義可以參考官方文檔: https://developer.android.com/guide/practices/ui_guidelines/widget_design.html#design
OK,小部件完成了,運行一下看看效果:
『陸』 如何在Android實現桌面清理內存簡單Widget小控制項
一、UI部分的編寫:
參照Google的文檔,首先在建立一個類繼承 AppWidgetProvider
import android.appwidget.AppWidgetProvider;
public class MyWidget extends AppWidgetProvider {
}
然後在清單文件中申明它,我們必須注意到,AppWidgetProvider實際上是BroadcastReceiver,所以要注冊成一個receiver,然後還有一些其他的東西需要注意:
<receiver android:name="com.alexchen.widget.MyWidget" >
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="@xml/example_appwidget_info" />
</receiver>
android.appwidget.action.APPWIDGET_UPDATE
表明這個receiver能夠接受一個APPWIDGET_UPDATE的廣播,而且在這里,只能加入這一個action。
android.appwidget.provider 表明數據類型時widget提供者提供的數據,example_appwidget_info 表明這個widget的參數配置文件名和位置
那麼接下來就需要在res目錄下建立一個xml文件夾,並且在其中建立一個example_appwidget_info.xml 的配置文件,Google的文檔中給出了示例有很多參數,實際上關鍵的參數只有下面的4個:
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:minWidth="94dp"
android:minHeight="72dp"
android:updatePeriodMillis="86400000"
android:initialLayout="@layout/example_appwidget">
</appwidget-provider>
其中, minWidth 和 minHeight 代表這個widget控制項所佔據的最小空間,這個空間一般來講不需要太大,因為太大的話,一個屏基陵幕可能都沒辦法放下,Google的官方文檔的說法是大於4x4的就可能無法顯示。
updatePeriodMillis 代表數據更新的時間,這里86400000毫秒實際上是24小時,可能最開始看到這個參數會想我能否將其設的很小,每一秒搏纖戚刷新很多次?, 實際上對於updatePeriodMillis 這個參數而言, 即算你設的再小也沒用,Google設定widget控制項這個參數控制的最短update時間為30分鍾,就算將其設置在30分鍾以內也會以30分鍾的頻率來更新數據。
initialLayout 參數代表的是本widget空間的布局文件。
那麼下一步就是定義出一個對應的布局文件。我們可以簡單的在layout目錄下建立一個布局文件example_appwidget.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="200dp"
android:layout_height="80dp"
android:background="@android:color/white"
android:gravity="豎旅center_vertical"
android:orientation="vertical" >
<TextView
android:id="@+id/tv_widget"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="widget控制項測試"
android:textColor="@android:color/black"
android:textSize="15sp" />
<Button
android:id="@+id/btn_clear"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="清理內存"
android:textColor="#ff000000" />
</LinearLayout>
在Google的文檔中有指出,並非所有的布局組件都可以在上面的這個布局中生效,有效的組件或布局為:
FrameLayout
LinearLayout
RelativeLayout
GridLayout
AnalogClock
Button
Chronometer
ImageButton
ImageView
ProgressBar
TextView
ViewFlipper
ListView
GridView
StackView
AdapterViewFlipper
至此,一個簡單的widget控制項就寫好了,我們可以在模擬器上將其拖到桌面上看一看效果:
二、功能邏輯部分的實現
大部分的Widget小控制項都會需要在特定情況下更新上面顯示的數據,那麼這個是如何實現的呢,我們經過上面的代碼不難發現實際上這個widget控制項並沒有一個Activity,所以說這個控制項的顯示實際上不是本應用來實現的,它實際上是桌面這個應用來顯示的,所以我們也不可能直接去更新它上面的數據。
回過頭去看看上面我們寫的那個receiver,實際上沒有實現任何方法。實際上AppWidgetProvider裡面有幾個比較重要的方法: onReceive、 onUpdate、onDisabled、onEnabled
其中 onReceive 方法跟大多數廣播接收者的onReceive方法一樣,但是在這里,onReceive方法的調用並不是我們可以決定的, 它依賴於顯示該widget控制項的Host組件,在這里也就是Android桌面應用,所以我們會發現在不同的手機上,將widget控制項拖到桌面上顯示的時候onReceive可能調用的次數和先後順序可能完全不一樣,這依賴於Host組件是如何實現的。
所以在這里onReceive方法對於我們刷新widget數據基本沒有什麼幫助。
而 onUpdate 方法則是由上面所說的 updatePeriodMillis 參數來控制的,經過上面的分析,我們都知道了,它的最小周期為30分鍾。所以我們一般將這個參數設為0即可。那麼在這個方法里,我們往往會在其中放置一些啟動更新數據服務的功能,因為如果後台的更新數據的Service被意外停止了,那麼每30分鍾還會被重新啟用,不至於一直啟動不了了:
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds) {
super.onUpdate(context, appWidgetManager, appWidgetIds);
// System.out.println("onUpdate");
//每隔一段時間重新啟動服務,防止服務中間被終止了之後沒法重啟
Intent intent = new Intent(context, UpdateWidgetService.class);
context.startService(intent);
}
下面是比較重要的兩個方法了:
onDisabled和onEnabled
我們知道,widget 小控制項是可 以拖動多個到桌面上的,而 onEnabled 方法會在第一個widget控制項拖到桌面上的時候調用一次, onDisabled 會在最後一個widget控制項從桌面被刪除時調用一次,那麼我們需要做的就是在 onEnabled 這個方法中啟用一個刷新widget數據的服務,在 onDisabled 方法中使用 stopService 方法來停止這個服務。
@Override
public void onDisabled(Context context) {
super.onDisabled(context);
System.out.println("onDisabled");
//停止數據刷新服務
Intent intent = new Intent(context, UpdateWidgetService.class);
context.stopService(intent);
}
@Override
public void onEnabled(Context context) {
super.onEnabled(context);
System.out.println("onEnabled");
//開啟數據刷新服務
Intent intent = new Intent(context, UpdateWidgetService.class);
context.startService(intent);
}
三、刷新數據的服務
那麼下面的任務就只剩下 UpdateWidgetService 這個刷新數據的服務(Service)如何實現的問題了。
我們在這里的想法很簡單,比如說每隔三秒鍾來刷新一下widget中的數據。Android中定時執行任務的方法有很多,我們這里使用 Timer 和 TimerTask 來實現,之後我們需要關心的就是具體如何實現刷新widget中的數據,畢竟這些數據是在桌面應用中顯示的。
並且我們需要用到一個API-- AppWidgetManager ,它有一個實例方法AppWidgetManager .updateAppWidget( ComponentName provider, RemoteViews views) 來實現更新widget數據,我們都知道,如果需要調用另外應用的方法,需要使用遠程調用的方法來實現,在這里起到在我們的應用和桌面應用之間的橋梁作用的就是這第二個參數:RemoteViews views, 它會將我們設置的數據傳送到桌面應用來刷新widget上的數據,我們需要經過下面幾步:
1、定義一個RemoteViews的實例:
RemoteViews views = new RemoteViews(getPackageName(),R.layout.process_widget);
2、設置views的內容,也就是刷新其中的數據,這里的方法名會比較奇怪,RemoteViews .setTextViewText( int viewId, CharSequence text)
其中viewId是在我們前面定義的widget布局文件中的子組件的id,也就是我們要刷新內容的對象,這里就是R.id.tv_test,第二個參數是我們要更新的內容
3、定義好第一個參數ComponentName provider 之後,就可以調用AppWidgetManager .updateAppWidget( ComponentName provider, RemoteViews views) 來實現更新數據
if (timer == null && task == null) {
//AppWidgetManager對象,用於更新widget的數據
awm = AppWidgetManager.getInstance(this);
timer = new Timer();
task = new TimerTask() {
@Override
public void run() {
ComponentName provider = new ComponentName(UpdateWidgetService.this, MyWidget.class);
//遠程view對象,用於在本應用和桌面應用中起傳遞數據的橋梁作用
RemoteViews views = new RemoteViews(getPackageName(),R.layout.example_appwidget);
views.setTextViewText(R.id.tv_widget, "想刷新的數據的內容");
awm.updateAppWidget(provider, views);
System.out.println("====刷新了widget====");
}
//設置循環時間
timer.schele(task, 0, 3000);
}
四、定時刷新可用內存和一鍵清理內存功能實現
要實現這個功能,我們需要再上面定時刷新數據服務中將定時刷新的內容改為當前內存所剩餘的量,我們這里寫一個工具類方法來實現返回內存剩餘量;
另外我們還需要在widget控制項的布局文件中添加一個button,並在更新widget數據的服務中,設置這個button的點擊事件,但是這里也不像以前的點擊事件,同樣要應用到RemoteView對象,在這個點擊事件中需要發送一個廣播,Action為自定義的,我們這里設為: "com.alexchen.mobilesafeexercise.killall" ,之後,我們需要再寫一個廣播接收者,來接收這個廣播,在onReceive方法中執行殺死後台進程的操作。這里也不能直接使用Intent,由於我們這個意圖的Action不是由我們自己執行而是由其他應用程序(桌面應用)執行的,所以需要用到 PendingIntent 。
刷新widget數據的服務代碼:
package com.alexchen.widget.service;
import java.util.Timer;
import java.util.TimerTask;
import android.app.PendingIntent;
import android.app.Service;
import android.appwidget.AppWidgetManager;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.IBinder;
import android.text.format.Formatter;
import android.widget.RemoteViews;
import com.alexchen.widget.MyWidget;
import com.alexchen.widget.R;
import com.alexchen.widget.utils.SystemInfoUtils;
public class UpdateWidgetService extends Service {
private Timer timer;
private TimerTask task;
private AppWidgetManager awm;
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate() {
super.onCreate();
startTimer();
}
private void startTimer() {
if (timer == null && task == null) {
awm = AppWidgetManager.getInstance(this);
timer = new Timer();
task = new TimerTask() {
@Override
public void run() {
ComponentName provider = new ComponentName(
UpdateWidgetService.this, MyWidget.class);
RemoteViews views = new RemoteViews(getPackageName(),
R.layout.example_appwidget);
views.setTextViewText(R.id.tv_widget, "dd");
views.setTextViewText(R.id.tv_widget,
"可用內存:"+ Formatter.formatFileSize(getApplicationContext(),
SystemInfoUtils.getAvailableMem(getApplicationContext())));
// 自定義一個廣播,殺死後台進程的事件
Intent intent = new Intent();
intent.setAction("com.alexchen.mobilesafeexercise.killall");
// 描述一個動作,這個動作是由另外一個應用程序執行的
PendingIntent pendingIntent = PendingIntent.getBroadcast(
getApplicationContext(), 0, intent,
PendingIntent.FLAG_UPDATE_CURRENT);
views.setOnClickPendingIntent(R.id.btn_clear, pendingIntent);
awm.updateAppWidget(provider, views);
System.out.println("====刷新了widget====");
}
};
timer.schele(task, 0, 3000);
}
}
@Override
public void onDestroy() {
super.onDestroy();
stopTimer();
unregisterReceiver(offReceiver);
unregisterReceiver(onReceiver);
}
private void stopTimer() {
if (timer != null && task != null) {
timer.cancel();
task.cancel();
task = null;
timer = null;
}
}
}
按鍵清理內存的廣播接收者:
package com.alexchen.widget.receiver;
import java.util.List;
import android.app.ActivityManager;
import android.app.ActivityManager.RunningAppProcessInfo;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
public class KillAllReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
System.out.println("自定義的廣播消息接收到了...開始清理內存...");
ActivityManager am = (ActivityManager) context
.getSystemService(Context.ACTIVITY_SERVICE);
List<RunningAppProcessInfo> runningAppProcesses = am
.getRunningAppProcesses();
for (RunningAppProcessInfo info : runningAppProcesses) {
am.killBackgroundProcesses(info.processName);
}
}
}
獲取可用內存的工具類方法:
/**
* 獲取手機可用的剩餘內存
*
* @param context
* 上下文
* @return
*/
public static long getAvailableMem(Context context) {
ActivityManager am = (ActivityManager) context
.getSystemService(Context.ACTIVITY_SERVICE);
MemoryInfo outInfo = new MemoryInfo();
am.getMemoryInfo(outInfo);
return outInfo.availMem;
}