亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Android的Launcher啟動器中添加快捷方式及小部件實例

 更新時間:2016年02月29日 16:37:02   作者:qinjuning  
這篇文章主要介紹了在Android的Launcher啟動器中添加快捷方式及窗口小部件的方法,包括在自己的應用程序中添加窗口小部件AppWidget的例子,需要的朋友可以參考下

前言: 最近一直在看Launcher模塊,經過差不多兩個月學習,終于摸透了Launcher的一些主要功能實現(xiàn),目前繼續(xù)還處于
摸索狀態(tài)。未看Launcher時,于我而言,只能膜拜,以為所有功能都是它實現(xiàn)的 ;入門后,才發(fā)現(xiàn),Launcher的很多功能只是
集成了框架/應用程序提供的功能。很多陌生的東西,只有接觸了才感嘆:“oh ,原來是這樣的!”

添加快捷方式

今天先給大家分享下Launcher如何實現(xiàn)添加快捷方式(Shortcut) ,后續(xù)會慢慢增加其他方面的功能,幫助大家“一葉而知秋”。
具體來說,Launcher中的快捷方式有兩種類型:
1 、"偽"快捷方式 —— 應用程序類型
2 、"真"快捷方式 —— Activity具備<action/>為ACTION_CREATE_SHORTCUT的配置信息
這兩種類型的快捷方式是怎么勾搭在一起的,在下面大家通過代碼自己理解,也不方便細說了。
知識點介紹:
知識點一 、ACTION_PICK_ACTIVITY使用說明 ,具體可以參考SDK Intent類
功能:顯示匹配附加值為EXTRA_INTENT的所有Activity,并將它們以列表呈現(xiàn)給用戶。當用戶從該列表選中一項 
時,并不會啟動該Activity(這與與ACTION_CHOOSER不同,此Action會啟動用戶選擇的Activity),而是將該Activity的詳細信
息(可能包括Action、ComponentName、data信息等)以Intent對象返回給調用者(通常為onActivityResult方法)。

附加值:EXTRA_INTENT  顯示所有匹配顯示所有匹配附加值為EXTRA_INTENT的Activity,
EXTRA_TITLE     作為顯示列表即所有Activity的標題 。

因此,根據ACTION_PICK_ACTIVITY的特性,真正地創(chuàng)建快捷方式需要兩步走:

第一步:發(fā)送ACTION_PICK_ACTIVITY以及EXTRA_INTENT,找到我們希望能創(chuàng)建快捷方式的Activity列表。
第二步:根據第一步所選擇的Activity返回的Intent對象,再次發(fā)送此Intent對象,即可創(chuàng)建該Activity提供給
我們快捷方式了。

例如,下面我們只是簡單的發(fā)送一個請求顯示所有應用程序的Intent,如下:

//重新發(fā)送一個Action為Pick_Activity的Intent,獲取所有應用程序信息 
    Intent pickIntent = new Intent(Intent.ACTION_PICK_ACTIVITY); 
    Intent mainIntent = new Intent () ; 
    mainIntent.setAction(Intent.ACTION_MAIN); 
    mainIntent.addCategory(Intent.CATEGORY_LAUNCHER); 
    
    pickIntent.putExtra(Intent.EXTRA_INTENT, mainIntent); 
    pickIntent.putExtra(Intent.EXTRA_TITLE, "選擇應用程序"); //設置界面title 
    
    //繼續(xù)選擇所有應用程序 
    startActivityForResult(pickIntent,MY_REQUEST_ALL_APPLICATION ); 

 
ACTION_PICK_ACTIVITY效果圖如下:

2016229162933152.jpg (342×465)

點擊某一具體Activity  , 即可選擇創(chuàng)建該Activity的快捷方式了。

知識點二、 Intent.ShortcutIconResource類介紹
功能: 為快捷方式(Shortcut)和文件夾(live folder)提供圖片資源
常用方法為:
public static Intent.ShortcutIconResource fromContext(Context context, int resourceId)
功能: 創(chuàng)建一個 Intent.ShortcutIconResource 對象
參數說明:context        Context類對象
resourceId  具體的圖片資源id 。
常用屬性:
packageName    該應用程序所在包名,類型為 packageName:type/entityname
resourceName   resourceId所對應地的資源名

例如: 某個圖片資源 R.id.icon = 0x7f020000, 則resourceName 為 packageName:drawable/icon

具體怎么通過 Intent.ShortcutIconResource對象獲取圖片資源,請參考示例Demo。

示例Demo
說明:點擊創(chuàng)建快捷方式對話框后, 選擇某一項具體的快捷方式,即可添加至MainActivity界面中 ,繼續(xù)點擊每個View,則
可啟動該快快捷方式的App,挺給力的吧。

PS: 由于我只是簡單的利用了LinearLayout去當容器,會存在局限性,大家可在此基礎上,利用GridView/ListView構建更好
的布局,當然更NB的是,去提供類似Launcher的自定義布局。

由于執(zhí)行快捷方式可能需要一些特定的權限,因此我們必須得在AndroidManifest.xml里配置對應的權限。例如,直接撥打電話
需要的權限為:   <uses-permission android:name="android.permission.CALL_PHONE"></uses-permission>

如上效果圖,增加幾個快捷方式后截圖如下,點擊即可啟動該應用。

2016229163001636.jpg (320×480)

主工程邏輯如下:

package com.qin.addshortcut; 
 
import java.util.ArrayList; 
 
import android.app.Activity; 
import android.content.ComponentName; 
import android.content.Intent; 
import android.content.Intent.ShortcutIconResource; 
import android.content.pm.ActivityInfo; 
import android.content.pm.PackageManager; 
import android.content.pm.PackageManager.NameNotFoundException; 
import android.content.res.Resources; 
import android.graphics.Bitmap; 
import android.graphics.Rect; 
import android.graphics.drawable.BitmapDrawable; 
import android.graphics.drawable.Drawable; 
import android.os.Bundle; 
import android.os.Parcelable; 
import android.util.Log; 
import android.view.LayoutInflater; 
import android.view.View; 
import android.widget.Button; 
import android.widget.ImageView; 
import android.widget.LinearLayout; 
import android.widget.TextView; 
import android.widget.Toast; 
/** 
 * 
 * @author http://http://blog.csdn.net/qinjuning 
 */ 
public class MainActivity extends Activity implements View.OnClickListener 
{ 
 
 private LinearLayout linearlayout ; //用來存放所有快捷方式的容器 --- 父視圖 
 private Button btAddShortCut; 
 
  
 private static final int MY_REQUEST_SHORT_CUT = 1; // 第一步 、 顯示所有能創(chuàng)建快捷方式的Activity 
 private static final int MY_CREATE_SHOURT_CUT = 2;   //第二步、 創(chuàng)建 真快捷方式 
 private static final int MY_REQUEST_ALL_APPLICATION = 3 ; //第二步 、創(chuàng)建 偽快捷方式 -- 應用程序類 
 private static String TAG = "AddShortActivity" ; 
  
 private PackageManager mPackageManager = null ; 
  
 /** Called when the activity is first created. */ 
 @Override 
 public void onCreate(Bundle savedInstanceState) 
 { 
  super.onCreate(savedInstanceState); 
  setContentView(R.layout.main); 
 
  btAddShortCut = (Button) findViewById(R.id.bt_addShortcut); 
  linearlayout = (LinearLayout)findViewById(R.id.linearLayout) ; 
  linearlayout.setOnClickListener(this) ; 
   
  //演示如何通過一個資源的type獲取該資源文件在R文件中的整數描述符 
  // getIdentifier 參數為 package:type/entry . 例如求icon的資源描述符如下: 
  int iconId = this.getResources().getIdentifier("com.qin.addshortcut:drawable/icon", null, null);   
  Log.i(TAG, " icon id : " + iconId); 
   
  //獲取PackageManager對象 
  mPackageManager = getPackageManager(); 
     
  btAddShortCut.setOnClickListener(new View.OnClickListener() 
  { 
 
   @Override 
   public void onClick(View v) 
   { 
    //創(chuàng)建快捷方式對話框 
    createShortDialog() ; 
   } 
  }); 
   
 } 
 private void createShortDialog(){ 
   
  //begin :添加創(chuàng)建應用程序的圖標('快捷方式") 
  // 此bundle值為附加的創(chuàng)建PICK_ACTIVITY的一個列表項 
  Bundle bundle = new Bundle() ; 
  //設置name 
  ArrayList<String> shortcutNames = new ArrayList<String>(); 
  shortcutNames.add("應用程序"); 
  bundle.putStringArrayList(Intent.EXTRA_SHORTCUT_NAME, shortcutNames); 
  //設置對應的頭像 
  ArrayList<ShortcutIconResource> shortcutIconRes= new ArrayList<ShortcutIconResource>(); 
  shortcutIconRes.add(ShortcutIconResource.fromContext(MainActivity.this, R.drawable.icon)); 
  bundle.putParcelableArrayList(Intent.EXTRA_SHORTCUT_ICON_RESOURCE, shortcutIconRes); 
  // end     
   
  Intent pickIntent = new Intent(Intent.ACTION_PICK_ACTIVITY); 
 
  Intent extraIntent = new Intent(Intent.ACTION_CREATE_SHORTCUT); 
 
  pickIntent.putExtra(Intent.EXTRA_INTENT, extraIntent);//所要查找的Activity Intent 
  pickIntent.putExtra(Intent.EXTRA_TITLE, "選擇快捷方式"); // Title 
  //看到沒 , 偽快捷方式 是在這兒創(chuàng)建地。 
  pickIntent.putExtras(bundle); 
   
  startActivityForResult(pickIntent, MY_REQUEST_SHORT_CUT); 
 } 
  
  
 protected void onActivityResult(int requestCode, int resultCode, final Intent data) 
 { 
  super.onActivityResult(requestCode, resultCode, data); 
  //未成功的選擇任何一個shortcut(比如直接按back鍵) , 直接返回 
  if(resultCode == RESULT_CANCELED ) 
   return ; 
   
   
  switch(requestCode){ 
  case MY_REQUEST_SHORT_CUT: 
   //第一次發(fā)送 PICK_Activity后 ,對所選列表項進行選擇后,做的中間處理操作,需要判斷是選擇“應用程序” 抑或真正滴快捷方式 
    // 獲得快捷方式Label 
   String label = data.getStringExtra(Intent.EXTRA_SHORTCUT_NAME); 
   //這個字段是我們之前主動添加的 
   if(label.equals("應用程序")){ 
    //重新發(fā)送一個Action為Pick_Activity的Intent,獲取所有應用程序信息 
    Intent pickIntent = new Intent(Intent.ACTION_PICK_ACTIVITY); 
    Intent mainIntent = new Intent () ; 
    mainIntent.setAction(Intent.ACTION_MAIN); 
    mainIntent.addCategory(Intent.CATEGORY_LAUNCHER); 
     
    pickIntent.putExtra(Intent.EXTRA_INTENT, mainIntent); 
    pickIntent.putExtra(Intent.EXTRA_TITLE, "選擇應用程序"); //設置界面title 
     
    //繼續(xù)選擇所有應用程序 
    startActivityForResult(pickIntent,MY_REQUEST_ALL_APPLICATION ); 
     
   } 
   else{ //重新請求創(chuàng)建上一次點擊的Activity , 啟動后即可創(chuàng)建 
    Log.v(TAG, "MY_REQUEST_SHORT_CUT Intent Info--- >" + data); 
    //下一步,創(chuàng)建某一具體的shortcut 
    startActivityForResult(data, MY_CREATE_SHOURT_CUT); 
   } 
   break ; 
    
  //以下操作才是真正地處理添加快捷方式的操作  
  case MY_CREATE_SHOURT_CUT: 
   //data數據封裝了所有快捷方式應該該附加的值 
   Log.v(TAG, "MY_CREATE_SHOURT_CUT Intent Info--- >" + data); 
   completeAddShortCut(data); 
   break ; 
    
  case MY_REQUEST_ALL_APPLICATION: //創(chuàng)建一個應用程序的"快捷方式" 
   //data數據封裝了點擊某個應用程序的intent,包括action,ComponentName組信息等,繼而我們可以通過intent對象獲取該應用程序的信息 
   Log.v(TAG, "MY_REQUEST_ALL_APPLICATION Intent Info--- >" + data); 
   completeAddApplication(data) ; 
   break ; 
  default : 
   break ; 
    
  } 
   
 } 
  
 //添加一個應用程序的"快捷方式" 
 private void completeAddApplication(Intent data){ 
   
  //打印應用程序返回的intent信息, 一個完整的啟動應用程序的Intent 
  Log.i(TAG, "Application intent info ---->" +data) ; 
   
  ComponentName componentName = data.getComponent() ; 
  Log.i(TAG, "ComponentName Info ----> " + componentName) ; 
   
  try 
  { 
   //獲取資源圖片 
   ActivityInfo activityInfo = mPackageManager.getActivityInfo(componentName, 0); 
   CharSequence applabel = activityInfo.loadLabel(mPackageManager) ; 
   Drawable appIcon = activityInfo.loadIcon(mPackageManager) ; 
    
   //創(chuàng)建一個View對象 
   View view = makeViewForShortcut(applabel , appIcon) ; 
   //為該快捷方式的View設置onClick監(jiān)聽 
   view.setOnClickListener(this) ; 
   //將該intent對象設置為View的tag屬性 , onClick時獲取該tag , --->getTag() 
   view.setTag(data) ; 
    
   //將該View對象添加至LinearLayout中,由于大小發(fā)生了變化,系統(tǒng)會重新走”measure“ , ”layout“, ”draw“ 過程 
   //設置長寬高 
   LinearLayout.LayoutParams llparams = new LinearLayout.LayoutParams(80,90) ; 
   linearlayout.addView(view,llparams) ; 
  } 
  catch (NameNotFoundException e) 
  { 
    Log.e(TAG, "NameNotFoundException at completeAddApplication method") ; 
  }   
 } 
  
 //添加快捷方式(真正地,非應用程序) 
 private void completeAddShortCut(Intent data){ 
   
  Drawable shortcutIcon = null; //快捷方式的圖標 , 可以有兩種方式獲取,如下 if else 判斷 
  
  // 獲得快捷方式Label 
  String label = data.getStringExtra(Intent.EXTRA_SHORTCUT_NAME); 
   
  Parcelable bitmap = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_ICON); 
  // 直接了圖片 , 即設置了 EXTRA_SHORTCUT_ICON 參數值 
  if (bitmap != null && bitmap instanceof Bitmap) 
  { 
   shortcutIcon = new BitmapDrawable((Bitmap) bitmap); 
  } 
  else //設置了EXTRA_SHORTCUT_ICON_RESOURCE 附加值 
  { 
   Parcelable iconParcel = data .getParcelableExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE); 
   if(iconParcel != null && iconParcel instanceof ShortcutIconResource) 
   { 
    // 獲得ShortcutIconResource對象 
    ShortcutIconResource iconRes = (ShortcutIconResource) iconParcel; 
    //獲得inconRes對象的Resource對象 
    try 
    { 
     //獲取對應packageName的Resources對象 
     Resources resources = mPackageManager.getResourcesForApplication(iconRes.packageName);     
     //獲取對應圖片的id號 
     int iconid = resources.getIdentifier(iconRes.resourceName, null, null); 
     Log.i(TAG, "icon identifier is " + iconRes.resourceName) ; 
     //獲取資源圖片 
     shortcutIcon = resources.getDrawable(iconid); 
    } 
    catch (NameNotFoundException e) 
    { 
      Log.e(TAG, "NameNotFoundException at completeAddShortCut method") ; 
    } 
 
   } 
  } 
  //可能快捷方式沒有為我們設置任何圖像以及ShortcutIconResource對象,我們需要重置快捷方式的頭像 
  if ( shortcutIcon == null) { 
   // 一定會有圖片,這兒我簡單的處理了 . 
   Toast.makeText(MainActivity.this, "sorry , we could not shortcut image", Toast.LENGTH_SHORT) ; 
   return ; 
  } 
 
  // 獲得快捷方式Intent , 直接startActivity 即可 
  Intent shortcut_intent = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_INTENT); 
   
  if (shortcut_intent != null) 
   Log.i(TAG, "shortCut intent info ----> "+shortcut_intent) ; 
     
  //創(chuàng)建一個View對象 
  View view = makeViewForShortcut(label , shortcutIcon) ; 
  //為該快捷方式的View設置onClick監(jiān)聽 
  view.setOnClickListener(this) ; 
  //將該intent對象設置為View的tag屬性 , onClick時獲取該tag , --->getTag() 
  view.setTag(shortcut_intent) ; 
   
  //將該View對象添加至LinearLayout中,由于大小發(fā)生了變化,系統(tǒng)會重新走”measure“ , ”layout“, ”draw“ 過程 
  //設置長寬高 
  LinearLayout.LayoutParams llparams = new LinearLayout.LayoutParams(100,90) ; 
   
  linearlayout.addView(view,llparams) ; 
  
 } 
 
 //點擊事件 
 @Override 
 public void onClick(View v) { 
  Object tag = v.getTag() ; 
  if(tag !=null && tag instanceof Intent){ 
   Intent intent = (Intent)tag ; 
   startActivityForSafely(intent) ; 
  } 
   
 } 
 //安全啟動一個Activity 
 private void startActivityForSafely(Intent data) { 
  Intent launchIntent = data ; 
   
  //有些啟動后的Activity需要設置該選項,即為啟動的Activity設置一個界面,例如聯(lián)系人的快捷方式, so , 我們加上它吧 
  launchIntent.setSourceBounds(new Rect(0,0,300,300)); 
  launchIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 
   
  startActivity(launchIntent) ; 
 } 
  
 //為每個快捷方式創(chuàng)建一個View對象 
 private View makeViewForShortcut(CharSequence label , Drawable icon){ 
  LayoutInflater inflater = LayoutInflater.from(this) ; 
  View shortcut_view = inflater.inflate(R.layout.shortcut_view, null) ; 
   
  TextView tv = (TextView)shortcut_view.findViewById(R.id.shortcut_label) ; 
  tv.setText(label) ; 
   
  ImageView img = (ImageView)shortcut_view.findViewById(R.id.shortcut_img) ; 
  img.setImageDrawable(icon) ; 
  return shortcut_view ;  
 } 
  
  
} 


添加窗口小部件
我們知道:

1、每個AppWidget都有一個AppWidgetProviderInfo對象,該對象描述了每個AppWidget的基本數據(meta-data)信息 ,
其定義在<appwidget-provider>節(jié)點信息。

2、每個AppWidget都對應一個RemoteViews視圖對象,該RemoteViews提供了特定AppWidget的展示(View視圖)和操作
(例如,點擊該RemoteViews會跨進程處理一些事情)。

3、AppWidgetManager類維護了應用程序中所有的AppWidget,并且為給每個AppWidget特定的Id去標識他們(一般我們
用 appWidgetId去標識)。通過給定的appWidgetId,AppWidgetManager可以管理對應的AppWidget,例如:更新該
AppWidgetId的RemoteViews視圖,刪除該AppWidget對象等 。

4、AppWidgetProvider廣播類從來說是一個監(jiān)聽器,系統(tǒng)把對AppWidget的操作(例如,創(chuàng)建和更新等)分發(fā)給
AppWidgetProvider類去處理。


對每個AppWidget,我們可以創(chuàng)建多個其多個實例,當然這些實例對應于不同的appWidgetId。 假設存在這么個
MyAppWidgetProvider廣播類,以及對應的MyAppWidgetProviderInfo對象。 那么,則存在如下關系:

MyAppWidgetProvider.class : 代表了由該MyAppWidgetProvider創(chuàng)建的窗口小部件(AppWidget)的類型,一般用
CompontentName對象形式表示 。 那么存在如下關系:

2016229163103231.jpg (747×377)

從上圖可是,每個appWidget都對應于一個MyAppWidgetProvider類,于是當任何一個appWidgetId發(fā)生變化時,我們需要
同步其他實例,保持同步性。

AppWidgetProviderInfo類補充說明:
publicComponentNameconfigure: 一般為一個Activity,表明該Activity復雜需要管理AppWidget的創(chuàng)建操作。
public int updatePeriodMillis:用來更新AppWidget,但該屬性在SDK1.5已廢除

AppWidgetProvider類介紹:
常用方法:
onDeleted()   : 當該類型的AppWidget每次被刪除時,調用此方法
onDisabled() : 當該類型的窗口小部件(AppWidget)全被刪除時,調用此方法
onEnabled() : 當第一次創(chuàng)建該類型的AppWidget時,調用此方法
onReceive() : 廣播接受者方法  , 用來接受廣播消息
onUpdate()   : 每次創(chuàng)建該類型的AppWidget都會調用此方法 , 通常來說我們需要在該方法里為該AppWidget指定
RemoteViews對象。

AppWidgetManager類介紹:
常用常量:
ACTION_APPWIDGET_PICK= "android.appwidget.action.APPWIDGET_PICK“
說明:列出所有能夠創(chuàng)建AppWidget的對象,該對象一般為自定義的AppWidgetProvider廣播接受者。 
注意:發(fā)送該Intent必須添加附加值:EXTRA_APPWIDGET_ID 。
該EXTRA_APPWIDGET_ID含義:該appWidgetId與我們發(fā)送Action為ACTION_APPWIDGET_PICK 后
所選擇的AppWidget綁定。因此,我們可以通過這個appWidgetId獲取該AppWidget的信息了。

ACTION_APPWIDGET_CONFIGURE= "android.appwidget.action.APPWIDGET_CONFIGURE”
說明: 如果選擇的AppWidget配置了android:configure 屬性,需要再次啟動性對應的Activity,繼而進一步去選擇
AppWidget。同時發(fā)送該Intent必須添加附加值:EXTRA_APPWIDGET_ID,含義同上。

常用方法:

public int[] getAppWidgetIds(ComponentName provider)

功能:獲取對應ComponentName類型的所有appWidgetId
參數說明:   provider  通常為 XXXAppProvider.class類型

publicAppWidgetProviderInfo getAppWidgetInfo(int appWidgetId) 

功能: 獲取特定appWidgetId對應的AppWidgetProviderInfo對象

public staticAppWidgetManager getInstance(Contextcontext)

功能: 獲取 AppWidgetManager對象  

public void updateAppWidget(int appWidgetId, RemoteViews views)


功能: 以特定的views視圖更新appWidgetId的窗口小部件(AppWidget) 。同時會發(fā)送ACTION_APPWIDGET_UPDATE廣播

public void updateAppWidget(int[] appWidgetIds,RemoteViews views)

功能:以特定的views視圖更新所有appWidgetIds的窗口小部件(AppWidget),同時發(fā)送ACTION_APPWIDGET_UPDATE
廣播

public void updateAppWidget(ComponentName provider, RemoteViews views)

功能: 已特定的views更新組件類型為provider的所有窗口小部件(AppWidget),同時發(fā)送ACTION_APPWIDGET_UPDATE
廣播。

示例Demo :

說明:創(chuàng)建一個簡單的AppWidget實例,點擊按鈕后可以更該圖片資源顯示 ,具體代碼在
截圖為:

2016229163218073.jpg (325×290)

關于如何創(chuàng)建一個AppWidget的教材,我也不再多說了,大家可以參考上面我提到的兩篇重量級博客去學習:

1、SDK對AppWidget的介紹
2、Android 桌面組件【widget】初探

PS: 具體代碼可在后面下載 。

再次強調一點,每個AppWidget都對應與AppWidgetProvider , 我們需要同步更新這些AppWidget對象。
在自己的應用程序中添加窗口小部件
本部分的主要功能是像Launchcer那樣添加AppWidget 。 知識點介紹如下:

AppWidgetHost 類

功能:對每個應用程序App,該類提供了和AppWidgetService(該AppWidgetService用來管理所有AppWidget,類似于
NotificationManagerService系統(tǒng)服務管理所有Notifciation,不懂?其實我也不懂,知其大意即可)交互,用來更新、管理
AppWidget。打個比喻:AppWidgetHost是宿主對象,每個AppWidget都是寄生蟲,可以附加在(顯示)AppWidgetHost上。
每個能添加、顯示AppWidget的Activity都是一個AppWidgetHost對象,比如Launcher.java(Activity對象),以及我們后面自定
義的MainActivity.java(Activity對象)。

常用方法為:
public AppWidgetHost(Context context, int hostId)
功能:構造一個AppWidgetHost對象
參數:  hostId   大意是該AppWidgetHost(宿主對象)對應的Id號,一般賦予一整數即可。
public int allocateAppWidgetId()
功能:申請一個新的appWidgetId ,該id會與新創(chuàng)建的AppWidget綁定。
public void startListening()
功能:監(jiān)聽所有AppWidget的變化 ,該方法必須在Activity的onCreate()/onStart()調用,否則 AppWidget是不會得到更新的
public void stopListening()
功能: 對應于startListening(),即停止對AppWidget的更新監(jiān)聽。可以在Activity的onStop()方法里調用 ,
一般無需調用此方法去停止監(jiān)聽。

public final  AppWidgetHostView    createView(Context context, int appWidgetId, AppWidgetProviderInfo appWidget)
功能: 根據指定的appWidgetId以及AppWidgetProviderInfo對象去構建一個AppWidgetHostView對象(具體該對象,
參見下 文)。


AppWidgetHostView 與 RemoteViews的區(qū)別

對每個AppWidget內部而言,都有一個RemoteViews對象,用于視圖顯示;而對于外部而已,則以AppWidgetHostView形式代言 這個RemoteViews視圖。換句話來說就是,AppWidgetHost對象而言,它并不知道RemoteViews存在,而只是RemoteViews 的代言人AppWidgetHostView。


好了 ,該說明的都說明了,下面最后給大家補充一下如何利用在自己的應用程序里添加窗口小部件(AppWidget) 。
也是兩步走:

第一步:  發(fā)送Action為ACTION_APPWIDGET_PICK的 Intent ,則所有能創(chuàng)建窗口小部件的AppWidgetProvider的廣播
接收者都會顯示 ,同時為該新創(chuàng)建的AppWidget分配一個appWidgetId ,該appWidgetId即可唯一標記我們選擇的
AppWidget。

第二步:如果選擇的AppWidget對應地AppWidgetProviderInfo對象配置了android:configure屬性,則需要在此啟動該配置
屬性(一般為一個Activity類) ,然后在完成添加AppWidget的操作 ; 否則,沒有配置android:configure屬性,就可以添加
AppWidget的操作。

示例Demo截圖:

2016229163314400.jpg (350×388)

主工程流程如下:  

package com.qin.addappwidget; 
 
 
import android.app.Activity; 
import android.appwidget.AppWidgetHost; 
import android.appwidget.AppWidgetHostView; 
import android.appwidget.AppWidgetManager; 
import android.appwidget.AppWidgetProviderInfo; 
import android.content.Intent; 
import android.os.Bundle; 
import android.util.Log; 
import android.view.View; 
import android.widget.Button; 
import android.widget.ImageView; 
import android.widget.LinearLayout; 
import android.widget.TextView; 
import android.widget.Toast; 
 
public class MainActivity extends Activity 
{ 
 
 private static String TAG = "AddAppWidget" ; 
  
 private Button btAddShortCut; 
 private LinearLayout linearLayout ; // 裝載Appwidget的父視圖 
  
 private static final int MY_REQUEST_APPWIDGET = 1; 
 private static final int MY_CREATE_APPWIDGET = 2; 
  
 private static final int HOST_ID = 1024 ; 
  
 private AppWidgetHost mAppWidgetHost = null ; 
 AppWidgetManager appWidgetManager = null; 
  
 /** Called when the activity is first created. */ 
 @Override 
 public void onCreate(Bundle savedInstanceState) 
 { 
  super.onCreate(savedInstanceState); 
  setContentView(R.layout.main); 
 
  btAddShortCut = (Button) findViewById(R.id.bt_addShortcut); 
 
  linearLayout = (LinearLayout)findViewById(R.id.linearLayout) ; 
  
  //其參數hostid大意是指定該AppWidgetHost 即本Activity的標記Id, 直接設置為一個整數值吧 。 
  mAppWidgetHost = new AppWidgetHost(MainActivity.this, HOST_ID) ; 
   
  //為了保證AppWidget的及時更新 , 必須在Activity的onCreate/onStar方法調用該方法 
  // 當然可以在onStop方法中,調用mAppWidgetHost.stopListenering() 停止AppWidget更新 
  mAppWidgetHost.startListening() ; 
   
  //獲得AppWidgetManager對象 
  appWidgetManager = AppWidgetManager.getInstance(MainActivity.this) ; 
   
   
  btAddShortCut.setOnClickListener(new View.OnClickListener() 
  { 
   @Override 
   public void onClick(View v) 
   { 
     //顯示所有能創(chuàng)建AppWidget的列表 發(fā)送此 ACTION_APPWIDGET_PICK 的Action 
     Intent pickIntent = new Intent(AppWidgetManager.ACTION_APPWIDGET_PICK) ; 
     
     //向系統(tǒng)申請一個新的appWidgetId ,該appWidgetId與我們發(fā)送Action為ACTION_APPWIDGET_PICK 
     // 后所選擇的AppWidget綁定 。 因此,我們可以通過這個appWidgetId獲取該AppWidget的信息了 
     
     //為當前所在進程申請一個新的appWidgetId 
     int newAppWidgetId = mAppWidgetHost.allocateAppWidgetId() ; 
     Log.i(TAG, "The new allocate appWidgetId is ----> " + newAppWidgetId) ; 
     
     //作為Intent附加值 , 該appWidgetId將會與選定的AppWidget綁定     
     pickIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, newAppWidgetId) ; 
     
     //選擇某項AppWidget后,立即返回,即回調onActivityResult()方法 
     startActivityForResult(pickIntent , MY_REQUEST_APPWIDGET) ; 
         
   } 
  }); 
 } 
 
 // 如果 
 protected void onActivityResult(int requestCode, int resultCode, Intent data) 
 { 
  //直接返回,沒有選擇任何一項 ,例如按Back鍵 
  if(resultCode == RESULT_CANCELED) 
   return ; 
   
  switch(requestCode){ 
   case MY_REQUEST_APPWIDGET : 
    Log.i(TAG, "MY_REQUEST_APPWIDGET intent info is -----> "+data ) ; 
    int appWidgetId = data.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID , AppWidgetManager.INVALID_APPWIDGET_ID) ; 
     
    Log.i(TAG, "MY_REQUEST_APPWIDGET : appWidgetId is ----> " + appWidgetId) ; 
     
    //得到的為有效的id 
    if(appWidgetId != AppWidgetManager.INVALID_APPWIDGET_ID){ 
     //查詢指定appWidgetId的 AppWidgetProviderInfo對象 , 即在xml文件配置的<appwidget-provider />節(jié)點信息 
     AppWidgetProviderInfo appWidgetProviderInfo = appWidgetManager.getAppWidgetInfo(appWidgetId) ; 
      
     //如果配置了configure屬性 , 即android:configure = "" ,需要再次啟動該configure指定的類文件,通常為一個Activity 
     if(appWidgetProviderInfo.configure != null){ 
       
      Log.i(TAG, "The AppWidgetProviderInfo configure info -----> " + appWidgetProviderInfo.configure ) ; 
       
      //配置此Action 
      Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_CONFIGURE) ; 
      intent.setComponent(appWidgetProviderInfo.configure) ; 
      intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId); 
       
       
      startActivityForResult(intent , MY_CREATE_APPWIDGET) ;     
     } 
     else //直接創(chuàng)建一個AppWidget 
      onActivityResult(MY_CREATE_APPWIDGET , RESULT_OK , data) ; //參數不同,簡單回調而已       
    }    
    break ; 
   case MY_CREATE_APPWIDGET: 
    completeAddAppWidget(data) ; 
    break ; 
  } 
   
 } 
  
 //向當前視圖添加一個用戶選擇的 
 private void completeAddAppWidget(Intent data){ 
  Bundle extra = data.getExtras() ; 
  int appWidgetId = extra.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID , -1) ; 
  //等同于上面的獲取方式 
  //int appWidgetId = data.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID , AppWidgetManager.INVALID_APPWIDGET_ID) ; 
   
  Log.i(TAG, "completeAddAppWidget : appWidgetId is ----> " + appWidgetId) ; 
   
  if(appWidgetId == -1){ 
   Toast.makeText(MainActivity.this, "添加窗口小部件有誤", Toast.LENGTH_SHORT) ; 
   return ; 
  } 
   
  AppWidgetProviderInfo appWidgetProviderInfo = appWidgetManager.getAppWidgetInfo(appWidgetId) ; 
   
  AppWidgetHostView hostView = mAppWidgetHost.createView(MainActivity.this, appWidgetId, appWidgetProviderInfo); 
     
  //linearLayout.addView(hostView) ; 
   
  int widget_minWidht = appWidgetProviderInfo.minWidth ; 
  int widget_minHeight = appWidgetProviderInfo.minHeight ; 
  //設置長寬 appWidgetProviderInfo 對象的 minWidth 和 minHeight 屬性 
  LinearLayout.LayoutParams linearLayoutParams = new LinearLayout.LayoutParams(widget_minWidht, widget_minHeight); 
  //添加至LinearLayout父視圖中 
  linearLayout.addView(hostView,linearLayoutParams) ;   
 } 
} 

        
最后 ,關于AppWidget點擊后觸發(fā)的相應事件,是通過設置該AppWidget的RemoteViews的某個控件點擊事件而觸發(fā)的。

相關文章

  • Android Studio格式化(Format)代碼快捷鍵介紹

    Android Studio格式化(Format)代碼快捷鍵介紹

    這篇文章主要介紹了Android Studio格式化(Format)代碼快捷鍵,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-01-01
  • Android仿知乎懸浮功能按鈕FloatingActionButton效果

    Android仿知乎懸浮功能按鈕FloatingActionButton效果

    前段時間在看屬性動畫,恰巧這個按鈕的效果可以用屬性動畫實現(xiàn),下面通過本文給大家分享adroid仿知乎懸浮功能按鈕FloatingActionButton效果,需要的朋友參考下吧
    2017-04-04
  • Android實現(xiàn)短信驗證碼自動攔截讀取功能

    Android實現(xiàn)短信驗證碼自動攔截讀取功能

    這篇文章主要為大家詳細介紹了Android實現(xiàn)短信驗證碼自動攔截讀取功能,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-08-08
  • Android shape和selector 結合使用實例代碼

    Android shape和selector 結合使用實例代碼

    本篇文章主要介紹了Android shape和selector 的使用,這里提供了shape 和selector 的詳細介紹,并附有代碼實例,有興趣的朋友可以參考下
    2016-07-07
  • Android nativePollOnce函數解析

    Android nativePollOnce函數解析

    這篇文章主要介紹了Android nativePollOnce函數解析的相關資料,幫助大家更好的理解和學習使用Android,感興趣的朋友可以了解下
    2021-03-03
  • flutter項目引入iconfont阿里巴巴圖標

    flutter項目引入iconfont阿里巴巴圖標

    這篇文章主要為大家介紹了flutter項目引入iconfont阿里巴巴圖標的過程詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-05-05
  • Android中控件GridView實現(xiàn)設置行列分割線的方法示例

    Android中控件GridView實現(xiàn)設置行列分割線的方法示例

    這篇文章主要介紹了利用Android中控件GridView實現(xiàn)設置行列分割線的方法,文中給出了詳細的介紹與示例代碼,相信對大家具有一定的參考價值,有需要的朋友們下面來一起看看吧。
    2017-01-01
  • Android編程實現(xiàn)拍照功能的2種方法分析

    Android編程實現(xiàn)拍照功能的2種方法分析

    這篇文章主要介紹了Android編程實現(xiàn)拍照功能的2種方法,結合具體實例形式對比分析了Android通過調用系統(tǒng)攝像頭及程序調用照相機功能兩種實現(xiàn)技巧與相關注意事項,需要的朋友可以參考下
    2017-07-07
  • Android學習筆記之應用單元測試實例分析

    Android學習筆記之應用單元測試實例分析

    這篇文章主要介紹了Android學習筆記之應用單元測試,結合實例形式較為詳細的分析了Android單元測試的實現(xiàn)原理與具體步驟,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-11-11
  • android當前apn的狀態(tài)以及獲取方法

    android當前apn的狀態(tài)以及獲取方法

    在絕大多數android機器etc路徑下存放一個的apns-conf.xml文件,表示當前機器使用的apn信息通過root機器可以push出來看看,具體路徑可以上網搜下,接下來介紹獲取apn的狀態(tài)的方法
    2013-01-01

最新評論