5

私には問題があり、何らかの検索の後に私は肯定的な解決策を見いだせませんでした。 研究の後、私の問題のための実装がないという考えがありますが、この質問は私の最後のチャンスかもしれません。デバイスがスリープモードに入っている間に、強度信号(PhoneStateListener)を取得しています

取得する必要はありますか?

モバイルネットワークの強度信号に関する情報を取得するアプリケーションがあります。私は PhoneStateListenerでそれを行う。もちろん、それは素晴らしい作品が、私のデバイスがスリープモードになったとき、リスナーは動作しません:デバイスは、タイムアウトではオフに切り替えた場合

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

WakeLockは、唯一のケースで問題を解決します。私がハード電源ボタンを押すと、私のデバイスはスリープモードにもなります。電源ボタン操作を無効にすることはできません。

私の目標は、自分のデバイスが有効になっているときにいつも強度信号を得ることです。どのモードかは関係ありません。常にデータを収集する必要があります。

質問:

が任意のアイデアがありますか?それを達成する方法?これを行う方法はありますか、またはいくつかのハッキングがあるかもしれませんか?すべての解決策は大歓迎です。便利な経験があれば、これを共有してください。

ありがとうございました!私は、このトピックがこの問題に関する完全な情報を得ることを願っています。

+1

「ハードパワーボタンを押すと、デバイスもスリープモードになります。電源ボタンの操作を無効にすることはできません。」 - 「WakeLock」は電源ボタンの影響を受けません。 – CommonsWare

+0

サービスを利用してみませんか? –

+0

スリープモードでも動作しません。 –

答えて

9

アラームマネージャが移動するための方法である - トリッキーな部分は、アラームマネージャレシーバ戻った後目を覚まし携帯電話を維持することです。

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()で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; 
           } 
          } 
      } 
      

      を運がよければ、OTHこれは動作します(yourRetrieveSignalは()十分に速いです)あなたの受信機にIntentService(Wakeful)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; 
        } 
    } 
    

    これは、コード(ただし、確かに優雅さの頂点に取り組んでいます - コメント/修正を歓迎します)。マニフェストにサービスを登録して権限を取得することを忘れないでください。
    EDIT 2013年7月23日:私はonReceiveを使用していない - あなたはそれを使用する場合には、ANRます - あなたはonReceiveでWakefulIntentServiceを使用し、そこにあなたがSignalListenerServiceを呼び出す場合、これはコードを働いています。

  • +1

    Android 2.1以上しかサポートしていない場合は、 'PhoneStateListener.LISTEN_SIGNAL_STRENGTH'の代わりに' PhoneStateListener.LISTEN_SIGNAL_STRENGTHS'を使う必要があります。 – ChuongPham

    1

    私はPhoneStateListenerを理解しているので、アプリケーションCPUがスリープモードに入っている間はこれを行うことはできません。デバイスを目覚めさせておくと、バッテリの寿命が損なわれます。あるいは、アラームを使用して(AlarmManagerを参照)、一定間隔でデバイスを復帰させることができるため、データを収集することができます(バッテリの寿命に影響を与えます)。

    Some samples of using AlarmManager can be found here

    +0

    どうすればデバイスを起床させることができますか?ハードウェアの電源ボタンを押すと、デバイスはスリープモードになります。それとも私は何とかそれを達成することができますか?主な問題は電源ボタンの場合です。 –

    +0

    その後、AlarmManagerを使いたいと思うように聞こえます。 :) AlarmMangerは、CPUをスリープ状態にし、X分/秒ごとにコードを実行することを可能にします。 – AndersNS

    +0

    AlarmManagerを使用している場合でも、バッテリジュースに影響を与えます。私はあなたのアプリでこれを実装する場合は、あなたのバッテリーが少し流出するかもしれないことをユーザーに説明する必要がありますね。 – ChuongPham

    1

    CommonsWareのロケーションポーリングの例は、電話機をスリープ状態にして再びスリープ状態にすることについて本当に良いことです。 https://github.com/commonsguy/cwac-locpoll

    0

    アンドロイド問題10931の回避策の1つは、画面がオフになった後にandroid.intent.action.SCREEN_ONインテントを「電話」プロセスに送信することです。

    1. 画面は電話のみプロセスにSCREEN_ON意図を送る

      start(Context context) { 
          IntentFilter filter = new IntentFilter(); 
          filter.addAction(Intent.ACTION_SCREEN_OFF); 
          context.registerReceiver(mScreenReceiver, filter); 
      } 
      
      final BroadcastReceiver mScreenReceiver = new BroadcastReceiver() { 
          @Override 
          public void onReceive(final Context context, final Intent intent) { 
           if (Intent.ACTION_SCREEN_OFF.equals(intent.getAction())) { 
            Log.v(LOGTAG, "Screen is off. Running workaround"); 
            new Thread(mReportScreenIsOnRunnable).start(); 
           } 
          } 
      }; 
      
    2. をオフにしたときに通知をリッスンするBroadcastReceiverを作成して登録します。

      public final Runnable mReportScreenIsOnRunnable = new Runnable() { 
          @Override 
          public void run() { 
           try { 
            Thread.sleep(100); 
           } catch (InterruptedException e) { 
            e.printStackTrace(); 
           } 
           try { 
            Runtime.getRuntime().exec(new String[] { "su", "-c", 
              "am broadcast -a android.intent.action.SCREEN_ON com.android.phone" }); 
           } catch (IOException e) { 
            e.printStackTrace(); 
           } 
          } 
      }; 
      

    電話のプロセスは、セルの場所に 更新情報の送信を再開だろう、この意図を受け取った後。

    ルート特権が必要です。

    このソリューションは、少しハッキリで危険で、すべての携帯電話では機能しません。それはより高い電力消費につながりますが、画面をオンにしておくよりもそれほど多くはありません。

    関連する問題