Состояние батареи без активности только с использованием широковещательного приемника

Привет, я делаю приложение, которое использует только вещательный приемник. Он служит трем целям. Когда получено SMS, содержащее определенный код, он отправляет данные GPS. Другой код отправляет данные датчика. Никаких проблем до этого момента. Но для батареи я не могу этого сделать из-за функции registerreceiver(). Поскольку я не использую действие и метод onCreate, могу ли я отправлять данные о батарее при получении SMS?

Когда я попытался настроить это в методе onreceive() широковещательного приемника, мое приложение вылетает. Я искал везде, где создается активность. Я хочу сделать все только внутри вещательного приемника.

Мой код выглядит следующим образом:

public class MyPhoneReceiver extends BroadcastReceiver{
double current_lat,current_lng;
LocationManager mlocManager;
LocationListener mlocListener;
//addition//////////////////////////////
SensorManager mSensorManager;

Sensor mAccelerometer;  
////////////////////

private static final String SMS_RECEIVED = "android.provider.Telephony.SMS_RECEIVED";
private static final String TAG = "SMSBroadcastReceiver";

@Override
public void onReceive(Context context, Intent intent) {
Log.i(TAG, "Intent recieved: rama" + intent.getAction());


Bundle bundle = intent.getExtras();
if (bundle != null) {
Object[] pdus = (Object[]) bundle.get("pdus");
final SmsMessage[] messages = new SmsMessage[pdus.length];
for (int i = 0; i < pdus.length; i++)
messages[i] = SmsMessage.createFromPdu((byte[]) pdus[i]);
if (messages.length > -1) {
String messagebody=messages[0].getMessageBody();
Log.i(TAG, "Message recieved: in message receied " + messages[0].getMessageBody());
if(messagebody.toString().matches("HDPK GPS"))
{
Log.i(TAG, "Message recieved: HDPK RECEIVED " + messages[0].getMessageBody());
mlocManager=(LocationManager)context.getSystemService(context.LOCATION_SERVICE);
mlocManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,1000,1,new MyLocationListener());
}
if(messagebody.toString().matches("HDPK SENS"))
{
Log.i(TAG, "Message recieved: in msensior ");
mSensorManager = (SensorManager)context.getSystemService(Context.SENSOR_SERVICE);
mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
mSensorManager.registerListener(new MySensorListener(), mAccelerometer, SensorManager.SENSOR_DELAY_NORMAL);
}
if(messagebody.toString().matches("HDPK BAT"))
{
Log.i(TAG, "Message recieved: in battery ");
IntentFilter filter=new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
Intent batt=context.registerReceiver(null,filter);
int level = batt.getIntExtra("EXTRA_LEVEL", 0);
Log.i(TAG, "Message recieved: in battery level is "+level);
SmsManager sender=SmsManager.getDefault();
sender.sendTextMessage("9762281814", null, "Level is"+level, null,null);
}



}
}
}

public class MySensorListener implements SensorEventListener
{
public void onAccuracyChanged(Sensor arg0, int arg1) {
// TODO Auto-generated method stub

}

public void onSensorChanged(SensorEvent event) {
// TODO Auto-generated method stub
Log.i(TAG, "Message recieved: in msensior event change ");
float x = event.values[0];

float y = event.values[1];

float z = event.values[2];
SmsManager sender=SmsManager.getDefault();
String Text="x :"+x+" Y:"+y+ " Z:"+z;
sender.sendTextMessage("9762281814",null, Text, null, null);
mSensorManager.unregisterListener(this);
}

}

public class MyLocationListener implements LocationListener{

public void onLocationChanged(Location location) {
// TODO Auto-generated method stub
current_lat=location.getLatitude();
current_lng=location.getLongitude();
SmsManager sender=SmsManager.getDefault();
String Text = "My Location is : Latitude ->" +current_lat+" Longitude ->" + current_lng;
sender.sendTextMessage("9762281814", null, Text, null, null);

mlocManager.removeUpdates(this);

}

public void onProviderDisabled(String provider) {
// TODO Auto-generated method stub

}

public void onProviderEnabled(String provider) {
// TODO Auto-generated method stub

}

public void onStatusChanged(String provider, int status, Bundle extras) {
// TODO Auto-generated method stub

}


}

}

person harsh8888    schedule 07.06.2012    source источник


Ответы (1)


Попробуйте использовать приложение Context вместо приемника вещания Context при использовании registerReceiver() для замены липкой батареи Intent. Как это:

IntentFilter filter=new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
Intent batt=context.getApplicationContext().registerReceiver(null,filter);
int level = 99; // Default to some unknown/wild value
// registerReceiver method call could return null, so check that!
if (batt != null) {
    level = batt.getIntExtra(BatteryManager.EXTRA_LEVEL, 0);
}
person David Wasser    schedule 08.06.2012
comment
Я попробовал ваш код, но он не работает, нужно ли мне для этого давать какие-либо разрешения? - person Lucifer; 24.09.2012
comment
Нет, для этого не нужно никаких разрешений. Что значит не работает? Что возвращается в результате вызова registerReceiver()? Есть ли ошибки в логарифме? - person David Wasser; 24.09.2012
comment
Да, теперь у меня все работает, но в моем случае я использую level = batt.getIntExtra("level", 0);, EXTRA_LEVEL не работает, мое требование состояло в том, чтобы проверить уровень заряда батареи от BroadcastReceiver, другое действие успешно работает, спасибо за вашу помощь :) - person Lucifer; 24.09.2012
comment
Рад, что теперь работает. Если этот ответ был полезен, вы можете принять его, нажав зеленую галочку. - person David Wasser; 24.09.2012
comment
Моя вина. Прости за это. Мой пример кода был ошибочным. Я отредактировал код примера. - person David Wasser; 24.09.2012
comment
@ Люцифер А, верно. Извините, не видел этого. Я обновил свой ответ с правильным параметром. Должно быть BatteryManager.EXTRA_LEVEL вместо "EXTRA_LEVEL". - person David Wasser; 24.09.2012
comment
еще раз извините, но BatteryManager.EXTRA_LEVEL не работает, выдает ошибку, в классе BatteryManager нет константы EXTRA_LEVEL, но, как я уже сказал, уровень работает нормально. - person Lucifer; 24.09.2012
comment
Константа BatteryManager.EXTRA_LEVEL определяется на уровне API 5 (Android 2.0). Какой SDK вы используете? - person David Wasser; 24.09.2012
comment
о, хорошо, я работаю над Android 1.6, очень простой. Я хочу использовать только более низкую версию, чтобы мое приложение могло работать на многих устройствах. Спасибо за эту полезную информацию, я думал, что Константа была удалена, потому что я так много пытался ее реализовать, а также нашел в сети во многих местах один и тот же код. - person Lucifer; 24.09.2012
comment
Спасибо за этот ответ! Я целую вечность пытался понять, как получить уровень заряда батареи в моем BroadcastReceiver, не совсем уверен, почему использование контекста приложения вместо этого должно иметь значение, но если это работает, я не буду жаловаться! Но на всякий случай, может ли кто-нибудь резюмировать, почему использование контекста приложения вместо того, который предоставляется методу onReceive(), действительно работает? - person Haravikk; 27.08.2013
comment
@Haravikk это легко. Context, которое вы получаете в onReceive(), недолговечно. Он живет только до тех пор, пока метод onReceive() не завершится, а затем исчезает. В связи с этим есть определенные вещи, которые вам не разрешено делать с этим Context. Как правило, вам не разрешено выполнять какие-либо асинхронные операции с этим Context, потому что он, вероятно, не будет существовать достаточно долго для завершения асинхронных операций. Если вы посмотрите на исходный код Android, вы обнаружите, что Context, которое вы получаете в onReceive(), на самом деле является ReceiverRestrictedContext. - person David Wasser; 28.08.2013
comment
@Haravikk ReceiverRestrictedContext выдает ReceiverCallNotAllowedException, если вы пытаетесь вызвать registerReceiver(), потому что, вообще говоря, registerReceiver() — это асинхронный вызов. Интересно, что, поскольку вы делаете этот вызов, указав null для параметра BroadcastReceiver, на самом деле это синхронный вызов, но я думаю, что разработчики Android забыли об этом ;-) - person David Wasser; 28.08.2013