技术开发 频道

AppWidget开发简介

  3.一个按需更新的AppWidget案例

  接下来,我们创建一个监控系统CPU使用率的小应用来具体讲解AppWidget的使用方法。在OPhone平台上,如果使用定时更新策略来更新AppWidget,则会增加电量和CPU资源的开销,因此,在本例中,我们提供了一种按需更新的策略,并且确保该应用不会因时延而造成ANR故障。

  3.1 AppWidgetProviderInfo

  首先,建立MyAppWidget工程,并在res/xml/目录下添加mywidget_info.xml文件来反应 AppWidgetProviderInfo信息。AppWidget的像素大小取决于它所占的方块多少,其计算公式是(块数 * 74) – 2,因此,我们取高度是72像素,宽度220像素。android:initialLayout设置了AppWidget的布局文件是 mywidget_frame.xml。因为本例采用按需更新的策略,所以没有标注android:updatePeriodMillis属性。

<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider                      
xmlns:android
="http://schemas.android.com/apk/res/android"
android:minWidth
="220dip" android:minHeight="72dip"
android:initialLayout
="@layout/mywidget_frame"
/>

   3.2 RemoteView

  第二步,建立RemoteViews对应的布局文件。目前, RemoteViews支持的控件暂时有TextView, ImageView, Button,Progressbar等。我们在一个LinearLayout类中添加一个ImageView和一个TextView,并将布局文件命名为mywidget_frame.xml

  3.3 AppWidgetProvider

  第三步,创建自定义的MyWidgetProvider类,它继承自AppWidgetProvider。在添加AppWidget应用或自动定时更新时,AppWidgetManager会广播动作名字是“android.appwidget.action.APPWIDGET_UPDATE”的 Intent,当onReceive()方法没有被重载时,onUpdate方法会接受到这些广播的Intent。类似普通 BroadcastReceiver类,我们可以重载MyWidgetProvider的onReceive方法,并在其中指定我们想要接受的 Intent。在本例子中,我们自定义的更新动作名为"com.OPhone.update"。在OPhone平台中,对于 BroadcastReceiver类,如果其运行时间过长,有可能会出现ANR(Application Not Response)的故障。因此,我们在onReceive方法中,添加了一个Service来保持应用一直存在。这个Service和 AppWidget应用运行在同一个进程中。通过重载onReceive()方法,我们开辟了直接对AppWidget的更新途径,从而不依赖于 AppWidgetManager发出的更新消息。onReceiver()方法的示例代码如下:

    @Override
    
public void onReceive(Context context, Intent intent) {
        
String action = intent.getAction();
        
if("android.appwidget.action.APPWIDGET_UPDATE".equals(action)
                ||
"com.OPhone.update".equals(action))
            context.startService(
new Intent(context,UpdateService.class));  
        
Log.d(TAG,"Action: "+ action);
        
Log.d(TAG,"onReceive Process Id: "+ Process.myPid());
    }

   AppWidget依赖RemoteViews来完成内容的更新,我们在Service的onStart()方法中对新的RemoteViews对象赋值。和普通的控件(如Botton, TextView等)不同的是,RemoteView没有OnClickListener方法,去而代之的是 setOnClickPendingIntent方法---在点击RemoteViews对象时,用PendingIntent的方式来启动一个新的 Activity,新的广播或新Service。AppWidgetManager负责把新生成的Remote更新到AppWidget上。在本例中,我们采用PendingIntent的getBroadcast方法来发送广播,其携带的Intent有自定义的接收动作。onStart()方法的示例代码如下:

    @Override
        
public void onStart(Intent intent, int startId) {
            
String info=null;
            
//创建RemoteViews
            RemoteViews views
= new RemoteViews(getPackageName(),
                    R.layout.mywidget_frame);  
            
            try{
                info
= String.valueOf(getCpuInfo()); //获取CPU消耗信息
            }catch(Exception e){
                e.printStackTrace();
            }
            
            
//设置控件
            views.setTextViewText(R.id.text_1, info);
            views.setImageViewResource(R.id.image_1, R.drawable.icon);
                        
            Intent intent_b
= new Intent();
            intent_b.setAction(
"com.OPhone.update");
            pendingIntent
= PendingIntent.getBroadcast(this, 0, intent_b, 0);
            
//给图片设置响应事件
            views.setOnClickPendingIntent(R.id.image_1, pendingIntent);
                    
            
//获得组建的完整名字
            ComponentName thisWidget
= new ComponentName(this, MyWidgetProvider.class);  
            AppWidgetManager manager
= AppWidgetManager.getInstance(this);  
            
//执行内容更新
            manager.updateAppWidget(thisWidget, views);  
        }
    

   在以上代码中,AppWidgetManager类的updateAppWidget方法完成了将RemoteViews对象推送到显示区的作用。如果没有这句操作,则主屏上会显示小应用加载错误的提示。OPhone平台基于Linux,因此getCpuInfo()方法采用读取平台"/proc /stat/"目录下信息的方法来计算CPU耗用信息。

0
相关文章