Android,在设备处于睡眠模式时获得强度信号(PhoneStateListener)

Ily*_*dov 5 android sleep signal-strength android-wake-lock phone-state-listener

我有问题,经过一些搜索,我没有找到任何积极的解决方案.经过研究,我认为我的问题没有实施,但这个问题可能是我的最后一次机会.

我需要得到什么?

有应用程序获取有关移动网络强度信号的信息.我是这样做的 PhoneStateListener.当然它工作得很好但是当我的设备进入睡眠模式时,监听器不起作用:

https://code.google.com/p/android/issues/detail?id=10931 https://code.google.com/p/android/issues/detail?id=7592

WakeLock仅在设备因超时关闭的情况下解决问题.如果我按下硬电源按钮,我的设备也会进入睡眠模式.我们无法覆盖电源按钮操作.

我的目标是在启用设备时始终获得强度信号.什么模式无关紧要.它应该一直收集数据.

题:

有什么想法吗?怎么实现呢?有没有办法做到这一点,或者可能有一些黑客?欢迎所有解决方案.如果您有一些有用的经验,请分享一下.

感谢大家的帮助!!! 我希望,这个主题将获得有关此问题的完整信息.

Mr_*_*s_D 9

警报管理器是可行的方法 - 棘手的部分是在警报管理器接收器返回后保持电话唤醒.所以

  • 设置一个警报(注意你还应注册一个"On Boot completed"接收器,以便在重新启动后设置警报 - 你的警报在重新启动后仍然存在):

    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);
    
    Run Code Online (Sandbox Code Playgroud)
  • 接收它 - 接收器在onReceive()其中保存一个永不失败的WakeLock :

    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;
            }
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)

    如果你很幸运(yourRetrieveSignal()足够快),这将有效,否则你需要在你的接收器中有一个(Wakeful)IntentService模式.
    WakefulIntentService会照顾唤醒锁(如果你想避免依赖看看这里) -编辑:记住,你不能在一个意图服务定义监听器-看到这里.

如果接收者ANR在你身上,你必须尝试WakefulIntentService模式.在这两种情况下,你可以使用这个:

事实证明这是最困难的部分:

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

其中:

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

这是有效的代码(但不是优雅的顶峰 - 欢迎评论/更正).不要忘记在清单中注册您的服务并获取权限.
编辑2013.07.23:我没有使用onReceive- 如果你使用它,它将是ANR - 这是工作代码,如果你使用WakefulIntentService在onReceive你打电话SignalListenerService.