Autore Topic: Activity, Service, BroadCastReceiver  (Letto 1711 volte)

Offline truccoandroid

  • Nuovo arrivato
  • *
  • Post: 17
  • Respect: 0
    • Mostra profilo
Activity, Service, BroadCastReceiver
« il: 05 Agosto 2011, 13:47:13 CEST »
0
Salve, ogni tot tempo (60 minuti) devo controllare 10 numeri in un db online, se sono diversi da quelli che ho io nel db devo creare una notifica e visualizzare i nuovi numeri.

Ho letto molto in questo sito e altrove e convengo che la soluzione è la creazione di un Service un Broadcast Receiver e un Pending Intent. Solo che all' atto pratico o logico non riesco a collegare il tutto.

Caso A.

Applicazione chiusa. Il Service controlla i numeri, "si accorge" che ci sono dei numeri nuovi e comunica al BroadCastReceiver l' evento  e quest' ultimo apre una notifica. L' utente clicca la notifica e apre l' applicazione.

E' corretto


Caso B.

Applicazione aperta. check, nuovi numeri, broadcast... non viene aperta la notifica.

La mia difficoltà è riuscire a legare il tutto.

Conoscete qualche esempio che sia avvicini a questa procedura ?

E' logico che non mi dovete passare il codice ma una cosa alla volta.
Come creo un Service collegato ad un BroadCastReceiver? La buona volontà non mi manca.

Offline truccoandroid

  • Nuovo arrivato
  • *
  • Post: 17
  • Respect: 0
    • Mostra profilo
Re:Activity, Service, BroadCastReceiver
« Risposta #1 il: 05 Agosto 2011, 17:23:01 CEST »
0
Allora metto un po di codice che ho ricavato da tanti esempi


Activity principale
Codice (Java): [Seleziona]
package it.example.numbertime;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;

public class NumberTimerActivity extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);                  
       
               
        AlarmManagerExample.startAlarmNumber(this);
               
       
    }
}

la classe che crea l' allarme

Codice (Java): [Seleziona]
package it.example.numbertime;

import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.util.Log;

public class AlarmManagerExample {
       
        public static int created=0;
       
         private static PendingIntent getPendingIntent(Context paramOfContext)
          {        
                 Intent pendingIntent = new Intent("it.truccoandroid.example.CHECK_NUMBER");       
           
            Intent data = pendingIntent.putExtra("SOURCE_NUMBERS", "http://mysite.it/getNumbers.php");
            return PendingIntent.getBroadcast(paramOfContext, 0, data , PendingIntent.FLAG_CANCEL_CURRENT);
          }
         
         
         public static void startAlarmNumber(Context paramOfContext)
          {
                 
                     
             
              PendingIntent localPendingIntent = AlarmManagerExample.getPendingIntent(paramOfContext);
              AlarmManager alarm= (AlarmManager) paramOfContext.getSystemService(paramOfContext.ALARM_SERVICE);
              alarm.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() ,15*1000, localPendingIntent);
             
                               
           
             
          }

          public static void removeAlarmManager(Context context)
          {
                  AlarmManager alarm= (AlarmManager) context.getSystemService(context.ALARM_SERVICE);
                  PendingIntent pendingIntent = getPendingIntent(context);
                  alarm.cancel(pendingIntent);
          }

}

Il BroadCastReceiver
Codice (Java): [Seleziona]
package it.example.numbertime;

import java.util.Map;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.AsyncTask;
import android.util.Log;

public class UpdateNumberReceiver extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {

                String action = intent.getAction();

                if (action.equals("it.truccoandroid.example.CHECK_NUMBER")) {

                        AlarmManagerExample.removeAlarmManager(context);

                        String path_site = intent.getStringExtra("SOURCE_NUMBERS");

                        AsyncTask getNumberTask = new GetNumberAsyncTask(context)
                                        .execute(path_site);

                }

        }

        class GetNumberAsyncTask extends
                        AsyncTask<String, String, Map<String, Integer>> {

                private Context context;

                public GetNumberAsyncTask(Context context) {

                        this.context = context;
                }

                @Override
                protected Map<String, Integer> doInBackground(String... arg0) {

                        // qui faccio un controllo dei numeri se sono nuovi creo la notifica

                        // creo la notifica

                        Log.i("debug", "creo la notifica");
                        String ns = this.context.NOTIFICATION_SERVICE;
                        NotificationManager nm = (NotificationManager) this.context
                                        .getSystemService(ns);
                        int icon = R.drawable.icon;
                        CharSequence testo = "Nuovi numeri";
                        long when = System.currentTimeMillis();
                        Notification notification = new Notification(icon, testo, when);
                        String contentTitle = "Attenzione nuovi numeri";
                        String subMessage = "Attenzione nuovi numeri";
                        Intent notificationIntent = new Intent(context,
                                        NumberTimerActivity.class);
                        PendingIntent contentIntent = PendingIntent.getActivity(
                                        this.context, 100, notificationIntent,
                                        notification.flags |= Notification.FLAG_AUTO_CANCEL);

                        notification.setLatestEventInfo(this.context, contentTitle,
                                        subMessage, contentIntent);

                        nm.notify(100, notification);

                        return null;
                }

        }

}

Ok sostalziamente sembra funzionare. allarme, broadcast, recupero i dati, notifica, apertura Activity.

La domanda è come faccio a sapere che io sono già con l' applicazione aperta quindi devo solo aggiornare la UI ?

Altra domanda.. se volessi sostituire AsyncTask posso usare anche una classe separare che implementa una Runnable o extends un Thread ?








Offline truccoandroid

  • Nuovo arrivato
  • *
  • Post: 17
  • Respect: 0
    • Mostra profilo
Re:Activity, Service, BroadCastReceiver
« Risposta #2 il: 07 Agosto 2011, 06:00:22 CEST »
0
Ho scoperto che basta mettere nel Mafifest launchmode="singleTop" che se l' activity è aperta non viene rilanciata una nuova Actvity.

La domanda principale rimane, se ho un aggiornamento come faccio a capire che l' app è già aperta con l' activity e non creare la notifica

Offline teskio

  • Moderatore globale
  • Utente normale
  • *****
  • Post: 387
  • Respect: +118
    • Github
    • Google+
    • Mostra profilo
    • Skullab
  • Dispositivo Android:
    Cubot GT99 / SurfTab Ventos 10.1
  • Play Store ID:
    Skullab Software
  • Sistema operativo:
    windows 7 / ubuntu 12.04
Re:Activity, Service, BroadCastReceiver
« Risposta #3 il: 07 Agosto 2011, 13:15:10 CEST »
0
Potresti usare :
ActivityManager | Android Reference
prendere la lista dei processi che sono in "running" e verificare se la tua Activity è attiva, attraverso ActivityManager.RunningAppProcessInfo e/o ActivityManager.RunningTaskInfo

Un po' macchinoso ma dovrebbe funzionare.

Oppure :

Gestire il tutto all'interno della tua app, ad esempio comunicando al Service quando l'Activity viene lanciata ed è visibile, in questo modo dal Service potrai gestire se mandare o meno la notifica. :-P

Offline truccoandroid

  • Nuovo arrivato
  • *
  • Post: 17
  • Respect: 0
    • Mostra profilo
Re:Activity, Service, BroadCastReceiver
« Risposta #4 il: 07 Agosto 2011, 16:05:52 CEST »
0
Forse il primo caso il secondo la vedo dura.. visto che l' OS può chiudere l' Activity senza che il Service lo sappia...

Offline truccoandroid

  • Nuovo arrivato
  • *
  • Post: 17
  • Respect: 0
    • Mostra profilo
Re:Activity, Service, BroadCastReceiver
« Risposta #5 il: 08 Agosto 2011, 09:12:35 CEST »
0
Se non trovo soluzioni mi sa che mi tocca decompilare qualche applicazione per vedere come hanno fatto.

Offline teskio

  • Moderatore globale
  • Utente normale
  • *****
  • Post: 387
  • Respect: +118
    • Github
    • Google+
    • Mostra profilo
    • Skullab
  • Dispositivo Android:
    Cubot GT99 / SurfTab Ventos 10.1
  • Play Store ID:
    Skullab Software
  • Sistema operativo:
    windows 7 / ubuntu 12.04
Re:Activity, Service, BroadCastReceiver
« Risposta #6 il: 08 Agosto 2011, 10:23:50 CEST »
0
In primo luogo è eticamente, nonchè legalmente, scorretto decompilare applicazioni altrui, ci sono un sacco di progetti open source...guarda quelli.

Ci sono molti modi per effettuare una comunicazione tra Activity e Service, spiegati anche nella Official-Doc. Ricordo che un Service non è un processo separato e non è nemmeno un Thread, ma è parte dell'app stessa.
LocalServiceSample

Ci sono molti modi per comunicare con i Service, si possono usare gli Intent e i BroadcastReceiver, usare gli Handler e i Messenger, creare una AIDL (per i casi inter-processo)  o usare il Service in singleton.
Se si ha ben chiaro il lifecycle di una Activity e quello di un Service non ci sono grossi problemi ad implementare e gestire questo tipo di comunicazione.
Comunque se il tuo problema è legato solo alla comunicazione : Bound Services | Android Developers

Offline truccoandroid

  • Nuovo arrivato
  • *
  • Post: 17
  • Respect: 0
    • Mostra profilo
Re:Activity, Service, BroadCastReceiver
« Risposta #7 il: 08 Agosto 2011, 10:35:27 CEST »
0
quindi dalla mia Activity dovrei lanciare sia un AlarmManager che un Service.

AlarmManager fa il controllo degli aggornamenti e il Service apre l' Activity.

Il BroadCast ok... ricevo il messaggio ma apro la notifica e fin qui ci sono il problema è aprire senza notifica se l' app è aperta

Offline truccoandroid

  • Nuovo arrivato
  • *
  • Post: 17
  • Respect: 0
    • Mostra profilo
Re:Activity, Service, BroadCastReceiver
« Risposta #8 il: 08 Agosto 2011, 11:45:20 CEST »
0
Ho trovato questo script penso che mi possa servire


Codice (Java): [Seleziona]
public static boolean isServiceRunning(Context context) {

    Log.i(TAG, "Checking if service is running");

    ActivityManager activityManager = (ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE);

    List<RunningServiceInfo> services = activityManager.getRunningServices(Integer.MAX_VALUE);

    boolean isServiceFound = false;

    for (int i = 0; i < services.size(); i++) {

        if (Constants.PACKAGE.equals(services.get(i).service.getPackageName())){

            if (Constants.BACKGROUND_SERVICE_CLASS.equals(services.get(i).service.getClassName())){
                isServiceFound = true;
            }
        }
    }

    Log.i(TAG, "Service was" + (isServiceFound ? "" : " not") + " running");

    return isServiceFound;

}

Offline truccoandroid

  • Nuovo arrivato
  • *
  • Post: 17
  • Respect: 0
    • Mostra profilo
Re:Activity, Service, BroadCastReceiver
« Risposta #9 il: 09 Agosto 2011, 09:22:10 CEST »
0
Risolverei tutto con un Service.

Il Service è possibile ottenere l' istanza in altre classi ?