Android AppWidget电池状态 [英] Android AppWidget Battery-Status

查看:83
本文介绍了Android AppWidget电池状态的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在寻找制作一个可检查电池状态(电量,充电/不充电)的AppWidget.

I'm looking for make an AppWidget that check the battery status (level, charging/not charging).

我写了很多代码行,但是,即使它工作得很好,我仍然看到它放在屏幕上会使电话变慢,并且有时会崩溃.

I wrote a lot of codelines, but, even if it work perfectly, I see that put it on the screen make the telephone slower and, sometimes crash.

我认为这是因为我做错了什么.有人能帮我吗?谢谢

I think it's because I make something wrong. Can someone help me? Thank's

这是我的清单:

    <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="it.bisneff.widgetone"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="10" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >


       <receiver android:name="MyWidgetProvider" >
            <intent-filter >
                <action 
                    android:name="android.appwidget.action.APPWIDGET_UPDATE" />

                <action android:name="android.intent.action.ACTION_POWER_CONNECTED"/>
                <action android:name="android.intent.action.ACTION_POWER_DISCONNECTED"/>

            </intent-filter>

            <meta-data
                android:name="android.appwidget.provider"
                android:resource="@xml/widget_info" />
            </receiver>


    </application>

</manifest>

这是我的主要班级:

package it.bisneff.widgetone;


import it.bisneff.widgetone.R;
import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.BatteryManager;
import android.os.Bundle;
import android.util.Log;
import android.widget.RemoteViews;

public class MyWidgetProvider extends AppWidgetProvider {

    //Unused String
    private static final String ACTION_CLICK = "ACTION_CLICK"; 


      @Override
      public void onUpdate(Context context, AppWidgetManager appWidgetManager,
          int[] appWidgetIds) {

        ComponentName thisWidget = new ComponentName(context,
            MyWidgetProvider.class);
        int[] allWidgetIds = appWidgetManager.getAppWidgetIds(thisWidget);

         for (int widgetId : allWidgetIds) {


                Intent batteryStatus =context.getApplicationContext().registerReceiver(this,
                        new IntentFilter(Intent.ACTION_BATTERY_CHANGED));

                    //Battery Level
                int level = batteryStatus.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);

                //Max Battery Level
                int scale = batteryStatus.getIntExtra(BatteryManager.EXTRA_SCALE, -1);

                // %
                float batteryPct = level / (float)scale;
                batteryPct=batteryPct*100;



          RemoteViews remoteViews = new RemoteViews(context.getPackageName(),
              R.layout.widget_layout);

          //Charging or not
          int status = batteryStatus.getIntExtra(BatteryManager.EXTRA_STATUS, -1);


          boolean isCharging = status == BatteryManager.BATTERY_STATUS_CHARGING ||
                  status == BatteryManager.BATTERY_STATUS_FULL;

          //integer convertion
          int batteryPctz=(int)batteryPct;
          Log.w("WidgetExample", String.valueOf(batteryPctz)+"%");


          //USB or AC charge
          int chargePlug = batteryStatus.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);
          boolean usbCharge = chargePlug == BatteryManager.BATTERY_PLUGGED_USB;
          boolean acCharge = chargePlug == BatteryManager.BATTERY_PLUGGED_AC;

          //update view
          remoteViews.setTextViewText(R.id.update, String.valueOf(batteryPctz)+"%");

          //select the image for the battery level
            String res=new String();
            res="it.bisneff.widgetone:drawable/battery";



                    if (batteryPct >= 90)
            {       res+="6";
            }
            if (batteryPct >= 75 && batteryPct < 90)
            {
                res+="5";
            }
            if (batteryPct >= 60 && batteryPct < 75 )
            {
            res+="4";
            }
            if (batteryPct >= 35 && batteryPct < 60 )
            {
            res+="3";
            }
            if (batteryPct >= 15 && batteryPct < 35 )
            {
            res+="2";
            }
            if (batteryPct < 15 )
            {
            res+="1";
            }


          if(isCharging){


            if(acCharge)
            {

                res+="cha";

            }


            if(usbCharge)
            {
            res+="usb";
            }


            if (batteryPctz==100){res="it.bisneff.widgetone:drawable/battery6full";}
          }

            //check the resource
            int reso= context.getResources().getIdentifier(res, null, null);    

            //put the right image
            remoteViews.setImageViewResource(R.id.imageView1, reso);



          //Set Click Listener

          Intent intent = new Intent(context, MyWidgetProvider.class);

          intent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
          intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, appWidgetIds);

          PendingIntent pendingIntent = PendingIntent.getBroadcast(context,
              0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
          remoteViews.setOnClickPendingIntent(R.id.update, pendingIntent);
          appWidgetManager.updateAppWidget(widgetId, remoteViews);
        }

      }


      @Override
      public void onReceive(Context context, Intent intent) {
       super.onReceive(context, intent);

       //check received intent action
       if(  ((intent.getAction()).equals(Intent.ACTION_BATTERY_CHANGED)) || ((intent.getAction()).equals(Intent.ACTION_POWER_CONNECTED)) || ((intent.getAction()).equals(Intent.ACTION_POWER_DISCONNECTED))){

           //get Bundle
           Bundle extras = intent.getExtras();

           //if extras
           if(extras!=null) {


               AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);         
               ComponentName thisAppWidget = new ComponentName(context.getPackageName(), MyWidgetProvider.class.getName());
               int[] appWidgetIds = appWidgetManager.getAppWidgetIds(thisAppWidget);

          //call the onUpdate
          onUpdate(context, appWidgetManager, appWidgetIds);

         }

       }
      }

      }

我知道问题出在哪里.

如果我有

  ....
        Intent batteryStatus =context.getApplicationContext().registerReceiver(this,
                        new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
            context.getApplicationContext().unregisterReceiver(this);//this line
     ....

小部件停止循环播放.但是它停止更新电池电量变化...

The widget stop to loop. But it stop to update on battery level changes...

我添加了

@Override
public void onEnabled(Context context){

    context.getApplicationContext().registerReceiver(this, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));

}

为了确保注册我的接收器,但它无法工作,并且我无法从XML进行注册,原因是文档指出无法在其中注册.

to be sure to register my receiver, but it won't work, and I cannot register it from XML cause documentation says it cannot be register there.

我该怎么办?

推荐答案

你好Valerio Bisneff Ponza,

Hello Valerio Bisneff Ponza,

您必须面对以下例外情况:

You must be facing this exception:

android.content.ReceiverCallNotAllowedException: BroadcastReceiver components are not allowed to register to receive intents

原因:这是因为,您(小部件/BroadCast接收器)无法在(小部件/BroadCast接收器)内部向另一个Intent_Filter注册自己或注册其他接收器...

Reason: This is because, you(Widget/ BroadCast Receiver) can not register itself with another Intent_Filter OR register another receiver, from within (Widget/ BroadCast Receiver)...

如果您添加清单时,则在注册小部件时:

If you add in manifest, while registering Widget:

  • action android:name ="android.intent.action.BATTERY_CHANGED"或
  • action android:name ="android.intent.action.ACTION_POWER_CONNECTED"或
  • action android:name ="android.intent.action.ACTION_POWER_DISCONNECTED"等.

...大多数情况下,您的小部件不会响应.

... most of the times your Widget won't respond.

原因:小部件与进程(pid)或服务相关联,如果独立运行(活动/服务)未运行,则它不会收到Intent.

Reason: Widget is associated with a process(pid) OR service, if run independently(activity/ service) not running, it shall not receive Intents.

接下来要做什么?

在启用"中,显式启动服务以更新窗口小部件,在服务的onStart()中注册BroadCast接收器,然后从服务中更新窗口小部件.

In On Enabled, start a service, explicitly for updating your widget, register your BroadCast receiver in onStart() of service and update Widget from Service.

注意:请记住要在服务的onStop()中注销接收者,否则会出现另一个异常……并从Widget的onDisabled()中显式调用stopService().如果需要,请在清单中将您的服务保留为export ="false".

NOTE: Please Remember to unregister receiver in onStop() of service, else another exception would come up......And explicitly call stopService() from onDisabled() of Widget. Keep your service as exported="false" in manifest if needed enter code here`d.

亲爱的Ponza,我曾经遇到过某些情况,基于某些基于使用情况的GC,您的服务会被Android杀死.但是在那种情况下,我们始终可以在Widget的每个操作中使用一些共享的Pref布尔值进行智能检查.

Dear Ponza, I have faced that sometimes, your service gets killed by Android, based on some usage based GC. But in that case, we can always have a smart check using some shared Pref boolean in every action of Widget.

希望我的回答足够详细;)

HOPE my answer is detailed enough ;)

这篇关于Android AppWidget电池状态的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆