2013-08-13 11 views
8

Sto scrivendo un'app che rileva l'audio dal jack delle cuffie e trasmette Intenti quando vengono soddisfatte determinate condizioni audio (in particolare quando rileva la lettura di una tessera sfiorata da un dispositivo audio ausiliario) .Come mantenere attivo un servizio a tempo indeterminato

La mia app non ha attività, è solo un'applicazione e un servizio.

Tutto funziona bene tranne che il servizio viene ripulito da Android dopo un periodo di tempo relativamente breve (~ un minuto).

Sono curioso di sapere cosa devo fare per dire ad Android che questo è un servizio utile e che dovrebbe lasciarlo da solo a meno che non abbia davvero bisogno della sua memoria. Mi rendo conto che posso creare un allarme che si attiva ogni due secondi e attiva il servizio se nota che non è lì, ma sembra un kluge. C'è un modo più Android (y) per mantenerlo vivo rispetto a quello?

risposta

6

mia app non ha attività, è solo un'applicazione e un servizio.

Ciò significa che la tua app non funzionerà mai, su qualsiasi dispositivo Android 3.1 o versioni successive, a meno che tu non abbia qualche vincolo da qualche altra applicazione che sta per avviare manualmente il tuo servizio.

Sto scrivendo un'app che rileva l'audio dal jack delle cuffie e trasmette Intenti quando vengono soddisfatte determinate condizioni audio (in particolare quando rileva la lettura di una tessera sfiorare attraverso un dispositivo audio ausiliario).

Non nominare la propria azienda dopo una forma geometrica: è stato fatto. :-)

Sono curioso di sapere che cosa devo fare per dire a Android che questo è un servizio utile e che dovrebbe lasciarlo da solo a meno che non abbia davvero bisogno della sua memoria.

Siete invitati a utilizzare startForeground() per dichiarare che si tratta di un servizio in primo piano. Il compromesso è che sarà necessario mostrare uno Notification, idealmente uno che consenta all'utente di interrompere il servizio. Tenere presente che gli utenti potrebbero non apprezzare questo Notification, ma you are stuck with it, particularly on Android 4.3+. Potresti essere meglio servito passando da un servizio a un'attività, in modo che l'utente possa avviarlo, passare una carta e processare qualsiasi transazione.

+0

Ehi Marco. Grazie per l'aiuto. Come con (quasi) tutte le app che scrivo è un'app kiosk personalizzata che non lascia all'utente molto spazio per fare qualsiasi cosa. Il chiosco è perennemente in "primo piano" e il servizio consegna le carte su di esso (via broadcast). C'è una buona ragione (che ometterò) perché questo deve essere eseguito come app separata, anziché essere inserito direttamente nel Kiosk. Quindi, sono felice di avere l'attività che attiva tutto e io sto bene con il primo piano. Il chiosco in cima interferisce in primo piano con il primo piano? –

+0

@ Dr.Dredel: "Il chiosco in cima interferisce in primo piano con il primo piano?" - No, non dovrebbe essere un problema. Se hai mai usato un lettore musicale su un dispositivo Android e hai visto che ha inserito un 'Notification' nella barra di stato durante la riproduzione, questo perché la riproduzione è gestita da un servizio in primo piano. Questo, o brevemente durante una transazione (ad esempio, ricorda il download degli aggiornamenti di Milk in base a un messaggio GCM), è il tipico caso d'uso per un servizio in primo piano. – CommonsWare

+0

sì, questo ha perfettamente senso. grazie ancora. –

0

Non è possibile limitare l'utente ad interrompere manualmente il servizio da Impostazioni, servizi in esecuzione. Anche come amministratore del dispositivo.

È possibile aggiungere il ricevitore di avvio, l'armadietto dello schermo e qualsiasi evento, che riavvierà il servizio ucciso e l'app se sarebbe anche possibile riavviare il servizio con le impostazioni di un flag se viene ucciso con un'attività uccisa Attività avanzata uccisore.

3

Utilizzare START_STICKY per mantenere il servizio in giro.

@Override 
public int onStartCommand(Intent intent, int flags, int startId) { 
     Log.i("LocalService", "Received start id " + startId + ": " + intent); 
     // We want this service to continue running until it is explicitly 
     // stopped, so return sticky. 
     return START_STICKY; 
} 

Esempio Uso:

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

Ulteriori informazioni:

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

1

Ho provato AlarmManager. Funziona. Ho usato Contex.startService() in AlarmReceiver. E posso verificare se il mio servizio è in esecuzione in modo da decidere se riavviare il servizio. Quindi, anche se il mio servizio viene interrotto manualmente dagli utenti nelle impostazioni o ucciso da qualche app di pulizia, il servizio può essere riavviato. Ecco il codice principale qui sotto.

package com.example.androidnetwork; 

    import android.app.ActivityManager; 
    import android.app.ActivityManager.RunningServiceInfo; 
    import android.app.AlarmManager; 
    import android.app.PendingIntent; 
    import android.content.BroadcastReceiver; 
    import android.content.Context; 
    import android.content.Intent; 
    import android.os.Bundle; 
    import android.support.v7.app.ActionBarActivity; 
    import android.util.Log; 
    import android.view.View; 
    import android.view.View.OnClickListener; 
    import android.widget.Button; 

public class MainActivity extends ActionBarActivity { 

    private static final long INTERVAL = 5 * 1000; // unit: ms 

    private Button mRegisterReceiverBtn; 
    private Button mCheckNetStatusBtn; 
    private Button mStopButton; 
    private AlarmManager mAlarmManager; 
    private PendingIntent mPendingIntent; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 

     initData(); 

     initView(); 
    } 

    private void initData() { 
     mAlarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE); 
    } 

    private void initView() { 
     mRegisterReceiverBtn = (Button) findViewById(R.id.activity_main_start_btn); 
     mCheckNetStatusBtn = (Button) findViewById(R.id.activity_main_start_check_net_status_bnt); 
     mStopButton = (Button) findViewById(R.id.activity_main_stop); 
     mRegisterReceiverBtn.setOnClickListener(new OnClickListener() { 

      @Override 
      public void onClick(View v) { 
       MainActivity.this.createServiceControllerPendIntent(); 
       mAlarmManager.setInexactRepeating(
         AlarmManager.ELAPSED_REALTIME_WAKEUP, 0, INTERVAL, 
         mPendingIntent); 
      } 
     }); 
     mCheckNetStatusBtn.setOnClickListener(new OnClickListener() { 

      @Override 
      public void onClick(View v) { 
       MainActivity.this.startActivity(new Intent(MainActivity.this, 
         NetStatusActivity.class)); 
      } 
     }); 
     mStopButton.setOnClickListener(new OnClickListener() { 

      @Override 
      public void onClick(View v) { 
       if (mPendingIntent != null) { 
        mAlarmManager.cancel(mPendingIntent); 
       } else { 
        createServiceControllerPendIntent(); 
        mAlarmManager.cancel(mPendingIntent); 
       } 
       // MainActivity.this.stopService(ServiceController 
       // .getServiceIntent()); 
       Intent intent = new Intent(); 
       intent.setClass(getApplicationContext(), 
         NetStatusMonitorService.class); 
       stopService(intent); 
      } 
     }); 

    } 

    private void createServiceControllerPendIntent() { 
     Intent intent = new Intent(MainActivity.this, 
       ServiceController.class); 
     mPendingIntent = PendingIntent.getBroadcast(MainActivity.this, 
       0, intent, 0); 
    } 

    @Override 
    protected void onDestroy() { 
     deInitView(); 
     super.onDestroy(); 
    } 

    private void deInitView() { 

    } 


    public static class ServiceController extends BroadcastReceiver { 

     private static Intent sMonitorServiceIntent = null; 

     @Override 
     public void onReceive(Context context, Intent intent) { 
      Log.d("Service Controller", "onReceiver"); 
      if (isServiceRunning(context, NetStatusMonitorService.class) == false) { 
       String info = "starting service by AlarmManager"; 
       Log.d("Service Controller", info); 
       sMonitorServiceIntent = new Intent(context, 
         NetStatusMonitorService.class); 
       context.startService(sMonitorServiceIntent); 
      } 
     } 

      // this method is very important 
     private boolean isServiceRunning(Context context, Class<?> serviceClass) { 
      ActivityManager am = (ActivityManager) context 
        .getSystemService(Context.ACTIVITY_SERVICE); 
      for (RunningServiceInfo serviceInfo : am 
        .getRunningServices(Integer.MAX_VALUE)) { 
       String className1 = serviceInfo.service.getClassName(); 
       String className2 = serviceClass.getName(); 
       if (className1.equals(className2)) { 
        return true; 
       } 
      } 
      return false; 
     } 

     public static Intent getServiceIntent() { 
      return sMonitorServiceIntent; 
     } 
    } 

} 
+0

AlarmManager non è stabile. Se controlli il log in un giorno, l'intervallo di tempo è di 2 minuti, vedrai che si ferma circa 30 minuti qualche volta. – Brave

Problemi correlati