欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Android開發(fā)5:應(yīng)用程序窗口小部件App Widgets的實(shí)現(xiàn)(附demo)

 更新時(shí)間:2016年11月19日 09:32:31   作者:yanglh6  
本篇文章主要介紹了android應(yīng)用程序窗口小部件App Widgets的實(shí)現(xiàn),具有一定的參考價(jià)值,有需要的可以了解一下。

前言

本次主要是實(shí)現(xiàn)一個(gè)Android應(yīng)用,實(shí)現(xiàn)靜態(tài)廣播、動(dòng)態(tài)廣播兩種改變 widget內(nèi)容的方法,即在上篇博文中實(shí)驗(yàn)的基礎(chǔ)上進(jìn)行修改,所以此次實(shí)驗(yàn)的重點(diǎn)是AppWidget小部件的實(shí)現(xiàn)啦~

首先,我們簡單說一下Widget是一個(gè)啥玩意~

應(yīng)用程序窗口小部件(Widget)是微小的應(yīng)用程序視圖,可以被嵌入到其它應(yīng)用程序中(比如桌面)并接收周期性的更新。你可以通過一個(gè)App Widget provider來發(fā)布一個(gè)Widget??梢匀菁{其它App Widget的應(yīng)用程序組件被稱為App Widget宿主。

Widget是在桌面上的一塊顯示信息的東西,也通過單擊Widget跳轉(zhuǎn)到一個(gè)程序里面。而系統(tǒng)自帶的程序,典型的Widget是music,這個(gè)Android內(nèi)置的音樂播放小程序。這個(gè)是典型的Widget+app應(yīng)用。就是一個(gè)程序既可以通過Widget啟動(dòng),也可以通過App啟動(dòng)。Widget就是一個(gè)AppWidgetProvider+一個(gè)UI界面顯示(預(yù)先綁定了好多Intent),界面上的信息可以通過程序控制而改變,單擊Widget,上的控件只能激發(fā)發(fā)送一個(gè)Intent,或發(fā)出一個(gè)Service的啟動(dòng)通知。而AppWidgetProvider可以攔截這個(gè)Intent,而進(jìn)行相應(yīng)的處理(比如顯示新的信息)。

基礎(chǔ)知識(shí)

為了創(chuàng)建一個(gè)App Widget,你需要下面這些:

AppWidgetProviderInfo 對(duì)象

描述一個(gè)App Widget元數(shù)據(jù),比如App Widget的布局,更新頻率,以及AppWidgetProvider 類。這應(yīng)該在XML里定義。

AppWidgetProvider 類的實(shí)現(xiàn)

定義基本方法以允許你編程來和App Widget連接,這基于廣播事件。通過它,當(dāng)這個(gè)App Widget被更新,啟用,禁用和刪除的時(shí)候,你都將接收到廣播通知。

視圖布局

為這個(gè)App Widget定義初始布局,在XML中。

另外,你可以實(shí)現(xiàn)一個(gè)App Widget配置活動(dòng)。這是一個(gè)可選的活動(dòng)Activity,當(dāng)用戶添加App Widget時(shí)加載并允許他在創(chuàng)建時(shí)來修改App Widget的設(shè)置。

widget 的添加:長按菜單鍵,點(diǎn)擊 widgets 選項(xiàng)。找到對(duì)應(yīng)的 widget 將其拖入桌面。對(duì) 于不同的 API 版本顯示會(huì)稍有不同。

  

典型的 Android Widget 有三個(gè)主要組件,一個(gè)邊框、一個(gè)框架和圖形控件以及其他元素。 在 Android Studio 中創(chuàng)建 Widget 類后,會(huì)直接生成相關(guān)文件。

首先,在應(yīng)用程序AndroidManifest.xml文件中聲明AppWidgetProvider 類,比如:

<receiver Android:name="ExampleAppWidgetProvider" >
 <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>

<receiver>元素需要android:name屬性,它指定了App Widget使用的AppWidgetProvider 。

<intent-filter> 元素必須包括一個(gè)含有android:name屬性的<action>元素。該元素指定AppWidgetProvider接受ACTION_APPWIDGET_UPDATE 廣播。這是唯一你必須顯式聲明的廣播。當(dāng)需要的時(shí)候,AppWidgetManager 會(huì)自動(dòng)發(fā)送所有其他App Widget廣播給AppWidgetProvider。

<meta-data> 元素指定了AppWidgetProviderInfo 資源并需要以下屬性:

  • android:name – 指定元數(shù)據(jù)名稱。
  • android:resource – 指定AppWidgetProviderInfo 資源路徑。

1. Widget 布局文件 widget_demo.xml,布局中有一個(gè) ImageView,一個(gè) TextView。 要求:文字顏色為紅色,大小為 20dp,整體背景為透明。最后效果如下:

2.增加AppWidgetProviderInfo元數(shù)據(jù)

AppWidgetProviderInfo定義一個(gè)App Widget的基本特性,比如最小布局尺寸,初始布局資源,刷新頻率,以及(可選的)創(chuàng)建時(shí)加載的一個(gè)配置活動(dòng)。使用單獨(dú)的一個(gè)<appwidget-provider>元素在XML資源里定義AppWidgetProviderInfo 對(duì)象并保存到項(xiàng)目的res/xml/目錄下。

Widget 內(nèi)容提供者文件 widget_demo_info.xml,編輯該文件,設(shè)置其大小屬性和布 局,如下圖:

其中,minWidth 為最小寬度,minHeight 為最小高度,initialLayout 為初始布局。

 3. 修改 WidgetDemo.java 代碼,重寫 onUpdate 方法,為 Widget 添加事件,使得能夠返 回主頁面。

這里需要使用到一種用戶程序訪問主屏幕和修改特定區(qū)域內(nèi)容的方法:RemoteView 架 構(gòu) 。RemoteView 架構(gòu)允許用戶程序更新主屏幕的 View,點(diǎn)擊 Widget 激活點(diǎn)擊事件,Android 會(huì)將其轉(zhuǎn)發(fā)給用戶程序,由 AppWidgetProviders 類處理,使得用戶程序可更新主 屏幕 Widget。

pendingIntent是一種特殊的 Intent。主要的區(qū)別在于 Intent 的執(zhí)行立刻的,而 pendingIntent 的執(zhí)行不是立刻的。本次使用方法類的靜態(tài)方法為 getActivity(Context, int, Intent, int),對(duì)應(yīng) Intent 的跳轉(zhuǎn)到一個(gè) activity 組件的操作。

 使用AppWidgetProvider類

你必須通過在清單文件中使用<receiver>元素來聲明你的AppWidgetProvider 類實(shí)現(xiàn)為一個(gè)廣播接收器(參見上面的Declaring an App Widget in the Manifest)。

AppWidgetProvider 類擴(kuò)展BroadcastReceiver 為一個(gè)簡便類來處理App Widget廣播。AppWidgetProvider只接收和這個(gè)App Widget相關(guān)的事件廣播,比如這個(gè)App Widget被更新,刪除,啟用,以及禁用。當(dāng)這些廣播事件發(fā)生時(shí),AppWidgetProvider 將接收到下面的方法調(diào)用:

onUpdate(Context, AppWidgetManager, int[])

這個(gè)方法調(diào)用來間隔性的更新App Widget,間隔時(shí)間用AppWidgetProviderInfo 里的updatePeriodMillis屬性定義(參見添加AppWidgetProviderInfo元數(shù)據(jù))。這個(gè)方法也會(huì)在用戶添加App Widget時(shí)被調(diào)用,因此它應(yīng)該執(zhí)行基礎(chǔ)的設(shè)置,比如為視圖定義事件處理器并啟動(dòng)一個(gè)臨時(shí)的服務(wù)Service,如果需要的話。但是,如果你已經(jīng)聲明了一個(gè)配置活動(dòng),這個(gè)方法在用戶添加App Widget時(shí)將不會(huì)被調(diào)用,而只在后續(xù)更新時(shí)被調(diào)用。配置活動(dòng)應(yīng)該在配置完成時(shí)負(fù)責(zé)執(zhí)行第一次更新。(參見下面的創(chuàng)建一個(gè)App Widget配置活動(dòng)Creating an App Widget Configuration Activity。)

onDeleted(Context, int[])

當(dāng)App Widget從宿主中刪除時(shí)被調(diào)用。

onEnabled(Context)

當(dāng)一個(gè)App Widget實(shí)例第一次創(chuàng)建時(shí)被調(diào)用。比如,如果用戶添加兩個(gè)你的App Widget實(shí)例,只在第一次被調(diào)用。如果你需要打開一個(gè)新的數(shù)據(jù)庫或者執(zhí)行其他對(duì)于所有的App Widget實(shí)例只需要發(fā)生一次的設(shè)置,那么這里是完成這個(gè)工作的好地方。

onDisabled(Context)

當(dāng)你的App Widget的最后一個(gè)實(shí)例被從宿主中刪除時(shí)被調(diào)用。你應(yīng)該在onEnabled(Context)中做一些清理工作,比如刪除一個(gè)臨時(shí)的數(shù)據(jù)庫。

onReceive(Context, Intent)

這個(gè)接收到每個(gè)廣播時(shí)都會(huì)被調(diào)用,而且在上面的回調(diào)函數(shù)之前。你通常不需要實(shí)現(xiàn)這個(gè)方法,因?yàn)槿笔〉腁ppWidgetProvider 實(shí)現(xiàn)過濾所有App Widget 廣播并恰當(dāng)?shù)恼{(diào)用上述方法。

注意: 在Android 1.5中, 有一個(gè)已知問題,onDeleted()方法在該調(diào)用時(shí)不被調(diào)用。為了規(guī)避這個(gè)問題,你可以像Group post中描述的那樣實(shí)現(xiàn)onReceive() 來接收這個(gè)onDeleted()回調(diào)。

最重要的AppWidgetProvider 回調(diào)函數(shù)是onUpdated(), 因?yàn)樗窃诿總€(gè)App Widget添加進(jìn)宿主時(shí)被調(diào)用的(除非你使用一個(gè)配置活動(dòng))。如果你的App Widget 要接受任何用戶交互事件,那么你需要在這個(gè)回調(diào)函數(shù)中注冊(cè)事件處理器。如果你的App Widget不創(chuàng)建臨時(shí)文件或數(shù)據(jù)庫,或者執(zhí)行其它需要清理的工作,那么onUpdated() 可能是你需要定義的唯一的回調(diào)函數(shù)。

4.重寫 onReceive 方法

在 Widget 類中重寫 onReceive 方法,這里需要使用到 RemoteView 以及 Bundle。當(dāng)接 收到對(duì)應(yīng)廣播時(shí)進(jìn)行數(shù)據(jù)處理。

if 條件語句中主要用到的函數(shù)為:setTextViewText、setImageViewResource。 之后使用 AppWidgetManager 類對(duì) Widget 進(jìn)行更新。
 

實(shí)驗(yàn)內(nèi)容

實(shí)現(xiàn)一個(gè) Android 應(yīng)用,實(shí)現(xiàn)靜態(tài)廣播、動(dòng)態(tài)廣播兩種改變 widget 內(nèi)容的方法。在上次實(shí) 驗(yàn)的基礎(chǔ)上進(jìn)行修改,所以一些關(guān)于靜態(tài)動(dòng)態(tài)廣播的內(nèi)容會(huì)簡略。

具體要求:

(1)該界面為應(yīng)用啟動(dòng)后看到的界面。

widget 初始情況如下 

(2)點(diǎn)擊靜態(tài)注冊(cè)按鈕,跳轉(zhuǎn)至如下界面?! ?br />

點(diǎn)擊表單項(xiàng)目。如 banana。widget 會(huì)發(fā)生對(duì)應(yīng)變化。點(diǎn)擊 Widget 上的圖片可以跳轉(zhuǎn)回主頁面

(3)點(diǎn)擊動(dòng)態(tài)注冊(cè)按鈕,跳轉(zhuǎn)至如下界面。 實(shí)現(xiàn)以下功能:

a)可以編輯廣播的信息,點(diǎn)擊 Send 按鈕發(fā)送廣播。

b)設(shè)置一個(gè)按鈕進(jìn)行廣播接收器的注冊(cè)與注銷。

c)廣播接收器若已被注冊(cè),發(fā)送出的廣播信息能夠及時(shí)更新桌面上 Widget 上文字內(nèi)容及 更新為默認(rèn) dynamic 圖片。

d)點(diǎn)擊 Widget 上的圖片可以跳轉(zhuǎn)回主頁面。

實(shí)驗(yàn)步驟

首先,在Android Studio中創(chuàng)建Widget類,直接生成相關(guān)文件,其中包括界面布局XML文件、widget的provider文件信息(xml)以及在項(xiàng)目的AndroidMenifest.xml文件中添加了一個(gè)receiver標(biāo)簽,需要我們添加過濾更新事件,并需要指向之前創(chuàng)建的Widget類。

AndroidMenifest.xml文件中,intent-filter中過濾了APPWIDGET_UPDATE事件,這個(gè)事件是由系統(tǒng)觸發(fā)的更新事件,每個(gè)widget必須包含這個(gè)事件;meta-data標(biāo)簽描述的是widget的配置文件指向,該文件描述了widget的一些基本信息(其中由于需要在靜態(tài)注冊(cè)中實(shí)現(xiàn),intent-filter中也過濾了staticreceiver):

<receiver
   android:name=".MyAppWidget"
   android:enabled="true"
   android:exported="true">
   <intent-filter>
    <action android:name="android.appwidget.action.APPWIDGET_UPDATE"/>
    <action android:name="com.example.yanglh6.myapplication4.staticreceiver" />
   </intent-filter>
   <meta-data
    android:name="android.appwidget.provider"
    android:resource="@xml/my_app_widget_info"/>
</receiver>

接下來根據(jù)要求編寫widget的provider文件信息(xml),minWidth和minHeight是widget的最小寬度和高度,這個(gè)值是一個(gè)參考值,系統(tǒng)會(huì)根據(jù)實(shí)際情況進(jìn)行改變,initialLayout屬性指明widge的視圖布局文件,updatePeriodMillis屬性是widget每隔多久更新一次的時(shí)間,單位為毫秒:

<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
 android:initialKeyguardLayout="@layout/my_app_widget"
 android:initialLayout="@layout/my_app_widget"
 android:minHeight="55dp"
 android:minWidth="200dp"
 android:previewImage="@drawable/example_appwidget_preview"
 android:resizeMode="horizontal|vertical"
 android:updatePeriodMillis="86400000"
 android:widgetCategory="home_screen"></appwidget-provider>

接下來就是界面布局,在這個(gè)示例中需要一個(gè)ImageView控件和一個(gè)TextView控件:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:gravity="center">

 <ImageView
  android:id="@+id/WidgetImage"
  android:layout_width="60dp"
  android:layout_height="60dp"
  android:gravity="center"
  android:src="@mipmap/apple"/>

 <TextView
  android:id="@+id/WidgetName"
  android:layout_width="wrap_content"
  android:layout_height="60dp"
  android:textColor="@color/red"
  android:textSize="20dp"
  android:layout_toRightOf="@+id/WidgetImage"
  android:text="Apple"
  android:gravity="center"/>

</RelativeLayout>

布局文件實(shí)現(xiàn)了一個(gè)如下圖的布局:

然后在Widget中,重寫onUpdate方法,為Widget添加事件,使得能夠返回主頁面。這里需要使用到一種用戶程序訪問主屏幕和修改特定區(qū)域內(nèi)容的方法RemoteView架構(gòu)。RemoteView架構(gòu)允許用戶程序更新主屏幕的View,點(diǎn)擊 Widget激活點(diǎn)擊事件,Android會(huì)將其轉(zhuǎn)發(fā)給用戶程序,由AppWidgetProviders類處理,使得用戶程序可更新主屏幕Widget。

@Override
 public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
  super.onUpdate(context, appWidgetManager, appWidgetIds);
  Intent clickInt = new Intent(context, MainActivity.class);
  PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, clickInt, 0);
  RemoteViews view = new RemoteViews(context.getPackageName(),R.layout.my_app_widget);
  view.setOnClickPendingIntent(R.id.WidgetImage, pendingIntent);
  appWidgetManager.updateAppWidget(appWidgetIds, view);
 }

接下來在Widge類中重寫onReceive方法,這里需要使用到RemoteView以及Bundle。當(dāng)接收到對(duì)應(yīng)廣播時(shí)進(jìn)行數(shù)據(jù)處理(由于我們?cè)贏ndroidMenifest.xml文件中注冊(cè)時(shí)將APPWIDGET_UPDAT事件和staticreceiver都指向Widge類,所以在這里我們StaticReceiver類刪掉,將里面對(duì)OnReceive函數(shù)重寫的部分添加在Widget類中):

@Override
 public void onReceive(Context context, Intent intent) {
  Log.i("debug", intent.toString());
  super.onReceive(context, intent);
  RemoteViews view = new RemoteViews(context.getPackageName(),R.layout.my_app_widget);
  Bundle bundle = intent.getExtras();
  String widgetName = bundle.getString("name");
  int widgetImage = bundle.getInt("ItemImage");
  if (intent.getAction().equals("com.example.yanglh6.myapplication4.staticreceiver")) {
   view.setTextViewText(R.id.WidgetName, widgetName);
   view.setImageViewResource(R.id.WidgetImage, widgetImage);
   AppWidgetManager appWidgetManager=AppWidgetManager.getInstance(context);
   appWidgetManager.updateAppWidget(new ComponentName(context, MyAppWidget.class), view);

   Bitmap bitmap= BitmapFactory.decodeResource(context.getResources(),bundle.getInt("ItemImage"));
   int imageId = (int) bundle.get("ItemImage");
   NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
   Notification.Builder builder = new Notification.Builder(context);
   builder.setContentTitle("靜態(tài)廣播")
     .setContentText(bundle.getString("name"))
     .setLargeIcon(bitmap)
     .setSmallIcon(imageId)
     .setTicker("您有一條新消息")
     .setAutoCancel(true);
   Intent Intent1 = new Intent(context, MainActivity.class);

   PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, Intent1, 0);
   builder.setContentIntent(pendingIntent);
   Notification notify = builder.build();
   notificationManager.notify(0, notify);
  }
 }

單獨(dú)把Widget部分onReceive方法的重寫列出:

public void onReceive(Context context, Intent intent) {
  Log.i("debug", intent.toString());
  super.onReceive(context, intent);
  RemoteViews view = new RemoteViews(context.getPackageName(),R.layout.my_app_widget);
  Bundle bundle = intent.getExtras();
  String widgetName = bundle.getString("name");
  int widgetImage = bundle.getInt("ItemImage");
  if (intent.getAction().equals("com.example.yanglh6.myapplication4.staticreceiver")) {
   view.setTextViewText(R.id.WidgetName, widgetName);
   view.setImageViewResource(R.id.WidgetImage, widgetImage);
   AppWidgetManager appWidgetManager=AppWidgetManager.getInstance(context);
   appWidgetManager.updateAppWidget(new ComponentName(context, MyAppWidget.class), view);
  }
 }

對(duì)于動(dòng)態(tài)注冊(cè)來說,不需要在AndroidMenifest.xml添加receiver,但在DynamicActivity中進(jìn)行注冊(cè):

 dynamicReceiver = new DynamicReceiver();
     IntentFilter dynamic_filter = new IntentFilter();
     dynamic_filter.addAction("com.example.yanglh6.myapplication4.dynamicreceiver");
     registerReceiver(dynamicReceiver, dynamic_filter);

所以動(dòng)態(tài)注冊(cè)時(shí)只能在DynamicReceiver中對(duì)Onreceive函數(shù)進(jìn)行重寫,完成Widget的更新(與靜態(tài)注冊(cè)類似):

 @Override
 public void onReceive(Context context, Intent intent) {
  if (intent.getAction().equals("com.example.yanglh6.myapplication4.dynamicreceiver")) {
   Bundle bundle = intent.getExtras();
   Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), bundle.getInt("ItemImage"));
   int imageId = bundle.getInt("ItemImage");
   RemoteViews view = new RemoteViews(context.getPackageName(),R.layout.my_app_widget);
   String widgetName = bundle.getString("name");

   view.setTextViewText(R.id.WidgetName, widgetName);
   view.setImageViewResource(R.id.WidgetImage, imageId);
   AppWidgetManager appWidgetManager=AppWidgetManager.getInstance(context);
   appWidgetManager.updateAppWidget(new ComponentName(context, MyAppWidget.class), view);

   NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
   Notification.Builder builder = new Notification.Builder(context);
   builder.setContentTitle("動(dòng)態(tài)廣播")
     .setContentText(widgetName)
     .setLargeIcon(bitmap)
     .setSmallIcon(imageId)
     .setTicker("您有一條新消息")
     .setAutoCancel(true);
   Intent mIntent = new Intent(context, MainActivity.class);

   PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, mIntent, 0);
   builder.setContentIntent(pendingIntent);
   Notification notify = builder.build();
   notificationManager.notify(0, notify);
  }
 }

完成實(shí)驗(yàn)~

運(yùn)行截圖

注意事項(xiàng)

自己要充分理解AndroidMenifest.xml各部分的含義以及Android的機(jī)制,在AndroidMenifest.xml的注冊(cè)和指向必須清晰。

對(duì)于靜態(tài)來說,在sendBroadcast(intent)實(shí)現(xiàn)后,在AndroidMenifest.xml找到intent注冊(cè)時(shí)的receiver并指向?qū)?yīng)的廣播接收函數(shù),在這個(gè)函數(shù)中實(shí)現(xiàn)各個(gè)事件;對(duì)于動(dòng)態(tài)來說,由于在DynamicActivity中進(jìn)行注冊(cè),在那時(shí)可以定義指向的動(dòng)態(tài)廣播接收類。

源碼下載

源碼下載點(diǎn)擊這里~


本實(shí)驗(yàn)實(shí)驗(yàn)環(huán)境:

操作系統(tǒng) Windows 10
實(shí)驗(yàn)軟件 Android Studio 2.2.1
虛擬設(shè)備:Galaxy_Nexus
API:21

以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

最新評(píng)論