android 桌面小工具(Widget)开发教程

刚学做了个Widget,感觉不错哦,先来秀下效果(用朋友手机截的图)

android 桌面小工具(Widget)开发教程_第1张图片

这个Widget会每隔5秒钟自动切换内容和图片,图片最好使用小图,大图会导致你手机桌面(UI)线程卡顿


教程开始:

1、首先创建一个布局(layout),用以显示Wdiget

activity_main.xml

[java]  view plain copy
  1. "http://schemas.android.com/apk/res/android"  
  2.     android:layout_width="wrap_content"  
  3.     android:layout_height="wrap_content"  
  4.     android:background="@drawable/ddz_gameend_frame"              
  5.     >  
  6.      
  7.    
  8.         android:id="@+id/textview_1"  
  9.         android:layout_width="60.0dp"  
  10.         android:layout_height="90.0dp"  
  11.         android:layout_marginLeft="35.0dp"  
  12.         android:layout_marginTop="34.0dp"  
  13.         android:textColor="#000000"  
  14.         android:text=""  
  15.         />  
  16.     
  17.         android:id="@+id/imageview_1"  
  18.         android:layout_width="136.0dp"  
  19.         android:layout_height="92.0dp"  
  20.         android:layout_toRightOf="@+id/textview_1"  
  21.         android:layout_marginLeft="5.0dp"  
  22.         android:layout_marginTop="42.0dp"  
  23.         />  
  24.     
  25.         android:id="@+id/button_1"  
  26.         android:layout_width="50.0dp"  
  27.         android:layout_height="20.0dp"  
  28.         android:layout_below="@+id/textview_1"  
  29.         android:layout_marginTop="10.0dp"  
  30.         android:layout_marginLeft="35.0dp"  
  31.         android:text="详情"          
  32.         />  
  33.        
  34.    

2、然后创建一个appwidget-provider 的XML文件,点击资源目录的Res文件夹,鼠标右键选择New- android xml file

mywidget_provider.xml

[java]  view plain copy
  1. "1.0" encoding="utf-8"?>  
  2. "http://schemas.android.com/apk/res/android"  
  3.     android:resizeMode="horizontal"  
  4.     android:minWidth="250.0dp"  
  5.     android:minHeight="110.0dp"  
  6.     android:updatePeriodMillis="86400000"  
  7.     android:initialLayout="@layout/activity_main"  
  8.     android:widgetCategory="home_screen|keyguard"  
  9.     >  
  10.   

android:updatePeriodMillis指示了更新间隔,8640000024小时,也就是一天一次,本程序自己采用后台服务更新,所以该设置其实对本程序来说关系不大。 android:initialLayout就是指向的Widget布局
android:widgetCategory指示该Widget可以用作桌面和锁屏


3、在src目录创建代码文件(本实例建了包  com.feature.test;)

Constant.class   (用来定义一些常量的类)

[java]  view plain copy
  1. package com.feature.test;  
  2.   
  3. public class Constant {  
  4.   
  5.     //更新广播  
  6.     public static final String ACTION_UPDATE_ALL="com.feature.test.update_all";  
  7.       
  8.     //intent integer data  
  9.     public static final String INTEGER_DATA="integer_data";  
  10. }  



MyAppWidgetProvider.class    (用来处理Widget更新的类)

[java]  view plain copy
  1. package com.feature.test;  
  2.   
  3. import java.util.HashSet;  
  4. import java.util.Iterator;  
  5.   
  6. import android.app.PendingIntent;  
  7. import android.appwidget.AppWidgetManager;  
  8. import android.appwidget.AppWidgetProvider;  
  9. import android.content.Context;  
  10. import android.content.Intent;  
  11. import android.net.Uri;  
  12. import android.util.Log;  
  13. import android.widget.RemoteViews;  
  14. import android.widget.Toast;  
  15.   
  16. public class MyAppWidgetProvider extends AppWidgetProvider{  
  17.   
  18.     private static final Intent AppWidget_Service=new Intent("com.feature.test.MyAppWidgetService");  
  19.       
  20.     //保存WidgetId HashSet  可能有用户创建了多个Widget  
  21.     private static HashSet hashSet=new HashSet();  
  22.     //图片资源,作者请自行修改成自己的图片  
  23.     private static final int[] ResId={R.drawable.a1,R.drawable.a2,R.drawable.a3,R.drawable.a4,R.drawable.a5};  
  24.     //文本资源  
  25.     private static final String[] intro={"神挡杀神,佛挡杀佛","仿佛兮若轻云之蔽月,飘飘兮若流风之回雪",  
  26.                                  "此乃驱狼吐虎之计,敬你之手他一搏吧","汝等小儿,可敢杀我",  
  27.                                  "汝等看好了"};  
  28.     private static int iCur=-1;  
  29.       
  30.     //周期更新时调用  
  31.     @Override  
  32.     public void onUpdate(Context context,AppWidgetManager appWidgetProvider,int[] appWidgetIds)  
  33.     {  
  34.         Log.v("创建Widget""OK");  
  35.         // 每次 widget 被创建时,对应的将widget的id添加到set中  
  36.         for(int id:appWidgetIds)  
  37.             hashSet.add(Integer.valueOf(id));  
  38.           
  39.     }  
  40.       
  41.     //当桌面组件删除时调用  
  42.     @Override  
  43.     public void onDeleted(Context context,int[] appWidgetIds)  
  44.     {  
  45.         for(int id:appWidgetIds)  
  46.             hashSet.remove(id);  
  47.           
  48.         super.onDeleted(context, appWidgetIds);  
  49.     }  
  50.       
  51.     //当桌面提供的第一个组件创建时调用  
  52.     @Override  
  53.     public void onEnabled(Context context)  
  54.     {  
  55.         //启动服务  
  56.         context.startService(AppWidget_Service);  
  57.           
  58.         super.onEnabled(context);  
  59.     }  
  60.       
  61.     //当桌面提供的最后一个组件删除时调用  
  62.     @Override  
  63.     public void onDisabled(Context context)  
  64.     {  
  65.         //停止服务  
  66.         context.stopService(AppWidget_Service);  
  67.           
  68.         super.onDisabled(context);  
  69.     }  
  70.       
  71.     /* 
  72.      * 重写广播接收方法 
  73.      * 用于接收除系统默认的更新广播外的  自定义广播(本程序由服务发送过来的,一个是更新UI,一个是按钮事件消息) 
  74.      */  
  75.     @Override  
  76.     public void onReceive(Context context,Intent intent)  
  77.     {  
  78.         String getAction=intent.getAction();  
  79.         if(getAction.equals(Constant.ACTION_UPDATE_ALL))  
  80.         {  
  81.             //更新广播  
  82.               
  83.             updateAllWidget(context,AppWidgetManager.getInstance(context), hashSet);  
  84.         }  
  85.         else if(intent.hasCategory(Intent.CATEGORY_ALTERNATIVE))  
  86.         {  
  87.             Uri data=intent.getData();  
  88.             Log.v("button",data.toString()+" ");  
  89.             int buttonid=Integer.parseInt(data.getSchemeSpecificPart());  
  90.             Toast.makeText(context, intro[buttonid],Toast.LENGTH_SHORT).show();  
  91.         }  
  92.           
  93.         super.onReceive(context, intent);  
  94.     }  
  95.       
  96.     //更新UI  
  97.     public void updateAllWidget(Context context,AppWidgetManager manager,HashSet set)  
  98.     {  
  99.         int AppId;  
  100.         Iterator iterator=set.iterator();  
  101.           
  102.         iCur=iCur+1>=intro.length? 0: iCur+1;  
  103.           
  104.         while(iterator.hasNext())  
  105.         {  
  106.             AppId=((Integer)iterator.next()).intValue();  
  107.               
  108.             RemoteViews remoteViews=new RemoteViews(context.getPackageName(),R.layout.activity_main);  
  109.             //设置显示的文字图片  
  110.             remoteViews.setTextViewText(R.id.textview_1, intro[iCur]);  
  111.             remoteViews.setImageViewResource(R.id.imageview_1, ResId[iCur]);  
  112.             //添加按钮事件处理  
  113.             remoteViews.setOnClickPendingIntent(R.id.button_1, getPendingIntent(context, iCur));  
  114.             //更新  
  115.             manager.updateAppWidget(AppId, remoteViews);  
  116.         }  
  117.     }  
  118.       
  119.     //设置按钮事件处理  
  120.     private PendingIntent getPendingIntent(Context context,int buttonid)  
  121.     {  
  122.         Intent intent=new Intent("test.test");  
  123.         intent.setClass(context, MyAppWidgetProvider.class);  
  124.         intent.addCategory(Intent.CATEGORY_ALTERNATIVE);  
  125.         intent.setData(Uri.parse("custom:"+buttonid));  
  126.         //进行广播  
  127.         PendingIntent pi=PendingIntent.getBroadcast(context, 0, intent, 0);  
  128.         return pi;  
  129.     }  
  130. }  

4、创建后台服务,用来定时发送广播,通知Widget需要更新了

MyAppWidgetService。class

[java]  view plain copy
  1. package com.feature.test;  
  2.   
  3. import android.app.Service;  
  4. import android.content.Context;  
  5. import android.content.Intent;  
  6. import android.os.IBinder;  
  7.   
  8. public class MyAppWidgetService extends Service{  
  9.   
  10.     private Context context;  
  11.     //更新周期  
  12.     private static final int UPDATE_TIME=5000;  
  13.     //周期性更新的Widget 线程  
  14.     private WidgetThread widgetThread;  
  15.       
  16.     @Override  
  17.     public IBinder onBind(Intent intent) {  
  18.         // TODO Auto-generated method stub  
  19.         return null;  
  20.     }  
  21.   
  22.     @Override  
  23.     public void onCreate()  
  24.     {  
  25.         widgetThread=new WidgetThread();  
  26.         widgetThread.start();  
  27.           
  28.         context=this.getApplicationContext();  
  29.         super.onCreate();  
  30.     }  
  31.       
  32.     @Override  
  33.     public void onDestroy()  
  34.     {  
  35.         if(widgetThread!=null&&widgetThread.isAlive())  
  36.             widgetThread.interrupt();  
  37.           
  38.         super.onDestroy();  
  39.     }  
  40.       
  41.     private class WidgetThread extends Thread  
  42.     {  
  43.         @Override  
  44.         public void run()  
  45.         {  
  46.             try  
  47.             {  
  48.                 while(true)  
  49.                 {  
  50.                     Intent intent=new Intent(Constant.ACTION_UPDATE_ALL);  
  51.                     context.sendBroadcast(intent);  
  52.                       
  53.                     sleep(UPDATE_TIME);  
  54.                 }  
  55.             }catch(InterruptedException error)  
  56.             {  
  57.                 // 将 InterruptedException 定义在while循环之外,意味着抛出 InterruptedException 异常时,终止线程。  
  58.             }  
  59.         }  
  60.     }  
  61. }  

5、在AndroidManifest.xml注册Widget和服务

[java]  view plain copy
  1. "1.0" encoding="utf-8"?>  
  2. "http://schemas.android.com/apk/res/android"  
  3.     package="com.feature.test"  
  4.     android:versionCode="1"  
  5.     android:versionName="1.0" >    
  6.    
  7.     "8"  android:targetSdkVersion="8"/>  
  8.     
  9.         android:allowBackup="true"  
  10.         android:icon="@drawable/ic_launcher"  
  11.         android:label="@string/app_name"  
  12.         android:theme="@android:style/Theme.Black" >  
  13.           
  14.         
  15.             android:name="com.feature.test.MyAppWidgetProvider">  
  16.             "android.appwidget.provider"  
  17.                        android:resource="@xml/mywidget_provider"  
  18.                        />  
  19.                                                     
  20.                 "android.appwidget.action.APPWIDGET_UPDATE" />  
  21.                 "com.feature.test.update_all" />  
  22.               
  23.           
  24.           
  25.           
  26.         ".MyAppWidgetService">  
  27.               
  28.                 "com.feature.test.MyAppWidgetService"/>  
  29.               
  30.           
  31.               
  32.               
  33.       
  34.   
  35.   

至此大功告成!有问题请、意见请回复,本人虚心求教


另外:

1、如果你手机安装了自己做的Widget,在添加-窗口小工具显示不出来,那是因为你把它装到SD卡导致的,请在应用程序里找到自己的Widget将其移至手机存储即可显示

2、如果你安装的Widget放到桌面上,一直在显示“正在加载窗口小工具”,说明该Widget使用了您手机版本不支持的Widget控件,如EditText,使用它就会报错


转载地址:http://blog.csdn.net/tabactivity/article/details/9923281

你可能感兴趣的:(android 桌面小工具(Widget)开发教程)