在查找并结合多方资料后终于实现,效果图如下:
长按桌面空白处,出现菜单,点击Widgets,此时的插件已经装入:
在电源连接时,机器人周围会星光闪闪,表明正在充电,不在充电时,周围的星光会消失。
机器人身上显示电池电量百分比。
单击机器人图标,会跳出电池信息的详情,再次单击屏幕关闭详情信息。
下面介绍代码的实现:
整个工程主要实现两个部分,一个是AppWidget部分,实现桌面Widget的显示,更新等,另一个部分就是点击widget后出现的显示电池详细信息的Activity的实现了。
首先是AppWidget部分,上代码,NewBatteryWidget.java部分:
- <span style="font-family:Microsoft YaHei;">package com.ritterliu.newBatteryWidget;
- import android.app.AlarmManager;
- import android.app.PendingIntent;
- import android.app.Service;
- import android.appwidget.AppWidgetManager;
- import android.appwidget.AppWidgetProvider;
- import android.content.BroadcastReceiver;
- import android.content.ComponentName;
- import android.content.Context;
- import android.content.Intent;
- import android.content.IntentFilter;
- import android.graphics.Bitmap;
- import android.graphics.BitmapFactory;
- import android.os.IBinder;
- import android.widget.RemoteViews;
- public class NewBatteryWidget extends AppWidgetProvider{
- private static int currentBatteryLevel;
- private static int currentBatteryStatus;
- public void onUpdate(Context context,AppWidgetManager appWidgetManager,int[] appWidgetIds)
- {
- super.onUpdate(context, appWidgetManager, appWidgetIds);
- /** 启动自动更新电池信息的service */
- context.startService(new Intent(context,updateService.class));
- /** 为AppWidget设置点击事件的响应,启动显示电池信息详情的activity */
- Intent startActivityIntent = new Intent(context,NewBatteryInfoActivity.class);
- PendingIntent Pintent = PendingIntent.getActivity(context,0,startActivityIntent,0);
- RemoteViews views = new RemoteViews(context.getPackageName(),R.layout.newrelativelayout);
- views.setOnClickPendingIntent(R.id.imageView,Pintent);
- appWidgetManager.updateAppWidget(appWidgetIds,views);
- }
- /** 自动更新电池信息的service,通过AlarmManager实现定时不间断地发送电池信息 */
- public static class updateService extends Service{
- Bitmap bmp; //定义机器人图片
- @Override
- public IBinder onBind(Intent intent) {
- // TODO Auto-generated method stub
- return null;
- }
- /** 定义一个接收电池信息的broascastReceiver */
- private BroadcastReceiver batteryReceiver=new BroadcastReceiver()
- {
- @Override
- public void onReceive(Context context, Intent intent) {
- // TODO Auto-generated method stub
- currentBatteryLevel=intent.getIntExtra("level", 0);
- currentBatteryStatus=intent.getIntExtra("status", 0);
- }
- };
- public void onStart(Intent intent,int startId)
- {
- super.onStart(intent, startId);
- /** 注册接收器 */
- registerReceiver(batteryReceiver,new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
- /** 定义一个AppWidgetManager */
- AppWidgetManager manager=AppWidgetManager.getInstance(this);
- /** 定义一个RemoteViews,实现对AppWidget界面控制 */
- RemoteViews views=new RemoteViews(getPackageName(),R.layout.newrelativelayout);
- if(currentBatteryStatus==2||currentBatteryStatus==5) //当正在充电或充满电时,显示充电的图片
- {
- if(currentBatteryLevel>=95)
- {
- bmp=BitmapFactory.decodeResource(getResources(),R.drawable.jcharge);
- }
- else if(currentBatteryLevel>=85&& currentBatteryLevel<95)
- {
- bmp=BitmapFactory.decodeResource(getResources(),R.drawable.icharge);
- }
- else if(currentBatteryLevel>=75&& currentBatteryLevel<85)
- {
- bmp=BitmapFactory.decodeResource(getResources(),R.drawable.hcharge);
- }
- else if(currentBatteryLevel>=65&& currentBatteryLevel<75)
- {
- bmp=BitmapFactory.decodeResource(getResources(),R.drawable.gcharge);
- }
- else if(currentBatteryLevel>=55&& currentBatteryLevel<65)
- {
- bmp=BitmapFactory.decodeResource(getResources(),R.drawable.fcharge);
- }
- else if(currentBatteryLevel>=45&& currentBatteryLevel<55)
- {
- bmp=BitmapFactory.decodeResource(getResources(),R.drawable.echarge);
- }
- else if(currentBatteryLevel>=35&& currentBatteryLevel<45)
- {
- bmp=BitmapFactory.decodeResource(getResources(),R.drawable.dcharge);
- }
- else if(currentBatteryLevel>=25&& currentBatteryLevel<35)
- {
- bmp=BitmapFactory.decodeResource(getResources(),R.drawable.ccharge);
- }
- else if(currentBatteryLevel>=15&& currentBatteryLevel<25)
- {
- bmp=BitmapFactory.decodeResource(getResources(),R.drawable.bcharge);
- }
- else
- {
- bmp=BitmapFactory.decodeResource(getResources(),R.drawable.acharge);
- }
- }
- else //未在充电时,显示不在充电状态的系列图片
- {
- if(currentBatteryLevel>=95)
- {
- bmp=BitmapFactory.decodeResource(getResources(),R.drawable.j);
- }
- else if(currentBatteryLevel>=85&¤tBatteryLevel<95)
- {
- bmp=BitmapFactory.decodeResource(getResources(),R.drawable.i);
- }
- else if(currentBatteryLevel>=75&¤tBatteryLevel<85)
- {
- bmp=BitmapFactory.decodeResource(getResources(),R.drawable.h);
- }
- else if(currentBatteryLevel>=65&¤tBatteryLevel<75)
- {
- bmp=BitmapFactory.decodeResource(getResources(),R.drawable.g);
- }
- else if(currentBatteryLevel>=55&¤tBatteryLevel<65)
- {
- bmp=BitmapFactory.decodeResource(getResources(),R.drawable.f);
- }
- else if(currentBatteryLevel>=45&¤tBatteryLevel<55)
- {
- bmp=BitmapFactory.decodeResource(getResources(),R.drawable.e);
- }
- else if(currentBatteryLevel>=35&¤tBatteryLevel<45)
- {
- bmp=BitmapFactory.decodeResource(getResources(),R.drawable.d);
- }
- else if(currentBatteryLevel>=25&¤tBatteryLevel<35)
- {
- bmp=BitmapFactory.decodeResource(getResources(),R.drawable.c);
- }
- else if(currentBatteryLevel>=15&¤tBatteryLevel<25)
- {
- bmp=BitmapFactory.decodeResource(getResources(),R.drawable.b);
- }
- else
- {
- bmp=BitmapFactory.decodeResource(getResources(),R.drawable.a);
- }
- }
- /** 设置AppWidget上显示的图片和文字的内容 */
- views.setImageViewBitmap(R.id.imageView,bmp);
- views.setTextViewText(R.id.tv,currentBatteryLevel+"%");
- ComponentName thisWidget=new ComponentName(this,NewBatteryWidget.class);
- /** 使用AlarmManager实现每隔一秒发送一次更新提示信息,实现信息实时动态变化 */
- long now=System.currentTimeMillis();
- long pause=1000;
- Intent alarmIntent=new Intent();
- alarmIntent=intent;
- PendingIntent pendingIntent=PendingIntent.getService(this, 0, alarmIntent, 0);
- AlarmManager alarm=(AlarmManager)getSystemService(Context.ALARM_SERVICE);
- alarm.set(AlarmManager.RTC_WAKEUP,now+pause,pendingIntent);
- /** 更新AppWidget */
- manager.updateAppWidget(thisWidget, views);
- }
- }
- }
- </span>
对于Widget,配置它的显示layout,一个简单的RelativeLayout布局,一个ImageView和一个TextView,居中显示:
- <span style="font-family:Microsoft YaHei;font-size:13px;"><?xml version="1.0" encoding="utf-8"?>
- <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent" >
- <ImageView
- android:id="@+id/imageView"
- android:layout_centerInParent="true"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:src="@drawable/j"
- />
- <TextView
- android:id="@+id/tv"
- android:layout_centerInParent="true"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textColor="#000000"
- android:textStyle="bold"
- android:textSize="14sp"
- />
- </RelativeLayout></span>
- <span style="font-family:Microsoft YaHei;font-size:13px;"><?xml version="1.0" encoding="utf-8"?>
- <appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
- android:minHeight="72dip"
- android:minWidth="72dip"
- android:updatePeriodMillis="1000000"
- android:initialLayout="@layout/newrelativelayout"
- >
- <!--
- 关于android:minHeight和android:minWidth
- 分别对应appWidget在屏幕上所占位置的高和宽,
- 最小高和宽各为一个单元格,值为72dip,
- 有资料说计算公式为(74*N)-2
- 例如要设置宽为四个单元格时,(74*4)-2=294
- android:minWidth="294dip"
- 注意,看网上资料说,在SDK1.5之后,
- android:updatePeriodMillis就没用了,
- 不会再定时更新appWidget了,所以这里的值
- 设置多少都不会有影响,但是最好设置大一点,
- 防止万一又有效了,更新的太频繁会不好。
- -->
- </appwidget-provider></span>
备注1,备注2:
请注意,在一些资料上说widget配置文件new_battery_widget.xml中的android:updatePeriodMillis是用来实现widget自动更新的,但本人编程时却发现,这个设置根本就没有效果,后来上网一搜,人家说这个功能在SDK1.5以后就不支持了。所以本次程序自动更新响应系统的battery change事件是通过一个AlarmManager定时发送响应来实现的,同学们千万注意,别像我一样一开始等着靠android:updatePeriodMillis实现更新,看没效果,还以为是别的什么地方出了问题,浪费了不少时间。
Widget的部分差不多了,下面介绍显示电池详情的Activity部分,上代码:
- <span style="font-family:Microsoft YaHei;font-size:13px;">package com.ritterliu.newBatteryWidget;
- import android.app.Activity;
- import android.app.Service;
- import android.content.BroadcastReceiver;
- import android.content.Context;
- import android.content.Intent;
- import android.content.IntentFilter;
- import android.os.Bundle;
- import android.os.IBinder;
- import android.view.MotionEvent;
- import android.view.Window;
- import android.widget.TextView;
- public class NewBatteryInfoActivity extends Activity{
- /** 定义电池信息变量 */
- private static int currentBatteryPlugged=0;
- private static int currentBatteryStatus=0;
- private static int currentBatteryLevel=0;
- private static int currentBatteryHealth=0;
- private static int currentBatteryTemperature=0;
- private static int currentBatteryVoltage=0;
- private static String currentBatteryTechnology="";
- /** TextView 声明 */
- private static TextView tvBatteryStatus;
- private static TextView tvBatteryLevel;
- private static TextView tvBatteryHealth;
- private static TextView tvBatteryTemperature;
- private static TextView tvBatteryVoltage;
- private static TextView tvBatteryTechnology;
- /** 定义好字符串以备使用 */
- private static String batteryStatus="电池状态: ";
- private static String batteryLevel="电池电量: ";
- private static String batteryHealth="电池健康: ";
- private static String batteryTemperature="电池温度: ";
- private static String batteryVoltage="电池电压: ";
- private static String batteryTechnology="电池技术: ";
- private static String batteryStatusCharging="正在充电";
- private static String batteryStatusDischarging="正在放电";
- private static String batteryStatusFull="已充满";
- private static String batteryStatusNotCharging="未在充电";
- private static String batteryStatusUnknown="状态未知";
- private static String batteryPluggedAC="(AC)";
- private static String batteryPluggedUSB="(USB)";
- private static String batteryHealthCold="过冷";
- private static String batteryHealthDead="损坏";
- private static String batteryHealthGood="良好";
- private static String batteryHealthOverheat="过热";
- private static String batteryHealthOverVoltage="过压";
- private static String batteryHealthUnknown="未知";
- private static String batteryHealthUnspecifiedFailure="未知的故障";
- /** 提示Service启动标志位 */
- private static boolean flag;
- /** 提示信息接收器 */
- BroadcastReceiver infoReceiver;
- public void onCreate(Bundle savedInstanceState)
- {
- super.onCreate(savedInstanceState);
- this.requestWindowFeature(Window.FEATURE_NO_TITLE); //设置activity无标题
- setContentView(R.layout.newlayout); //使用newlayout的布局
- tvBatteryStatus=(TextView)findViewById(R.id.tvBatteryStatus);
- tvBatteryLevel=(TextView)findViewById(R.id.tvBatteryLevel);
- tvBatteryHealth=(TextView)findViewById(R.id.tvBatteryHealth);
- tvBatteryTemperature=(TextView)findViewById(R.id.tvBatteryTemperature);
- tvBatteryVoltage=(TextView)findViewById(R.id.tvBatteryVoltage);
- tvBatteryTechnology=(TextView)findViewById(R.id.tvBatteryTechnology);
- flag=true; //提示service的标志位置为true
- infoReceiver=new BroadcastReceiver() //提示信息接收器的定义
- {
- @Override
- public void onReceive(Context context, Intent intent) {
- // TODO Auto-generated method stub
- setText(); //收到intent,就及时修改TextView信息,使得Activity显示时,电池信息也能动态显示
- }
- };
- /** 注册提示信息的intentFilter */
- IntentFilter filter=new IntentFilter();
- filter.addAction("com.ritterliu.newBatteryWidget");
- registerReceiver(infoReceiver,filter);
- /** 启动提示service */
- Intent startService=new Intent(this,updateService.class);
- startService(startService);
- }
- /** 点击屏幕任意位置,关闭电池信息Activity */
- public boolean onTouchEvent(MotionEvent event)
- {
- this.finish();
- // onDestroy();
- // System.exit(0);
- return true;
- }
- @Override
- protected void onDestroy() {
- // TODO Auto-generated method stub
- flag=false;
- unregisterReceiver(infoReceiver);
- super.onDestroy();
- }
- /** 及时动态修改Activity上文字信息的函数 */
- public static void setText()
- {
- String plugState="";
- switch(currentBatteryPlugged)
- {
- case 0:
- plugState="";
- break;
- case 1:
- plugState=batteryPluggedAC;
- break;
- case 2:
- plugState=batteryPluggedUSB;
- break;
- default:
- plugState="";
- }
- switch(currentBatteryStatus)
- {
- case 1:
- tvBatteryStatus.setText(batteryStatus+batteryStatusUnknown);
- break;
- case 2:
- tvBatteryStatus.setText(batteryStatus+batteryStatusCharging+plugState);
- break;
- case 3:
- tvBatteryStatus.setText(batteryStatus+batteryStatusDischarging);
- break;
- case 4:
- tvBatteryStatus.setText(batteryStatus+batteryStatusNotCharging);
- break;
- case 5:
- tvBatteryStatus.setText(batteryStatus+batteryStatusFull+plugState);
- break;
- default:
- tvBatteryStatus.setText(batteryStatus+batteryStatusUnknown);
- }
- tvBatteryLevel.setText(batteryLevel+String.valueOf(currentBatteryLevel)+"%");
- switch(currentBatteryHealth)
- {
- case 1:
- tvBatteryHealth.setText(batteryHealth+batteryHealthUnknown);
- break;
- case 2:
- tvBatteryHealth.setText(batteryHealth+batteryHealthGood);
- break;
- case 3:
- tvBatteryHealth.setText(batteryHealth+batteryHealthOverheat);
- break;
- case 4:
- tvBatteryHealth.setText(batteryHealth+batteryHealthDead);
- break;
- case 5:
- tvBatteryHealth.setText(batteryHealth+batteryHealthOverVoltage);
- break;
- case 6:
- tvBatteryHealth.setText(batteryHealth+batteryHealthUnspecifiedFailure);
- break;
- case 7:
- tvBatteryHealth.setText(batteryHealth+batteryHealthCold);
- break;
- default:
- tvBatteryHealth.setText(batteryHealth+batteryHealthUnknown);
- }
- tvBatteryTemperature.setText(batteryTemperature+currentBatteryTemperature/10f+"℃");
- tvBatteryVoltage.setText(batteryVoltage+currentBatteryVoltage+"mv");
- tvBatteryTechnology.setText(batteryTechnology+currentBatteryTechnology);
- }
- /** 提示信息变化的service,约每隔一秒,就发送intent,
- * 提醒activity更新电池信息,主要为了检测电池状态的变化,
- * 例如连上充电时,状态会从“未在充电”变为“正在充电”
- * 通过调用plugged方式,还能判断是AC方式充电还是USB方式充电
- */
- public static class updateService extends Service{
- @Override
- public IBinder onBind(Intent intent) {
- // TODO Auto-generated method stub
- return null;
- }
- /** 定义得到电池信息的BroadcastReceiver,提取出关键信息,存入变量中 */
- private BroadcastReceiver batteryReceiver=new BroadcastReceiver()
- {
- @Override
- public void onReceive(Context context, Intent intent) {
- // TODO Auto-generated method stub
- currentBatteryStatus=intent.getIntExtra("status", 0);
- currentBatteryLevel=intent.getIntExtra("level", 0);
- currentBatteryHealth=intent.getIntExtra("health", 0);
- currentBatteryTemperature=intent.getIntExtra("temperature",0);
- currentBatteryVoltage=intent.getIntExtra("voltage",0);
- currentBatteryTechnology=intent.getStringExtra("technology");
- currentBatteryPlugged=intent.getIntExtra("plugged",0);
- }
- };
- public void onStart(Intent intent,int startId)
- {
- registerReceiver(batteryReceiver,new IntentFilter(Intent.ACTION_BATTERY_CHANGED));//注册BroadcastReceiver
- /** 启动一个线程,约每隔一秒就发送intent提醒Activity更新电池信息 */
- new Thread()
- {
- public void run()
- {
- while(flag)
- {
- Intent sendInfoToActivity=new Intent();
- sendInfoToActivity.setAction("com.ritterliu.newBatteryWidget");
- sendBroadcast(sendInfoToActivity);
- try
- {
- Thread.sleep(1000);
- }
- catch(Exception ex)
- {
- ex.printStackTrace();
- }
- }
- }
- }.start();
- super.onStart(intent, startId);
- }
- }
- }
- </span>
- <span style="font-family:Microsoft YaHei;font-size:13px;"><?xml version="1.0" encoding="utf-8"?>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:orientation="vertical" >
- <TextView
- android:id="@+id/tvBatteryStatus"
- android:layout_marginLeft="3sp"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/batteryStatus"
- android:textSize="18dp"
- android:textColor="#FFFFFF"
- />
- <TextView
- android:id="@+id/tvBatteryLevel"
- android:layout_marginLeft="3sp"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/batteryLevel"
- android:textSize="18dp"
- android:textColor="#FFFFFF"
- />
- <TextView
- android:id="@+id/tvBatteryHealth"
- android:layout_marginLeft="3sp"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/batteryHealth"
- android:textSize="18dp"
- android:textColor="#FFFFFF"
- />
- <TextView
- android:id="@+id/tvBatteryTemperature"
- android:layout_marginLeft="3sp"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/batteryTemperature"
- android:textSize="18dp"
- android:textColor="#FFFFFF"
- />
- <TextView
- android:id="@+id/tvBatteryVoltage"
- android:layout_marginLeft="3sp"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/batteryVoltage"
- android:textSize="18dp"
- android:textColor="#FFFFFF"
- />
- <TextView
- android:id="@+id/tvBatteryTechnology"
- android:layout_marginLeft="3sp"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/batteryTechnology"
- android:textSize="18dp"
- android:textColor="#FFFFFF"
- />
- <TextView
- android:id="@+id/tvInfo"
- android:layout_marginLeft="3sp"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="http://blog.csdn.net/ritterliu"
- android:textSize="15dp"
- android:textColor="#FFFFFF"
- />
- </LinearLayout></span>
在代码中写了注释,还有什么不清楚的部分可以留言。
最后是AndroidManifest.xml:
- <span style="font-family:Microsoft YaHei;font-size:13px;"><?xml version="1.0" encoding="utf-8"?>
- <manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.ritterliu.newBatteryWidget"
- android:versionCode="1"
- android:versionName="1.0" >
- <uses-sdk android:minSdkVersion="4" />
- <application
- android:icon="@drawable/j"
- android:label="@string/app_name" >
- <receiver
- android:label="@string/app_name"
- android:name=".NewBatteryWidget" >
- <intent-filter >
- <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
- </intent-filter>
- <meta-data android:name="android.appwidget.provider"
- android:resource="@xml/new_battery_widget"
- />
- </receiver>
- <service android:name=".NewBatteryWidget$updateService"/>
- <activity android:name=".NewBatteryInfoActivity" android:label="OtherActiviy_app_name"
- android:theme="@android:style/Theme.Dialog">
- <!-- android:theme="@android:style/Theme.Dialog" 这是设置Activity的主题风格为对话框形式 -->
- </activity>
- <service android:name=".NewBatteryInfoActivity$updateService"/>
- </application>
- </manifest></span>
大功告成
总结:
本次开发大概前后折腾了4天时间,这其中绕了一段弯路(就是那个android:updatePeriodMillis),不仅学习了如何开发Widget,还对Activity的一些写法,比如设置风格为Dialog等又有了进一步的学习,在关闭Activity时,我是直接调用的finish关闭的,也许在用法上还有不当之处,本人从9月份开始自学Android开发至今两个多月的时间,开发水平还十分有限,代码中有写的不好的地方还请大家多多指点,不甚感激。
附上完整文件下载地址,由于本人积分很少(只有19 ),故略收1分,一周后将改为免费,谢谢大家。
http://download.csdn.net/detail/ritterliu/3791897
——————————————————————————————————————————————————————
更新于2011.11.14 15:17
经过昨晚一夜的测试,发现在AppWidget中设置AlarmManager每隔一秒刷新一次频率太高,过于费电了,一夜耗电量居然占到了8%,故针对这个问题正在修改,修改完成后将及时上传。
使用AlarmManager实现每隔一秒刷新一次主要是为了实现实时的充电状态的检测,电池信息的更新自然不用这么频繁,修改中。。。
修改完成,原来的通过AlarmManager每隔一秒刷新一次实现的对充电事件的及时响应改为对ACTION_POWER_CONNECTED和ACTION_POWER_DISCONNECTED监听来实现。
就修改了AppWidget部分:
- package com.ritterliu.newBatteryWidget;
- import android.app.AlarmManager;
- import android.app.PendingIntent;
- import android.app.Service;
- import android.appwidget.AppWidgetManager;
- import android.appwidget.AppWidgetProvider;
- import android.content.BroadcastReceiver;
- import android.content.ComponentName;
- import android.content.Context;
- import android.content.Intent;
- import android.content.IntentFilter;
- import android.graphics.Bitmap;
- import android.graphics.BitmapFactory;
- import android.os.IBinder;
- import android.util.Log;
- import android.widget.RemoteViews;
- import android.widget.Toast;
- public class NewBatteryWidget extends AppWidgetProvider{
- private static int currentBatteryLevel;
- private static int currentBatteryStatus;
- private static boolean firstTimeToCreate=true;
- public void onUpdate(Context context,AppWidgetManager appWidgetManager,int[] appWidgetIds)
- {
- super.onUpdate(context, appWidgetManager, appWidgetIds);
- /** 启动自动更新电池信息的service */
- context.startService(new Intent(context,updateService.class));
- /** 为AppWidget设置点击事件的响应,启动显示电池信息详情的activity */
- Intent startActivityIntent = new Intent(context,NewBatteryInfoActivity.class);
- PendingIntent Pintent = PendingIntent.getActivity(context,0,startActivityIntent,0);
- RemoteViews views = new RemoteViews(context.getPackageName(),R.layout.newrelativelayout);
- views.setOnClickPendingIntent(R.id.imageView,Pintent);
- appWidgetManager.updateAppWidget(appWidgetIds,views);
- }
- /** 自动更新电池信息的service,通过AlarmManager实现定时不间断地发送电池信息 */
- public static class updateService extends Service{
- Bitmap bmp; //定义机器人图片
- @Override
- public IBinder onBind(Intent intent) {
- // TODO Auto-generated method stub
- return null;
- }
- /** 定义一个接收电池信息的broascastReceiver */
- private BroadcastReceiver batteryReceiver=new BroadcastReceiver()
- {
- @Override
- public void onReceive(Context context, Intent intent) {
- // TODO Auto-generated method stub
- currentBatteryLevel=intent.getIntExtra("level", 0);
- currentBatteryStatus=intent.getIntExtra("status", 0);
- }
- };
- private BroadcastReceiver powerConnectedReceiver=new BroadcastReceiver()
- {
- @Override
- public void onReceive(Context context, Intent intent) {
- // TODO Auto-generated method stub
- setViews();
- }
- };
- private BroadcastReceiver powerDisconnectedReceiver=new BroadcastReceiver()
- {
- @Override
- public void onReceive(Context context, Intent intent) {
- // TODO Auto-generated method stub
- setViews();
- }
- };
- /** 设置Widget的显示 */
- private void setViews()
- {
- /** 定义一个AppWidgetManager */
- AppWidgetManager manager=AppWidgetManager.getInstance(this);
- /** 定义一个RemoteViews,实现对AppWidget界面控制 */
- RemoteViews views=new RemoteViews(getPackageName(),R.layout.newrelativelayout);
- if(currentBatteryStatus==2||currentBatteryStatus==5) //当正在充电或充满电时,显示充电的图片
- {
- if(currentBatteryLevel>=95)
- {
- bmp=BitmapFactory.decodeResource(getResources(),R.drawable.jcharge);
- }
- else if(currentBatteryLevel>=85&& currentBatteryLevel<95)
- {
- bmp=BitmapFactory.decodeResource(getResources(),R.drawable.icharge);
- }
- else if(currentBatteryLevel>=75&& currentBatteryLevel<85)
- {
- bmp=BitmapFactory.decodeResource(getResources(),R.drawable.hcharge);
- }
- else if(currentBatteryLevel>=65&& currentBatteryLevel<75)
- {
- bmp=BitmapFactory.decodeResource(getResources(),R.drawable.gcharge);
- }
- else if(currentBatteryLevel>=55&& currentBatteryLevel<65)
- {
- bmp=BitmapFactory.decodeResource(getResources(),R.drawable.fcharge);
- }
- else if(currentBatteryLevel>=45&& currentBatteryLevel<55)
- {
- bmp=BitmapFactory.decodeResource(getResources(),R.drawable.echarge);
- }
- else if(currentBatteryLevel>=35&& currentBatteryLevel<45)
- {
- bmp=BitmapFactory.decodeResource(getResources(),R.drawable.dcharge);
- }
- else if(currentBatteryLevel>=25&& currentBatteryLevel<35)
- {
- bmp=BitmapFactory.decodeResource(getResources(),R.drawable.ccharge);
- }
- else if(currentBatteryLevel>=15&& currentBatteryLevel<25)
- {
- bmp=BitmapFactory.decodeResource(getResources(),R.drawable.bcharge);
- }
- else
- {
- bmp=BitmapFactory.decodeResource(getResources(),R.drawable.acharge);
- }
- }
- else //未在充电时,显示不在充电状态的系列图片
- {
- if(currentBatteryLevel>=95)
- {
- bmp=BitmapFactory.decodeResource(getResources(),R.drawable.j);
- }
- else if(currentBatteryLevel>=85&& currentBatteryLevel<95)
- {
- bmp=BitmapFactory.decodeResource(getResources(),R.drawable.i);
- }
- else if(currentBatteryLevel>=75&& currentBatteryLevel<85)
- {
- bmp=BitmapFactory.decodeResource(getResources(),R.drawable.h);
- }
- else if(currentBatteryLevel>=65&& currentBatteryLevel<75)
- {
- bmp=BitmapFactory.decodeResource(getResources(),R.drawable.g);
- }
- else if(currentBatteryLevel>=55&& currentBatteryLevel<65)
- {
- bmp=BitmapFactory.decodeResource(getResources(),R.drawable.f);
- }
- else if(currentBatteryLevel>=45&& currentBatteryLevel<55)
- {
- bmp=BitmapFactory.decodeResource(getResources(),R.drawable.e);
- }
- else if(currentBatteryLevel>=35&& currentBatteryLevel<45)
- {
- bmp=BitmapFactory.decodeResource(getResources(),R.drawable.d);
- }
- else if(currentBatteryLevel>=25&& currentBatteryLevel<35)
- {
- bmp=BitmapFactory.decodeResource(getResources(),R.drawable.c);
- }
- else if(currentBatteryLevel>=15&& currentBatteryLevel<25)
- {
- bmp=BitmapFactory.decodeResource(getResources(),R.drawable.b);
- }
- else
- {
- bmp=BitmapFactory.decodeResource(getResources(),R.drawable.a);
- }
- }
- /** 设置AppWidget上显示的图片和文字的内容 */
- views.setImageViewBitmap(R.id.imageView,bmp);
- views.setTextViewText(R.id.tv,currentBatteryLevel+"%");
- ComponentName thisWidget=new ComponentName(this,NewBatteryWidget.class);
- /** 更新AppWidget */
- manager.updateAppWidget(thisWidget, views);
- }
- public void onStart(Intent intent,int startId)
- {
- super.onStart(intent, startId);
- /** 注册接收器 */
- registerReceiver(batteryReceiver,new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
- /** 增加了对于POWER_CONNECTED和DISCONNECTED事件的监听,
- * 以实现充电时信息的动态变化,避免了原来需要依赖AlarmManager
- * 每隔一秒发送检测信息来实现,节约了电量,用原来隔一秒更新的方法,
- * 经过一夜测试,插件耗电量居然占到了8%,汗。。。
- *
- * */
- registerReceiver(powerConnectedReceiver,new IntentFilter(Intent.ACTION_POWER_CONNECTED));
- registerReceiver(powerDisconnectedReceiver,new IntentFilter(Intent.ACTION_POWER_DISCONNECTED ));
- /** 使用AlarmManager实现,第一次启动Widget时隔一秒立即更新,
- * 以后均为两分钟发送一次更新提示信息,实现信息实时动态变化,
- * 实现节电功能
- * */
- long now=System.currentTimeMillis();
- long pause;
- if(firstTimeToCreate)
- {
- firstTimeToCreate=false;
- pause=1000;
- }
- else
- {
- pause=1000*60*2;
- }
- Intent alarmIntent=new Intent();
- alarmIntent=intent;
- PendingIntent pendingIntent=PendingIntent.getService(this, 0, alarmIntent, 0);
- AlarmManager alarm=(AlarmManager)getSystemService(Context.ALARM_SERVICE);
- alarm.set(AlarmManager.RTC_WAKEUP,now+pause,pendingIntent);
- setViews();
- }
- }
- }
新的源码下载地址:
http://download.csdn.net/detail/ritterliu/3794539
同样将在一周后将改为免费,谢谢大家。
-----------------------------------------------------------------------------------------------------------------------------------------------------
更新于2011.11.15 10:52pm
真是不好意思,今天又有同学测出了BUG,桌面横竖屏切换后,点击Widget没反应了,无发启动Activity,显示电池信息详情了。
经过1个小时查找资料,修改完成,依旧是在Service中新增了一个intent检测,用来监听横竖屏切换事件,screenOrientationChangedReceiver接收到 ACTION_CONFIGURATION_CHANGED 后,再次注册widget的click事件,解决横竖屏切换后,widget点击无响应的BUG。
同样只修改了AppWidget部分,上代码:
- package com.ritterliu.newBatteryWidgetV2;
- import android.app.AlarmManager;
- import android.app.PendingIntent;
- import android.app.Service;
- import android.appwidget.AppWidgetManager;
- import android.appwidget.AppWidgetProvider;
- import android.content.BroadcastReceiver;
- import android.content.ComponentName;
- import android.content.Context;
- import android.content.Intent;
- import android.content.IntentFilter;
- import android.graphics.Bitmap;
- import android.graphics.BitmapFactory;
- import android.os.IBinder;
- import android.widget.RemoteViews;
- public class NewBatteryWidget extends AppWidgetProvider{
- private static int currentBatteryLevel;
- private static int currentBatteryStatus;
- private static boolean firstTimeToCreate=true;
- /** 声明全局变量,方便screenOrientationChangedReceiver里使用 */
- private static AppWidgetManager appWidgetManager;
- private static int[] appWidgetIds;
- public void onUpdate(Context context,AppWidgetManager appWidgetManager,int[] appWidgetIds)
- {
- super.onUpdate(context, appWidgetManager, appWidgetIds);
- /** 启动自动更新电池信息的service */
- context.startService(new Intent(context,updateService.class));
- /** 定义全局变量,方便screenOrientationChangedReceiver里使用 */
- this.appWidgetManager=appWidgetManager;
- this.appWidgetIds=appWidgetIds;
- /** 为AppWidget设置点击事件的响应,启动显示电池信息详情的activity */
- Intent startActivityIntent = new Intent(context,NewBatteryInfoActivity.class);
- PendingIntent Pintent = PendingIntent.getActivity(context,0,startActivityIntent,0);
- RemoteViews views = new RemoteViews(context.getPackageName(),R.layout.newrelativelayout);
- views.setOnClickPendingIntent(R.id.imageView,Pintent);
- appWidgetManager.updateAppWidget(appWidgetIds,views);
- }
- /** 自动更新电池信息的service,通过AlarmManager实现定时不间断地发送电池信息 */
- public static class updateService extends Service{
- Bitmap bmp; //定义机器人图片
- @Override
- public IBinder onBind(Intent intent) {
- // TODO Auto-generated method stub
- return null;
- }
- /** 定义一个接收电池信息的broadcastReceiver */
- private BroadcastReceiver batteryReceiver=new BroadcastReceiver()
- {
- @Override
- public void onReceive(Context context, Intent intent) {
- // TODO Auto-generated method stub
- currentBatteryLevel=intent.getIntExtra("level", 0);
- currentBatteryStatus=intent.getIntExtra("status", 0);
- }
- };
- /** 定义一个接受电源连接的broadcastReceiver */
- private BroadcastReceiver powerConnectedReceiver=new BroadcastReceiver()
- {
- @Override
- public void onReceive(Context context, Intent intent) {
- // TODO Auto-generated method stub
- setViews();
- }
- };
- /** 定义一个接受电源断开的broadcastReceiver */
- private BroadcastReceiver powerDisconnectedReceiver=new BroadcastReceiver()
- {
- @Override
- public void onReceive(Context context, Intent intent) {
- // TODO Auto-generated method stub
- setViews();
- }
- };
- /** 定义一个监听横竖屏切换的broadcastReceiver */
- private BroadcastReceiver screenOrientationChangedReceiver=new BroadcastReceiver()
- {
- public void onReceive(Context context,Intent intent)
- {
- /** 为AppWidget设置点击事件的响应,启动显示电池信息详情的activity */
- Intent startActivityIntent = new Intent(context,NewBatteryInfoActivity.class);
- PendingIntent Pintent = PendingIntent.getActivity(context,0,startActivityIntent,0);
- RemoteViews views = new RemoteViews(context.getPackageName(),R.layout.newrelativelayout);
- views.setOnClickPendingIntent(R.id.imageView,Pintent);
- /** 设置AppWidget上显示的图片和文字的内容 */
- views.setImageViewBitmap(R.id.imageView,bmp);
- views.setTextViewText(R.id.tv,currentBatteryLevel+"%");
- appWidgetManager.updateAppWidget(appWidgetIds,views);
- }
- };
- /** 设置Widget的显示 */
- private void setViews()
- {
- /** 定义一个AppWidgetManager */
- AppWidgetManager manager=AppWidgetManager.getInstance(this);
- /** 定义一个RemoteViews,实现对AppWidget界面控制 */
- RemoteViews views=new RemoteViews(getPackageName(),R.layout.newrelativelayout);
- if(currentBatteryStatus==2||currentBatteryStatus==5) //当正在充电或充满电时,显示充电的图片
- {
- if(currentBatteryLevel>=95)
- {
- bmp=BitmapFactory.decodeResource(getResources(),R.drawable.jcharge);
- }
- else if(currentBatteryLevel>=85&& currentBatteryLevel<95)
- {
- bmp=BitmapFactory.decodeResource(getResources(),R.drawable.icharge);
- }
- else if(currentBatteryLevel>=75&& currentBatteryLevel<85)
- {
- bmp=BitmapFactory.decodeResource(getResources(),R.drawable.hcharge);
- }
- else if(currentBatteryLevel>=65&& currentBatteryLevel<75)
- {
- bmp=BitmapFactory.decodeResource(getResources(),R.drawable.gcharge);
- }
- else if(currentBatteryLevel>=55&& currentBatteryLevel<65)
- {
- bmp=BitmapFactory.decodeResource(getResources(),R.drawable.fcharge);
- }
- else if(currentBatteryLevel>=45&& currentBatteryLevel<55)
- {
- bmp=BitmapFactory.decodeResource(getResources(),R.drawable.echarge);
- }
- else if(currentBatteryLevel>=35&& currentBatteryLevel<45)
- {
- bmp=BitmapFactory.decodeResource(getResources(),R.drawable.dcharge);
- }
- else if(currentBatteryLevel>=25&& currentBatteryLevel<35)
- {
- bmp=BitmapFactory.decodeResource(getResources(),R.drawable.ccharge);
- }
- else if(currentBatteryLevel>=15&& currentBatteryLevel<25)
- {
- bmp=BitmapFactory.decodeResource(getResources(),R.drawable.bcharge);
- }
- else
- {
- bmp=BitmapFactory.decodeResource(getResources(),R.drawable.acharge);
- }
- }
- else //未在充电时,显示不在充电状态的系列图片
- {
- if(currentBatteryLevel>=95)
- {
- bmp=BitmapFactory.decodeResource(getResources(),R.drawable.j);
- }
- else if(currentBatteryLevel>=85&& currentBatteryLevel<95)
- {
- bmp=BitmapFactory.decodeResource(getResources(),R.drawable.i);
- }
- else if(currentBatteryLevel>=75&& currentBatteryLevel<85)
- {
- bmp=BitmapFactory.decodeResource(getResources(),R.drawable.h);
- }
- else if(currentBatteryLevel>=65&& currentBatteryLevel<75)
- {
- bmp=BitmapFactory.decodeResource(getResources(),R.drawable.g);
- }
- else if(currentBatteryLevel>=55&& currentBatteryLevel<65)
- {
- bmp=BitmapFactory.decodeResource(getResources(),R.drawable.f);
- }
- else if(currentBatteryLevel>=45&& currentBatteryLevel<55)
- {
- bmp=BitmapFactory.decodeResource(getResources(),R.drawable.e);
- }
- else if(currentBatteryLevel>=35&& currentBatteryLevel<45)
- {
- bmp=BitmapFactory.decodeResource(getResources(),R.drawable.d);
- }
- else if(currentBatteryLevel>=25&& currentBatteryLevel<35)
- {
- bmp=BitmapFactory.decodeResource(getResources(),R.drawable.c);
- }
- else if(currentBatteryLevel>=15&& currentBatteryLevel<25)
- {
- bmp=BitmapFactory.decodeResource(getResources(),R.drawable.b);
- }
- else
- {
- bmp=BitmapFactory.decodeResource(getResources(),R.drawable.a);
- }
- }
- /** 设置AppWidget上显示的图片和文字的内容 */
- views.setImageViewBitmap(R.id.imageView,bmp);
- views.setTextViewText(R.id.tv,currentBatteryLevel+"%");
- ComponentName thisWidget=new ComponentName(this,NewBatteryWidget.class);
- /** 更新AppWidget */
- manager.updateAppWidget(thisWidget, views);
- }
- public void onStart(Intent intent,int startId)
- {
- super.onStart(intent, startId);
- /** 注册接收器 */
- registerReceiver(batteryReceiver,new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
- /** 增加了对于POWER_CONNECTED和DISCONNECTED事件的监听,
- * 以实现充电时信息的动态变化,避免了原来需要依赖AlarmManager
- * 每隔一秒发送检测信息来实现,节约了电量,用原来隔一秒更新的方法,
- * 经过一夜测试,插件耗电量居然占到了8%,汗。。。
- *
- * */
- registerReceiver(powerConnectedReceiver,new IntentFilter(Intent.ACTION_POWER_CONNECTED));
- registerReceiver(powerDisconnectedReceiver,new IntentFilter(Intent.ACTION_POWER_DISCONNECTED ));
- /** 新增用以检测横竖屏切换事件 */
- registerReceiver(screenOrientationChangedReceiver,new IntentFilter(Intent.ACTION_CONFIGURATION_CHANGED));
- /** 使用AlarmManager实现,第一次启动Widget时隔一秒立即更新,
- * 以后均为两分钟发送一次更新提示信息,实现信息实时动态变化,
- * 实现节电功能
- * */
- long now=System.currentTimeMillis();
- long pause;
- if(firstTimeToCreate)
- {
- firstTimeToCreate=false;
- pause=1000;
- }
- else
- {
- pause=1000*60*2;
- }
- Intent alarmIntent=new Intent();
- alarmIntent=intent;
- PendingIntent pendingIntent=PendingIntent.getService(this, 0, alarmIntent, 0);
- AlarmManager alarm=(AlarmManager)getSystemService(Context.ALARM_SERVICE);
- alarm.set(AlarmManager.RTC_WAKEUP,now+pause,pendingIntent);
- setViews();
- }
- }
- }
最新的工程就不上传了,大家将这个部分替换就可以了。
![吐舌头](http://static.blog.csdn.net/xheditor/xheditor_emot/default/tongue.gif)