Autore Topic: Continuo Resume Activity chiamata dall'AlarmManager  (Letto 1054 volte)

Offline Grifith

  • Utente junior
  • **
  • Post: 56
  • Respect: +1
    • Mostra profilo
    • La mia prima applicazione...
Continuo Resume Activity chiamata dall'AlarmManager
« il: 16 Febbraio 2012, 16:27:40 CET »
0
Buonasera.

Nella solita applicazione che sto creando, avevo il problema della gestione di una connessione continua in background e in fase di standby.
Tale problematica è stata risolta richiamando una Activity tramite la gestione degli Alarm.
E fin qui, tutto ok. Su alcune device funziona, su altri pare di no... Ma questo è poco problematico.

Il problema, se così si può dire, accade nel momento in cui l'applicazione è in background e magari sto facendo altro. Ovvero, dato che il timeout dell'allarme è ogni 30 secondi, accade che ogni trenta secondi mi viene tirata nuovamente su l'applicazione, facendomela comparire a video.

Esiste un modo per evitare tutto questo?

Premetto che nel codice ho utilizzato unicamente i metodi OnCreate dell'activity, sia per l'activity chiamante, sia per quella chiamata.

Grazie mille per l'aiuto.

Offline undead

  • Utente senior
  • ****
  • Post: 666
  • Respect: +113
    • Mostra profilo
  • Dispositivo Android:
    Samsung Galaxy S6
  • Play Store ID:
    DrKappa
  • Sistema operativo:
    Windows 10 64-bit, Windows 8.1 64-bit
Re:Continuo Resume Activity chiamata dall'AlarmManager
« Risposta #1 il: 16 Febbraio 2012, 16:35:28 CET »
0
Usare un Service invece di una Activity.  :-)

Offline Grifith

  • Utente junior
  • **
  • Post: 56
  • Respect: +1
    • Mostra profilo
    • La mia prima applicazione...
Re:Continuo Resume Activity chiamata dall'AlarmManager
« Risposta #2 il: 16 Febbraio 2012, 16:38:53 CET »
0
Usare un Service invece di una Activity.  :-)

Ovvero? Spiegati meglio, per favore...

Offline undead

  • Utente senior
  • ****
  • Post: 666
  • Respect: +113
    • Mostra profilo
  • Dispositivo Android:
    Samsung Galaxy S6
  • Play Store ID:
    DrKappa
  • Sistema operativo:
    Windows 10 64-bit, Windows 8.1 64-bit
Re:Continuo Resume Activity chiamata dall'AlarmManager
« Risposta #3 il: 16 Febbraio 2012, 16:49:23 CET »
+1
Il problema è che viene fatta partire la tua activity che mi pare di capire abbia una view e tutto il resto.

Se dalla tua activity crei un servizio (Service) puoi fare in modo che l'allarme chiami il servizio e non l'activity.
Il servizio quando viene chiamato fa il suo lavoro senza inteferire con quello che stai facendo.

http://developer.android.com/reference/android/app/Service.html

Qui trovi un tutorial:

http://www.anddev.it/index.php/topic,870.0.html

E qui uno dei molti esempi che puoi trovare "googlando":
http://www.vogella.de/articles/AndroidServices/article.html

 :-)

Offline Grifith

  • Utente junior
  • **
  • Post: 56
  • Respect: +1
    • Mostra profilo
    • La mia prima applicazione...
Re:Continuo Resume Activity chiamata dall'AlarmManager
« Risposta #4 il: 17 Febbraio 2012, 11:46:28 CET »
0
Il problema è che viene fatta partire la tua activity che mi pare di capire abbia una view e tutto il resto.

Se dalla tua activity crei un servizio (Service) puoi fare in modo che l'allarme chiami il servizio e non l'activity.
Il servizio quando viene chiamato fa il suo lavoro senza inteferire con quello che stai facendo.

http://developer.android.com/reference/android/app/Service.html

Qui trovi un tutorial:

http://www.anddev.it/index.php/topic,870.0.html

E qui uno dei molti esempi che puoi trovare "googlando":
http://www.vogella.de/articles/AndroidServices/article.html

 :-)

Grazie per il suggerimento. Sto dando un occhiata su come fare, ma non riesco a far partire il Service dal mio AlarmManager... Il codice che ho scritto è questo:

Class Polling extends Activity, classe che deve chiamare il mio service...
Codice (Java): [Seleziona]
am = (AlarmManager) getSystemService(ALARM_SERVICE);
pollingServiceIntent = new Intent(getApplicationContext(),PollingReceiver.class);
pollingService = PendingIntent.getService(getApplicationContext(), 0, pollingServiceIntent, PendingIntent.FLAG_UPDATE_CURRENT);
am.setRepeating(AlarmManager.RTC, System.currentTimeMillis(), 30000, pollingService);

PollingReceiver è un receiver... Avevo letto che era necessario per far partire il service...
Codice (Java): [Seleziona]
public class PollingReceiver extends BroadcastReceiver {

        /* (non-Javadoc)
         * @see android.content.BroadcastReceiver#onReceive(android.content.Context, android.content.Intent)
         */

        @Override
        public void onReceive(Context arg0, Intent arg1) {
                // TODO Auto-generated method stub
                Intent pollingServiceIntent = new Intent(arg0, PollingService.class);
                arg0.startService(pollingServiceIntent);
        }

}

E poi c'è la classe PollingService, che è il servizio con il suo metodo onStart():
Codice (Java): [Seleziona]
public void onStart(Intent intent, int startId) {
                // TODO Auto-generated method stub
                super.onStart(intent, startId);
               
                try{
                        Response response = Connections.pollingResponse(Login.authCode);
                       
                        if(response == null || response.getCode()==null ||
                                        response.getCode().equals("1") || response.getCode().equals("2")){
                               
                               
        ....

Il manifest è così realizzato: (Omettendo tutte le activity inserite...)
Codice (XML): [Seleziona]
 <service android:enabled="true" android:name="PollingService" />    
                <receiver android:name="PollingReceiver">
                <intent-filter>
                    <action android:name="android.intent.action.BOOT_COMPLETED">
                    </action>
                </intent-filter>
        </receiver>

Ma, in questo modo, non viene avviato il servizio. Se invece non uso il receaver, ma avvio direttametne il service, in questo modo:

Codice (Java): [Seleziona]
pollingServiceIntent = new Intent(getApplicationContext(),PollingService.class);
pollingService = PendingIntent.getService(getApplicationContext(), 0, pollingServiceIntent, PendingIntent.FLAG_UPDATE_CURRENT);    

esso parte. Ma sorge un problema sullo start delle activity. Mi viene sparata un eccezione nel momento in cui arrivo a queste righe:
Codice (Java): [Seleziona]
polling = new Intent(getApplicationContext(), PollingResponse2.class);
startActivity(polling);
che dice: android.util.AndroidRuntimeException: Calling startActivity() from outside of an Activity  context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want?

Da che dipende questo errore? [Risolto! Basterebbe inserire il flag Intent.FLAG_ACTIVITY_NEW_TASK alla intent... Me lo dice anche lui!!!]
Ma soprattutto, come mai il receiver non mi si fila di pezzo?
« Ultima modifica: 17 Febbraio 2012, 11:48:25 CET da Grifith »

Offline undead

  • Utente senior
  • ****
  • Post: 666
  • Respect: +113
    • Mostra profilo
  • Dispositivo Android:
    Samsung Galaxy S6
  • Play Store ID:
    DrKappa
  • Sistema operativo:
    Windows 10 64-bit, Windows 8.1 64-bit
Re:Continuo Resume Activity chiamata dall'AlarmManager
« Risposta #5 il: 17 Febbraio 2012, 11:54:43 CET »
0
Il receiver non ti si fila perchè il service non ha una onStart (scelta forse un pò discutibile... ), bensì onStartCommand(Intent, int, int).
Prova a utilizzare la onStartCommand e non la onStart... chiamando startService dal broadcastreceiver dovrebbe essere tutto ok. ;-)

Offline Grifith

  • Utente junior
  • **
  • Post: 56
  • Respect: +1
    • Mostra profilo
    • La mia prima applicazione...
Re:Continuo Resume Activity chiamata dall'AlarmManager
« Risposta #6 il: 17 Febbraio 2012, 14:34:29 CET »
0
Il receiver non ti si fila perchè il service non ha una onStart (scelta forse un pò discutibile... ), bensì onStartCommand(Intent, int, int).
Prova a utilizzare la onStartCommand e non la onStart... chiamando startService dal broadcastreceiver dovrebbe essere tutto ok. ;-)

A me, stranamente, non compare il metodo onStarCommand... Ma si vede che dipende dalla versione (io sto utilizzando la 1.6).
Tale metodo, è presente anche nelle versioni successive oppure è stato completamente eliminato?

Offline undead

  • Utente senior
  • ****
  • Post: 666
  • Respect: +113
    • Mostra profilo
  • Dispositivo Android:
    Samsung Galaxy S6
  • Play Store ID:
    DrKappa
  • Sistema operativo:
    Windows 10 64-bit, Windows 8.1 64-bit
Re:Continuo Resume Activity chiamata dall'AlarmManager
« Risposta #7 il: 17 Febbraio 2012, 14:38:55 CET »
0
Eh si ci sono molte differenze!

Qui trovi un post riguardo alle queste differenze a partire dalla 2.0!

http://android-developers.blogspot.com/2010/02/service-api-changes-starting-with.html

Offline Grifith

  • Utente junior
  • **
  • Post: 56
  • Respect: +1
    • Mostra profilo
    • La mia prima applicazione...
Re:Continuo Resume Activity chiamata dall'AlarmManager
« Risposta #8 il: 17 Febbraio 2012, 15:00:21 CET »
0
Eh si ci sono molte differenze!

Qui trovi un post riguardo alle queste differenze a partire dalla 2.0!

http://android-developers.blogspot.com/2010/02/service-api-changes-starting-with.html


Ecchecca!
Perdonami per il disturbo, ma ho qualche dubbio sul return dello startOnCommand. O meglio, sulla differenza tra START_STICKY, START_NOT_STICKY, START_REDELIVER_INTENT.

Offline undead

  • Utente senior
  • ****
  • Post: 666
  • Respect: +113
    • Mostra profilo
  • Dispositivo Android:
    Samsung Galaxy S6
  • Play Store ID:
    DrKappa
  • Sistema operativo:
    Windows 10 64-bit, Windows 8.1 64-bit
Re:Continuo Resume Activity chiamata dall'AlarmManager
« Risposta #9 il: 17 Febbraio 2012, 15:19:31 CET »
+1
Puoi utilizzare la modalità compatibile 1.6 START_STICKY_COMPATIBILITY.

Comunque traducendo alla meno peggio nella 1.6 poteva succedere questo:

1- lanciavi un servizio con startservice
2- il servizio entrava in oncreate e onstart e poi creava un thread
3- il servizio viene terminato perchè c'è poca memoria
4- il servizio viene fatto ripartire quando si libera memoria ma la onstart non viene chiamata

In pratica il problema è che il servizio viene fatto ripartire senza un intent e quindi per non passare un intent NULL e magari trovarsi di fronte a crash hanno pensato (pensato male) di non chiamare la onstart.

Il comportamento appena descritto è quello che accade in modalità compatibile.

Dalla 2.0 hanno cambiato il sistema facendo in modo che in una situazione del genere si possa passare un intent NULL (START_STICKY) o non si ripristini il servizio automaticamente (START_NOT_STICKY).

START_REDELIVER_INTENT è più complicata, in pratica funziona come START_NOT_STICKY ma se tu non chiami la stopSelf() per un certo intent l'intent viene reinviato (in pratica serve se non vuoi che venga fatto ripartire ma al tempo stesso vuoi completare un certo lavoro).

Dipende da quello che devi fare.

 ;-)

Offline Grifith

  • Utente junior
  • **
  • Post: 56
  • Respect: +1
    • Mostra profilo
    • La mia prima applicazione...
Re:Continuo Resume Activity chiamata dall'AlarmManager
« Risposta #10 il: 17 Febbraio 2012, 15:33:24 CET »
0
Puoi utilizzare la modalità compatibile 1.6 START_STICKY_COMPATIBILITY.

Comunque traducendo alla meno peggio nella 1.6 poteva succedere questo:

1- lanciavi un servizio con startservice
2- il servizio entrava in oncreate e onstart e poi creava un thread
3- il servizio viene terminato perchè c'è poca memoria
4- il servizio viene fatto ripartire quando si libera memoria ma la onstart non viene chiamata

In pratica il problema è che il servizio viene fatto ripartire senza un intent e quindi per non passare un intent NULL e magari trovarsi di fronte a crash hanno pensato (pensato male) di non chiamare la onstart.

Il comportamento appena descritto è quello che accade in modalità compatibile.

Dalla 2.0 hanno cambiato il sistema facendo in modo che in una situazione del genere si possa passare un intent NULL (START_STICKY) o non si ripristini il servizio automaticamente (START_NOT_STICKY).

START_REDELIVER_INTENT è più complicata, in pratica funziona come START_NOT_STICKY ma se tu non chiami la stopSelf() per un certo intent l'intent viene reinviato (in pratica serve se non vuoi che venga fatto ripartire ma al tempo stesso vuoi completare un certo lavoro).

Dipende da quello che devi fare.

 ;-)

Ho capito. Grazie mille per la spiegazione... Forse, tra tutte quante, conviene quasi aumentare la versione minima della SDK e utilizzare lo START_STICKY... Vedremo più avanti.

Grazie ancora. Mi stai salvando il posto di lavoro :D

Offline undead

  • Utente senior
  • ****
  • Post: 666
  • Respect: +113
    • Mostra profilo
  • Dispositivo Android:
    Samsung Galaxy S6
  • Play Store ID:
    DrKappa
  • Sistema operativo:
    Windows 10 64-bit, Windows 8.1 64-bit
Re:Continuo Resume Activity chiamata dall'AlarmManager
« Risposta #11 il: 17 Febbraio 2012, 18:09:14 CET »
0
Penso proprio che passare alla 2.0 sia la soluzione migliore.

http://developer.android.com/resources/dashboard/platform-versions.html

Questo è un grafico UFFICIALE di google che rappresenta gli accessi al market per device dal 18 gennaio al 1 febbraio.

Device 1.6 o minori rappresentano l'1.5% degli accessi. In realtà saranno di più ma vista la crescita esponenziale di android credo che un target 2.0 a meno di problemi specifici (hai solo un device 1.6 per testare la tua app o per lavoro hai dei limiti imposti) sia abbastanza sicuro.

D'altra parte la frammentazione della piattaforma esiste, inutile nasconderla.  :-(