2014-07-13 17 views
5

Próbuję obejść problem z limitem czasu GCM, istnieje wiele wątków na ten temat, tutaj jest one w celach informacyjnych.Problemy z utrzymaniem Google Cloud Message przy życiu

Proponowane obejście polega na emisji pary intencji w odstępie krótszym niż limit czasu tcp.

Moja implementacja polega na utworzeniu klasy, która rozszerza klasę CountDownTimer i zatrzymuje instancję tej klasy w istniejącej usłudze. Ta wyprowadzona klasa uruchamia się ponownie po jej zakończeniu, a usługa jest oznaczona jako STICKY_START, więc po uruchomieniu, powinienem uważać, że powinna ona nadal nadawać intencje co 4 minuty, ale z jakiegoś powodu istnieją luki, gdy licznik nie nadaje zamiary i nadal tracę kontakt z serwerem GCM.

Dwie odpowiednie klasy znajdują się poniżej. Czy ktoś może wyjaśnić i zaoferować rozwiązanie, dlaczego ta strategia nie działa?

Stworzyłem klasę rozszerzającą CounDownTimer, która powinna nadawać intencje co 4 minuty.

public class GcmKeepAlive extends CountDownTimer { 

    protected CountDownTimer timer; 
    protected Context mContext; 
    protected Intent gTalkHeartBeatIntent; 
    protected Intent mcsHeartBeatIntent; 


    public GcmKeepAlive(Context context) { 
     super(4*60* 1000,4*60*1000); 
     mContext = context; 
     gTalkHeartBeatIntent = new Intent("com.google.android.intent.action.GTALK_HEARTBEAT"); 
     mcsHeartBeatIntent = new Intent("com.google.android.intent.action.MCS_HEARTBEAT"); 
     System.out.println("stariing heartbeat countdown timer"); 
     this.start(); 
    } 


    @Override 
    public void onTick(long millisUntilFinished) { 

    } 

    @Override 
    public void onFinish() { 
     System.out.println("sending heart beat to keep gcm alive"); 
     mContext.sendBroadcast(gTalkHeartBeatIntent); 
     mContext.sendBroadcast(mcsHeartBeatIntent); 
     this.start(); 

    } 

} 

tutaj jest usługa w mojej aplikacji, która posiada instancję klasy GcmKeepAlive

import android.app.Service; import android.content.Intent; import android.os.IBinder;

public class LocationMonitorService extends Service { 

    private DeviceLocationClient deviceLocationClient; 
    private GcmKeepAlive gcmKeepAlive; 

    @Override 
    public void onCreate() { 
     // TODO Auto-generated method stub 
     super.onCreate(); 
     System.out.println("creating the LocationMonitorService"); 
     deviceLocationClient = new DeviceLocationClient(this); 
     gcmKeepAlive = new GcmKeepAlive(this); 
    } 

    @Override 
    public int onStartCommand(Intent intent, int flags, int startId) { 
     // TODO Auto-generated method stub 
     System.out.println("inside service making request for location updates"); 
     deviceLocationClient.requestLLocationUpdates(); 
     gcmKeepAlive.start(); 
     return START_STICKY; 
    } 

    @Override 
    public IBinder onBind(Intent intent) { 
     // TODO Auto-generated method stub 
     return null; 
    } 


} 

Oto przykład luki widziany w logcat.

07-13 14:59:05.583 I/System.out(21651): sending heart beat to keep gcm alive 
07-13 15:03:05.640 I/System.out(21651): sending heart beat to keep gcm alive 
07-13 15:07:05.776 I/System.out(21651): sending heart beat to keep gcm alive 
07-13 15:11:05.922 I/System.out(21651): sending heart beat to keep gcm alive 
07-13 15:27:31.994 I/System.out(21651): sending heart beat to keep gcm alive 
+0

Tutaj przykład zastosowania ma znaczenie. Pozostajesz w aplikacji, gdy tak się dzieje, czy aplikacja jest zminimalizowana? System może zabić proces aplikacji, jeśli aplikacja nie jest na pierwszym planie, a START_STICKY nie będzie miało znaczenia, jeśli tak się stanie. Użyj usługi startForeground w usłudze http://developer.android.com/reference/android/app/Service.html # startForeground (int,% 20android.app.Notification), jeśli chcesz zagwarantować, że nie zostanie zabity. –

+0

@ErikZ Dzięki za komentarz. Rozwiązałem to chwilę, używając menedżera alarmów. Poniżej zamieściłem moje rozwiązanie, ale usługa polegająca na zabijaniu zdecydowanie zepsuła luki. – nPn

+0

Nie działa na moim notebooku Samsung Note 4, ale działa doskonale na wszystkich innych sprawdzanych urządzeniach (około 10 różnych urządzeń). – FunkSoulBrother

Odpowiedz

3

Naprawdę to rozwiązałem jakiś czas temu, ostatni komentarz Erika Z pozostawił mnie do opublikowania mojego rozwiązania.

Rozwiązałem to, tworząc alarm cykliczny, który wyzwala emisję, która tworzy i emituje intencje. Luki były spowodowane przez zabicie pierwotnej usługi, a następnie jej ponowne uruchomienie w wyniku flagi START_STICKY.

Oto różne części (pobierane z różnych plików)

było to potrzebne wstępnie KitKat przynajmniej, ja nie wiem, czy to jest nadal potrzebna, zakładam, że jest. Nie wyłączyłem go, aby potwierdzić.


Menedżer alarmów, zamiar i zamiar oczekujący.

AlarmManager alarmManager = (AlarmManager) Context.getSystemService(Context.ALARM_SERVICE); 

Intent gcmKeepAliveIntent = new Intent("com.gmail.npnster.ourlatitude.gcmKeepAlive"); 

PendingIntent gcmKeepAlivePendingIntent = PendingIntent.getBroadcast(mContext, 0, gcmKeepAliveIntent, PendingIntent.FLAG_CANCEL_CURRENT); 

alarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, 1000, 4*60*1000, gcmKeepAlivePendingIntent); 

Odbiornik transmisji:

public class GcmKeepAliveBroadcastReceiver extends BroadcastReceiver { 

    private GcmKeepAlive gcmKeepAlive; 

    @Override 
    public void onReceive(Context context, Intent intent) { 
     MyLog.p(this,"inside gcm keep alive receiver"); 
     gcmKeepAlive = new GcmKeepAlive(context); 
     gcmKeepAlive.broadcastIntents(); 

    } 

} 

podtrzymanie klasę, która wysyła Podtrzymywanie transmisje.

public class GcmKeepAlive { 

    protected Context mContext; 
    protected Intent gTalkHeartBeatIntent; 
    protected Intent mcsHeartBeatIntent; 

    public GcmKeepAlive(Context context) { 
     mContext = context; 
     gTalkHeartBeatIntent = new Intent(
       "com.google.android.intent.action.GTALK_HEARTBEAT"); 
     mcsHeartBeatIntent = new Intent(
       "com.google.android.intent.action.MCS_HEARTBEAT"); 
    } 

    public void broadcastIntents() { 
     MyLog.p(this,"sending heart beat to keep gcm alive"); 
     mContext.sendBroadcast(gTalkHeartBeatIntent); 
     mContext.sendBroadcast(mcsHeartBeatIntent); 
    } 

} 
+0

Czy to wszystko jest wymagane? Nie dostaję w mojej aplikacji loginu "wysyłanie bicia serca, by utrzymać gcm żywy"? – Apqu

+0

Potem znowu nie otrzymuję "wewnątrz gcm keep alive receiver" albo – Apqu

Powiązane problemy