報警經理是要走的路 - 棘手的部分是要保持電話報警經理接收器返回後清醒。所以
設置一個報警(請注意,你也應該註冊一個「引導完成」接收器設置在重啓後報警 - 你報警沒有生存重啓):
Intent monitoringIntent = new Intent(context, YourReceiver.class);
monitoringIntent.setAction("your action");
PendingIntent pi = PendingIntent.getBroadcast(context, NOT_USED,
monitoringIntent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager am = (AlarmManager)
context.getSystemService(Context.ALARM_SERVICE);
// here is the alarm set up
am.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
SystemClock.elapsedRealtime() + INITIAL_DELAY,
INTERVAL_BETWEEN_ALARMS, pi);
接受它 - 接收器在其onReceive()
,從來沒有失敗持有喚醒鎖定:
public abstract class YourReceiver extends BroadcastReceiver {
@Override
final public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
if ("your action".equals(action)) {
// monitoring - got broadcast from ALARM
try {
d("SS : " + new Signal().getSignalStrength(context));
} catch (InterruptedException e) {
e.printStackTrace();
}
// Actu8ally the lines above will ANR
// I did it with WakefulIntentService :
// WakefulIntentService.sendWakefulWork(
// context, YourWakefulService.class);
// Will be posting it asap
} else {
w("Received bogus intent : " + intent);
return;
}
}
}
如果你是幸運的(yourRetrieveSignal()是足夠快),這將工作,OTH否則,您需要在接收器中使用(喚醒)IntentService模式。
WakefulIntentService將照顧喚醒鎖(如果你想避免依賴看看here) - 編輯:請記住,你不能在意圖服務中定義監聽者 - 請參閱here。
如果接收者ANR在你身上,你必須嘗試WakefulIntentService模式。在這兩種情況下,你可以使用this:
這實際上證明是最困難的部分:
class Signal {
static volatile CountDownLatch latch; //volatile is an overkill quite probably
static int asu;
private final static String TAG = Signal.class.getName();
int getSignalStrength(Context ctx) throws InterruptedException {
Intent i = new Intent(TAG + ".SIGNAL_ACTION", Uri.EMPTY, ctx,
SignalListenerService.class);
latch = new CountDownLatch(1);
asu = -1;
ctx.startService(i);
Log.d(TAG, "I wait");
latch.await();
ctx.stopService(i);
return asu;
}
}
其中:
public class SignalListenerService extends Service {
private TelephonyManager Tel;
private SignalListener listener;
private final static String TAG = SignalListenerService.class.getName();
private static class SignalListener extends PhoneStateListener {
private volatile CountDownLatch latch;
private SignalListener(CountDownLatch la) {
Log.w(this.getClass().getName(), "CSTOR");
this.latch = la;
}
@Override
public void onSignalStrengthChanged(int asu) {
Signal.asu = asu;
latch.countDown();
}
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.w(TAG, "Received : " + intent.getAction());
Tel = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
listener = new SignalListener(Signal.latch);
@SuppressWarnings("deprecation")
final int listenSs = PhoneStateListener.LISTEN_SIGNAL_STRENGTH;
Tel.listen(listener, listenSs);
return START_STICKY;
}
@Override
public void onDestroy() {
Log.w(TAG, "onDestroy");
Tel.listen(listener, PhoneStateListener.LISTEN_NONE);
super.onDestroy();
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
}
這是工作的代碼(但不承認優雅的巔峯之作 - 意見/更正歡迎)。不要忘記在清單中註冊您的服務並獲取權限。
編輯2013年7月23日:我沒有使用onReceive
- 如果你使用它它會ANR - 如果你在onReceive
使用WakefulIntentService,並在那裏你調用SignalListenerService
這是工作的代碼。
「如果我用力按壓電源鍵,我的設備獲得的休眠模式以及我們不能忽略電源按鈕的動作。」 - 「WakeLock」不受電源按鈕的影響。 – CommonsWare
爲什麼不使用服務? –
它在睡眠模式下也不起作用。 –