使用 Intent 和 BroadcastReceiver 获取 Android 电池电量时的奇怪行为
我试图在运行 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
首先,intent.getIntExtra("level", 0);不是百分比。
intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 1)
需要与intent.getIntExtra(BatteryManager.EXTRA_SCALE, 1)
进行比较才能获得百分比。其次,不要在主应用程序线程上执行网络 I/O,例如
BroadcastReceiver
的onReceive()
。第三,您正在将电池电量与自身进行比较。您需要等待下一个
ACTION_BATTERY_CHANGED
广播才能找到新的电池电量。First,
intent.getIntExtra("level", 0);
is not a percentage.intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 1)
needs to be compared tointent.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 aBroadcastReceiver
.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.您不应该将应用程序逻辑放在 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.