使用 Intent 和 BroadcastReceiver 获取 Android 电池电量时的奇怪行为

发布于 2024-10-16 10:29:24 字数 6592 浏览 4 评论 0原文

我试图在运行 Android 应用程序后找到电池电量。当手机启动应用程序并完全充电时,代码始终返回 100% 电池电量(即使电量已耗尽)。如果我以 75% 电量或其他电量启动应用程序,那么它会在测试结束时返回实际电池电量。我开始测试时,将手机插入计算机并保持电量,然后在执行应用程序之前拔掉它。理想情况下,我希望能够获得开始%和结束%,但两者的读取率也都是100%。所以这就是我正在做的事情...我从我的活动中称之为:

this.registerReceiver(this.mBatInfoReceiver, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));

然后在 BroadcastReceiver 中我做了很多事情(这需要一个多小时,因此电池电量会发生变化)。然后在BoradcastReceiver的末尾我调用它

int level2 = intent.getIntExtra("level", 0);    /* Ending battery level */
String end = "Ending battery level: " + String.valueOf(level2) + "%";

然后将String端发送到服务器。

我的代码如下所示:

package com.mdog.datareceive;

import java.io.IOException;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;

import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.os.PowerManager;
import android.util.Log;
import android.widget.TextView;


public class Receive extends Activity {

    /* Test parameters */
    static int BYTES_TO_READ = 1024*1024*50;    /* The size of the data for each transfer */
    static int TIMES_TO_READ = 20;              /* The number of times the client will request the data */
    static int PLAYER_BUFFER_SIZE = 1638400;    /* Clients buffer size 1638400 = 1.57MB */
    static int SLEEP_TIME_MS = 5000;

    /* Display Info */
    String start = "empty";                 /* String holder for the starting battery life */
    String end = "empty2";                  /* String holder for the ending battery life */
    int allMBytes = 0;                      /* Integer holder for the total number of megabytes received during the test */
    TextView tv;                            /* The view the phone displays after completion of test */

    /* Server Info */
    String serverIP = "192.168.0.104";      /* Server IP */
    int serverPort = 11313;                 /* Server port number */



    private BroadcastReceiver mBatInfoReceiver = new BroadcastReceiver(){

        @Override
        public void onReceive(Context arg0, Intent intent) {

            //int level = intent.getIntExtra("level", 0);

            Socket connectionSocket = null;                         /* Socket to communicate with server */
            byte[] inputHolderByteArray = new byte[PLAYER_BUFFER_SIZE]; /* Used to read from the socket */

            int bufferBytes = 0;        /* filling the second buffer */
            int totalBytesRead = 0;     /* The total number of bytes read for this transfer round */
            int read=0;                 /* reading from stream, will contain the number of bytes read or -1 if the end has been hit */

            /* Acquire a wake lock for the phone so it does not go to sleep */
            PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
            PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK, getClass().getName());

            /* Connect to Server */
            try {

                connectionSocket = new Socket(serverIP, serverPort);
                connectionSocket.setReceiveBufferSize(PLAYER_BUFFER_SIZE); //1.5ish MB
                connectionSocket.setKeepAlive(true);
                PrintWriter out = new PrintWriter(connectionSocket.getOutputStream(), true);

                out.print("Client Info: Bytes expected per transfer:" + BYTES_TO_READ + ", Number of transfer to request:" + TIMES_TO_READ+ ", Buffer size:" +PLAYER_BUFFER_SIZE+ ", Sleep time(ms):" + SLEEP_TIME_MS + "\n");
                out.flush();

                wl.acquire();

                for(int i=0; i<TIMES_TO_READ; i++){

                    out.print("Start\n");
                    out.flush();

                    while(totalBytesRead < BYTES_TO_READ){

                        /* Read at most PLAYER_BUFFER_SIZE bytes */
                        read = connectionSocket.getInputStream().read(inputHolderByteArray, 0, PLAYER_BUFFER_SIZE);

                        if(read != -1){
                            bufferBytes += read;
                            totalBytesRead  += read;
                            if(bufferBytes >= PLAYER_BUFFER_SIZE){
                                    try {
                                        Thread.sleep(SLEEP_TIME_MS);
                                    } catch (InterruptedException e) {
                                        e.printStackTrace();
                                    }
                                bufferBytes = 0;
                            }
                        }
                        else{
                            /* End of stream reached */
                            break;
                        }     
                    }

                    allMBytes += ((totalBytesRead/1024)/1024);
                    totalBytesRead = 0;

                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                }

                int level2 = intent.getIntExtra("level", 0);    /* Ending battery level */

                /* Put data on screen */
                start = "Starting battery level: 100%";
                end = "Ending battery level: " + String.valueOf(level2) + "%";
                out.print("Test Completed: " + start + ", " + end + ", Megabytes Read: " + allMBytes + "\n");
                out.flush();

                wl.release();

                tv.setText(start + "    \n" + end + "    \n Total MB transferred:" + allMBytes);
                setContentView(tv);

            } catch (UnknownHostException e) {
                Log.i("UnknownHost exception ", " ******************** Log Msg UHE " + e.getLocalizedMessage());
                e.printStackTrace();
            } catch (IOException e2) {
                Log.i("IO exception ", "******************** Log Msg IOE " + e2.toString());
                e2.printStackTrace();
            }
        }
    };


    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {

        tv = new TextView(this);                /* The view to post text to */
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        this.registerReceiver(this.mBatInfoReceiver, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
    }
}

I am trying to find the battery level after running an android app. When the phone starts the app completely charged the code always returns 100% battery level (even though it has drained a lot). If I start the app at 75% battery or whatever then it returns the actual battery level at the end of the test. I start my test with the phone plugged into my computer keeping its charge up then right before executing the app I unplug it. Ideally I'd like tobe able to get starting% and ending% but that read 100% on both as well. So here is what I am doing... I call this from my activity:

this.registerReceiver(this.mBatInfoReceiver, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));

Then in BroadcastReceiver I do a bunch of stuff (that takes over an hour so battery level changes). Then at the end of BoradcastReceiver I call this

int level2 = intent.getIntExtra("level", 0);    /* Ending battery level */
String end = "Ending battery level: " + String.valueOf(level2) + "%";

And then send the String end to the server.

Here is what my code looks like:

package com.mdog.datareceive;

import java.io.IOException;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;

import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.os.PowerManager;
import android.util.Log;
import android.widget.TextView;


public class Receive extends Activity {

    /* Test parameters */
    static int BYTES_TO_READ = 1024*1024*50;    /* The size of the data for each transfer */
    static int TIMES_TO_READ = 20;              /* The number of times the client will request the data */
    static int PLAYER_BUFFER_SIZE = 1638400;    /* Clients buffer size 1638400 = 1.57MB */
    static int SLEEP_TIME_MS = 5000;

    /* Display Info */
    String start = "empty";                 /* String holder for the starting battery life */
    String end = "empty2";                  /* String holder for the ending battery life */
    int allMBytes = 0;                      /* Integer holder for the total number of megabytes received during the test */
    TextView tv;                            /* The view the phone displays after completion of test */

    /* Server Info */
    String serverIP = "192.168.0.104";      /* Server IP */
    int serverPort = 11313;                 /* Server port number */



    private BroadcastReceiver mBatInfoReceiver = new BroadcastReceiver(){

        @Override
        public void onReceive(Context arg0, Intent intent) {

            //int level = intent.getIntExtra("level", 0);

            Socket connectionSocket = null;                         /* Socket to communicate with server */
            byte[] inputHolderByteArray = new byte[PLAYER_BUFFER_SIZE]; /* Used to read from the socket */

            int bufferBytes = 0;        /* filling the second buffer */
            int totalBytesRead = 0;     /* The total number of bytes read for this transfer round */
            int read=0;                 /* reading from stream, will contain the number of bytes read or -1 if the end has been hit */

            /* Acquire a wake lock for the phone so it does not go to sleep */
            PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
            PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK, getClass().getName());

            /* Connect to Server */
            try {

                connectionSocket = new Socket(serverIP, serverPort);
                connectionSocket.setReceiveBufferSize(PLAYER_BUFFER_SIZE); //1.5ish MB
                connectionSocket.setKeepAlive(true);
                PrintWriter out = new PrintWriter(connectionSocket.getOutputStream(), true);

                out.print("Client Info: Bytes expected per transfer:" + BYTES_TO_READ + ", Number of transfer to request:" + TIMES_TO_READ+ ", Buffer size:" +PLAYER_BUFFER_SIZE+ ", Sleep time(ms):" + SLEEP_TIME_MS + "\n");
                out.flush();

                wl.acquire();

                for(int i=0; i<TIMES_TO_READ; i++){

                    out.print("Start\n");
                    out.flush();

                    while(totalBytesRead < BYTES_TO_READ){

                        /* Read at most PLAYER_BUFFER_SIZE bytes */
                        read = connectionSocket.getInputStream().read(inputHolderByteArray, 0, PLAYER_BUFFER_SIZE);

                        if(read != -1){
                            bufferBytes += read;
                            totalBytesRead  += read;
                            if(bufferBytes >= PLAYER_BUFFER_SIZE){
                                    try {
                                        Thread.sleep(SLEEP_TIME_MS);
                                    } catch (InterruptedException e) {
                                        e.printStackTrace();
                                    }
                                bufferBytes = 0;
                            }
                        }
                        else{
                            /* End of stream reached */
                            break;
                        }     
                    }

                    allMBytes += ((totalBytesRead/1024)/1024);
                    totalBytesRead = 0;

                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                }

                int level2 = intent.getIntExtra("level", 0);    /* Ending battery level */

                /* Put data on screen */
                start = "Starting battery level: 100%";
                end = "Ending battery level: " + String.valueOf(level2) + "%";
                out.print("Test Completed: " + start + ", " + end + ", Megabytes Read: " + allMBytes + "\n");
                out.flush();

                wl.release();

                tv.setText(start + "    \n" + end + "    \n Total MB transferred:" + allMBytes);
                setContentView(tv);

            } catch (UnknownHostException e) {
                Log.i("UnknownHost exception ", " ******************** Log Msg UHE " + e.getLocalizedMessage());
                e.printStackTrace();
            } catch (IOException e2) {
                Log.i("IO exception ", "******************** Log Msg IOE " + e2.toString());
                e2.printStackTrace();
            }
        }
    };


    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {

        tv = new TextView(this);                /* The view to post text to */
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        this.registerReceiver(this.mBatInfoReceiver, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

紙鸢 2024-10-23 10:29:24

首先,intent.getIntExtra("level", 0);不是百分比。 intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 1) 需要与 intent.getIntExtra(BatteryManager.EXTRA_SCALE, 1) 进行比较才能获得百分比。

其次,不要在主应用程序线程上执行网络 I/O,例如 BroadcastReceiveronReceive()

第三,您正在将电池电量与自身进行比较。您需要等待下一个 ACTION_BATTERY_CHANGED 广播才能找到新的电池电量。

First, intent.getIntExtra("level", 0); is not a percentage. intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 1) needs to be compared to intent.getIntExtra(BatteryManager.EXTRA_SCALE, 1) to get a percentage.

Second, do NOT do network I/O on the main application thread, such as onReceive() of a BroadcastReceiver.

Third, you are comparing the battery level with itself. You need to wait for the next ACTION_BATTERY_CHANGED broadcast to find out a new battery level.

悟红尘 2024-10-23 10:29:24

您不应该将应用程序逻辑放在 onReceive() 方法中。此方法应该只处理意图。否则,您可能会阻止向其他应用程序传递意图。

您的电池状态不会改变,因为您在此方法中阻塞时不会收到意图传递。传递的意图本身不会改变。只要电池状态发生变化,onReceive() 方法就会被调用——只要你不阻止它。

You are not supposed to put your application logic in the onReceive() method. This method should only process the intent. Otherwise you will probably block intent delivery to other apps.

Your battery state does not change because you don't get intents delivered while you are blocking in this method. The passed intent itself does not change. The onReceive() method will be called whenever the battery state changes - as long as you don't block it.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文