5

Sorunum var ve aradıktan sonra herhangi bir olumlu çözüm bulamadım. Araştırmadan sonra, benim sorunum için bir uygulama olmadığını düşündüm ama bu soru benim son şansım olabilir.Android, uyku modunda cihazda güç sinyali almak (PhoneStateListener)

Almak için neye ihtiyacım var?

Mobil ağ gücü sinyali hakkında bilgi alan uygulama var. PhoneStateListener ile yapıyorum. Tabii o inşaat büyük ama benim Cihaz modunu uyku moduna geçtiğinde, dinleyici çalışmıyor: Cihazın zaman aşımı tarafından kapatmak eğer

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

WakeLock, sadece durumda sorunu çözer. Sabit güç düğmesine bastığımda, cihazım da uyku moduna geçer. Güç düğmesi eylemini geçersiz kılabiliriz.

Amacım, aygıtım her zaman etkinleştirildiğinde güç sinyali alıyor. Hangi modun önemi yoktur. Tüm zaman veri toplamalı.

Soru:

herhangi bir fikir var mı? Bunu nasıl başarabilirim? Bunu yapmanın yolları var mı yoksa bazı hackler var mı? Bütün çözümler hoş geldiniz. Bazı yararlı deneyimleriniz varsa, lütfen bunu paylaşın.

Yardımlarınız için herkese teşekkürler! Umarım, bu konu bu sorun hakkında tam bilgi alacak.

+1

"Sabit güç düğmesine bastığımda, aygıtım da uyku moduna geçer. Güç düğmesi eylemini geçersiz kılabiliriz." - "WakeLock", güç düğmesinden etkilenmez. – CommonsWare

+0

Neden bir hizmet kullanmıyorsunuz? –

+0

, uyku modunda da çalışmıyor. –

cevap

9

Alarm yöneticisi gitmek yoludur - Zor kısmı alarmı yöneticisi alıcı döndükten sonra uyanık telefon tutmaktır. Yani

  • kurulumu bir alarm (ayrıca bir yeniden başlatma sonrasında alarm kurmak için bir "Boot üzerinde tamamlandı" alıcıyı kayıt gerektiğini fark - Alarmlarınızı yeniden başlatma hayatta değildir):

    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); 
    
  • bunu almak - alıcı onun onReceive() asla başarısız bir Uyandırma kilidi tutan: Eğer (yourRetrieveSignal() yeterince hızlı) şanslı iseniz

    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; 
         } 
        } 
    } 
    

    bu çalışacaktır, OTH Aksi halde, alıcınızda bir (Wakeful) IntentService desenine ihtiyacınız olacaktır.
    WakefulIntentServiceWakefulIntentService uyandırma kilidine dikkat edecektir (bağımlılıktan kaçınmak istiyorsanız here) - DÜZENLEME: Dinleyicileri bir niyet hizmetinde tanımlayamazsınız - bkz. here.

size alıcı ANR'ler, sen WakefulIntentService desen denemek varsa.Her iki durumda da sen this kullanabilirsiniz:

Bu aslında en zor kısmı olduğunu kanıtladı:

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; 
    } 
} 

burada: Bu (kod çalışıyor

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; 
    } 
} 

ama kuşkusuz zerafet değil zirvesi - yorumlar/düzeltmeler hoş geldiniz). Hizmetlerinizi bildirimde kaydetmeyi ve izinleri almayı unutmayın.
DÜZENLEME 2013/07/23: kullandığım vermedi onReceive - Eğer o olacak kullanırsanız ANR - Eğer onReceive bir WakefulIntentService kullanmak ve orada size SignalListenerService ararsanız bu çalışmaktadır kodu.

+1

Sadece Android 2.1 ve üstü sürümleri destekliyorsanız, 'PhoneStateListener.LISTEN_SIGNAL_STRENGTH' yerine 'PhoneStateListener.LISTEN_SIGNAL_STRENGTHS' adresini kullanmanız gerekir. – ChuongPham

1

PhoneStateListener konusundaki anlayışımdan, uygulama CPU uyku modundayken bunu yapamazsınız. Cihazı, pil ömrünü mahvedecek şekilde uyanık tutabilirsiniz. Alternatif olarak, cihazı aralıklarla uyandırmak için bir alarm kullanabilirsiniz (bkz. AlarmManager), böylece verileri toplayabilirsiniz (pil ömrünü hala etkiler).

Some samples of using AlarmManager can be found here

+0

Cihazı nasıl uyanık tutabilirim? Donanım güç düğmesine basıldıktan sonra cihazım zaten uyku moduna geçiyor. Ya da bir şekilde bunu başarabilir miyim? Ana sorun güç düğmesi ile durumdur. –

+0

Sonra AlarmManager kullanmak istediğiniz gibi geliyor. :) AlarmManger, CPU'yu uyandırmanıza ve her X dakikada/saniye bir kod parçası yürütmenize izin verecektir. – AndersNS

+0

Eğer AlarmManager kullanıyorsanız, akü suyunu etkilemezsiniz. Bunu uygulamanızda uygularsanız, kullanıcılara akülerinin biraz boşaltabileceğini açıklamanız gerekir. – ChuongPham

0

Android sayısının 10931 olası çözümlerinden biri, ekran kapandıktan sonra 'telefon' işleminin amacını android.intent.action.SCREEN_ON göndermektir.

  1. oluşturma ve ekran

    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. SCREEN_ON niyet telefon sürecini sadece gönder kapandığında bildirimleri dinlemek için BroadcastReceiver kayıt olun.

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

telefon süreç hücre konuma güncellemeleri göndermeye devam edeceğini bu niyeti aldıktan sonra.

Kök ayrıcalıkları gerekli.

Bu çözüm biraz bulanık, tehlikeli ve tüm telefonlarda çalışmaz. Daha yüksek güç tüketimine yol açabilir, ancak ekranı açık tuttuğunuzdan çok daha fazla değil.

İlgili konular